@coinbase/cds-mobile-visualization 3.4.0-beta.2 → 3.4.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +122 -0
- package/dts/chart/CartesianChart.d.ts +92 -34
- 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/ChartProvider.d.ts +3 -0
- package/dts/chart/ChartProvider.d.ts.map +1 -1
- package/dts/chart/Path.d.ts +97 -32
- package/dts/chart/Path.d.ts.map +1 -1
- package/dts/chart/PeriodSelector.d.ts +6 -13
- package/dts/chart/PeriodSelector.d.ts.map +1 -1
- package/dts/chart/area/Area.d.ts +39 -28
- 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 +86 -118
- 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 +49 -12
- package/dts/chart/bar/Bar.d.ts.map +1 -1
- package/dts/chart/bar/BarChart.d.ts +40 -19
- package/dts/chart/bar/BarChart.d.ts.map +1 -1
- package/dts/chart/bar/BarPlot.d.ts +3 -1
- package/dts/chart/bar/BarPlot.d.ts.map +1 -1
- package/dts/chart/bar/BarStack.d.ts +41 -46
- package/dts/chart/bar/BarStack.d.ts.map +1 -1
- package/dts/chart/bar/BarStackGroup.d.ts +2 -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 +4 -1
- package/dts/chart/index.d.ts.map +1 -1
- package/dts/chart/legend/DefaultLegendEntry.d.ts +5 -0
- package/dts/chart/legend/DefaultLegendEntry.d.ts.map +1 -0
- package/dts/chart/legend/DefaultLegendShape.d.ts +5 -0
- package/dts/chart/legend/DefaultLegendShape.d.ts.map +1 -0
- package/dts/chart/legend/Legend.d.ts +168 -0
- package/dts/chart/legend/Legend.d.ts.map +1 -0
- package/dts/chart/legend/index.d.ts +4 -0
- package/dts/chart/legend/index.d.ts.map +1 -0
- 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 +61 -27
- 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 +68 -20
- 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 +136 -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 +38 -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 +230 -42
- package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts +54 -0
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts.map +1 -0
- package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts +46 -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/axis.d.ts +25 -1
- package/dts/chart/utils/axis.d.ts.map +1 -1
- package/dts/chart/utils/bar.d.ts +34 -0
- package/dts/chart/utils/bar.d.ts.map +1 -1
- package/dts/chart/utils/chart.d.ts +52 -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 +59 -0
- package/dts/chart/utils/path.d.ts.map +1 -1
- package/dts/chart/utils/point.d.ts +71 -7
- package/dts/chart/utils/point.d.ts.map +1 -1
- package/dts/chart/utils/scale.d.ts +102 -0
- package/dts/chart/utils/scale.d.ts.map +1 -1
- package/dts/chart/utils/scrubber.d.ts +40 -0
- package/dts/chart/utils/scrubber.d.ts.map +1 -0
- package/dts/chart/utils/transition.d.ts +178 -0
- package/dts/chart/utils/transition.d.ts.map +1 -0
- package/esm/chart/CartesianChart.js +199 -75
- package/esm/chart/ChartContextBridge.js +159 -0
- package/esm/chart/ChartProvider.js +2 -2
- package/esm/chart/Path.js +200 -114
- package/esm/chart/PeriodSelector.js +7 -3
- package/esm/chart/__stories__/CartesianChart.stories.js +307 -134
- package/esm/chart/__stories__/ChartTransitions.stories.js +629 -0
- package/esm/chart/__stories__/PeriodSelector.stories.js +201 -75
- package/esm/chart/area/Area.js +27 -35
- package/esm/chart/area/AreaChart.js +17 -12
- package/esm/chart/area/DottedArea.js +64 -108
- package/esm/chart/area/GradientArea.js +37 -91
- package/esm/chart/area/SolidArea.js +24 -8
- package/esm/chart/area/__stories__/AreaChart.stories.js +1 -1
- package/esm/chart/axis/Axis.js +5 -39
- package/esm/chart/axis/DefaultAxisTickLabel.js +11 -0
- package/esm/chart/axis/XAxis.js +148 -66
- package/esm/chart/axis/YAxis.js +149 -65
- package/esm/chart/axis/__stories__/Axis.stories.js +259 -1
- package/esm/chart/axis/index.js +1 -0
- package/esm/chart/bar/Bar.js +7 -1
- package/esm/chart/bar/BarChart.js +17 -37
- package/esm/chart/bar/BarPlot.js +43 -35
- package/esm/chart/bar/BarStack.js +84 -37
- package/esm/chart/bar/BarStackGroup.js +7 -17
- package/esm/chart/bar/DefaultBar.js +29 -51
- package/esm/chart/bar/DefaultBarStack.js +34 -58
- package/esm/chart/bar/__stories__/BarChart.stories.js +948 -88
- package/esm/chart/gradient/Gradient.js +53 -0
- package/esm/chart/gradient/index.js +1 -0
- package/esm/chart/index.js +4 -1
- package/esm/chart/legend/DefaultLegendEntry.js +42 -0
- package/esm/chart/legend/DefaultLegendShape.js +64 -0
- package/esm/chart/legend/Legend.js +59 -0
- package/esm/chart/legend/__stories__/Legend.stories.js +574 -0
- package/esm/chart/legend/index.js +3 -0
- package/esm/chart/line/DefaultReferenceLineLabel.js +66 -0
- package/esm/chart/line/DottedLine.js +31 -14
- package/esm/chart/line/Line.js +96 -68
- package/esm/chart/line/LineChart.js +21 -14
- package/esm/chart/line/ReferenceLine.js +80 -63
- package/esm/chart/line/SolidLine.js +27 -10
- package/esm/chart/line/__stories__/LineChart.stories.js +1748 -2048
- package/esm/chart/line/__stories__/ReferenceLine.stories.js +177 -28
- package/esm/chart/line/index.js +1 -1
- package/esm/chart/point/DefaultPointLabel.js +39 -0
- package/esm/chart/point/Point.js +186 -0
- package/esm/chart/point/index.js +2 -0
- package/esm/chart/scrubber/DefaultScrubberBeacon.js +180 -0
- package/esm/chart/scrubber/DefaultScrubberBeaconLabel.js +43 -0
- package/esm/chart/scrubber/DefaultScrubberLabel.js +28 -0
- package/esm/chart/scrubber/Scrubber.js +130 -144
- package/esm/chart/scrubber/ScrubberBeaconGroup.js +165 -0
- package/esm/chart/scrubber/ScrubberBeaconLabelGroup.js +208 -0
- package/esm/chart/scrubber/ScrubberProvider.js +46 -54
- package/esm/chart/scrubber/__stories__/Scrubber.stories.js +760 -0
- 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/axis.js +47 -31
- package/esm/chart/utils/bar.js +43 -0
- package/esm/chart/utils/chart.js +57 -3
- package/esm/chart/utils/gradient.js +305 -0
- package/esm/chart/utils/index.js +3 -0
- package/esm/chart/utils/path.js +84 -8
- package/esm/chart/utils/point.js +171 -17
- package/esm/chart/utils/scale.js +242 -2
- package/esm/chart/utils/scrubber.js +146 -0
- package/esm/chart/utils/transition.js +220 -0
- package/esm/sparkline/__figma__/Sparkline.figma.js +1 -1
- package/esm/sparkline/__stories__/Sparkline.stories.js +11 -7
- package/esm/sparkline/__stories__/SparklineGradient.stories.js +7 -4
- package/esm/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.js +1 -1
- package/esm/sparkline/sparkline-interactive/__stories__/SparklineInteractive.stories.js +51 -26
- package/esm/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.js +1 -1
- package/esm/sparkline/sparkline-interactive-header/__stories__/SparklineInteractiveHeader.stories.js +17 -9
- package/package.json +15 -10
- 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/__stories__/Chart.stories.js +0 -79
- package/esm/chart/line/GradientLine.js +0 -62
- package/esm/chart/scrubber/ScrubberBeacon.js +0 -199
|
@@ -1,1718 +1,1133 @@
|
|
|
1
|
-
const _excluded = ["
|
|
1
|
+
const _excluded = ["dataX", "dataY"],
|
|
2
2
|
_excluded2 = ["label"],
|
|
3
|
-
_excluded3 = ["style"]
|
|
4
|
-
_excluded4 = ["dataX"];
|
|
5
|
-
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; }
|
|
3
|
+
_excluded3 = ["style"];
|
|
6
4
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
5
|
+
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; }
|
|
6
|
+
import { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
7
|
+
import { useAnimatedReaction, useDerivedValue, useSharedValue, withDelay, withTiming } from 'react-native-reanimated';
|
|
8
|
+
import { assets, ethBackground } from '@coinbase/cds-common/internal/data/assets';
|
|
11
9
|
import { prices } from '@coinbase/cds-common/internal/data/prices';
|
|
12
10
|
import { sparklineInteractiveData } from '@coinbase/cds-common/internal/visualizations/SparklineInteractiveData';
|
|
13
11
|
import { useTabsContext } from '@coinbase/cds-common/tabs/TabsContext';
|
|
12
|
+
import { NoopFn } from '@coinbase/cds-common/utils/mockUtils';
|
|
14
13
|
import { useTheme } from '@coinbase/cds-mobile';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
14
|
+
import { DataCard } from '@coinbase/cds-mobile/alpha/data-card/DataCard';
|
|
15
|
+
import { IconButton } from '@coinbase/cds-mobile/buttons';
|
|
16
|
+
import { ListCell } from '@coinbase/cds-mobile/cells';
|
|
17
|
+
import { ExampleScreen } from '@coinbase/cds-mobile/examples/ExampleScreen';
|
|
17
18
|
import { Box, HStack, VStack } from '@coinbase/cds-mobile/layout';
|
|
18
|
-
import { RemoteImage } from '@coinbase/cds-mobile/media';
|
|
19
|
+
import { Avatar, RemoteImage } from '@coinbase/cds-mobile/media';
|
|
19
20
|
import { SectionHeader } from '@coinbase/cds-mobile/section-header/SectionHeader';
|
|
20
|
-
import {
|
|
21
|
+
import { Pressable } from '@coinbase/cds-mobile/system';
|
|
21
22
|
import { SegmentedTab } from '@coinbase/cds-mobile/tabs/SegmentedTab';
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import { Area, DottedArea
|
|
25
|
-
import { XAxis, YAxis } from '../../axis';
|
|
23
|
+
import { Text } from '@coinbase/cds-mobile/typography';
|
|
24
|
+
import { Circle, FontWeight, Group, Skia, TextAlign } from '@shopify/react-native-skia';
|
|
25
|
+
import { Area, DottedArea } from '../../area';
|
|
26
|
+
import { DefaultAxisTickLabel, XAxis, YAxis } from '../../axis';
|
|
26
27
|
import { CartesianChart } from '../../CartesianChart';
|
|
27
28
|
import { useCartesianChartContext } from '../../ChartProvider';
|
|
28
29
|
import { PeriodSelector, PeriodSelectorActiveIndicator } from '../../PeriodSelector';
|
|
29
|
-
import { Point } from '../../
|
|
30
|
-
import { Scrubber } from '../../scrubber';
|
|
31
|
-
import {
|
|
30
|
+
import { Point } from '../../point';
|
|
31
|
+
import { DefaultScrubberBeacon, Scrubber } from '../../scrubber';
|
|
32
|
+
import { buildTransition, defaultTransition, projectPointWithSerializableScale, unwrapAnimatedValue, useScrubberContext } from '../../utils';
|
|
33
|
+
import { DottedLine, Line, LineChart, ReferenceLine, SolidLine } from '..';
|
|
32
34
|
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];
|
|
35
|
+
function MultipleLine() {
|
|
36
|
+
const theme = useTheme();
|
|
37
|
+
const [scrubberPosition, setScrubberPosition] = useState();
|
|
38
|
+
const pages = useMemo(() => ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'], []);
|
|
39
|
+
const pageViews = useMemo(() => [2400, 1398, 9800, 3908, 4800, 3800, 4300], []);
|
|
40
|
+
const uniqueVisitors = useMemo(() => [4000, 3000, 2000, 2780, 1890, 2390, 3490], []);
|
|
41
|
+
const chartAccessibilityLabel = "Website visitors across " + pageViews.length + " pages.";
|
|
42
|
+
const scrubberAccessibilityLabel = useCallback(index => {
|
|
43
|
+
return pages[index] + " has " + pageViews[index] + " views and " + uniqueVisitors[index] + " unique visitors.";
|
|
44
|
+
}, [pages, pageViews, uniqueVisitors]);
|
|
45
|
+
const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
46
|
+
maximumFractionDigits: 0
|
|
47
|
+
}).format(value), []);
|
|
48
|
+
const accessibilityLabel = useMemo(() => {
|
|
49
|
+
if (scrubberPosition !== undefined) {
|
|
50
|
+
return scrubberAccessibilityLabel(scrubberPosition);
|
|
51
|
+
}
|
|
52
|
+
return chartAccessibilityLabel;
|
|
53
|
+
}, [scrubberPosition, chartAccessibilityLabel, scrubberAccessibilityLabel]);
|
|
102
54
|
return /*#__PURE__*/_jsx(LineChart, {
|
|
103
55
|
enableScrubbing: true,
|
|
56
|
+
showArea: true,
|
|
57
|
+
showXAxis: true,
|
|
104
58
|
showYAxis: true,
|
|
105
|
-
|
|
106
|
-
|
|
59
|
+
accessibilityLabel: accessibilityLabel,
|
|
60
|
+
height: 200,
|
|
61
|
+
onScrubberPositionChange: setScrubberPosition,
|
|
107
62
|
series: [{
|
|
108
|
-
id: '
|
|
109
|
-
data:
|
|
110
|
-
|
|
111
|
-
|
|
63
|
+
id: 'pageViews',
|
|
64
|
+
data: pageViews,
|
|
65
|
+
color: theme.color.accentBoldGreen,
|
|
66
|
+
// Label will render next to scrubber beacon
|
|
67
|
+
label: 'Page Views'
|
|
68
|
+
}, {
|
|
69
|
+
id: 'uniqueVisitors',
|
|
70
|
+
data: uniqueVisitors,
|
|
71
|
+
color: theme.color.accentBoldPurple,
|
|
72
|
+
label: 'Unique Visitors',
|
|
73
|
+
// Default area is gradient
|
|
74
|
+
areaType: 'dotted'
|
|
112
75
|
}],
|
|
76
|
+
xAxis: {
|
|
77
|
+
// Used on the x-axis to provide context for each index from the series data array
|
|
78
|
+
data: pages
|
|
79
|
+
},
|
|
113
80
|
yAxis: {
|
|
114
|
-
|
|
115
|
-
tickLabelFormatter:
|
|
116
|
-
showGrid: true
|
|
81
|
+
showGrid: true,
|
|
82
|
+
tickLabelFormatter: numberFormatter
|
|
117
83
|
},
|
|
118
84
|
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
119
85
|
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
|
|
86
|
+
}
|
|
87
|
+
function DataFormat() {
|
|
88
|
+
const [scrubberPosition, setScrubberPosition] = useState();
|
|
89
|
+
const yData = useMemo(() => [2, 5.5, 2, 8.5, 1.5, 5], []);
|
|
90
|
+
const xData = useMemo(() => [1, 2, 3, 5, 8, 10], []);
|
|
91
|
+
const chartAccessibilityLabel = "Chart with custom X and Y data. " + yData.length + " data points";
|
|
92
|
+
const scrubberAccessibilityLabel = useCallback(index => {
|
|
93
|
+
return "Point " + (index + 1) + ": X value " + xData[index] + ", Y value " + yData[index];
|
|
94
|
+
}, [xData, yData]);
|
|
95
|
+
const accessibilityLabel = useMemo(() => {
|
|
96
|
+
if (scrubberPosition !== undefined) {
|
|
97
|
+
return scrubberAccessibilityLabel(scrubberPosition);
|
|
98
|
+
}
|
|
99
|
+
return chartAccessibilityLabel;
|
|
100
|
+
}, [scrubberPosition, chartAccessibilityLabel, scrubberAccessibilityLabel]);
|
|
101
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
102
|
+
enableScrubbing: true,
|
|
103
|
+
points: true,
|
|
104
|
+
showArea: true,
|
|
105
|
+
showXAxis: true,
|
|
124
106
|
showYAxis: true,
|
|
125
|
-
|
|
126
|
-
|
|
107
|
+
accessibilityLabel: accessibilityLabel,
|
|
108
|
+
curve: "natural",
|
|
109
|
+
height: 200,
|
|
110
|
+
inset: {
|
|
111
|
+
top: 16,
|
|
112
|
+
right: 16,
|
|
113
|
+
bottom: 0,
|
|
114
|
+
left: 0
|
|
115
|
+
},
|
|
116
|
+
onScrubberPositionChange: setScrubberPosition,
|
|
127
117
|
series: [{
|
|
128
|
-
id: '
|
|
129
|
-
data:
|
|
130
|
-
label: 'Monthly Growth',
|
|
131
|
-
color: '#2ca02c'
|
|
118
|
+
id: 'line',
|
|
119
|
+
data: yData
|
|
132
120
|
}],
|
|
121
|
+
xAxis: {
|
|
122
|
+
data: xData,
|
|
123
|
+
showLine: true,
|
|
124
|
+
showTickMarks: true,
|
|
125
|
+
showGrid: true
|
|
126
|
+
},
|
|
133
127
|
yAxis: {
|
|
134
|
-
|
|
135
|
-
|
|
128
|
+
domain: {
|
|
129
|
+
min: 0
|
|
130
|
+
},
|
|
131
|
+
position: 'left',
|
|
132
|
+
showLine: true,
|
|
133
|
+
showTickMarks: true,
|
|
136
134
|
showGrid: true
|
|
137
135
|
},
|
|
138
|
-
children:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
136
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
137
|
+
hideOverlay: true
|
|
138
|
+
})
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function LiveUpdates() {
|
|
142
|
+
const scrubberRef = useRef(null);
|
|
143
|
+
const initialData = useMemo(() => {
|
|
144
|
+
return sparklineInteractiveData.hour.map(d => d.value);
|
|
145
|
+
}, []);
|
|
146
|
+
const [priceData, setPriceData] = useState(initialData);
|
|
147
|
+
const lastDataPointTimeRef = useRef(Date.now());
|
|
148
|
+
const updateCountRef = useRef(0);
|
|
149
|
+
const intervalSeconds = 3600 / initialData.length;
|
|
150
|
+
const maxPercentChange = Math.abs(initialData[initialData.length - 1] - initialData[0]) * 0.05;
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
const priceUpdateInterval = setInterval(() => {
|
|
153
|
+
var _scrubberRef$current;
|
|
154
|
+
setPriceData(currentData => {
|
|
155
|
+
const newData = [...currentData];
|
|
156
|
+
const lastPrice = newData[newData.length - 1];
|
|
157
|
+
const priceChange = (Math.random() - 0.5) * maxPercentChange;
|
|
158
|
+
const newPrice = Math.round((lastPrice + priceChange) * 100) / 100;
|
|
159
|
+
|
|
160
|
+
// Check if we should roll over to a new data point
|
|
161
|
+
const currentTime = Date.now();
|
|
162
|
+
const timeSinceLastPoint = (currentTime - lastDataPointTimeRef.current) / 1000;
|
|
163
|
+
if (timeSinceLastPoint >= intervalSeconds) {
|
|
164
|
+
// Time for a new data point - remove first, add new at end
|
|
165
|
+
lastDataPointTimeRef.current = currentTime;
|
|
166
|
+
newData.shift(); // Remove oldest data point
|
|
167
|
+
newData.push(newPrice); // Add new data point
|
|
168
|
+
updateCountRef.current = 0;
|
|
169
|
+
} else {
|
|
170
|
+
// Just update the last data point
|
|
171
|
+
newData[newData.length - 1] = newPrice;
|
|
172
|
+
updateCountRef.current++;
|
|
173
|
+
}
|
|
174
|
+
return newData;
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Pulse the scrubber on each update
|
|
178
|
+
(_scrubberRef$current = scrubberRef.current) == null || _scrubberRef$current.pulse();
|
|
179
|
+
}, 2000 + Math.random() * 1000);
|
|
180
|
+
return () => clearInterval(priceUpdateInterval);
|
|
181
|
+
}, [intervalSeconds, maxPercentChange]);
|
|
182
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
183
|
+
enableScrubbing: true,
|
|
184
|
+
showArea: true,
|
|
185
|
+
height: 200,
|
|
186
|
+
inset: {
|
|
187
|
+
right: 64
|
|
188
|
+
},
|
|
189
|
+
series: [{
|
|
190
|
+
id: 'btc',
|
|
191
|
+
data: priceData,
|
|
192
|
+
color: assets.btc.color
|
|
193
|
+
}],
|
|
194
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
195
|
+
ref: scrubberRef
|
|
196
|
+
})
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
function MissingData() {
|
|
200
|
+
const theme = useTheme();
|
|
201
|
+
const pages = ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'];
|
|
202
|
+
const pageViews = [2400, 1398, null, 3908, 4800, 3800, 4300];
|
|
203
|
+
const uniqueVisitors = [4000, 3000, null, 2780, 1890, 2390, 3490];
|
|
204
|
+
const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
205
|
+
maximumFractionDigits: 0
|
|
206
|
+
}).format(value), []);
|
|
207
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
208
|
+
enableScrubbing: true,
|
|
209
|
+
points: true,
|
|
210
|
+
showArea: true,
|
|
211
|
+
showXAxis: true,
|
|
212
|
+
showYAxis: true,
|
|
213
|
+
height: 200,
|
|
214
|
+
series: [{
|
|
215
|
+
id: 'pageViews',
|
|
216
|
+
data: pageViews,
|
|
217
|
+
color: theme.color.accentBoldGreen,
|
|
218
|
+
// Label will render next to scrubber beacon
|
|
219
|
+
label: 'Page Views',
|
|
220
|
+
connectNulls: true
|
|
221
|
+
}, {
|
|
222
|
+
id: 'uniqueVisitors',
|
|
223
|
+
data: uniqueVisitors,
|
|
224
|
+
color: theme.color.accentBoldPurple,
|
|
225
|
+
label: 'Unique Visitors'
|
|
226
|
+
}],
|
|
227
|
+
xAxis: {
|
|
228
|
+
// Used on the x-axis to provide context for each index from the series data array
|
|
229
|
+
data: pages
|
|
230
|
+
},
|
|
231
|
+
yAxis: {
|
|
232
|
+
showGrid: true,
|
|
233
|
+
tickLabelFormatter: numberFormatter
|
|
234
|
+
},
|
|
235
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
236
|
+
overlayOffset: 6
|
|
237
|
+
})
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
function Interaction() {
|
|
241
|
+
const [scrubberPosition, setScrubberPosition] = useState();
|
|
242
|
+
return /*#__PURE__*/_jsxs(VStack, {
|
|
243
|
+
gap: 2,
|
|
244
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
245
|
+
font: "label1",
|
|
246
|
+
children: scrubberPosition !== undefined ? "Scrubber position: " + scrubberPosition : 'Not scrubbing'
|
|
247
|
+
}), /*#__PURE__*/_jsx(LineChart, {
|
|
248
|
+
enableScrubbing: true,
|
|
249
|
+
showArea: true,
|
|
250
|
+
height: 200,
|
|
251
|
+
onScrubberPositionChange: setScrubberPosition,
|
|
252
|
+
series: [{
|
|
253
|
+
id: 'prices',
|
|
254
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
|
|
255
|
+
}],
|
|
256
|
+
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
257
|
+
})]
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
function Points() {
|
|
261
|
+
const theme = useTheme();
|
|
262
|
+
const keyMarketShiftIndices = [4, 6, 7, 9, 10];
|
|
263
|
+
const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
|
|
264
|
+
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
265
|
+
height: 200,
|
|
266
|
+
series: [{
|
|
267
|
+
id: 'prices',
|
|
268
|
+
data: data
|
|
269
|
+
}],
|
|
270
|
+
children: [/*#__PURE__*/_jsx(Area, {
|
|
271
|
+
fill: "rgb(" + theme.spectrum.blue5 + ")",
|
|
272
|
+
seriesId: "prices"
|
|
273
|
+
}), /*#__PURE__*/_jsx(Line, {
|
|
274
|
+
points: _ref => {
|
|
275
|
+
let {
|
|
276
|
+
dataX,
|
|
277
|
+
dataY
|
|
278
|
+
} = _ref,
|
|
279
|
+
props = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
280
|
+
return keyMarketShiftIndices.includes(dataX) ? _extends({}, props, {
|
|
281
|
+
strokeWidth: 2,
|
|
282
|
+
stroke: theme.color.bg,
|
|
283
|
+
radius: 5,
|
|
284
|
+
onClick: () => alert("You have clicked a key market shift at position " + (dataX + 1) + " with value " + dataY + "!"),
|
|
285
|
+
accessibilityLabel: "Key market shift point at position " + (dataX + 1) + ", value " + dataY + ". Click to view details."
|
|
286
|
+
}) : false;
|
|
147
287
|
},
|
|
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
|
|
288
|
+
seriesId: "prices"
|
|
171
289
|
})]
|
|
172
290
|
});
|
|
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
|
-
|
|
291
|
+
}
|
|
292
|
+
function Transitions() {
|
|
293
|
+
const theme = useTheme();
|
|
294
|
+
const dataCount = 20;
|
|
295
|
+
const maxDataOffset = 15000;
|
|
296
|
+
const minStepOffset = 2500;
|
|
297
|
+
const maxStepOffset = 10000;
|
|
298
|
+
const domainLimit = 20000;
|
|
299
|
+
const updateInterval = 500;
|
|
300
|
+
const myTransitionConfig = {
|
|
301
|
+
type: 'spring',
|
|
302
|
+
stiffness: 700,
|
|
303
|
+
damping: 20
|
|
304
|
+
};
|
|
305
|
+
const negativeColor = "rgb(" + theme.spectrum.gray15 + ")";
|
|
306
|
+
const positiveColor = theme.color.fgPositive;
|
|
307
|
+
function generateNextValue(previousValue) {
|
|
308
|
+
const range = maxStepOffset - minStepOffset;
|
|
309
|
+
const offset = Math.random() * range + minStepOffset;
|
|
310
|
+
let direction;
|
|
311
|
+
if (previousValue >= maxDataOffset) {
|
|
312
|
+
direction = -1;
|
|
313
|
+
} else if (previousValue <= -maxDataOffset) {
|
|
314
|
+
direction = 1;
|
|
315
|
+
} else {
|
|
316
|
+
direction = Math.random() < 0.5 ? -1 : 1;
|
|
317
|
+
}
|
|
318
|
+
let newValue = previousValue + offset * direction;
|
|
319
|
+
newValue = Math.max(-maxDataOffset, Math.min(maxDataOffset, newValue));
|
|
320
|
+
return newValue;
|
|
321
|
+
}
|
|
322
|
+
function generateInitialData() {
|
|
323
|
+
const data = [];
|
|
324
|
+
let previousValue = Math.random() * 2 * maxDataOffset - maxDataOffset;
|
|
325
|
+
data.push(previousValue);
|
|
326
|
+
for (let i = 1; i < dataCount; i++) {
|
|
327
|
+
const newValue = generateNextValue(previousValue);
|
|
328
|
+
data.push(newValue);
|
|
329
|
+
previousValue = newValue;
|
|
330
|
+
}
|
|
331
|
+
return data;
|
|
332
|
+
}
|
|
333
|
+
const MyGradient = /*#__PURE__*/memo(props => {
|
|
334
|
+
const areaGradient = {
|
|
335
|
+
stops: _ref2 => {
|
|
336
|
+
let {
|
|
337
|
+
min,
|
|
338
|
+
max
|
|
339
|
+
} = _ref2;
|
|
340
|
+
return [{
|
|
341
|
+
offset: min,
|
|
342
|
+
color: negativeColor,
|
|
343
|
+
opacity: 1
|
|
344
|
+
}, {
|
|
345
|
+
offset: 0,
|
|
346
|
+
color: negativeColor,
|
|
347
|
+
opacity: 0
|
|
348
|
+
}, {
|
|
349
|
+
offset: 0,
|
|
350
|
+
color: positiveColor,
|
|
351
|
+
opacity: 0
|
|
352
|
+
}, {
|
|
353
|
+
offset: max,
|
|
354
|
+
color: positiveColor,
|
|
355
|
+
opacity: 1
|
|
356
|
+
}];
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
return /*#__PURE__*/_jsx(DottedArea, _extends({}, props, {
|
|
360
|
+
gradient: areaGradient
|
|
361
|
+
}));
|
|
362
|
+
});
|
|
363
|
+
function CustomTransitionsChart() {
|
|
364
|
+
const [data, setData] = useState(generateInitialData);
|
|
365
|
+
useEffect(() => {
|
|
366
|
+
const intervalId = setInterval(() => {
|
|
367
|
+
setData(currentData => {
|
|
368
|
+
var _currentData;
|
|
369
|
+
const lastValue = (_currentData = currentData[currentData.length - 1]) != null ? _currentData : 0;
|
|
370
|
+
const newValue = generateNextValue(lastValue);
|
|
371
|
+
return [...currentData.slice(1), newValue];
|
|
372
|
+
});
|
|
373
|
+
}, updateInterval);
|
|
374
|
+
return () => clearInterval(intervalId);
|
|
375
|
+
}, []);
|
|
376
|
+
const tickLabelFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
197
377
|
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', {
|
|
378
|
+
currency: 'USD',
|
|
379
|
+
maximumFractionDigits: 0
|
|
380
|
+
}).format(value), []);
|
|
381
|
+
const valueAtIndexFormatter = useCallback(dataIndex => new Intl.NumberFormat('en-US', {
|
|
210
382
|
style: 'currency',
|
|
211
383
|
currency: 'USD'
|
|
212
|
-
}).format(
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
384
|
+
}).format(data[dataIndex]), [data]);
|
|
385
|
+
const lineGradient = {
|
|
386
|
+
stops: [{
|
|
387
|
+
offset: 0,
|
|
388
|
+
color: negativeColor
|
|
389
|
+
}, {
|
|
390
|
+
offset: 0,
|
|
391
|
+
color: positiveColor
|
|
392
|
+
}]
|
|
217
393
|
};
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
children: /*#__PURE__*/_jsxs(LineChart, {
|
|
222
|
-
showArea: true,
|
|
223
|
-
height: defaultChartHeight,
|
|
394
|
+
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
395
|
+
enableScrubbing: true,
|
|
396
|
+
height: 200,
|
|
224
397
|
inset: {
|
|
225
|
-
top:
|
|
226
|
-
bottom:
|
|
227
|
-
left:
|
|
228
|
-
right:
|
|
398
|
+
top: 32,
|
|
399
|
+
bottom: 32,
|
|
400
|
+
left: 16,
|
|
401
|
+
right: 16
|
|
229
402
|
},
|
|
230
|
-
onScrubberPositionChange: onScrubberPositionChange,
|
|
231
403
|
series: [{
|
|
232
|
-
id: '
|
|
233
|
-
data:
|
|
234
|
-
|
|
404
|
+
id: 'prices',
|
|
405
|
+
data: data,
|
|
406
|
+
gradient: lineGradient
|
|
235
407
|
}],
|
|
236
|
-
|
|
408
|
+
yAxis: {
|
|
237
409
|
domain: {
|
|
238
|
-
min:
|
|
239
|
-
max:
|
|
410
|
+
min: -domainLimit,
|
|
411
|
+
max: domainLimit
|
|
240
412
|
}
|
|
241
413
|
},
|
|
242
|
-
children: [/*#__PURE__*/_jsx(
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
414
|
+
children: [/*#__PURE__*/_jsx(YAxis, {
|
|
415
|
+
showGrid: true,
|
|
416
|
+
requestedTickCount: 2,
|
|
417
|
+
tickLabelFormatter: tickLabelFormatter
|
|
418
|
+
}), /*#__PURE__*/_jsx(Line, {
|
|
419
|
+
showArea: true,
|
|
420
|
+
AreaComponent: MyGradient,
|
|
421
|
+
seriesId: "prices",
|
|
422
|
+
strokeWidth: 3,
|
|
423
|
+
transition: myTransitionConfig
|
|
424
|
+
}), /*#__PURE__*/_jsx(Scrubber, {
|
|
425
|
+
hideOverlay: true,
|
|
426
|
+
beaconTransitions: {
|
|
427
|
+
update: myTransitionConfig
|
|
428
|
+
},
|
|
429
|
+
label: valueAtIndexFormatter
|
|
247
430
|
})]
|
|
248
|
-
})
|
|
249
|
-
}
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
const
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
return /*#__PURE__*/_jsx(CustomTransitionsChart, {});
|
|
434
|
+
}
|
|
435
|
+
function BasicAccessible() {
|
|
436
|
+
const [scrubberPosition, setScrubberPosition] = useState();
|
|
437
|
+
const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
|
|
438
|
+
|
|
439
|
+
// Chart-level accessibility label provides overview
|
|
440
|
+
const chartAccessibilityLabel = useMemo(() => {
|
|
441
|
+
const currentPrice = data[data.length - 1];
|
|
442
|
+
return "Price chart showing trend over " + data.length + " data points. Current value: " + currentPrice + ". Use arrow keys to adjust view";
|
|
443
|
+
}, [data]);
|
|
444
|
+
|
|
445
|
+
// Scrubber-level accessibility label provides specific position info
|
|
446
|
+
const scrubberAccessibilityLabel = useCallback(index => {
|
|
447
|
+
return "Price at position " + (index + 1) + " of " + data.length + ": " + data[index];
|
|
448
|
+
}, [data]);
|
|
449
|
+
const accessibilityLabel = useMemo(() => {
|
|
450
|
+
if (scrubberPosition !== undefined) {
|
|
451
|
+
return scrubberAccessibilityLabel(scrubberPosition);
|
|
452
|
+
}
|
|
453
|
+
return chartAccessibilityLabel;
|
|
454
|
+
}, [scrubberPosition, chartAccessibilityLabel, scrubberAccessibilityLabel]);
|
|
455
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
456
|
+
enableScrubbing: true,
|
|
457
|
+
showArea: true,
|
|
458
|
+
showYAxis: true,
|
|
459
|
+
accessibilityLabel: accessibilityLabel,
|
|
460
|
+
height: 200,
|
|
461
|
+
onScrubberPositionChange: setScrubberPosition,
|
|
258
462
|
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'
|
|
463
|
+
id: 'prices',
|
|
464
|
+
data: data
|
|
273
465
|
}],
|
|
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
|
-
})]
|
|
466
|
+
yAxis: {
|
|
467
|
+
showGrid: true
|
|
468
|
+
},
|
|
469
|
+
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
293
470
|
});
|
|
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]);
|
|
471
|
+
}
|
|
472
|
+
function Gradients() {
|
|
473
|
+
const theme = useTheme();
|
|
474
|
+
const spectrumColors = ['blue', 'green', 'orange', 'yellow', 'gray', 'indigo', 'pink', 'purple', 'red', 'teal', 'chartreuse'];
|
|
475
|
+
const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
|
|
476
|
+
const [currentSpectrumColor, setCurrentSpectrumColor] = useState('pink');
|
|
306
477
|
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
|
-
})
|
|
478
|
+
gap: 2,
|
|
479
|
+
children: [/*#__PURE__*/_jsx(HStack, {
|
|
480
|
+
flexWrap: "wrap",
|
|
481
|
+
gap: 1,
|
|
482
|
+
justifyContent: "flex-end",
|
|
483
|
+
children: spectrumColors.map(color => /*#__PURE__*/_jsx(Pressable, {
|
|
484
|
+
accessibilityLabel: "Select " + color,
|
|
485
|
+
height: 16,
|
|
486
|
+
onPress: () => setCurrentSpectrumColor(color),
|
|
487
|
+
style: {
|
|
488
|
+
backgroundColor: "rgb(" + theme.spectrum[color + "20"] + ")",
|
|
489
|
+
borderColor: "rgb(" + theme.spectrum[color + "50"] + ")",
|
|
490
|
+
borderWidth: 2
|
|
491
|
+
},
|
|
492
|
+
width: 16
|
|
493
|
+
}, color))
|
|
323
494
|
}), /*#__PURE__*/_jsx(LineChart, {
|
|
324
|
-
|
|
495
|
+
points: true,
|
|
325
496
|
showYAxis: true,
|
|
326
|
-
|
|
327
|
-
height: defaultChartHeight,
|
|
497
|
+
height: 200,
|
|
328
498
|
series: [{
|
|
329
|
-
id: '
|
|
330
|
-
data:
|
|
331
|
-
|
|
499
|
+
id: 'continuousGradient',
|
|
500
|
+
data: data,
|
|
501
|
+
gradient: {
|
|
502
|
+
stops: [{
|
|
503
|
+
offset: 0,
|
|
504
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "80"] + ")"
|
|
505
|
+
}, {
|
|
506
|
+
offset: Math.max(...data),
|
|
507
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "20"] + ")"
|
|
508
|
+
}]
|
|
509
|
+
}
|
|
510
|
+
}, {
|
|
511
|
+
id: 'discreteGradient',
|
|
512
|
+
data: data.map(d => d + 50),
|
|
513
|
+
// You can create a "discrete" gradient by having multiple stops at the same offset
|
|
514
|
+
gradient: {
|
|
515
|
+
stops: _ref3 => {
|
|
516
|
+
let {
|
|
517
|
+
min,
|
|
518
|
+
max
|
|
519
|
+
} = _ref3;
|
|
520
|
+
return [
|
|
521
|
+
// Allows a function which accepts min/max or direct array
|
|
522
|
+
{
|
|
523
|
+
offset: min,
|
|
524
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "80"] + ")"
|
|
525
|
+
}, {
|
|
526
|
+
offset: min + (max - min) / 3,
|
|
527
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "80"] + ")"
|
|
528
|
+
}, {
|
|
529
|
+
offset: min + (max - min) / 3,
|
|
530
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "50"] + ")"
|
|
531
|
+
}, {
|
|
532
|
+
offset: min + (max - min) / 3 * 2,
|
|
533
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "50"] + ")"
|
|
534
|
+
}, {
|
|
535
|
+
offset: min + (max - min) / 3 * 2,
|
|
536
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "20"] + ")"
|
|
537
|
+
}, {
|
|
538
|
+
offset: max,
|
|
539
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "20"] + ")"
|
|
540
|
+
}];
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}, {
|
|
544
|
+
id: 'xAxisGradient',
|
|
545
|
+
data: data.map(d => d + 100),
|
|
546
|
+
gradient: {
|
|
547
|
+
// You can also configure by the x-axis.
|
|
548
|
+
axis: 'x',
|
|
549
|
+
stops: _ref4 => {
|
|
550
|
+
let {
|
|
551
|
+
min,
|
|
552
|
+
max
|
|
553
|
+
} = _ref4;
|
|
554
|
+
return [{
|
|
555
|
+
offset: min,
|
|
556
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "80"] + ")",
|
|
557
|
+
opacity: 0
|
|
558
|
+
}, {
|
|
559
|
+
offset: max,
|
|
560
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "20"] + ")",
|
|
561
|
+
opacity: 1
|
|
562
|
+
}];
|
|
563
|
+
}
|
|
564
|
+
}
|
|
332
565
|
}],
|
|
566
|
+
strokeWidth: 4,
|
|
333
567
|
yAxis: {
|
|
334
|
-
|
|
335
|
-
requestedTickCount: 5,
|
|
336
|
-
tickLabelFormatter: value => value.toLocaleString(),
|
|
337
|
-
showGrid: true,
|
|
338
|
-
width: 70
|
|
568
|
+
showGrid: true
|
|
339
569
|
}
|
|
340
570
|
})]
|
|
341
571
|
});
|
|
342
|
-
}
|
|
343
|
-
|
|
572
|
+
}
|
|
573
|
+
function GainLossChart() {
|
|
344
574
|
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]);
|
|
575
|
+
const data = useMemo(() => [-40, -28, -21, -5, 48, -5, -28, 2, -29, -46, 16, -30, -29, 8], []);
|
|
576
|
+
const negativeColor = "rgb(" + theme.spectrum.gray15 + ")";
|
|
577
|
+
const positiveColor = theme.color.fgPositive;
|
|
578
|
+
const tickLabelFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
579
|
+
style: 'currency',
|
|
580
|
+
currency: 'USD',
|
|
581
|
+
maximumFractionDigits: 0
|
|
582
|
+
}).format(value), []);
|
|
381
583
|
|
|
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'
|
|
508
|
-
};
|
|
509
|
-
const currentPriceData = activeTab ? sparklineInteractiveData[tabConversion[activeTab.id]] : sparklineInteractiveData.hour;
|
|
510
|
-
const currentData = useMemo(() => [...currentPriceData.map(price => price.value)], [currentPriceData]);
|
|
511
|
-
const currentTimestamps = useMemo(() => [...currentPriceData.map(price => price.date.toISOString())], [currentPriceData]);
|
|
512
|
-
const startPrice = currentData[0];
|
|
513
|
-
const {
|
|
514
|
-
lowestPriceIndices,
|
|
515
|
-
highestPriceIndices
|
|
516
|
-
} = useMemo(() => {
|
|
517
|
-
if (currentData.length === 0) {
|
|
518
|
-
return {
|
|
519
|
-
lowestPriceIndices: [],
|
|
520
|
-
highestPriceIndices: [],
|
|
521
|
-
minPrice: 0,
|
|
522
|
-
maxPrice: 0
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
let minPrice = currentData[0];
|
|
526
|
-
let maxPrice = currentData[0];
|
|
527
|
-
|
|
528
|
-
// First pass: find min and max values
|
|
529
|
-
for (let i = 1; i < currentData.length; i++) {
|
|
530
|
-
if (currentData[i] < minPrice) {
|
|
531
|
-
minPrice = currentData[i];
|
|
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);
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
return {
|
|
550
|
-
lowestPriceIndices,
|
|
551
|
-
highestPriceIndices,
|
|
552
|
-
minPrice,
|
|
553
|
-
maxPrice
|
|
554
|
-
};
|
|
555
|
-
}, [currentData]);
|
|
556
|
-
const latestPriceCoords = useMemo(() => {
|
|
557
|
-
if (currentData.length === 0) return {};
|
|
558
|
-
return {
|
|
559
|
-
x: currentData.length - 1,
|
|
560
|
-
y: currentData[currentData.length - 1]
|
|
561
|
-
};
|
|
562
|
-
}, [currentData]);
|
|
563
|
-
const onScrubberPositionChange = useCallback(item => {
|
|
564
|
-
setIsHovering(item !== undefined);
|
|
565
|
-
}, []);
|
|
566
|
-
const {
|
|
567
|
-
trendPrice,
|
|
568
|
-
trendPreviousPrice,
|
|
569
|
-
trendDirection
|
|
570
|
-
} = useMemo(() => {
|
|
571
|
-
return calculateTrendData(undefined, currentData, currentTimestamps, startPrice, latestPrice, (activeTab == null ? void 0 : activeTab.id) || '1H');
|
|
572
|
-
}, [currentData, currentTimestamps, startPrice, latestPrice, activeTab]);
|
|
573
|
-
const calculatedPriceChange = trendPrice - trendPreviousPrice;
|
|
574
|
-
const calculatedPercentChange = calculatedPriceChange / trendPreviousPrice * 100;
|
|
575
|
-
const formattedPriceChange = "$" + Math.abs(calculatedPriceChange).toLocaleString('en-US', {
|
|
576
|
-
minimumFractionDigits: 2,
|
|
577
|
-
maximumFractionDigits: 2
|
|
578
|
-
}) + " (" + Math.abs(calculatedPercentChange).toLocaleString('en-US', {
|
|
579
|
-
minimumFractionDigits: 2,
|
|
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', {
|
|
608
|
-
minimumFractionDigits: 2,
|
|
609
|
-
maximumFractionDigits: 2
|
|
610
|
-
});
|
|
611
|
-
}, []);
|
|
612
|
-
return /*#__PURE__*/_jsxs(VStack, {
|
|
613
|
-
gap: 3,
|
|
614
|
-
width: "100%",
|
|
615
|
-
children: [/*#__PURE__*/_jsx(LineChart, {
|
|
616
|
-
showArea: true,
|
|
617
|
-
height: defaultChartHeight,
|
|
618
|
-
inset: {
|
|
619
|
-
left: 0,
|
|
620
|
-
right: 3,
|
|
621
|
-
bottom: 3,
|
|
622
|
-
top: 3
|
|
623
|
-
},
|
|
624
|
-
onScrubberPositionChange: onScrubberPositionChange,
|
|
625
|
-
series: [{
|
|
626
|
-
id: 'price',
|
|
627
|
-
data: currentData,
|
|
628
|
-
color: assets.eth.color,
|
|
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
|
|
663
|
-
})]
|
|
664
|
-
});
|
|
665
|
-
};
|
|
666
|
-
export const ForecastChart = () => {
|
|
667
|
-
const getDataFromSparkline = startDate => {
|
|
668
|
-
const allData = sparklineInteractiveData.all;
|
|
669
|
-
if (!allData || allData.length === 0) return [];
|
|
670
|
-
const timelineData = allData.filter(point => point.date >= startDate);
|
|
671
|
-
return timelineData.map(point => ({
|
|
672
|
-
date: point.date,
|
|
673
|
-
value: point.value
|
|
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
|
-
}, []);
|
|
718
|
-
return /*#__PURE__*/_jsx(LineChart, {
|
|
719
|
-
enableScrubbing: true,
|
|
720
|
-
showArea: true,
|
|
721
|
-
showXAxis: true,
|
|
722
|
-
areaType: "dotted",
|
|
723
|
-
height: defaultChartHeight,
|
|
724
|
-
inset: {
|
|
725
|
-
top: 4,
|
|
726
|
-
left: 0,
|
|
727
|
-
right: 0,
|
|
728
|
-
bottom: 0
|
|
729
|
-
},
|
|
730
|
-
series: [{
|
|
731
|
-
id: 'historical',
|
|
732
|
-
data: historicalData.map(d => d.value),
|
|
733
|
-
color: assets.btc.color
|
|
734
|
-
}, {
|
|
735
|
-
id: 'forecast',
|
|
736
|
-
data: [...historicalData.map(d => null), ...forecastData.map(d => d.value)],
|
|
737
|
-
color: assets.btc.color,
|
|
738
|
-
type: 'dotted'
|
|
739
|
-
}],
|
|
740
|
-
xAxis: {
|
|
741
|
-
data: allDataPoints.map(d => d.date.getTime()),
|
|
742
|
-
tickLabelFormatter: formatXAxisLabel,
|
|
743
|
-
tickInterval: 32
|
|
744
|
-
},
|
|
745
|
-
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
746
|
-
});
|
|
747
|
-
};
|
|
748
|
-
const PeriodSelectorExample = () => {
|
|
749
|
-
const tabs = [{
|
|
750
|
-
id: '1H',
|
|
751
|
-
label: '1H'
|
|
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
|
|
791
|
-
})
|
|
792
|
-
}, props));
|
|
793
|
-
}));
|
|
794
|
-
const BTCActiveIndicator = /*#__PURE__*/memo(_ref4 => {
|
|
795
|
-
let {
|
|
796
|
-
style
|
|
797
|
-
} = _ref4,
|
|
798
|
-
props = _objectWithoutPropertiesLoose(_ref4, _excluded3);
|
|
799
|
-
return /*#__PURE__*/_jsx(PeriodSelectorActiveIndicator, _extends({}, props, {
|
|
800
|
-
style: [style, {
|
|
801
|
-
backgroundColor: assets.btc.color + "1A"
|
|
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]);
|
|
839
|
-
const formatPrice = useCallback(price => {
|
|
840
|
-
return new Intl.NumberFormat('en-US', {
|
|
841
|
-
style: 'currency',
|
|
842
|
-
currency: 'USD'
|
|
843
|
-
}).format(price);
|
|
844
|
-
}, []);
|
|
845
|
-
const formatDate = useCallback(date => {
|
|
846
|
-
const dayOfWeek = date.toLocaleDateString('en-US', {
|
|
847
|
-
weekday: 'short'
|
|
848
|
-
});
|
|
849
|
-
const monthDay = date.toLocaleDateString('en-US', {
|
|
850
|
-
month: 'short',
|
|
851
|
-
day: 'numeric'
|
|
852
|
-
});
|
|
853
|
-
const time = date.toLocaleTimeString('en-US', {
|
|
854
|
-
hour: 'numeric',
|
|
855
|
-
minute: '2-digit',
|
|
856
|
-
hour12: true
|
|
857
|
-
});
|
|
858
|
-
return dayOfWeek + ", " + monthDay + ", " + time;
|
|
859
|
-
}, []);
|
|
860
|
-
const scrubberLabel = useCallback(dataIndex => {
|
|
861
|
-
const price = new Intl.NumberFormat('en-US', {
|
|
862
|
-
minimumFractionDigits: 2,
|
|
863
|
-
maximumFractionDigits: 2
|
|
864
|
-
}).format(sparklineTimePeriodDataValues[dataIndex]);
|
|
865
|
-
const date = formatDate(sparklineTimePeriodDataTimestamps[dataIndex]);
|
|
866
|
-
return price + " USD " + date;
|
|
867
|
-
}, [sparklineTimePeriodDataValues, formatDate, sparklineTimePeriodDataTimestamps]);
|
|
868
|
-
|
|
869
|
-
// Chart overview accessibility label
|
|
870
|
-
const chartOverviewLabel = useMemo(() => {
|
|
871
|
-
if (sparklineTimePeriodData.length === 0) return '';
|
|
872
|
-
const firstDate = sparklineTimePeriodData[0].date;
|
|
873
|
-
const lastDate = sparklineTimePeriodData[sparklineTimePeriodData.length - 1].date;
|
|
874
|
-
const currentYear = new Date().getFullYear();
|
|
875
|
-
const shouldIncludeTime = timePeriod.id === 'hour' || timePeriod.id === 'day';
|
|
876
|
-
const dateRangeOptions = _extends({
|
|
877
|
-
month: 'long',
|
|
878
|
-
day: 'numeric',
|
|
879
|
-
year: firstDate.getFullYear() !== currentYear ? 'numeric' : undefined
|
|
880
|
-
}, shouldIncludeTime && {
|
|
881
|
-
hour: 'numeric',
|
|
882
|
-
minute: '2-digit',
|
|
883
|
-
hour12: true
|
|
884
|
-
});
|
|
885
|
-
const startDateStr = shouldIncludeTime ? firstDate.toLocaleString('en-US', dateRangeOptions) : firstDate.toLocaleDateString('en-US', dateRangeOptions);
|
|
886
|
-
const endDateStr = shouldIncludeTime ? lastDate.toLocaleString('en-US', _extends({}, dateRangeOptions, {
|
|
887
|
-
year: lastDate.getFullYear() !== currentYear ? 'numeric' : undefined
|
|
888
|
-
})) : lastDate.toLocaleDateString('en-US', _extends({}, dateRangeOptions, {
|
|
889
|
-
year: lastDate.getFullYear() !== currentYear ? 'numeric' : undefined
|
|
890
|
-
}));
|
|
891
|
-
return "Price chart for Bitcoin, " + startDateStr + " to " + endDateStr + ". Swipe left or right to navigate data points.";
|
|
892
|
-
}, [sparklineTimePeriodData, timePeriod.id]);
|
|
893
|
-
return /*#__PURE__*/_jsx(Box, {
|
|
894
|
-
accessibilityLabel: chartOverviewLabel,
|
|
895
|
-
accessibilityLiveRegion: "polite",
|
|
896
|
-
children: /*#__PURE__*/_jsxs(VStack, {
|
|
897
|
-
gap: 2,
|
|
898
|
-
children: [/*#__PURE__*/_jsx(SectionHeader, {
|
|
899
|
-
"aria-hidden": "true",
|
|
900
|
-
balance: /*#__PURE__*/_jsxs(Text, {
|
|
901
|
-
font: "title2",
|
|
902
|
-
children: [formatPrice(currentPrice), " ", sparklineTimePeriodDataValues.length]
|
|
903
|
-
}),
|
|
904
|
-
end: /*#__PURE__*/_jsx(VStack, {
|
|
905
|
-
justifyContent: "center",
|
|
906
|
-
children: /*#__PURE__*/_jsx(RemoteImage, {
|
|
907
|
-
shape: "circle",
|
|
908
|
-
size: "xl",
|
|
909
|
-
source: assets.btc.imageUrl
|
|
910
|
-
})
|
|
911
|
-
}),
|
|
912
|
-
padding: 0,
|
|
913
|
-
title: /*#__PURE__*/_jsx(Text, {
|
|
914
|
-
font: "title1",
|
|
915
|
-
children: "Bitcoin"
|
|
916
|
-
})
|
|
917
|
-
}), /*#__PURE__*/_jsx(LineChart, {
|
|
918
|
-
enableScrubbing: true,
|
|
919
|
-
showArea: true,
|
|
920
|
-
accessibilityLiveRegion: "polite",
|
|
921
|
-
areaType: "dotted",
|
|
922
|
-
height: defaultChartHeight,
|
|
923
|
-
series: [{
|
|
924
|
-
id: 'btc',
|
|
925
|
-
data: sparklineTimePeriodDataValues,
|
|
926
|
-
color: assets.btc.color
|
|
927
|
-
}],
|
|
928
|
-
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
929
|
-
idlePulse: true,
|
|
930
|
-
label: scrubberLabel
|
|
931
|
-
})
|
|
932
|
-
}), /*#__PURE__*/_jsx(PeriodSelector, {
|
|
933
|
-
TabComponent: BTCTab,
|
|
934
|
-
TabsActiveIndicatorComponent: BTCActiveIndicator,
|
|
935
|
-
accessibilityLabel: "Select time period for chart",
|
|
936
|
-
activeTab: timePeriod,
|
|
937
|
-
onChange: onPeriodChange,
|
|
938
|
-
tabs: tabs
|
|
939
|
-
})]
|
|
940
|
-
})
|
|
941
|
-
});
|
|
942
|
-
};
|
|
943
|
-
const AssetPriceDottedNonMemoized = () => {
|
|
944
|
-
const [scrubIndex, setScrubIndex] = useState(undefined);
|
|
945
|
-
const currentPrice = sparklineInteractiveData.hour[sparklineInteractiveData.hour.length - 1].value;
|
|
946
|
-
const tabs = useMemo(() => [{
|
|
947
|
-
id: 'hour',
|
|
948
|
-
label: '1H'
|
|
949
|
-
}, {
|
|
950
|
-
id: 'day',
|
|
951
|
-
label: '1D'
|
|
952
|
-
}, {
|
|
953
|
-
id: 'week',
|
|
954
|
-
label: '1W'
|
|
955
|
-
}, {
|
|
956
|
-
id: 'month',
|
|
957
|
-
label: '1M'
|
|
958
|
-
}, {
|
|
959
|
-
id: 'year',
|
|
960
|
-
label: '1Y'
|
|
961
|
-
}, {
|
|
962
|
-
id: 'all',
|
|
963
|
-
label: 'All'
|
|
964
|
-
}], []);
|
|
965
|
-
const [timePeriod, setTimePeriod] = useState(tabs[0]);
|
|
966
|
-
const sparklineTimePeriodData = useMemo(() => {
|
|
967
|
-
return sparklineInteractiveData[timePeriod.id];
|
|
968
|
-
}, [timePeriod]);
|
|
969
|
-
const sparklineTimePeriodDataValues = useMemo(() => {
|
|
970
|
-
return sparklineTimePeriodData.map(d => d.value);
|
|
971
|
-
}, [sparklineTimePeriodData]);
|
|
972
|
-
const sparklineTimePeriodDataTimestamps = useMemo(() => {
|
|
973
|
-
return sparklineTimePeriodData.map(d => d.date);
|
|
974
|
-
}, [sparklineTimePeriodData]);
|
|
975
|
-
const onPeriodChange = useCallback(period => {
|
|
976
|
-
setTimePeriod(period || tabs[0]);
|
|
977
|
-
}, [tabs, setTimePeriod]);
|
|
978
|
-
const formatPrice = useCallback(price => {
|
|
979
|
-
return new Intl.NumberFormat('en-US', {
|
|
980
|
-
style: 'currency',
|
|
981
|
-
currency: 'USD'
|
|
982
|
-
}).format(price);
|
|
983
|
-
}, []);
|
|
984
|
-
const formatDate = useCallback(date => {
|
|
985
|
-
const dayOfWeek = date.toLocaleDateString('en-US', {
|
|
986
|
-
weekday: 'short'
|
|
987
|
-
});
|
|
988
|
-
const monthDay = date.toLocaleDateString('en-US', {
|
|
989
|
-
month: 'short',
|
|
990
|
-
day: 'numeric'
|
|
991
|
-
});
|
|
992
|
-
const time = date.toLocaleTimeString('en-US', {
|
|
993
|
-
hour: 'numeric',
|
|
994
|
-
minute: '2-digit',
|
|
995
|
-
hour12: true
|
|
996
|
-
});
|
|
997
|
-
return dayOfWeek + ", " + monthDay + ", " + time;
|
|
998
|
-
}, []);
|
|
999
|
-
const scrubberLabel = useMemo(() => {
|
|
1000
|
-
if (scrubIndex === undefined) return null;
|
|
1001
|
-
const price = new Intl.NumberFormat('en-US', {
|
|
1002
|
-
minimumFractionDigits: 2,
|
|
1003
|
-
maximumFractionDigits: 2
|
|
1004
|
-
}).format(sparklineTimePeriodDataValues[scrubIndex]);
|
|
1005
|
-
const date = formatDate(sparklineTimePeriodDataTimestamps[scrubIndex]);
|
|
1006
|
-
return price + " USD " + date;
|
|
1007
|
-
}, [scrubIndex, sparklineTimePeriodDataValues, formatDate, sparklineTimePeriodDataTimestamps]);
|
|
1008
|
-
return /*#__PURE__*/_jsxs(VStack, {
|
|
1009
|
-
gap: 2,
|
|
1010
|
-
children: [/*#__PURE__*/_jsx(SectionHeader, {
|
|
1011
|
-
balance: /*#__PURE__*/_jsxs(Text, {
|
|
1012
|
-
font: "title2",
|
|
1013
|
-
children: [formatPrice(currentPrice), " ", sparklineTimePeriodDataValues.length]
|
|
1014
|
-
}),
|
|
1015
|
-
end: /*#__PURE__*/_jsx(VStack, {
|
|
1016
|
-
justifyContent: "center",
|
|
1017
|
-
children: /*#__PURE__*/_jsx(RemoteImage, {
|
|
1018
|
-
shape: "circle",
|
|
1019
|
-
size: "xl",
|
|
1020
|
-
source: assets.btc.imageUrl
|
|
1021
|
-
})
|
|
1022
|
-
}),
|
|
1023
|
-
padding: 0,
|
|
1024
|
-
title: /*#__PURE__*/_jsx(Text, {
|
|
1025
|
-
font: "title1",
|
|
1026
|
-
children: "Bitcoin"
|
|
1027
|
-
})
|
|
1028
|
-
}), /*#__PURE__*/_jsx(LineChart, {
|
|
1029
|
-
enableScrubbing: true,
|
|
1030
|
-
showArea: true,
|
|
1031
|
-
areaType: "dotted",
|
|
1032
|
-
height: defaultChartHeight,
|
|
1033
|
-
onScrubberPositionChange: setScrubIndex,
|
|
1034
|
-
series: [{
|
|
1035
|
-
id: 'btc',
|
|
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
|
-
})]
|
|
1049
|
-
});
|
|
1050
|
-
};
|
|
1051
|
-
const AssetPriceMultipleDotted = () => {
|
|
1052
|
-
const [scrubIndex, setScrubIndex] = useState(undefined);
|
|
1053
|
-
const currentPrice = sparklineInteractiveData.hour[sparklineInteractiveData.hour.length - 1].value;
|
|
1054
|
-
const tabs = useMemo(() => [{
|
|
1055
|
-
id: 'hour',
|
|
1056
|
-
label: '1H'
|
|
1057
|
-
}, {
|
|
1058
|
-
id: 'day',
|
|
1059
|
-
label: '1D'
|
|
1060
|
-
}, {
|
|
1061
|
-
id: 'week',
|
|
1062
|
-
label: '1W'
|
|
1063
|
-
}, {
|
|
1064
|
-
id: 'month',
|
|
1065
|
-
label: '1M'
|
|
1066
|
-
}, {
|
|
1067
|
-
id: 'year',
|
|
1068
|
-
label: '1Y'
|
|
1069
|
-
}, {
|
|
1070
|
-
id: 'all',
|
|
1071
|
-
label: 'All'
|
|
1072
|
-
}], []);
|
|
1073
|
-
const [timePeriod, setTimePeriod] = useState(tabs[0]);
|
|
1074
|
-
const sparklineTimePeriodData = useMemo(() => {
|
|
1075
|
-
return sparklineInteractiveData[timePeriod.id];
|
|
1076
|
-
}, [timePeriod]);
|
|
1077
|
-
const sparklineTimePeriodDataValues = useMemo(() => {
|
|
1078
|
-
return sparklineTimePeriodData.map(d => d.value);
|
|
1079
|
-
}, [sparklineTimePeriodData]);
|
|
1080
|
-
const sparklineTimePeriodDataTimestamps = useMemo(() => {
|
|
1081
|
-
return sparklineTimePeriodData.map(d => d.date);
|
|
1082
|
-
}, [sparklineTimePeriodData]);
|
|
1083
|
-
const onPeriodChange = useCallback(period => {
|
|
1084
|
-
setTimePeriod(period || tabs[0]);
|
|
1085
|
-
}, [tabs, setTimePeriod]);
|
|
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]);
|
|
1116
|
-
return /*#__PURE__*/_jsxs(VStack, {
|
|
1117
|
-
gap: 2,
|
|
1118
|
-
children: [/*#__PURE__*/_jsx(SectionHeader, {
|
|
1119
|
-
balance: /*#__PURE__*/_jsxs(Text, {
|
|
1120
|
-
font: "title2",
|
|
1121
|
-
children: [formatPrice(currentPrice), " ", sparklineTimePeriodDataValues.length]
|
|
1122
|
-
}),
|
|
1123
|
-
end: /*#__PURE__*/_jsx(VStack, {
|
|
1124
|
-
justifyContent: "center",
|
|
1125
|
-
children: /*#__PURE__*/_jsx(RemoteImage, {
|
|
1126
|
-
shape: "circle",
|
|
1127
|
-
size: "xl",
|
|
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, {})
|
|
1153
|
-
}), /*#__PURE__*/_jsx(PeriodSelector, {
|
|
1154
|
-
TabComponent: BTCTab,
|
|
1155
|
-
TabsActiveIndicatorComponent: BTCActiveIndicator,
|
|
1156
|
-
activeTab: timePeriod,
|
|
1157
|
-
onChange: onPeriodChange,
|
|
1158
|
-
tabs: tabs
|
|
1159
|
-
})]
|
|
1160
|
-
});
|
|
1161
|
-
};
|
|
1162
|
-
const GainLossChart = () => {
|
|
1163
|
-
const theme = useTheme();
|
|
1164
|
-
const gradientId = useId();
|
|
1165
|
-
const data = [-40, -28, -21, -5, 48, -5, -28, 2, -29, -46, 16, -30, -29, 8];
|
|
1166
|
-
const ChartDefs = _ref5 => {
|
|
1167
|
-
let {
|
|
1168
|
-
threshold = 0
|
|
1169
|
-
} = _ref5;
|
|
1170
|
-
const {
|
|
1171
|
-
getYScale
|
|
1172
|
-
} = useCartesianChartContext();
|
|
1173
|
-
// get the default y-axis scale
|
|
1174
|
-
const yScale = getYScale();
|
|
1175
|
-
if (yScale) {
|
|
1176
|
-
const domain = yScale.domain();
|
|
1177
|
-
const range = yScale.range();
|
|
1178
|
-
const baselinePercentage = (threshold - domain[0]) / (domain[1] - domain[0]) * 100;
|
|
1179
|
-
const negativeColor = "rgb(" + theme.spectrum.gray20 + ")";
|
|
1180
|
-
const positiveColor = theme.color.fgPositive;
|
|
1181
|
-
return /*#__PURE__*/_jsxs(Defs, {
|
|
1182
|
-
children: [/*#__PURE__*/_jsxs(LinearGradient, {
|
|
1183
|
-
gradientUnits: "userSpaceOnUse",
|
|
1184
|
-
id: gradientId + "-solid",
|
|
1185
|
-
x1: "0%",
|
|
1186
|
-
x2: "0%",
|
|
1187
|
-
y1: range[0],
|
|
1188
|
-
y2: range[1],
|
|
1189
|
-
children: [/*#__PURE__*/_jsx(Stop, {
|
|
1190
|
-
offset: "0%",
|
|
1191
|
-
stopColor: negativeColor
|
|
1192
|
-
}), /*#__PURE__*/_jsx(Stop, {
|
|
1193
|
-
offset: baselinePercentage + "%",
|
|
1194
|
-
stopColor: negativeColor
|
|
1195
|
-
}), /*#__PURE__*/_jsx(Stop, {
|
|
1196
|
-
offset: baselinePercentage + "%",
|
|
1197
|
-
stopColor: positiveColor
|
|
1198
|
-
}), /*#__PURE__*/_jsx(Stop, {
|
|
1199
|
-
offset: "100%",
|
|
1200
|
-
stopColor: positiveColor
|
|
1201
|
-
})]
|
|
1202
|
-
}), /*#__PURE__*/_jsxs(LinearGradient, {
|
|
1203
|
-
gradientUnits: "userSpaceOnUse",
|
|
1204
|
-
id: gradientId + "-gradient",
|
|
1205
|
-
x1: "0%",
|
|
1206
|
-
x2: "0%",
|
|
1207
|
-
y1: range[0],
|
|
1208
|
-
y2: range[1],
|
|
1209
|
-
children: [/*#__PURE__*/_jsx(Stop, {
|
|
1210
|
-
offset: "0%",
|
|
1211
|
-
stopColor: negativeColor,
|
|
1212
|
-
stopOpacity: 0.3
|
|
1213
|
-
}), /*#__PURE__*/_jsx(Stop, {
|
|
1214
|
-
offset: baselinePercentage + "%",
|
|
1215
|
-
stopColor: negativeColor,
|
|
1216
|
-
stopOpacity: 0
|
|
1217
|
-
}), /*#__PURE__*/_jsx(Stop, {
|
|
1218
|
-
offset: baselinePercentage + "%",
|
|
1219
|
-
stopColor: positiveColor,
|
|
1220
|
-
stopOpacity: 0
|
|
1221
|
-
}), /*#__PURE__*/_jsx(Stop, {
|
|
1222
|
-
offset: "100%",
|
|
1223
|
-
stopColor: positiveColor,
|
|
1224
|
-
stopOpacity: 0.3
|
|
1225
|
-
})]
|
|
1226
|
-
})]
|
|
1227
|
-
});
|
|
1228
|
-
}
|
|
1229
|
-
return null;
|
|
584
|
+
// Line gradient: hard color change at 0 (full opacity for line)
|
|
585
|
+
const lineGradient = {
|
|
586
|
+
stops: [{
|
|
587
|
+
offset: 0,
|
|
588
|
+
color: negativeColor
|
|
589
|
+
}, {
|
|
590
|
+
offset: 0,
|
|
591
|
+
color: positiveColor
|
|
592
|
+
}]
|
|
1230
593
|
};
|
|
1231
|
-
const
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
594
|
+
const GradientDottedArea = /*#__PURE__*/memo(props => /*#__PURE__*/_jsx(DottedArea, _extends({}, props, {
|
|
595
|
+
gradient: {
|
|
596
|
+
stops: _ref5 => {
|
|
597
|
+
let {
|
|
598
|
+
min,
|
|
599
|
+
max
|
|
600
|
+
} = _ref5;
|
|
601
|
+
return [{
|
|
602
|
+
offset: min,
|
|
603
|
+
color: negativeColor,
|
|
604
|
+
opacity: 0.4
|
|
605
|
+
}, {
|
|
606
|
+
offset: 0,
|
|
607
|
+
color: negativeColor,
|
|
608
|
+
opacity: 0
|
|
609
|
+
}, {
|
|
610
|
+
offset: 0,
|
|
611
|
+
color: positiveColor,
|
|
612
|
+
opacity: 0
|
|
613
|
+
}, {
|
|
614
|
+
offset: max,
|
|
615
|
+
color: positiveColor,
|
|
616
|
+
opacity: 0.4
|
|
617
|
+
}];
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
})));
|
|
1237
621
|
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
1238
622
|
enableScrubbing: true,
|
|
1239
|
-
height:
|
|
1240
|
-
inset: {
|
|
1241
|
-
top: 1.5,
|
|
1242
|
-
bottom: 1.5,
|
|
1243
|
-
left: 0,
|
|
1244
|
-
right: 0
|
|
1245
|
-
},
|
|
623
|
+
height: 200,
|
|
1246
624
|
series: [{
|
|
1247
625
|
id: 'prices',
|
|
1248
626
|
data: data,
|
|
1249
|
-
|
|
627
|
+
gradient: lineGradient
|
|
1250
628
|
}],
|
|
1251
|
-
children: [/*#__PURE__*/_jsx(
|
|
629
|
+
children: [/*#__PURE__*/_jsx(YAxis, {
|
|
1252
630
|
showGrid: true,
|
|
1253
631
|
requestedTickCount: 2,
|
|
1254
632
|
tickLabelFormatter: tickLabelFormatter
|
|
1255
|
-
}), /*#__PURE__*/_jsx(Area, {
|
|
1256
|
-
curve: "monotone",
|
|
1257
|
-
fill: "url(#" + gradientId + "-gradient)",
|
|
1258
|
-
seriesId: "prices"
|
|
1259
633
|
}), /*#__PURE__*/_jsx(Line, {
|
|
1260
|
-
|
|
634
|
+
showArea: true,
|
|
635
|
+
AreaComponent: GradientDottedArea,
|
|
1261
636
|
seriesId: "prices",
|
|
1262
|
-
stroke: solidColor,
|
|
1263
637
|
strokeWidth: 3
|
|
1264
638
|
}), /*#__PURE__*/_jsx(Scrubber, {
|
|
1265
639
|
hideOverlay: true
|
|
1266
640
|
})]
|
|
1267
641
|
});
|
|
1268
|
-
}
|
|
1269
|
-
|
|
642
|
+
}
|
|
643
|
+
function HighLowPrice() {
|
|
644
|
+
const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
|
|
645
|
+
const minPrice = Math.min(...data);
|
|
646
|
+
const maxPrice = Math.max(...data);
|
|
647
|
+
const minPriceIndex = data.indexOf(minPrice);
|
|
648
|
+
const maxPriceIndex = data.indexOf(maxPrice);
|
|
649
|
+
const formatPrice = useCallback(price => {
|
|
650
|
+
return "$" + price.toLocaleString('en-US', {
|
|
651
|
+
minimumFractionDigits: 2,
|
|
652
|
+
maximumFractionDigits: 2
|
|
653
|
+
});
|
|
654
|
+
}, []);
|
|
655
|
+
return /*#__PURE__*/_jsxs(LineChart, {
|
|
656
|
+
showArea: true,
|
|
657
|
+
height: 200,
|
|
658
|
+
series: [{
|
|
659
|
+
id: 'prices',
|
|
660
|
+
data: data
|
|
661
|
+
}],
|
|
662
|
+
children: [/*#__PURE__*/_jsx(Point, {
|
|
663
|
+
dataX: minPriceIndex,
|
|
664
|
+
dataY: minPrice,
|
|
665
|
+
label: formatPrice(minPrice),
|
|
666
|
+
labelPosition: "bottom"
|
|
667
|
+
}), /*#__PURE__*/_jsx(Point, {
|
|
668
|
+
dataX: maxPriceIndex,
|
|
669
|
+
dataY: maxPrice,
|
|
670
|
+
label: formatPrice(maxPrice),
|
|
671
|
+
labelPosition: "top"
|
|
672
|
+
})]
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
function StylingScrubber() {
|
|
1270
676
|
const theme = useTheme();
|
|
1271
|
-
const
|
|
1272
|
-
const
|
|
1273
|
-
const
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
677
|
+
const pages = ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'];
|
|
678
|
+
const pageViews = [2400, 1398, 9800, 3908, 4800, 3800, 4300];
|
|
679
|
+
const uniqueVisitors = [4000, 3000, 2000, 2780, 1890, 2390, 3490];
|
|
680
|
+
const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
681
|
+
maximumFractionDigits: 0
|
|
682
|
+
}).format(value), []);
|
|
683
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
684
|
+
enableScrubbing: true,
|
|
685
|
+
showArea: true,
|
|
686
|
+
showXAxis: true,
|
|
687
|
+
showYAxis: true,
|
|
688
|
+
height: 200,
|
|
689
|
+
series: [{
|
|
690
|
+
id: 'pageViews',
|
|
691
|
+
data: pageViews,
|
|
692
|
+
color: theme.color.accentBoldGreen,
|
|
693
|
+
// Label will render next to scrubber beacon
|
|
694
|
+
label: 'Page Views'
|
|
695
|
+
}, {
|
|
696
|
+
id: 'uniqueVisitors',
|
|
697
|
+
data: uniqueVisitors,
|
|
698
|
+
color: theme.color.accentBoldPurple,
|
|
699
|
+
label: 'Unique Visitors',
|
|
700
|
+
// Default area is gradient
|
|
701
|
+
areaType: 'dotted'
|
|
702
|
+
}],
|
|
703
|
+
xAxis: {
|
|
704
|
+
// Used on the x-axis to provide context for each index from the series data array
|
|
705
|
+
data: pages
|
|
706
|
+
},
|
|
707
|
+
yAxis: {
|
|
708
|
+
showGrid: true,
|
|
709
|
+
tickLabelFormatter: numberFormatter
|
|
710
|
+
},
|
|
711
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
712
|
+
idlePulse: true,
|
|
713
|
+
LineComponent: SolidLine,
|
|
714
|
+
seriesIds: ['pageViews']
|
|
715
|
+
})
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
function Compact() {
|
|
719
|
+
const theme = useTheme();
|
|
720
|
+
const dimensions = {
|
|
721
|
+
width: 62,
|
|
722
|
+
height: 18
|
|
1278
723
|
};
|
|
1279
|
-
const
|
|
1280
|
-
|
|
1281
|
-
|
|
724
|
+
const sparklineData = prices.map(price => parseFloat(price)).filter((price, index) => index % 10 === 0);
|
|
725
|
+
const positiveFloor = Math.min(...sparklineData) - 10;
|
|
726
|
+
const negativeData = sparklineData.map(price => -1 * price).reverse();
|
|
727
|
+
const negativeCeiling = Math.max(...negativeData) + 10;
|
|
728
|
+
const formatPrice = useCallback(price => {
|
|
729
|
+
return "$" + price.toLocaleString('en-US', {
|
|
1282
730
|
minimumFractionDigits: 2,
|
|
1283
731
|
maximumFractionDigits: 2
|
|
1284
|
-
})
|
|
1285
|
-
};
|
|
1286
|
-
const
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
}
|
|
1293
|
-
|
|
732
|
+
});
|
|
733
|
+
}, []);
|
|
734
|
+
const CompactChart = /*#__PURE__*/memo(_ref6 => {
|
|
735
|
+
let {
|
|
736
|
+
data,
|
|
737
|
+
showArea,
|
|
738
|
+
color,
|
|
739
|
+
referenceY
|
|
740
|
+
} = _ref6;
|
|
741
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
1294
742
|
style: {
|
|
1295
|
-
|
|
743
|
+
padding: 1
|
|
1296
744
|
},
|
|
1297
|
-
children:
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
padding: 2,
|
|
1301
|
-
paddingBottom: 0,
|
|
1302
|
-
children: [/*#__PURE__*/_jsx(RemoteImage, {
|
|
1303
|
-
shape: "circle",
|
|
1304
|
-
size: "xxl",
|
|
1305
|
-
source: assets.btc.imageUrl
|
|
1306
|
-
}), /*#__PURE__*/_jsxs(VStack, {
|
|
1307
|
-
flexGrow: 1,
|
|
1308
|
-
gap: 0.25,
|
|
1309
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
1310
|
-
font: "title1",
|
|
1311
|
-
style: {
|
|
1312
|
-
color: 'white'
|
|
1313
|
-
},
|
|
1314
|
-
children: "BTC"
|
|
1315
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
1316
|
-
color: "fgMuted",
|
|
1317
|
-
font: "label1",
|
|
1318
|
-
children: "Bitcoin"
|
|
1319
|
-
})]
|
|
1320
|
-
}), /*#__PURE__*/_jsxs(VStack, {
|
|
1321
|
-
alignItems: "flex-end",
|
|
1322
|
-
gap: 0.25,
|
|
1323
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
1324
|
-
font: "title1",
|
|
1325
|
-
style: {
|
|
1326
|
-
color: 'white'
|
|
1327
|
-
},
|
|
1328
|
-
children: formatPrice(latestPrice)
|
|
1329
|
-
}), /*#__PURE__*/_jsxs(Text, {
|
|
1330
|
-
color: "fgPositive",
|
|
1331
|
-
font: "label1",
|
|
1332
|
-
children: ["+", formatPercentChange(percentChange)]
|
|
1333
|
-
})]
|
|
1334
|
-
})]
|
|
1335
|
-
}), /*#__PURE__*/_jsx(LineChart, {
|
|
1336
|
-
showArea: true,
|
|
1337
|
-
height: 64,
|
|
1338
|
-
inset: {
|
|
1339
|
-
left: 0,
|
|
1340
|
-
right: 3,
|
|
1341
|
-
bottom: 0,
|
|
1342
|
-
top: 2
|
|
1343
|
-
},
|
|
745
|
+
children: /*#__PURE__*/_jsx(LineChart, _extends({}, dimensions, {
|
|
746
|
+
enableScrubbing: false,
|
|
747
|
+
inset: 0,
|
|
1344
748
|
series: [{
|
|
1345
|
-
id: '
|
|
1346
|
-
data
|
|
1347
|
-
color
|
|
749
|
+
id: 'btc',
|
|
750
|
+
data,
|
|
751
|
+
color
|
|
1348
752
|
}],
|
|
1349
|
-
|
|
1350
|
-
children: /*#__PURE__*/_jsx(
|
|
1351
|
-
|
|
1352
|
-
|
|
753
|
+
showArea: showArea,
|
|
754
|
+
children: /*#__PURE__*/_jsx(ReferenceLine, {
|
|
755
|
+
dataY: referenceY
|
|
756
|
+
})
|
|
757
|
+
}))
|
|
758
|
+
});
|
|
1353
759
|
});
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
data:
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
id: 'priceC',
|
|
1378
|
-
data: [1000, 4910, 2300, 5910, 3940, 2940, 1940],
|
|
1379
|
-
label: 'Unique Visitors P',
|
|
1380
|
-
color: theme.color.accentBoldPurple,
|
|
1381
|
-
curve: 'natural'
|
|
1382
|
-
}],
|
|
1383
|
-
yAxis: {
|
|
1384
|
-
domain: {
|
|
1385
|
-
min: 0
|
|
1386
|
-
},
|
|
1387
|
-
showGrid: true,
|
|
1388
|
-
tickLabelFormatter: value => value.toLocaleString()
|
|
1389
|
-
},
|
|
1390
|
-
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
1391
|
-
ref: scrubberRef
|
|
1392
|
-
})
|
|
1393
|
-
}), /*#__PURE__*/_jsx(Button, {
|
|
1394
|
-
onPress: () => {
|
|
1395
|
-
var _scrubberRef$current;
|
|
1396
|
-
return (_scrubberRef$current = scrubberRef.current) == null ? void 0 : _scrubberRef$current.pulse();
|
|
760
|
+
const ChartCell = /*#__PURE__*/memo(_ref7 => {
|
|
761
|
+
let {
|
|
762
|
+
data,
|
|
763
|
+
showArea,
|
|
764
|
+
color,
|
|
765
|
+
referenceY,
|
|
766
|
+
subdetail
|
|
767
|
+
} = _ref7;
|
|
768
|
+
return /*#__PURE__*/_jsx(ListCell, {
|
|
769
|
+
detail: formatPrice(parseFloat(prices[0])),
|
|
770
|
+
intermediary: /*#__PURE__*/_jsx(CompactChart, {
|
|
771
|
+
color: color,
|
|
772
|
+
data: data,
|
|
773
|
+
referenceY: referenceY,
|
|
774
|
+
showArea: showArea
|
|
775
|
+
}),
|
|
776
|
+
media: /*#__PURE__*/_jsx(Avatar, {
|
|
777
|
+
src: assets.btc.imageUrl
|
|
778
|
+
}),
|
|
779
|
+
onPress: () => console.log('clicked'),
|
|
780
|
+
spacingVariant: "condensed",
|
|
781
|
+
style: {
|
|
782
|
+
padding: 0
|
|
1397
783
|
},
|
|
1398
|
-
|
|
1399
|
-
})
|
|
784
|
+
subdetail: subdetail
|
|
785
|
+
});
|
|
1400
786
|
});
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
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
|
-
const
|
|
1430
|
-
|
|
787
|
+
return /*#__PURE__*/_jsxs(VStack, {
|
|
788
|
+
children: [/*#__PURE__*/_jsx(ChartCell, {
|
|
789
|
+
color: assets.btc.color,
|
|
790
|
+
data: sparklineData,
|
|
791
|
+
referenceY: parseFloat(prices[Math.floor(prices.length / 4)]),
|
|
792
|
+
subdetail: "-4.55%"
|
|
793
|
+
}), /*#__PURE__*/_jsx(ChartCell, {
|
|
794
|
+
showArea: true,
|
|
795
|
+
color: assets.btc.color,
|
|
796
|
+
data: sparklineData,
|
|
797
|
+
referenceY: parseFloat(prices[Math.floor(prices.length / 4)]),
|
|
798
|
+
subdetail: "-4.55%"
|
|
799
|
+
}), /*#__PURE__*/_jsx(ChartCell, {
|
|
800
|
+
showArea: true,
|
|
801
|
+
color: theme.color.fgPositive,
|
|
802
|
+
data: sparklineData,
|
|
803
|
+
referenceY: positiveFloor,
|
|
804
|
+
subdetail: "+0.25%"
|
|
805
|
+
}), /*#__PURE__*/_jsx(ChartCell, {
|
|
806
|
+
showArea: true,
|
|
807
|
+
color: theme.color.fgNegative,
|
|
808
|
+
data: negativeData,
|
|
809
|
+
referenceY: negativeCeiling,
|
|
810
|
+
subdetail: "-4.55%"
|
|
811
|
+
})]
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
function AssetPriceWithDottedArea() {
|
|
815
|
+
const fontMgr = useMemo(() => {
|
|
816
|
+
const fontProvider = Skia.TypefaceFontProvider.Make();
|
|
817
|
+
// Register system fonts if available, otherwise Skia will use defaults
|
|
818
|
+
return fontProvider;
|
|
1431
819
|
}, []);
|
|
1432
|
-
const
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
820
|
+
const BTCTab = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref8, ref) => {
|
|
821
|
+
let {
|
|
822
|
+
label
|
|
823
|
+
} = _ref8,
|
|
824
|
+
props = _objectWithoutPropertiesLoose(_ref8, _excluded2);
|
|
825
|
+
const {
|
|
826
|
+
activeTab
|
|
827
|
+
} = useTabsContext();
|
|
828
|
+
const isActive = (activeTab == null ? void 0 : activeTab.id) === props.id;
|
|
829
|
+
return /*#__PURE__*/_jsx(SegmentedTab, _extends({
|
|
830
|
+
ref: ref,
|
|
831
|
+
label: /*#__PURE__*/_jsx(Text, {
|
|
832
|
+
font: "label1",
|
|
833
|
+
style: {
|
|
834
|
+
color: isActive ? assets.btc.color : undefined
|
|
835
|
+
},
|
|
836
|
+
children: label
|
|
837
|
+
})
|
|
838
|
+
}, props));
|
|
839
|
+
}));
|
|
840
|
+
const BTCActiveIndicator = /*#__PURE__*/memo(_ref9 => {
|
|
841
|
+
let {
|
|
842
|
+
style
|
|
843
|
+
} = _ref9,
|
|
844
|
+
props = _objectWithoutPropertiesLoose(_ref9, _excluded3);
|
|
845
|
+
return /*#__PURE__*/_jsx(PeriodSelectorActiveIndicator, _extends({}, props, {
|
|
846
|
+
style: [style, {
|
|
847
|
+
backgroundColor: assets.btc.color + "1A"
|
|
848
|
+
}]
|
|
849
|
+
}));
|
|
1442
850
|
});
|
|
1443
|
-
const
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
851
|
+
const AssetPriceDotted = /*#__PURE__*/memo(() => {
|
|
852
|
+
const theme = useTheme();
|
|
853
|
+
const currentPrice = sparklineInteractiveData.hour[sparklineInteractiveData.hour.length - 1].value;
|
|
854
|
+
const tabs = useMemo(() => [{
|
|
855
|
+
id: 'hour',
|
|
856
|
+
label: '1H'
|
|
857
|
+
}, {
|
|
858
|
+
id: 'day',
|
|
859
|
+
label: '1D'
|
|
860
|
+
}, {
|
|
861
|
+
id: 'week',
|
|
862
|
+
label: '1W'
|
|
863
|
+
}, {
|
|
864
|
+
id: 'month',
|
|
865
|
+
label: '1M'
|
|
866
|
+
}, {
|
|
867
|
+
id: 'year',
|
|
868
|
+
label: '1Y'
|
|
869
|
+
}, {
|
|
870
|
+
id: 'all',
|
|
871
|
+
label: 'All'
|
|
872
|
+
}], []);
|
|
873
|
+
const [timePeriod, setTimePeriod] = useState(tabs[0]);
|
|
874
|
+
const sparklineTimePeriodData = useMemo(() => {
|
|
875
|
+
return sparklineInteractiveData[timePeriod.id];
|
|
876
|
+
}, [timePeriod]);
|
|
877
|
+
const sparklineTimePeriodDataValues = useMemo(() => {
|
|
878
|
+
return sparklineTimePeriodData.map(d => d.value);
|
|
879
|
+
}, [sparklineTimePeriodData]);
|
|
880
|
+
const sparklineTimePeriodDataTimestamps = useMemo(() => {
|
|
881
|
+
return sparklineTimePeriodData.map(d => d.date);
|
|
882
|
+
}, [sparklineTimePeriodData]);
|
|
883
|
+
const onPeriodChange = useCallback(period => {
|
|
884
|
+
setTimePeriod(period || tabs[0]);
|
|
885
|
+
}, [tabs, setTimePeriod]);
|
|
886
|
+
const priceFormatter = useMemo(() => new Intl.NumberFormat('en-US', {
|
|
887
|
+
style: 'currency',
|
|
888
|
+
currency: 'USD'
|
|
889
|
+
}), []);
|
|
890
|
+
const formatPrice = useCallback(price => {
|
|
891
|
+
return priceFormatter.format(price);
|
|
892
|
+
}, [priceFormatter]);
|
|
893
|
+
const formatDate = useCallback(date => {
|
|
894
|
+
const dayOfWeek = date.toLocaleDateString('en-US', {
|
|
895
|
+
weekday: 'short'
|
|
896
|
+
});
|
|
897
|
+
const monthDay = date.toLocaleDateString('en-US', {
|
|
898
|
+
month: 'short',
|
|
899
|
+
day: 'numeric'
|
|
900
|
+
});
|
|
901
|
+
const time = date.toLocaleTimeString('en-US', {
|
|
902
|
+
hour: 'numeric',
|
|
903
|
+
minute: '2-digit',
|
|
904
|
+
hour12: true
|
|
905
|
+
});
|
|
906
|
+
return dayOfWeek + ", " + monthDay + ", " + time;
|
|
907
|
+
}, []);
|
|
908
|
+
return /*#__PURE__*/_jsxs(VStack, {
|
|
909
|
+
gap: 2,
|
|
910
|
+
children: [/*#__PURE__*/_jsx(SectionHeader, {
|
|
911
|
+
balance: /*#__PURE__*/_jsx(Text, {
|
|
912
|
+
font: "title2",
|
|
913
|
+
children: formatPrice(currentPrice)
|
|
914
|
+
}),
|
|
915
|
+
end: /*#__PURE__*/_jsx(VStack, {
|
|
1472
916
|
justifyContent: "center",
|
|
1473
917
|
children: /*#__PURE__*/_jsx(RemoteImage, {
|
|
1474
918
|
shape: "circle",
|
|
1475
|
-
size: "
|
|
919
|
+
size: "xl",
|
|
1476
920
|
source: assets.btc.imageUrl
|
|
1477
921
|
})
|
|
1478
|
-
})
|
|
1479
|
-
|
|
922
|
+
}),
|
|
923
|
+
title: /*#__PURE__*/_jsx(Text, {
|
|
924
|
+
font: "title1",
|
|
925
|
+
children: "Bitcoin"
|
|
926
|
+
})
|
|
927
|
+
}), /*#__PURE__*/_jsx(LineChart, {
|
|
1480
928
|
enableScrubbing: true,
|
|
929
|
+
showArea: true,
|
|
930
|
+
areaType: "dotted",
|
|
1481
931
|
height: 200,
|
|
1482
932
|
inset: {
|
|
1483
|
-
|
|
1484
|
-
right: 3,
|
|
1485
|
-
left: 0,
|
|
1486
|
-
top: 6
|
|
933
|
+
top: 52
|
|
1487
934
|
},
|
|
1488
|
-
onScrubberPositionChange: onScrubberPositionChange,
|
|
1489
935
|
series: [{
|
|
1490
|
-
id: '
|
|
1491
|
-
data:
|
|
1492
|
-
color:
|
|
936
|
+
id: 'btc',
|
|
937
|
+
data: sparklineTimePeriodDataValues,
|
|
938
|
+
color: assets.btc.color
|
|
1493
939
|
}],
|
|
1494
|
-
|
|
1495
|
-
children: [/*#__PURE__*/_jsx(Line, {
|
|
1496
|
-
showArea: true,
|
|
1497
|
-
AreaComponent: AreaComponent,
|
|
1498
|
-
seriesId: "price",
|
|
1499
|
-
strokeWidth: 3
|
|
1500
|
-
}), /*#__PURE__*/_jsx(Scrubber, {
|
|
940
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
1501
941
|
idlePulse: true,
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
942
|
+
labelElevated: true,
|
|
943
|
+
label: d => {
|
|
944
|
+
const date = formatDate(sparklineTimePeriodDataTimestamps[d]);
|
|
945
|
+
const price = formatPrice(sparklineTimePeriodDataValues[d]);
|
|
946
|
+
const regularStyle = {
|
|
947
|
+
fontFamilies: ['Inter'],
|
|
948
|
+
fontSize: 14,
|
|
949
|
+
fontStyle: {
|
|
950
|
+
weight: FontWeight.Normal
|
|
951
|
+
},
|
|
952
|
+
color: Skia.Color(theme.color.fgMuted)
|
|
953
|
+
};
|
|
954
|
+
const boldStyle = _extends({
|
|
955
|
+
fontFamilies: ['Inter']
|
|
956
|
+
}, regularStyle, {
|
|
957
|
+
fontStyle: {
|
|
958
|
+
weight: FontWeight.Bold
|
|
959
|
+
}
|
|
960
|
+
});
|
|
961
|
+
|
|
962
|
+
// 3. Use the ParagraphBuilder
|
|
963
|
+
const builder = Skia.ParagraphBuilder.Make({
|
|
964
|
+
textAlign: TextAlign.Left
|
|
965
|
+
}, fontMgr);
|
|
966
|
+
builder.pushStyle(boldStyle);
|
|
967
|
+
builder.addText(price);
|
|
968
|
+
builder.pushStyle(regularStyle);
|
|
969
|
+
builder.addText(" " + date);
|
|
970
|
+
const para = builder.build();
|
|
971
|
+
para.layout(512);
|
|
972
|
+
return para;
|
|
973
|
+
}
|
|
1514
974
|
})
|
|
975
|
+
}), /*#__PURE__*/_jsx(PeriodSelector, {
|
|
976
|
+
TabComponent: BTCTab,
|
|
977
|
+
TabsActiveIndicatorComponent: BTCActiveIndicator,
|
|
978
|
+
activeTab: timePeriod,
|
|
979
|
+
onChange: onPeriodChange,
|
|
980
|
+
tabs: tabs
|
|
1515
981
|
})]
|
|
1516
|
-
})
|
|
982
|
+
});
|
|
1517
983
|
});
|
|
1518
|
-
};
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
984
|
+
return /*#__PURE__*/_jsx(AssetPriceDotted, {});
|
|
985
|
+
}
|
|
986
|
+
const LegendDot = /*#__PURE__*/memo(props => {
|
|
987
|
+
return /*#__PURE__*/_jsx(Box, _extends({
|
|
988
|
+
borderRadius: 1000,
|
|
989
|
+
height: 10,
|
|
990
|
+
width: 10
|
|
991
|
+
}, props));
|
|
992
|
+
});
|
|
993
|
+
const LegendEntry = /*#__PURE__*/memo(_ref0 => {
|
|
994
|
+
let {
|
|
995
|
+
color = assets.btc.color,
|
|
996
|
+
label,
|
|
997
|
+
value
|
|
998
|
+
} = _ref0;
|
|
999
|
+
return /*#__PURE__*/_jsxs(Box, {
|
|
1000
|
+
alignItems: "center",
|
|
1001
|
+
flexDirection: "row",
|
|
1002
|
+
gap: 0.5,
|
|
1003
|
+
children: [/*#__PURE__*/_jsx(LegendDot, {
|
|
1004
|
+
style: {
|
|
1005
|
+
backgroundColor: color
|
|
1006
|
+
}
|
|
1007
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
1008
|
+
font: "label2",
|
|
1009
|
+
children: label
|
|
1010
|
+
}), value && /*#__PURE__*/_jsx(Text, {
|
|
1011
|
+
color: "fgMuted",
|
|
1012
|
+
font: "label2",
|
|
1013
|
+
style: {
|
|
1014
|
+
fontWeight: 'bold'
|
|
1015
|
+
},
|
|
1016
|
+
children: value
|
|
1017
|
+
})]
|
|
1018
|
+
});
|
|
1019
|
+
});
|
|
1020
|
+
const PerformanceHeader = /*#__PURE__*/memo(_ref1 => {
|
|
1021
|
+
let {
|
|
1022
|
+
scrubberPosition,
|
|
1023
|
+
sparklineTimePeriodDataValues
|
|
1024
|
+
} = _ref1;
|
|
1025
|
+
const theme = useTheme();
|
|
1026
|
+
const formatPriceThousands = useCallback(price => {
|
|
1027
|
+
return new Intl.NumberFormat('en-US', {
|
|
1028
|
+
style: 'currency',
|
|
1029
|
+
currency: 'USD',
|
|
1030
|
+
minimumFractionDigits: 0,
|
|
1031
|
+
maximumFractionDigits: 0
|
|
1032
|
+
}).format(price / 1000) + "k";
|
|
1523
1033
|
}, []);
|
|
1524
|
-
const
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1034
|
+
const shownPosition = scrubberPosition !== undefined ? scrubberPosition : sparklineTimePeriodDataValues.length - 1;
|
|
1035
|
+
return /*#__PURE__*/_jsxs(HStack, {
|
|
1036
|
+
gap: 1,
|
|
1037
|
+
paddingX: 1,
|
|
1038
|
+
children: [/*#__PURE__*/_jsx(LegendEntry, {
|
|
1039
|
+
color: theme.color.fgPositive,
|
|
1040
|
+
label: "High Price",
|
|
1041
|
+
value: formatPriceThousands(sparklineTimePeriodDataValues[shownPosition] * 1.2)
|
|
1042
|
+
}), /*#__PURE__*/_jsx(LegendEntry, {
|
|
1043
|
+
color: assets.btc.color,
|
|
1044
|
+
label: "Actual Price",
|
|
1045
|
+
value: formatPriceThousands(sparklineTimePeriodDataValues[shownPosition])
|
|
1046
|
+
}), /*#__PURE__*/_jsx(LegendEntry, {
|
|
1047
|
+
color: theme.color.fgNegative,
|
|
1048
|
+
label: "Low Price",
|
|
1049
|
+
value: formatPriceThousands(sparklineTimePeriodDataValues[shownPosition] * 0.8)
|
|
1050
|
+
})]
|
|
1051
|
+
});
|
|
1052
|
+
});
|
|
1053
|
+
const PerformanceChart = /*#__PURE__*/memo(_ref10 => {
|
|
1054
|
+
let {
|
|
1055
|
+
timePeriod,
|
|
1056
|
+
onScrubberPositionChange
|
|
1057
|
+
} = _ref10;
|
|
1058
|
+
const theme = useTheme();
|
|
1059
|
+
const sparklineTimePeriodData = useMemo(() => {
|
|
1060
|
+
return sparklineInteractiveData[timePeriod.id];
|
|
1061
|
+
}, [timePeriod]);
|
|
1062
|
+
const sparklineTimePeriodDataValues = useMemo(() => {
|
|
1063
|
+
return sparklineTimePeriodData.map(d => d.value);
|
|
1064
|
+
}, [sparklineTimePeriodData]);
|
|
1065
|
+
const sparklineTimePeriodDataTimestamps = useMemo(() => {
|
|
1066
|
+
return sparklineTimePeriodData.map(d => d.date);
|
|
1067
|
+
}, [sparklineTimePeriodData]);
|
|
1068
|
+
const formatPriceThousands = useCallback(price => {
|
|
1069
|
+
return new Intl.NumberFormat('en-US', {
|
|
1070
|
+
style: 'currency',
|
|
1071
|
+
currency: 'USD',
|
|
1072
|
+
minimumFractionDigits: 0,
|
|
1073
|
+
maximumFractionDigits: 0
|
|
1074
|
+
}).format(price / 1000) + "k";
|
|
1075
|
+
}, []);
|
|
1076
|
+
const formatDate = useCallback(date => {
|
|
1077
|
+
const dayOfWeek = date.toLocaleDateString('en-US', {
|
|
1078
|
+
weekday: 'short'
|
|
1079
|
+
});
|
|
1080
|
+
const monthDay = date.toLocaleDateString('en-US', {
|
|
1081
|
+
month: 'short',
|
|
1082
|
+
day: 'numeric'
|
|
1083
|
+
});
|
|
1084
|
+
const time = date.toLocaleTimeString('en-US', {
|
|
1085
|
+
hour: 'numeric',
|
|
1086
|
+
minute: '2-digit',
|
|
1087
|
+
hour12: true
|
|
1088
|
+
});
|
|
1089
|
+
return dayOfWeek + ", " + monthDay + ", " + time;
|
|
1090
|
+
}, []);
|
|
1091
|
+
const getScrubberLabel = useCallback(d => formatDate(sparklineTimePeriodDataTimestamps[d]), [formatDate, sparklineTimePeriodDataTimestamps]);
|
|
1560
1092
|
return /*#__PURE__*/_jsx(LineChart, {
|
|
1561
1093
|
enableScrubbing: true,
|
|
1562
1094
|
showArea: true,
|
|
1563
|
-
|
|
1095
|
+
showYAxis: true,
|
|
1096
|
+
areaType: "dotted",
|
|
1097
|
+
height: 300,
|
|
1098
|
+
inset: {
|
|
1099
|
+
top: 52,
|
|
1100
|
+
left: 0,
|
|
1101
|
+
right: 0
|
|
1102
|
+
},
|
|
1103
|
+
onScrubberPositionChange: onScrubberPositionChange,
|
|
1564
1104
|
series: [{
|
|
1105
|
+
id: 'high',
|
|
1106
|
+
data: sparklineTimePeriodDataValues.map(d => d * 1.2),
|
|
1107
|
+
color: theme.color.fgPositive,
|
|
1108
|
+
label: 'High Price'
|
|
1109
|
+
}, {
|
|
1565
1110
|
id: 'btc',
|
|
1566
|
-
data:
|
|
1567
|
-
color: assets.btc.color
|
|
1111
|
+
data: sparklineTimePeriodDataValues,
|
|
1112
|
+
color: assets.btc.color,
|
|
1113
|
+
label: 'Actual Price'
|
|
1114
|
+
}, {
|
|
1115
|
+
id: 'low',
|
|
1116
|
+
data: sparklineTimePeriodDataValues.map(d => d * 0.8),
|
|
1117
|
+
color: theme.color.fgNegative,
|
|
1118
|
+
label: 'Low Price'
|
|
1568
1119
|
}],
|
|
1120
|
+
yAxis: {
|
|
1121
|
+
showGrid: true,
|
|
1122
|
+
tickLabelFormatter: formatPriceThousands
|
|
1123
|
+
},
|
|
1569
1124
|
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
1570
|
-
|
|
1125
|
+
idlePulse: true,
|
|
1126
|
+
label: getScrubberLabel
|
|
1571
1127
|
})
|
|
1572
1128
|
});
|
|
1573
|
-
};
|
|
1574
|
-
|
|
1575
|
-
date: new Date('2022-01-01'),
|
|
1576
|
-
availability: 79
|
|
1577
|
-
}, {
|
|
1578
|
-
date: new Date('2022-01-03'),
|
|
1579
|
-
availability: 81
|
|
1580
|
-
}, {
|
|
1581
|
-
date: new Date('2022-01-04'),
|
|
1582
|
-
availability: 82
|
|
1583
|
-
}, {
|
|
1584
|
-
date: new Date('2022-01-06'),
|
|
1585
|
-
availability: 91
|
|
1586
|
-
}, {
|
|
1587
|
-
date: new Date('2022-01-07'),
|
|
1588
|
-
availability: 92
|
|
1589
|
-
}, {
|
|
1590
|
-
date: new Date('2022-01-10'),
|
|
1591
|
-
availability: 86
|
|
1592
|
-
}];
|
|
1593
|
-
|
|
1594
|
-
// Generate prediction probability data for three candidates
|
|
1595
|
-
const generatePredictionData = () => {
|
|
1596
|
-
const now = new Date();
|
|
1597
|
-
const baseTimestamp = now.getTime();
|
|
1598
|
-
|
|
1599
|
-
// Generate data for different time periods
|
|
1600
|
-
const generateForPeriod = (points, intervalMs) => {
|
|
1601
|
-
return Array.from({
|
|
1602
|
-
length: points
|
|
1603
|
-
}, (_, i) => {
|
|
1604
|
-
const timestamp = new Date(baseTimestamp - (points - 1 - i) * intervalMs);
|
|
1605
|
-
|
|
1606
|
-
// Generate percentage values for three candidates that roughly sum to 100%
|
|
1607
|
-
const candidate1 = 45 + Math.random() * 30; // 45-75%
|
|
1608
|
-
const candidate2 = 15 + Math.random() * 20; // 15-35%
|
|
1609
|
-
const candidate3 = Math.max(0, 100 - candidate1 - candidate2 - Math.random() * 5); // remainder
|
|
1610
|
-
|
|
1611
|
-
return {
|
|
1612
|
-
date: timestamp,
|
|
1613
|
-
candidate1: Math.round(candidate1 * 10) / 10,
|
|
1614
|
-
candidate2: Math.round(candidate2 * 10) / 10,
|
|
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]);
|
|
1648
|
-
return /*#__PURE__*/_jsxs(VStack, {
|
|
1649
|
-
gap: 2,
|
|
1650
|
-
children: [/*#__PURE__*/_jsxs(HStack, {
|
|
1651
|
-
alignItems: "center",
|
|
1652
|
-
gap: 2,
|
|
1653
|
-
children: [/*#__PURE__*/_jsx(Box, {
|
|
1654
|
-
style: {
|
|
1655
|
-
width: 12,
|
|
1656
|
-
height: 12,
|
|
1657
|
-
borderRadius: 6,
|
|
1658
|
-
backgroundColor: colors.pink
|
|
1659
|
-
}
|
|
1660
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
1661
|
-
font: "label2",
|
|
1662
|
-
children: "Noah Wyle"
|
|
1663
|
-
}), /*#__PURE__*/_jsxs(Text, {
|
|
1664
|
-
font: "label1",
|
|
1665
|
-
children: [candidate1Value, "%"]
|
|
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, "%"]
|
|
1700
|
-
})]
|
|
1701
|
-
})]
|
|
1702
|
-
});
|
|
1703
|
-
}));
|
|
1704
|
-
const PredictionChart = () => {
|
|
1705
|
-
const theme = useTheme();
|
|
1706
|
-
|
|
1707
|
-
// Ref for the legend component
|
|
1708
|
-
const legendRef = useRef(null);
|
|
1709
|
-
|
|
1710
|
-
// Define colors using spectrum
|
|
1711
|
-
const colors = useMemo(() => ({
|
|
1712
|
-
pink: "rgb(" + theme.spectrum.pink50 + ")",
|
|
1713
|
-
teal: "rgb(" + theme.spectrum.teal50 + ")",
|
|
1714
|
-
green: "rgb(" + theme.spectrum.green50 + ")"
|
|
1715
|
-
}), [theme.spectrum]);
|
|
1129
|
+
});
|
|
1130
|
+
function Performance() {
|
|
1716
1131
|
const tabs = useMemo(() => [{
|
|
1717
1132
|
id: 'hour',
|
|
1718
1133
|
label: '1H'
|
|
@@ -1733,231 +1148,305 @@ const PredictionChart = () => {
|
|
|
1733
1148
|
label: 'All'
|
|
1734
1149
|
}], []);
|
|
1735
1150
|
const [timePeriod, setTimePeriod] = useState(tabs[0]);
|
|
1736
|
-
const
|
|
1737
|
-
|
|
1151
|
+
const [scrubberPosition, setScrubberPosition] = useState();
|
|
1152
|
+
const sparklineTimePeriodData = useMemo(() => {
|
|
1153
|
+
return sparklineInteractiveData[timePeriod.id];
|
|
1738
1154
|
}, [timePeriod]);
|
|
1739
|
-
const
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
const timestamps = useMemo(() => periodData.map(d => d.date), [periodData]);
|
|
1743
|
-
|
|
1744
|
-
// Data object for the legend
|
|
1745
|
-
const legendData = useMemo(() => ({
|
|
1746
|
-
candidate1: candidate1Data,
|
|
1747
|
-
candidate2: candidate2Data,
|
|
1748
|
-
candidate3: candidate3Data
|
|
1749
|
-
}), [candidate1Data, candidate2Data, candidate3Data]);
|
|
1750
|
-
|
|
1751
|
-
// Update legend via imperative ref when scrubber position changes
|
|
1752
|
-
const onScrubberPositionChange = useCallback(dataIndex => {
|
|
1753
|
-
var _legendRef$current;
|
|
1754
|
-
const idx = dataIndex != null ? dataIndex : candidate1Data.length - 1;
|
|
1755
|
-
(_legendRef$current = legendRef.current) == null || _legendRef$current.updateSelectedIndex(idx);
|
|
1756
|
-
}, [candidate1Data.length]);
|
|
1757
|
-
|
|
1758
|
-
// Update legend when data length changes
|
|
1759
|
-
useEffect(() => {
|
|
1760
|
-
var _legendRef$current2;
|
|
1761
|
-
(_legendRef$current2 = legendRef.current) == null || _legendRef$current2.updateSelectedIndex(candidate1Data.length - 1);
|
|
1762
|
-
}, [candidate1Data.length]);
|
|
1155
|
+
const sparklineTimePeriodDataValues = useMemo(() => {
|
|
1156
|
+
return sparklineTimePeriodData.map(d => d.value);
|
|
1157
|
+
}, [sparklineTimePeriodData]);
|
|
1763
1158
|
const onPeriodChange = useCallback(period => {
|
|
1764
1159
|
setTimePeriod(period || tabs[0]);
|
|
1765
1160
|
}, [tabs]);
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1161
|
+
return /*#__PURE__*/_jsxs(VStack, {
|
|
1162
|
+
gap: 2,
|
|
1163
|
+
style: {
|
|
1164
|
+
marginLeft: -8,
|
|
1165
|
+
marginRight: -8
|
|
1166
|
+
},
|
|
1167
|
+
children: [/*#__PURE__*/_jsx(PerformanceHeader, {
|
|
1168
|
+
scrubberPosition: scrubberPosition,
|
|
1169
|
+
sparklineTimePeriodDataValues: sparklineTimePeriodDataValues
|
|
1170
|
+
}), /*#__PURE__*/_jsx(PerformanceChart, {
|
|
1171
|
+
onScrubberPositionChange: setScrubberPosition,
|
|
1172
|
+
timePeriod: timePeriod
|
|
1173
|
+
}), /*#__PURE__*/_jsx(PeriodSelector, {
|
|
1174
|
+
activeTab: timePeriod,
|
|
1175
|
+
onChange: onPeriodChange,
|
|
1176
|
+
tabs: tabs
|
|
1177
|
+
})]
|
|
1178
|
+
});
|
|
1179
|
+
}
|
|
1180
|
+
function MonotoneAssetPrice() {
|
|
1181
|
+
const theme = useTheme();
|
|
1182
|
+
const prices = sparklineInteractiveData.hour;
|
|
1183
|
+
const fontMgr = useMemo(() => {
|
|
1184
|
+
const fontProvider = Skia.TypefaceFontProvider.Make();
|
|
1185
|
+
// Register system fonts if available, otherwise Skia will use defaults
|
|
1186
|
+
return fontProvider;
|
|
1187
|
+
}, []);
|
|
1188
|
+
const priceFormatter = useMemo(() => new Intl.NumberFormat('en-US', {
|
|
1189
|
+
style: 'currency',
|
|
1190
|
+
currency: 'USD'
|
|
1191
|
+
}), []);
|
|
1192
|
+
const scrubberPriceFormatter = useMemo(() => new Intl.NumberFormat('en-US', {
|
|
1193
|
+
minimumFractionDigits: 2,
|
|
1194
|
+
maximumFractionDigits: 2
|
|
1195
|
+
}), []);
|
|
1196
|
+
const formatPrice = useCallback(price => {
|
|
1197
|
+
return priceFormatter.format(price);
|
|
1198
|
+
}, [priceFormatter]);
|
|
1199
|
+
const formatDate = useCallback(date => {
|
|
1200
|
+
const dayOfWeek = date.toLocaleDateString('en-US', {
|
|
1201
|
+
weekday: 'short'
|
|
1202
|
+
});
|
|
1203
|
+
const monthDay = date.toLocaleDateString('en-US', {
|
|
1772
1204
|
month: 'short',
|
|
1773
|
-
day: 'numeric'
|
|
1774
|
-
year: date.getFullYear() !== currentYear ? 'numeric' : undefined
|
|
1775
|
-
}, shouldIncludeTime && {
|
|
1776
|
-
hour: 'numeric',
|
|
1777
|
-
minute: '2-digit',
|
|
1778
|
-
hour12: true
|
|
1205
|
+
day: 'numeric'
|
|
1779
1206
|
});
|
|
1780
|
-
const
|
|
1781
|
-
return dateStr;
|
|
1782
|
-
}, [timestamps, timePeriod.id]);
|
|
1783
|
-
const chartOverviewLabel = useMemo(() => {
|
|
1784
|
-
if (periodData.length === 0) return '';
|
|
1785
|
-
const firstDate = periodData[0].date;
|
|
1786
|
-
const lastDate = periodData[periodData.length - 1].date;
|
|
1787
|
-
const currentYear = new Date().getFullYear();
|
|
1788
|
-
const shouldIncludeTime = timePeriod.id === 'hour' || timePeriod.id === 'day';
|
|
1789
|
-
const dateRangeOptions = _extends({
|
|
1790
|
-
month: 'long',
|
|
1791
|
-
day: 'numeric',
|
|
1792
|
-
year: firstDate.getFullYear() !== currentYear ? 'numeric' : undefined
|
|
1793
|
-
}, shouldIncludeTime && {
|
|
1207
|
+
const time = date.toLocaleTimeString('en-US', {
|
|
1794
1208
|
hour: 'numeric',
|
|
1795
1209
|
minute: '2-digit',
|
|
1796
1210
|
hour12: true
|
|
1797
1211
|
});
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
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
|
|
1873
|
-
})]
|
|
1874
|
-
})
|
|
1875
|
-
});
|
|
1876
|
-
};
|
|
1877
|
-
const AvailabilityChart = () => {
|
|
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;
|
|
1212
|
+
return dayOfWeek + ", " + monthDay + ", " + time;
|
|
1213
|
+
}, []);
|
|
1214
|
+
const scrubberLabel = useCallback(index => {
|
|
1215
|
+
const price = scrubberPriceFormatter.format(prices[index].value);
|
|
1216
|
+
const date = formatDate(prices[index].date);
|
|
1217
|
+
const regularStyle = {
|
|
1218
|
+
fontFamilies: ['Inter'],
|
|
1219
|
+
fontSize: 14,
|
|
1220
|
+
fontStyle: {
|
|
1221
|
+
weight: FontWeight.Normal
|
|
1222
|
+
},
|
|
1223
|
+
color: Skia.Color(theme.color.fgMuted)
|
|
1224
|
+
};
|
|
1225
|
+
const boldStyle = _extends({
|
|
1226
|
+
fontFamilies: ['Inter']
|
|
1227
|
+
}, regularStyle, {
|
|
1228
|
+
fontStyle: {
|
|
1229
|
+
weight: FontWeight.Bold
|
|
1230
|
+
}
|
|
1231
|
+
});
|
|
1232
|
+
const builder = Skia.ParagraphBuilder.Make({
|
|
1233
|
+
textAlign: TextAlign.Left
|
|
1234
|
+
}, fontMgr);
|
|
1235
|
+
builder.pushStyle(boldStyle);
|
|
1236
|
+
builder.addText(price + " USD");
|
|
1237
|
+
builder.pushStyle(regularStyle);
|
|
1238
|
+
builder.addText(" " + date);
|
|
1239
|
+
const para = builder.build();
|
|
1240
|
+
para.layout(512);
|
|
1241
|
+
return para;
|
|
1242
|
+
}, [scrubberPriceFormatter, prices, formatDate, theme.color.fgMuted, fontMgr]);
|
|
1243
|
+
const formatAxisLabelPrice = useCallback(price => {
|
|
1244
|
+
return formatPrice(price);
|
|
1245
|
+
}, [formatPrice]);
|
|
1246
|
+
|
|
1247
|
+
// Custom tick label component with offset positioning
|
|
1248
|
+
const CustomYAxisTickLabel = useCallback(props => /*#__PURE__*/_jsx(DefaultAxisTickLabel, _extends({}, props, {
|
|
1249
|
+
dx: 4,
|
|
1250
|
+
dy: -12,
|
|
1251
|
+
horizontalAlignment: "left"
|
|
1252
|
+
})), []);
|
|
1253
|
+
const CustomScrubberBeacon = /*#__PURE__*/memo(_ref11 => {
|
|
1882
1254
|
let {
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1255
|
+
dataX,
|
|
1256
|
+
dataY,
|
|
1257
|
+
seriesId,
|
|
1258
|
+
isIdle,
|
|
1259
|
+
animate = true
|
|
1260
|
+
} = _ref11;
|
|
1886
1261
|
const {
|
|
1887
|
-
|
|
1888
|
-
|
|
1262
|
+
getSeries,
|
|
1263
|
+
getXSerializableScale,
|
|
1264
|
+
getYSerializableScale
|
|
1889
1265
|
} = useCartesianChartContext();
|
|
1890
|
-
const
|
|
1891
|
-
const
|
|
1892
|
-
|
|
1893
|
-
const
|
|
1894
|
-
const
|
|
1895
|
-
const rangeMax = (_rangeBounds$max = rangeBounds == null ? void 0 : rangeBounds.max) != null ? _rangeBounds$max : 100;
|
|
1266
|
+
const targetSeries = useMemo(() => getSeries(seriesId), [getSeries, seriesId]);
|
|
1267
|
+
const xScale = useMemo(() => getXSerializableScale(), [getXSerializableScale]);
|
|
1268
|
+
const yScale = useMemo(() => getYSerializableScale(targetSeries == null ? void 0 : targetSeries.yAxisId), [getYSerializableScale, targetSeries == null ? void 0 : targetSeries.yAxisId]);
|
|
1269
|
+
const animatedX = useSharedValue(0);
|
|
1270
|
+
const animatedY = useSharedValue(0);
|
|
1896
1271
|
|
|
1897
|
-
// Calculate the
|
|
1898
|
-
const
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1272
|
+
// Calculate the target point position - project data to pixels
|
|
1273
|
+
const targetPoint = useDerivedValue(() => {
|
|
1274
|
+
if (!xScale || !yScale) return {
|
|
1275
|
+
x: 0,
|
|
1276
|
+
y: 0
|
|
1277
|
+
};
|
|
1278
|
+
return projectPointWithSerializableScale({
|
|
1279
|
+
x: unwrapAnimatedValue(dataX),
|
|
1280
|
+
y: unwrapAnimatedValue(dataY),
|
|
1281
|
+
xScale,
|
|
1282
|
+
yScale
|
|
1283
|
+
});
|
|
1284
|
+
}, [dataX, dataY, xScale, yScale]);
|
|
1285
|
+
useAnimatedReaction(() => {
|
|
1286
|
+
return {
|
|
1287
|
+
point: targetPoint.value,
|
|
1288
|
+
isIdle: unwrapAnimatedValue(isIdle)
|
|
1289
|
+
};
|
|
1290
|
+
}, (current, previous) => {
|
|
1291
|
+
// When animation is disabled, on initial render, or when we are starting,
|
|
1292
|
+
// continuing, or finishing scrubbing we should immediately transition
|
|
1293
|
+
if (!animate || previous === null || !previous.isIdle || !current.isIdle) {
|
|
1294
|
+
animatedX.value = current.point.x;
|
|
1295
|
+
animatedY.value = current.point.y;
|
|
1296
|
+
return;
|
|
1297
|
+
}
|
|
1298
|
+
animatedX.value = buildTransition(current.point.x, defaultTransition);
|
|
1299
|
+
animatedY.value = buildTransition(current.point.y, defaultTransition);
|
|
1300
|
+
}, [animate]);
|
|
1902
1301
|
|
|
1903
|
-
//
|
|
1904
|
-
const
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
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
|
-
})
|
|
1302
|
+
// Create animated point using the animated values
|
|
1303
|
+
const animatedPoint = useDerivedValue(() => {
|
|
1304
|
+
return {
|
|
1305
|
+
x: animatedX.value,
|
|
1306
|
+
y: animatedY.value
|
|
1307
|
+
};
|
|
1308
|
+
}, [animatedX, animatedY]);
|
|
1309
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
1310
|
+
children: [/*#__PURE__*/_jsx(Circle, {
|
|
1311
|
+
c: animatedPoint,
|
|
1312
|
+
color: theme.color.bg,
|
|
1313
|
+
r: 5
|
|
1314
|
+
}), /*#__PURE__*/_jsx(Circle, {
|
|
1315
|
+
c: animatedPoint,
|
|
1316
|
+
color: theme.color.fg,
|
|
1317
|
+
r: 5,
|
|
1318
|
+
strokeWidth: 3,
|
|
1319
|
+
style: "stroke"
|
|
1320
|
+
})]
|
|
1934
1321
|
});
|
|
1935
1322
|
});
|
|
1323
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
1324
|
+
enableScrubbing: true,
|
|
1325
|
+
showYAxis: true,
|
|
1326
|
+
height: 200,
|
|
1327
|
+
inset: {
|
|
1328
|
+
top: 64
|
|
1329
|
+
},
|
|
1330
|
+
series: [{
|
|
1331
|
+
id: 'btc',
|
|
1332
|
+
data: prices.map(price => price.value),
|
|
1333
|
+
color: theme.color.fg,
|
|
1334
|
+
gradient: {
|
|
1335
|
+
axis: 'x',
|
|
1336
|
+
stops: _ref12 => {
|
|
1337
|
+
let {
|
|
1338
|
+
min
|
|
1339
|
+
} = _ref12;
|
|
1340
|
+
return [{
|
|
1341
|
+
offset: min,
|
|
1342
|
+
color: theme.color.fg,
|
|
1343
|
+
opacity: 0
|
|
1344
|
+
}, {
|
|
1345
|
+
offset: 32,
|
|
1346
|
+
color: theme.color.fg,
|
|
1347
|
+
opacity: 1
|
|
1348
|
+
}];
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
}],
|
|
1352
|
+
xAxis: {
|
|
1353
|
+
range: _ref13 => {
|
|
1354
|
+
let {
|
|
1355
|
+
max
|
|
1356
|
+
} = _ref13;
|
|
1357
|
+
return {
|
|
1358
|
+
min: 96,
|
|
1359
|
+
max
|
|
1360
|
+
};
|
|
1361
|
+
}
|
|
1362
|
+
},
|
|
1363
|
+
yAxis: {
|
|
1364
|
+
position: 'left',
|
|
1365
|
+
width: 0,
|
|
1366
|
+
showGrid: true,
|
|
1367
|
+
tickLabelFormatter: formatAxisLabelPrice,
|
|
1368
|
+
TickLabelComponent: CustomYAxisTickLabel
|
|
1369
|
+
},
|
|
1370
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
1371
|
+
hideOverlay: true,
|
|
1372
|
+
labelElevated: true,
|
|
1373
|
+
BeaconComponent: CustomScrubberBeacon,
|
|
1374
|
+
LineComponent: SolidLine,
|
|
1375
|
+
label: scrubberLabel
|
|
1376
|
+
})
|
|
1377
|
+
});
|
|
1378
|
+
}
|
|
1379
|
+
function ServiceAvailability() {
|
|
1380
|
+
const theme = useTheme();
|
|
1381
|
+
const availabilityEvents = useMemo(() => [{
|
|
1382
|
+
date: new Date('2022-01-01'),
|
|
1383
|
+
availability: 79
|
|
1384
|
+
}, {
|
|
1385
|
+
date: new Date('2022-01-03'),
|
|
1386
|
+
availability: 81
|
|
1387
|
+
}, {
|
|
1388
|
+
date: new Date('2022-01-04'),
|
|
1389
|
+
availability: 82
|
|
1390
|
+
}, {
|
|
1391
|
+
date: new Date('2022-01-06'),
|
|
1392
|
+
availability: 91
|
|
1393
|
+
}, {
|
|
1394
|
+
date: new Date('2022-01-07'),
|
|
1395
|
+
availability: 92
|
|
1396
|
+
}, {
|
|
1397
|
+
date: new Date('2022-01-10'),
|
|
1398
|
+
availability: 86
|
|
1399
|
+
}], []);
|
|
1936
1400
|
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
1937
1401
|
enableScrubbing: true,
|
|
1938
|
-
height:
|
|
1939
|
-
onScrubberPositionChange: setScrubIndex,
|
|
1402
|
+
height: 200,
|
|
1940
1403
|
series: [{
|
|
1941
1404
|
id: 'availability',
|
|
1942
1405
|
data: availabilityEvents.map(event => event.availability),
|
|
1943
|
-
|
|
1406
|
+
gradient: {
|
|
1407
|
+
stops: _ref14 => {
|
|
1408
|
+
let {
|
|
1409
|
+
min,
|
|
1410
|
+
max
|
|
1411
|
+
} = _ref14;
|
|
1412
|
+
return [{
|
|
1413
|
+
offset: min,
|
|
1414
|
+
color: theme.color.fgNegative
|
|
1415
|
+
}, {
|
|
1416
|
+
offset: 85,
|
|
1417
|
+
color: theme.color.fgNegative
|
|
1418
|
+
}, {
|
|
1419
|
+
offset: 85,
|
|
1420
|
+
color: theme.color.fgWarning
|
|
1421
|
+
}, {
|
|
1422
|
+
offset: 90,
|
|
1423
|
+
color: theme.color.fgWarning
|
|
1424
|
+
}, {
|
|
1425
|
+
offset: 90,
|
|
1426
|
+
color: theme.color.fgPositive
|
|
1427
|
+
}, {
|
|
1428
|
+
offset: max,
|
|
1429
|
+
color: theme.color.fgPositive
|
|
1430
|
+
}];
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1944
1433
|
}],
|
|
1945
1434
|
xAxis: {
|
|
1946
1435
|
data: availabilityEvents.map(event => event.date.getTime())
|
|
1947
1436
|
},
|
|
1948
1437
|
yAxis: {
|
|
1949
|
-
domain:
|
|
1438
|
+
domain: _ref15 => {
|
|
1950
1439
|
let {
|
|
1951
1440
|
min,
|
|
1952
1441
|
max
|
|
1953
|
-
} =
|
|
1442
|
+
} = _ref15;
|
|
1954
1443
|
return {
|
|
1955
1444
|
min: Math.max(min - 2, 0),
|
|
1956
1445
|
max: Math.min(max + 2, 100)
|
|
1957
1446
|
};
|
|
1958
1447
|
}
|
|
1959
1448
|
},
|
|
1960
|
-
children: [/*#__PURE__*/_jsx(
|
|
1449
|
+
children: [/*#__PURE__*/_jsx(XAxis, {
|
|
1961
1450
|
showGrid: true,
|
|
1962
1451
|
showLine: true,
|
|
1963
1452
|
showTickMarks: true,
|
|
@@ -1970,279 +1459,490 @@ const AvailabilityChart = () => {
|
|
|
1970
1459
|
tickLabelFormatter: value => value + "%"
|
|
1971
1460
|
}), /*#__PURE__*/_jsx(Line, {
|
|
1972
1461
|
curve: "stepAfter",
|
|
1973
|
-
|
|
1462
|
+
points: props => _extends({}, props, {
|
|
1974
1463
|
fill: theme.color.bg,
|
|
1975
|
-
stroke:
|
|
1976
|
-
strokeWidth: 2
|
|
1464
|
+
stroke: props.fill
|
|
1977
1465
|
}),
|
|
1978
1466
|
seriesId: "availability"
|
|
1979
1467
|
}), /*#__PURE__*/_jsx(Scrubber, {
|
|
1980
|
-
|
|
1468
|
+
hideOverlay: true
|
|
1981
1469
|
})]
|
|
1982
1470
|
});
|
|
1983
|
-
}
|
|
1984
|
-
|
|
1985
|
-
const
|
|
1986
|
-
const
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1471
|
+
}
|
|
1472
|
+
function ForecastAssetPrice() {
|
|
1473
|
+
const startYear = 2020;
|
|
1474
|
+
const data = [50, 45, 47, 46, 54, 54, 60, 61, 63, 66, 70];
|
|
1475
|
+
const currentIndex = 6;
|
|
1476
|
+
const strokeWidth = 3;
|
|
1477
|
+
// To prevent cutting off the edge of our lines
|
|
1478
|
+
const clipOffset = strokeWidth;
|
|
1479
|
+
const axisFormatter = useCallback(dataIndex => {
|
|
1480
|
+
return "" + (startYear + dataIndex);
|
|
1481
|
+
}, [startYear]);
|
|
1482
|
+
const HistoricalLineComponent = /*#__PURE__*/memo(props => {
|
|
1483
|
+
const {
|
|
1484
|
+
drawingArea,
|
|
1485
|
+
getXScale
|
|
1486
|
+
} = useCartesianChartContext();
|
|
1487
|
+
const xScale = getXScale();
|
|
1488
|
+
const historicalClipPath = useMemo(() => {
|
|
1489
|
+
if (!xScale || !drawingArea) return null;
|
|
1490
|
+
const currentX = xScale(currentIndex);
|
|
1491
|
+
if (currentX === undefined) return null;
|
|
1492
|
+
|
|
1493
|
+
// Create clip path for historical data (left side)
|
|
1494
|
+
const clip = Skia.Path.Make();
|
|
1495
|
+
clip.addRect({
|
|
1496
|
+
x: drawingArea.x - clipOffset,
|
|
1497
|
+
y: drawingArea.y - clipOffset,
|
|
1498
|
+
width: currentX + clipOffset - drawingArea.x,
|
|
1499
|
+
height: drawingArea.height + clipOffset * 2
|
|
1500
|
+
});
|
|
1501
|
+
return clip;
|
|
1502
|
+
}, [xScale, drawingArea]);
|
|
1503
|
+
if (!historicalClipPath) return null;
|
|
1504
|
+
return /*#__PURE__*/_jsx(Group, {
|
|
1505
|
+
clip: historicalClipPath,
|
|
1506
|
+
children: /*#__PURE__*/_jsx(SolidLine, _extends({
|
|
1507
|
+
strokeWidth: strokeWidth
|
|
1508
|
+
}, props))
|
|
1509
|
+
});
|
|
1510
|
+
});
|
|
1511
|
+
|
|
1512
|
+
// Since the solid and dotted line have different curves,
|
|
1513
|
+
// we need two separate line components. Otherwise we could
|
|
1514
|
+
// have one line component with SolidLine and DottedLine inside
|
|
1515
|
+
// of it and two clipPaths.
|
|
1516
|
+
const ForecastLineComponent = /*#__PURE__*/memo(props => {
|
|
1517
|
+
const {
|
|
1518
|
+
drawingArea,
|
|
1519
|
+
getXScale
|
|
1520
|
+
} = useCartesianChartContext();
|
|
1521
|
+
const xScale = getXScale();
|
|
1522
|
+
const forecastClipPath = useMemo(() => {
|
|
1523
|
+
if (!xScale || !drawingArea) return null;
|
|
1524
|
+
const currentX = xScale(currentIndex);
|
|
1525
|
+
if (currentX === undefined) return null;
|
|
1526
|
+
|
|
1527
|
+
// Create clip path for forecast data (right side)
|
|
1528
|
+
const clip = Skia.Path.Make();
|
|
1529
|
+
clip.addRect({
|
|
1530
|
+
x: currentX,
|
|
1531
|
+
y: drawingArea.y - clipOffset,
|
|
1532
|
+
width: drawingArea.x + drawingArea.width - currentX + clipOffset * 2,
|
|
1533
|
+
height: drawingArea.height + clipOffset * 2
|
|
1534
|
+
});
|
|
1535
|
+
return clip;
|
|
1536
|
+
}, [xScale, drawingArea]);
|
|
1537
|
+
if (!forecastClipPath) return null;
|
|
1538
|
+
return /*#__PURE__*/_jsx(Group, {
|
|
1539
|
+
clip: forecastClipPath,
|
|
1540
|
+
children: /*#__PURE__*/_jsx(DottedLine, _extends({
|
|
1541
|
+
dashIntervals: [0, strokeWidth * 2],
|
|
1542
|
+
strokeWidth: strokeWidth
|
|
1543
|
+
}, props))
|
|
1544
|
+
});
|
|
1545
|
+
});
|
|
1546
|
+
const CustomScrubber = /*#__PURE__*/memo(() => {
|
|
1547
|
+
const {
|
|
1548
|
+
scrubberPosition
|
|
1549
|
+
} = useScrubberContext();
|
|
1550
|
+
const idleScrubberOpacity = useDerivedValue(() => scrubberPosition.value === undefined ? 1 : 0, [scrubberPosition]);
|
|
1551
|
+
const scrubberOpacity = useDerivedValue(() => scrubberPosition.value !== undefined ? 1 : 0, [scrubberPosition]);
|
|
1552
|
+
|
|
1553
|
+
// Fade in animation for the Scrubber
|
|
1554
|
+
const fadeInOpacity = useSharedValue(0);
|
|
1555
|
+
useEffect(() => {
|
|
1556
|
+
fadeInOpacity.value = withDelay(350, withTiming(1, {
|
|
1557
|
+
duration: 150
|
|
1558
|
+
}));
|
|
1559
|
+
}, [fadeInOpacity]);
|
|
1560
|
+
return /*#__PURE__*/_jsxs(Group, {
|
|
1561
|
+
opacity: fadeInOpacity,
|
|
1562
|
+
children: [/*#__PURE__*/_jsx(Group, {
|
|
1563
|
+
opacity: scrubberOpacity,
|
|
1564
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
1565
|
+
hideOverlay: true
|
|
1566
|
+
})
|
|
1567
|
+
}), /*#__PURE__*/_jsx(Group, {
|
|
1568
|
+
opacity: idleScrubberOpacity,
|
|
1569
|
+
children: /*#__PURE__*/_jsx(DefaultScrubberBeacon, {
|
|
1570
|
+
isIdle: true,
|
|
1571
|
+
dataX: currentIndex,
|
|
1572
|
+
dataY: data[currentIndex],
|
|
1573
|
+
seriesId: "price"
|
|
1574
|
+
})
|
|
1575
|
+
})]
|
|
1576
|
+
});
|
|
1577
|
+
});
|
|
1578
|
+
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
1579
|
+
enableScrubbing: true,
|
|
1580
|
+
height: 200,
|
|
1581
|
+
series: [{
|
|
1582
|
+
id: 'price',
|
|
1583
|
+
data,
|
|
1584
|
+
color: assets.btc.color
|
|
1585
|
+
}],
|
|
1586
|
+
children: [/*#__PURE__*/_jsx(Line, {
|
|
1587
|
+
LineComponent: HistoricalLineComponent,
|
|
1588
|
+
curve: "linear",
|
|
1589
|
+
seriesId: "price"
|
|
1590
|
+
}), /*#__PURE__*/_jsx(Line, {
|
|
1591
|
+
LineComponent: ForecastLineComponent,
|
|
1592
|
+
curve: "monotone",
|
|
1593
|
+
seriesId: "price",
|
|
1594
|
+
type: "dotted"
|
|
1595
|
+
}), /*#__PURE__*/_jsx(XAxis, {
|
|
1596
|
+
position: "bottom",
|
|
1597
|
+
requestedTickCount: 3,
|
|
1598
|
+
tickLabelFormatter: axisFormatter
|
|
1599
|
+
}), /*#__PURE__*/_jsx(CustomScrubber, {})]
|
|
1600
|
+
});
|
|
1601
|
+
}
|
|
1602
|
+
function DataCardWithLineChart() {
|
|
1603
|
+
const {
|
|
1604
|
+
spectrum
|
|
1605
|
+
} = useTheme();
|
|
1606
|
+
const exampleThumbnail = /*#__PURE__*/_jsx(RemoteImage, {
|
|
1607
|
+
accessibilityLabel: "Ethereum",
|
|
1608
|
+
shape: "circle",
|
|
1609
|
+
size: "xl",
|
|
1610
|
+
source: ethBackground,
|
|
1611
|
+
testID: "thumbnail"
|
|
1612
|
+
});
|
|
1613
|
+
const getLineChartSeries = useCallback(() => [{
|
|
1614
|
+
id: 'price',
|
|
1615
|
+
data: prices.slice(0, 30).map(price => parseFloat(price)),
|
|
1616
|
+
color: "rgb(" + spectrum.green70 + ")"
|
|
1617
|
+
}], [spectrum.green70]);
|
|
1618
|
+
const lineChartSeries = useMemo(() => getLineChartSeries(), [getLineChartSeries]);
|
|
1619
|
+
const lineChartSeries2 = useMemo(() => getLineChartSeries(), [getLineChartSeries]);
|
|
1620
|
+
const ref = useRef(null);
|
|
1621
|
+
return /*#__PURE__*/_jsxs(VStack, {
|
|
1622
|
+
gap: 2,
|
|
1623
|
+
children: [/*#__PURE__*/_jsx(DataCard, {
|
|
1624
|
+
layout: "vertical",
|
|
1625
|
+
subtitle: "Price trend",
|
|
1626
|
+
thumbnail: exampleThumbnail,
|
|
1627
|
+
title: "Line Chart Card",
|
|
1990
1628
|
children: /*#__PURE__*/_jsx(LineChart, {
|
|
1991
|
-
enableScrubbing: true,
|
|
1992
1629
|
showArea: true,
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
height:
|
|
1996
|
-
|
|
1997
|
-
|
|
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
|
-
})]
|
|
1630
|
+
accessibilityLabel: "Ethereum price chart",
|
|
1631
|
+
areaType: "dotted",
|
|
1632
|
+
height: 120,
|
|
1633
|
+
inset: 0,
|
|
1634
|
+
series: lineChartSeries
|
|
2088
1635
|
})
|
|
2089
|
-
}), /*#__PURE__*/_jsx(
|
|
2090
|
-
|
|
1636
|
+
}), /*#__PURE__*/_jsx(DataCard, {
|
|
1637
|
+
layout: "vertical",
|
|
1638
|
+
subtitle: "Price trend",
|
|
1639
|
+
thumbnail: exampleThumbnail,
|
|
1640
|
+
title: "Line Chart with Tag",
|
|
1641
|
+
titleAccessory: /*#__PURE__*/_jsx(Text, {
|
|
1642
|
+
dangerouslySetColor: "rgb(" + spectrum.green70 + ")",
|
|
1643
|
+
font: "label1",
|
|
1644
|
+
children: "\u2197 25.25%"
|
|
1645
|
+
}),
|
|
2091
1646
|
children: /*#__PURE__*/_jsx(LineChart, {
|
|
2092
|
-
enableScrubbing: true,
|
|
2093
1647
|
showArea: true,
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
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, {})
|
|
1648
|
+
accessibilityLabel: "Ethereum price chart",
|
|
1649
|
+
areaType: "dotted",
|
|
1650
|
+
height: 100,
|
|
1651
|
+
inset: 0,
|
|
1652
|
+
series: lineChartSeries
|
|
2119
1653
|
})
|
|
2120
|
-
}), /*#__PURE__*/_jsx(
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
title: "
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
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",
|
|
1654
|
+
}), /*#__PURE__*/_jsx(DataCard, {
|
|
1655
|
+
ref: ref,
|
|
1656
|
+
renderAsPressable: true,
|
|
1657
|
+
layout: "vertical",
|
|
1658
|
+
onPress: NoopFn,
|
|
1659
|
+
subtitle: "Clickable line chart card",
|
|
1660
|
+
thumbnail: exampleThumbnail,
|
|
1661
|
+
title: "Actionable Line Chart",
|
|
1662
|
+
titleAccessory: /*#__PURE__*/_jsx(Text, {
|
|
1663
|
+
dangerouslySetColor: "rgb(" + spectrum.green70 + ")",
|
|
1664
|
+
font: "label1",
|
|
1665
|
+
children: "\u2197 8.5%"
|
|
1666
|
+
}),
|
|
2163
1667
|
children: /*#__PURE__*/_jsx(LineChart, {
|
|
2164
|
-
enableScrubbing: true,
|
|
2165
1668
|
showArea: true,
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
height:
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
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
|
-
}]
|
|
1669
|
+
accessibilityLabel: "Ethereum price chart",
|
|
1670
|
+
areaType: "dotted",
|
|
1671
|
+
height: 120,
|
|
1672
|
+
inset: 0,
|
|
1673
|
+
series: lineChartSeries,
|
|
1674
|
+
showXAxis: false,
|
|
1675
|
+
showYAxis: false
|
|
2187
1676
|
})
|
|
2188
|
-
}), /*#__PURE__*/_jsx(
|
|
2189
|
-
|
|
1677
|
+
}), /*#__PURE__*/_jsx(DataCard, {
|
|
1678
|
+
layout: "vertical",
|
|
1679
|
+
subtitle: "Price trend",
|
|
1680
|
+
thumbnail: /*#__PURE__*/_jsx(RemoteImage, {
|
|
1681
|
+
accessibilityLabel: "Bitcoin",
|
|
1682
|
+
shape: "circle",
|
|
1683
|
+
size: "xl",
|
|
1684
|
+
source: assets.btc.imageUrl,
|
|
1685
|
+
testID: "thumbnail"
|
|
1686
|
+
}),
|
|
1687
|
+
title: "Card with Line Chart",
|
|
1688
|
+
titleAccessory: /*#__PURE__*/_jsx(Text, {
|
|
1689
|
+
dangerouslySetColor: "rgb(" + spectrum.green70 + ")",
|
|
1690
|
+
font: "label1",
|
|
1691
|
+
children: "\u2197 25.25%"
|
|
1692
|
+
}),
|
|
2190
1693
|
children: /*#__PURE__*/_jsx(LineChart, {
|
|
2191
|
-
enableScrubbing: true,
|
|
2192
1694
|
showArea: true,
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
series:
|
|
2198
|
-
|
|
2199
|
-
|
|
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, {})
|
|
1695
|
+
accessibilityLabel: "Price chart",
|
|
1696
|
+
areaType: "dotted",
|
|
1697
|
+
height: 100,
|
|
1698
|
+
inset: 0,
|
|
1699
|
+
series: lineChartSeries2,
|
|
1700
|
+
showXAxis: false,
|
|
1701
|
+
showYAxis: false
|
|
2217
1702
|
})
|
|
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
1703
|
})]
|
|
2246
1704
|
});
|
|
2247
|
-
}
|
|
2248
|
-
|
|
1705
|
+
}
|
|
1706
|
+
function ExampleNavigator() {
|
|
1707
|
+
const theme = useTheme();
|
|
1708
|
+
const [currentIndex, setCurrentIndex] = useState(0);
|
|
1709
|
+
const examples = useMemo(() => [{
|
|
1710
|
+
title: 'Basic',
|
|
1711
|
+
component: /*#__PURE__*/_jsx(LineChart, {
|
|
1712
|
+
showArea: true,
|
|
1713
|
+
height: 200,
|
|
1714
|
+
series: [{
|
|
1715
|
+
id: 'prices',
|
|
1716
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
|
|
1717
|
+
}]
|
|
1718
|
+
})
|
|
1719
|
+
}, {
|
|
1720
|
+
title: 'Multiple Lines',
|
|
1721
|
+
component: /*#__PURE__*/_jsx(MultipleLine, {})
|
|
1722
|
+
}, {
|
|
1723
|
+
title: 'Data Format',
|
|
1724
|
+
component: /*#__PURE__*/_jsx(DataFormat, {})
|
|
1725
|
+
}, {
|
|
1726
|
+
title: 'Live Updates',
|
|
1727
|
+
component: /*#__PURE__*/_jsx(LiveUpdates, {})
|
|
1728
|
+
}, {
|
|
1729
|
+
title: 'Missing Data',
|
|
1730
|
+
component: /*#__PURE__*/_jsx(MissingData, {})
|
|
1731
|
+
}, {
|
|
1732
|
+
title: 'Empty State',
|
|
1733
|
+
component: /*#__PURE__*/_jsx(LineChart, {
|
|
1734
|
+
height: 200,
|
|
1735
|
+
series: [{
|
|
1736
|
+
id: 'line',
|
|
1737
|
+
color: "rgb(" + theme.spectrum.gray50 + ")",
|
|
1738
|
+
data: [1, 1],
|
|
1739
|
+
showArea: true
|
|
1740
|
+
}],
|
|
1741
|
+
yAxis: {
|
|
1742
|
+
domain: {
|
|
1743
|
+
min: -1,
|
|
1744
|
+
max: 3
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
})
|
|
1748
|
+
}, {
|
|
1749
|
+
title: 'Scales',
|
|
1750
|
+
component: /*#__PURE__*/_jsx(LineChart, {
|
|
1751
|
+
showArea: true,
|
|
1752
|
+
showYAxis: true,
|
|
1753
|
+
height: 200,
|
|
1754
|
+
series: [{
|
|
1755
|
+
id: 'prices',
|
|
1756
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
|
|
1757
|
+
}],
|
|
1758
|
+
yAxis: {
|
|
1759
|
+
scaleType: 'log',
|
|
1760
|
+
showGrid: true,
|
|
1761
|
+
ticks: [1, 10, 100]
|
|
1762
|
+
}
|
|
1763
|
+
})
|
|
1764
|
+
}, {
|
|
1765
|
+
title: 'Interaction',
|
|
1766
|
+
component: /*#__PURE__*/_jsx(Interaction, {})
|
|
1767
|
+
}, {
|
|
1768
|
+
title: 'Points',
|
|
1769
|
+
component: /*#__PURE__*/_jsx(Points, {})
|
|
1770
|
+
}, {
|
|
1771
|
+
title: 'Transitions',
|
|
1772
|
+
component: /*#__PURE__*/_jsx(Transitions, {})
|
|
1773
|
+
}, {
|
|
1774
|
+
title: 'Basic Accessible',
|
|
1775
|
+
component: /*#__PURE__*/_jsx(BasicAccessible, {})
|
|
1776
|
+
}, {
|
|
1777
|
+
title: 'Styling Axes',
|
|
1778
|
+
component: /*#__PURE__*/_jsx(LineChart, {
|
|
1779
|
+
showArea: true,
|
|
1780
|
+
showXAxis: true,
|
|
1781
|
+
showYAxis: true,
|
|
1782
|
+
height: 200,
|
|
1783
|
+
series: [{
|
|
1784
|
+
id: 'prices',
|
|
1785
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
|
|
1786
|
+
}],
|
|
1787
|
+
xAxis: {
|
|
1788
|
+
showGrid: true,
|
|
1789
|
+
showLine: true,
|
|
1790
|
+
showTickMarks: true,
|
|
1791
|
+
tickLabelFormatter: dataX => "Day " + dataX
|
|
1792
|
+
},
|
|
1793
|
+
yAxis: {
|
|
1794
|
+
showGrid: true,
|
|
1795
|
+
showLine: true,
|
|
1796
|
+
showTickMarks: true
|
|
1797
|
+
}
|
|
1798
|
+
})
|
|
1799
|
+
}, {
|
|
1800
|
+
title: 'Gradients',
|
|
1801
|
+
component: /*#__PURE__*/_jsx(Gradients, {})
|
|
1802
|
+
}, {
|
|
1803
|
+
title: 'Gain/Loss',
|
|
1804
|
+
component: /*#__PURE__*/_jsx(GainLossChart, {})
|
|
1805
|
+
}, {
|
|
1806
|
+
title: 'Styling Lines',
|
|
1807
|
+
component: /*#__PURE__*/_jsx(LineChart, {
|
|
1808
|
+
height: 200,
|
|
1809
|
+
series: [{
|
|
1810
|
+
id: 'top',
|
|
1811
|
+
data: [15, 28, 32, 44, 46, 36, 40, 45, 48, 38]
|
|
1812
|
+
}, {
|
|
1813
|
+
id: 'upperMiddle',
|
|
1814
|
+
data: [12, 23, 21, 29, 34, 28, 31, 38, 42, 35],
|
|
1815
|
+
color: '#ef4444',
|
|
1816
|
+
type: 'dotted'
|
|
1817
|
+
}, {
|
|
1818
|
+
id: 'lowerMiddle',
|
|
1819
|
+
data: [8, 15, 14, 25, 20, 18, 22, 28, 24, 30],
|
|
1820
|
+
color: '#f59e0b',
|
|
1821
|
+
curve: 'natural',
|
|
1822
|
+
gradient: {
|
|
1823
|
+
axis: 'x',
|
|
1824
|
+
stops: [{
|
|
1825
|
+
offset: 0,
|
|
1826
|
+
color: '#E3D74D'
|
|
1827
|
+
}, {
|
|
1828
|
+
offset: 9,
|
|
1829
|
+
color: '#F7931A'
|
|
1830
|
+
}]
|
|
1831
|
+
},
|
|
1832
|
+
strokeWidth: 6
|
|
1833
|
+
}, {
|
|
1834
|
+
id: 'bottom',
|
|
1835
|
+
data: [4, 8, 11, 15, 16, 14, 16, 10, 12, 14],
|
|
1836
|
+
color: '#800080',
|
|
1837
|
+
curve: 'step',
|
|
1838
|
+
AreaComponent: DottedArea,
|
|
1839
|
+
showArea: true
|
|
1840
|
+
}]
|
|
1841
|
+
})
|
|
1842
|
+
}, {
|
|
1843
|
+
title: 'Styling Reference Lines',
|
|
1844
|
+
component: /*#__PURE__*/_jsxs(LineChart, {
|
|
1845
|
+
enableScrubbing: true,
|
|
1846
|
+
showArea: true,
|
|
1847
|
+
height: 200,
|
|
1848
|
+
series: [{
|
|
1849
|
+
id: 'prices',
|
|
1850
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
1851
|
+
color: theme.color.fgPositive
|
|
1852
|
+
}],
|
|
1853
|
+
xAxis: {
|
|
1854
|
+
// Give space before the end of the chart for the scrubber
|
|
1855
|
+
range: _ref16 => {
|
|
1856
|
+
let {
|
|
1857
|
+
min,
|
|
1858
|
+
max
|
|
1859
|
+
} = _ref16;
|
|
1860
|
+
return {
|
|
1861
|
+
min,
|
|
1862
|
+
max: max - 24
|
|
1863
|
+
};
|
|
1864
|
+
}
|
|
1865
|
+
},
|
|
1866
|
+
children: [/*#__PURE__*/_jsx(ReferenceLine, {
|
|
1867
|
+
LineComponent: props => /*#__PURE__*/_jsx(DottedLine, _extends({}, props, {
|
|
1868
|
+
dashIntervals: [0, 16],
|
|
1869
|
+
strokeWidth: 3
|
|
1870
|
+
})),
|
|
1871
|
+
dataY: 10,
|
|
1872
|
+
stroke: theme.color.fg
|
|
1873
|
+
}), /*#__PURE__*/_jsx(Scrubber, {})]
|
|
1874
|
+
})
|
|
1875
|
+
}, {
|
|
1876
|
+
title: 'High/Low Price',
|
|
1877
|
+
component: /*#__PURE__*/_jsx(HighLowPrice, {})
|
|
1878
|
+
}, {
|
|
1879
|
+
title: 'Styling Scrubber',
|
|
1880
|
+
component: /*#__PURE__*/_jsx(StylingScrubber, {})
|
|
1881
|
+
}, {
|
|
1882
|
+
title: 'Compact',
|
|
1883
|
+
component: /*#__PURE__*/_jsx(Compact, {})
|
|
1884
|
+
}, {
|
|
1885
|
+
title: 'Asset Price With Dotted Area',
|
|
1886
|
+
component: /*#__PURE__*/_jsx(AssetPriceWithDottedArea, {})
|
|
1887
|
+
}, {
|
|
1888
|
+
title: 'Performance',
|
|
1889
|
+
component: /*#__PURE__*/_jsx(Performance, {})
|
|
1890
|
+
}, {
|
|
1891
|
+
title: 'Monotone Asset Price',
|
|
1892
|
+
component: /*#__PURE__*/_jsx(MonotoneAssetPrice, {})
|
|
1893
|
+
}, {
|
|
1894
|
+
title: 'Service Availability',
|
|
1895
|
+
component: /*#__PURE__*/_jsx(ServiceAvailability, {})
|
|
1896
|
+
}, {
|
|
1897
|
+
title: 'Forecast Asset Price',
|
|
1898
|
+
component: /*#__PURE__*/_jsx(ForecastAssetPrice, {})
|
|
1899
|
+
}, {
|
|
1900
|
+
title: 'In DataCard',
|
|
1901
|
+
component: /*#__PURE__*/_jsx(DataCardWithLineChart, {})
|
|
1902
|
+
}], [theme.color.fg, theme.color.fgPositive, theme.spectrum.gray50]);
|
|
1903
|
+
const currentExample = examples[currentIndex];
|
|
1904
|
+
const handlePrevious = useCallback(() => {
|
|
1905
|
+
setCurrentIndex(prev => (prev - 1 + examples.length) % examples.length);
|
|
1906
|
+
}, [examples.length]);
|
|
1907
|
+
const handleNext = useCallback(() => {
|
|
1908
|
+
setCurrentIndex(prev => (prev + 1 + examples.length) % examples.length);
|
|
1909
|
+
}, [examples.length]);
|
|
1910
|
+
return /*#__PURE__*/_jsx(ExampleScreen, {
|
|
1911
|
+
paddingX: 0,
|
|
1912
|
+
children: /*#__PURE__*/_jsxs(VStack, {
|
|
1913
|
+
gap: 4,
|
|
1914
|
+
children: [/*#__PURE__*/_jsxs(HStack, {
|
|
1915
|
+
alignItems: "center",
|
|
1916
|
+
justifyContent: "space-between",
|
|
1917
|
+
padding: 2,
|
|
1918
|
+
children: [/*#__PURE__*/_jsx(IconButton, {
|
|
1919
|
+
accessibilityHint: "Navigate to previous example",
|
|
1920
|
+
accessibilityLabel: "Previous",
|
|
1921
|
+
name: "arrowLeft",
|
|
1922
|
+
onPress: handlePrevious,
|
|
1923
|
+
variant: "secondary"
|
|
1924
|
+
}), /*#__PURE__*/_jsxs(VStack, {
|
|
1925
|
+
alignItems: "center",
|
|
1926
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
1927
|
+
font: "title3",
|
|
1928
|
+
children: currentExample.title
|
|
1929
|
+
}), /*#__PURE__*/_jsxs(Text, {
|
|
1930
|
+
color: "fgMuted",
|
|
1931
|
+
font: "label1",
|
|
1932
|
+
children: [currentIndex + 1, " / ", examples.length]
|
|
1933
|
+
})]
|
|
1934
|
+
}), /*#__PURE__*/_jsx(IconButton, {
|
|
1935
|
+
accessibilityHint: "Navigate to next example",
|
|
1936
|
+
accessibilityLabel: "Next",
|
|
1937
|
+
name: "arrowRight",
|
|
1938
|
+
onPress: handleNext,
|
|
1939
|
+
variant: "secondary"
|
|
1940
|
+
})]
|
|
1941
|
+
}), /*#__PURE__*/_jsx(Box, {
|
|
1942
|
+
padding: 1,
|
|
1943
|
+
children: currentExample.component
|
|
1944
|
+
})]
|
|
1945
|
+
})
|
|
1946
|
+
});
|
|
1947
|
+
}
|
|
1948
|
+
export default ExampleNavigator;
|