@coinbase/cds-mobile-visualization 3.4.0-beta.17 → 3.4.0-beta.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dts/chart/Path.d.ts +35 -13
- package/dts/chart/Path.d.ts.map +1 -1
- package/dts/chart/area/Area.d.ts +7 -11
- package/dts/chart/area/Area.d.ts.map +1 -1
- package/dts/chart/area/AreaChart.d.ts +1 -1
- package/dts/chart/area/DottedArea.d.ts.map +1 -1
- package/dts/chart/area/GradientArea.d.ts.map +1 -1
- package/dts/chart/area/SolidArea.d.ts.map +1 -1
- package/dts/chart/bar/Bar.d.ts +32 -2
- package/dts/chart/bar/Bar.d.ts.map +1 -1
- package/dts/chart/bar/BarChart.d.ts +2 -0
- package/dts/chart/bar/BarChart.d.ts.map +1 -1
- package/dts/chart/bar/BarPlot.d.ts +2 -1
- package/dts/chart/bar/BarPlot.d.ts.map +1 -1
- package/dts/chart/bar/BarStack.d.ts +5 -10
- package/dts/chart/bar/BarStack.d.ts.map +1 -1
- package/dts/chart/bar/BarStackGroup.d.ts +1 -0
- package/dts/chart/bar/BarStackGroup.d.ts.map +1 -1
- package/dts/chart/bar/DefaultBar.d.ts.map +1 -1
- package/dts/chart/bar/DefaultBarStack.d.ts.map +1 -1
- package/dts/chart/line/DottedLine.d.ts.map +1 -1
- package/dts/chart/line/Line.d.ts +4 -9
- package/dts/chart/line/Line.d.ts.map +1 -1
- package/dts/chart/line/LineChart.d.ts +1 -1
- package/dts/chart/line/SolidLine.d.ts.map +1 -1
- package/dts/chart/point/Point.d.ts +18 -2
- package/dts/chart/point/Point.d.ts.map +1 -1
- package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts +9 -1
- package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts.map +1 -1
- package/dts/chart/scrubber/Scrubber.d.ts +45 -24
- package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
- package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts +9 -1
- package/dts/chart/scrubber/ScrubberBeaconLabelGroup.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/path.d.ts +6 -0
- package/dts/chart/utils/path.d.ts.map +1 -1
- package/dts/chart/utils/transition.d.ts +59 -21
- package/dts/chart/utils/transition.d.ts.map +1 -1
- package/esm/chart/Path.js +18 -17
- package/esm/chart/__stories__/CartesianChart.stories.js +3 -77
- package/esm/chart/__stories__/ChartTransitions.stories.js +629 -0
- package/esm/chart/area/Area.js +2 -0
- package/esm/chart/area/DottedArea.js +7 -3
- package/esm/chart/area/GradientArea.js +4 -2
- package/esm/chart/area/SolidArea.js +4 -2
- package/esm/chart/bar/Bar.js +2 -0
- package/esm/chart/bar/BarChart.js +4 -2
- package/esm/chart/bar/BarPlot.js +2 -0
- package/esm/chart/bar/BarStack.js +3 -0
- package/esm/chart/bar/DefaultBar.js +15 -15
- package/esm/chart/bar/DefaultBarStack.js +14 -3
- package/esm/chart/bar/__stories__/BarChart.stories.js +448 -52
- package/esm/chart/line/DottedLine.js +4 -2
- package/esm/chart/line/Line.js +6 -17
- package/esm/chart/line/SolidLine.js +4 -2
- package/esm/chart/line/__stories__/LineChart.stories.js +130 -235
- package/esm/chart/line/__stories__/ReferenceLine.stories.js +95 -1
- package/esm/chart/point/Point.js +33 -35
- package/esm/chart/scrubber/DefaultScrubberBeacon.js +2 -5
- package/esm/chart/scrubber/Scrubber.js +15 -14
- package/esm/chart/scrubber/ScrubberBeaconLabelGroup.js +29 -7
- package/esm/chart/utils/bar.js +43 -0
- package/esm/chart/utils/path.js +8 -0
- package/esm/chart/utils/transition.js +96 -61
- package/package.json +5 -5
- package/esm/chart/__stories__/Chart.stories.js +0 -77
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
const _excluded = ["dataX", "dataY"],
|
|
2
2
|
_excluded2 = ["label"],
|
|
3
|
-
_excluded3 = ["style"]
|
|
4
|
-
_excluded4 = ["x", "y", "width", "height", "originY", "dataX"];
|
|
3
|
+
_excluded3 = ["style"];
|
|
5
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); }
|
|
6
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; }
|
|
7
|
-
import { forwardRef, memo, useCallback, useEffect,
|
|
6
|
+
import { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
8
7
|
import { useAnimatedReaction, useDerivedValue, useSharedValue, withDelay, withTiming } from 'react-native-reanimated';
|
|
9
|
-
import { assets } from '@coinbase/cds-common/internal/data/assets';
|
|
10
|
-
import { candles as btcCandles } from '@coinbase/cds-common/internal/data/candles';
|
|
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';
|
|
14
|
+
import { DataCard } from '@coinbase/cds-mobile/alpha/data-card/DataCard';
|
|
15
15
|
import { IconButton } from '@coinbase/cds-mobile/buttons';
|
|
16
16
|
import { ListCell } from '@coinbase/cds-mobile/cells';
|
|
17
17
|
import { ExampleScreen } from '@coinbase/cds-mobile/examples/ExampleScreen';
|
|
@@ -21,16 +21,15 @@ import { SectionHeader } from '@coinbase/cds-mobile/section-header/SectionHeader
|
|
|
21
21
|
import { Pressable } from '@coinbase/cds-mobile/system';
|
|
22
22
|
import { SegmentedTab } from '@coinbase/cds-mobile/tabs/SegmentedTab';
|
|
23
23
|
import { Text } from '@coinbase/cds-mobile/typography';
|
|
24
|
-
import { Circle, FontWeight, Group,
|
|
24
|
+
import { Circle, FontWeight, Group, Skia, TextAlign } from '@shopify/react-native-skia';
|
|
25
25
|
import { Area, DottedArea } from '../../area';
|
|
26
26
|
import { DefaultAxisTickLabel, XAxis, YAxis } from '../../axis';
|
|
27
|
-
import { BarPlot } from '../../bar';
|
|
28
27
|
import { CartesianChart } from '../../CartesianChart';
|
|
29
28
|
import { useCartesianChartContext } from '../../ChartProvider';
|
|
30
29
|
import { PeriodSelector, PeriodSelectorActiveIndicator } from '../../PeriodSelector';
|
|
31
30
|
import { Point } from '../../point';
|
|
32
31
|
import { DefaultScrubberBeacon, Scrubber } from '../../scrubber';
|
|
33
|
-
import { buildTransition, defaultTransition,
|
|
32
|
+
import { buildTransition, defaultTransition, projectPointWithSerializableScale, unwrapAnimatedValue, useScrubberContext } from '../../utils';
|
|
34
33
|
import { DottedLine, Line, LineChart, ReferenceLine, SolidLine } from '..';
|
|
35
34
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
36
35
|
function MultipleLine() {
|
|
@@ -1178,210 +1177,6 @@ function Performance() {
|
|
|
1178
1177
|
})]
|
|
1179
1178
|
});
|
|
1180
1179
|
}
|
|
1181
|
-
const candlestickStockData = btcCandles.slice(0, 90).reverse();
|
|
1182
|
-
const CandlesticksHeader = /*#__PURE__*/memo(_ref11 => {
|
|
1183
|
-
let {
|
|
1184
|
-
currentIndex
|
|
1185
|
-
} = _ref11;
|
|
1186
|
-
const formatPrice = useCallback(price => {
|
|
1187
|
-
return new Intl.NumberFormat('en-US', {
|
|
1188
|
-
style: 'currency',
|
|
1189
|
-
currency: 'USD'
|
|
1190
|
-
}).format(parseFloat(price));
|
|
1191
|
-
}, []);
|
|
1192
|
-
const formatThousandsPriceNumber = useCallback(price => {
|
|
1193
|
-
const formattedPrice = new Intl.NumberFormat('en-US', {
|
|
1194
|
-
style: 'currency',
|
|
1195
|
-
currency: 'USD',
|
|
1196
|
-
minimumFractionDigits: 0,
|
|
1197
|
-
maximumFractionDigits: 0
|
|
1198
|
-
}).format(price / 1000);
|
|
1199
|
-
return formattedPrice + "k";
|
|
1200
|
-
}, []);
|
|
1201
|
-
const currentText = useMemo(() => {
|
|
1202
|
-
if (currentIndex !== undefined) {
|
|
1203
|
-
return "Open: " + formatThousandsPriceNumber(parseFloat(candlestickStockData[currentIndex].open)) + ", Close: " + formatThousandsPriceNumber(parseFloat(candlestickStockData[currentIndex].close)) + ", Volume: " + (parseFloat(candlestickStockData[currentIndex].volume) / 1000).toFixed(2) + "k";
|
|
1204
|
-
}
|
|
1205
|
-
return formatPrice(candlestickStockData[candlestickStockData.length - 1].close);
|
|
1206
|
-
}, [currentIndex, formatThousandsPriceNumber, formatPrice]);
|
|
1207
|
-
return /*#__PURE__*/_jsx(Text, {
|
|
1208
|
-
"aria-live": "polite",
|
|
1209
|
-
font: "headline",
|
|
1210
|
-
children: currentText
|
|
1211
|
-
});
|
|
1212
|
-
});
|
|
1213
|
-
const CandlesticksChart = /*#__PURE__*/memo(_ref12 => {
|
|
1214
|
-
let {
|
|
1215
|
-
infoTextId,
|
|
1216
|
-
onScrubberPositionChange
|
|
1217
|
-
} = _ref12;
|
|
1218
|
-
const theme = useTheme();
|
|
1219
|
-
const min = useMemo(() => Math.min(...candlestickStockData.map(data => parseFloat(data.low))), []);
|
|
1220
|
-
const ThinSolidLine = /*#__PURE__*/memo(props => /*#__PURE__*/_jsx(SolidLine, _extends({}, props, {
|
|
1221
|
-
strokeWidth: 1
|
|
1222
|
-
})));
|
|
1223
|
-
|
|
1224
|
-
// Custom line component that renders a rect to highlight the entire bandwidth
|
|
1225
|
-
const BandwidthHighlight = /*#__PURE__*/memo(_ref13 => {
|
|
1226
|
-
let {
|
|
1227
|
-
stroke
|
|
1228
|
-
} = _ref13;
|
|
1229
|
-
const {
|
|
1230
|
-
getXSerializableScale,
|
|
1231
|
-
drawingArea
|
|
1232
|
-
} = useCartesianChartContext();
|
|
1233
|
-
const {
|
|
1234
|
-
scrubberPosition
|
|
1235
|
-
} = useScrubberContext();
|
|
1236
|
-
const xScale = useMemo(() => getXSerializableScale(), [getXSerializableScale]);
|
|
1237
|
-
const rectWidth = useMemo(() => {
|
|
1238
|
-
if (xScale !== undefined && xScale.type === 'band') {
|
|
1239
|
-
return xScale.bandwidth;
|
|
1240
|
-
}
|
|
1241
|
-
return 0;
|
|
1242
|
-
}, [xScale]);
|
|
1243
|
-
const xPos = useDerivedValue(() => {
|
|
1244
|
-
const position = unwrapAnimatedValue(scrubberPosition);
|
|
1245
|
-
const xPos = position !== undefined && xScale ? getPointOnSerializableScale(position, xScale) : undefined;
|
|
1246
|
-
return xPos !== undefined ? xPos - rectWidth / 2 : 0;
|
|
1247
|
-
}, [scrubberPosition, xScale]);
|
|
1248
|
-
const opacity = useDerivedValue(() => xPos.value !== undefined ? 1 : 0, [xPos]);
|
|
1249
|
-
return /*#__PURE__*/_jsx(Rect, {
|
|
1250
|
-
color: stroke,
|
|
1251
|
-
height: drawingArea.height,
|
|
1252
|
-
opacity: opacity,
|
|
1253
|
-
width: rectWidth,
|
|
1254
|
-
x: xPos,
|
|
1255
|
-
y: drawingArea.y
|
|
1256
|
-
});
|
|
1257
|
-
});
|
|
1258
|
-
const candlesData = useMemo(() => candlestickStockData.map(data => [parseFloat(data.low), parseFloat(data.high)]), []);
|
|
1259
|
-
const CandlestickBarComponent = /*#__PURE__*/memo(_ref14 => {
|
|
1260
|
-
var _yScale, _yScale2;
|
|
1261
|
-
let {
|
|
1262
|
-
x,
|
|
1263
|
-
y,
|
|
1264
|
-
width,
|
|
1265
|
-
height,
|
|
1266
|
-
dataX
|
|
1267
|
-
} = _ref14,
|
|
1268
|
-
props = _objectWithoutPropertiesLoose(_ref14, _excluded4);
|
|
1269
|
-
const {
|
|
1270
|
-
getYScale
|
|
1271
|
-
} = useCartesianChartContext();
|
|
1272
|
-
const yScale = getYScale();
|
|
1273
|
-
const wickX = x + width / 2;
|
|
1274
|
-
const timePeriodValue = candlestickStockData[dataX];
|
|
1275
|
-
const open = parseFloat(timePeriodValue.open);
|
|
1276
|
-
const close = parseFloat(timePeriodValue.close);
|
|
1277
|
-
const bullish = open < close;
|
|
1278
|
-
const theme = useTheme();
|
|
1279
|
-
const color = bullish ? theme.color.fgPositive : theme.color.fgNegative;
|
|
1280
|
-
const openY = (_yScale = yScale == null ? void 0 : yScale(open)) != null ? _yScale : 0;
|
|
1281
|
-
const closeY = (_yScale2 = yScale == null ? void 0 : yScale(close)) != null ? _yScale2 : 0;
|
|
1282
|
-
const bodyHeight = Math.abs(openY - closeY);
|
|
1283
|
-
const bodyY = openY < closeY ? openY : closeY;
|
|
1284
|
-
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
1285
|
-
children: [/*#__PURE__*/_jsx(SkiaLine, {
|
|
1286
|
-
color: color,
|
|
1287
|
-
p1: {
|
|
1288
|
-
x: wickX,
|
|
1289
|
-
y
|
|
1290
|
-
},
|
|
1291
|
-
p2: {
|
|
1292
|
-
x: wickX,
|
|
1293
|
-
y: y + height
|
|
1294
|
-
},
|
|
1295
|
-
strokeWidth: 1
|
|
1296
|
-
}), /*#__PURE__*/_jsx(Rect, {
|
|
1297
|
-
color: color,
|
|
1298
|
-
height: bodyHeight,
|
|
1299
|
-
width: width,
|
|
1300
|
-
x: x,
|
|
1301
|
-
y: bodyY
|
|
1302
|
-
})]
|
|
1303
|
-
});
|
|
1304
|
-
});
|
|
1305
|
-
const formatThousandsPriceNumber = useCallback(price => {
|
|
1306
|
-
const formattedPrice = new Intl.NumberFormat('en-US', {
|
|
1307
|
-
style: 'currency',
|
|
1308
|
-
currency: 'USD',
|
|
1309
|
-
minimumFractionDigits: 0,
|
|
1310
|
-
maximumFractionDigits: 0
|
|
1311
|
-
}).format(price / 1000);
|
|
1312
|
-
return formattedPrice + "k";
|
|
1313
|
-
}, []);
|
|
1314
|
-
const formatTime = useCallback(index => {
|
|
1315
|
-
if (index === null || index === undefined || index >= candlestickStockData.length) return '';
|
|
1316
|
-
const ts = parseInt(candlestickStockData[index].start);
|
|
1317
|
-
return new Date(ts * 1000).toLocaleDateString('en-US', {
|
|
1318
|
-
month: 'short',
|
|
1319
|
-
day: 'numeric'
|
|
1320
|
-
});
|
|
1321
|
-
}, []);
|
|
1322
|
-
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
1323
|
-
enableScrubbing: true,
|
|
1324
|
-
animate: false,
|
|
1325
|
-
"aria-labelledby": infoTextId,
|
|
1326
|
-
borderRadius: 0,
|
|
1327
|
-
height: 150,
|
|
1328
|
-
inset: {
|
|
1329
|
-
top: 8,
|
|
1330
|
-
bottom: 8,
|
|
1331
|
-
left: 0,
|
|
1332
|
-
right: 0
|
|
1333
|
-
},
|
|
1334
|
-
onScrubberPositionChange: onScrubberPositionChange,
|
|
1335
|
-
series: [{
|
|
1336
|
-
id: 'stock-prices',
|
|
1337
|
-
data: candlesData
|
|
1338
|
-
}],
|
|
1339
|
-
xAxis: {
|
|
1340
|
-
scaleType: 'band'
|
|
1341
|
-
},
|
|
1342
|
-
yAxis: {
|
|
1343
|
-
domain: {
|
|
1344
|
-
min
|
|
1345
|
-
}
|
|
1346
|
-
},
|
|
1347
|
-
children: [/*#__PURE__*/_jsx(XAxis, {
|
|
1348
|
-
tickLabelFormatter: formatTime
|
|
1349
|
-
}), /*#__PURE__*/_jsx(YAxis, {
|
|
1350
|
-
showGrid: true,
|
|
1351
|
-
GridLineComponent: ThinSolidLine,
|
|
1352
|
-
tickLabelFormatter: formatThousandsPriceNumber,
|
|
1353
|
-
width: 40
|
|
1354
|
-
}), /*#__PURE__*/_jsx(Scrubber, {
|
|
1355
|
-
hideOverlay: true,
|
|
1356
|
-
LineComponent: BandwidthHighlight,
|
|
1357
|
-
lineStroke: theme.color.fgMuted,
|
|
1358
|
-
seriesIds: []
|
|
1359
|
-
}), /*#__PURE__*/_jsx(BarPlot, {
|
|
1360
|
-
BarComponent: CandlestickBarComponent,
|
|
1361
|
-
BarStackComponent: _ref15 => {
|
|
1362
|
-
let {
|
|
1363
|
-
children
|
|
1364
|
-
} = _ref15;
|
|
1365
|
-
return /*#__PURE__*/_jsx("g", {
|
|
1366
|
-
children: children
|
|
1367
|
-
});
|
|
1368
|
-
}
|
|
1369
|
-
})]
|
|
1370
|
-
});
|
|
1371
|
-
});
|
|
1372
|
-
function Candlesticks() {
|
|
1373
|
-
const infoTextId = useId();
|
|
1374
|
-
const [currentIndex, setCurrentIndex] = useState();
|
|
1375
|
-
return /*#__PURE__*/_jsxs(VStack, {
|
|
1376
|
-
gap: 2,
|
|
1377
|
-
children: [/*#__PURE__*/_jsx(CandlesticksHeader, {
|
|
1378
|
-
currentIndex: currentIndex
|
|
1379
|
-
}), /*#__PURE__*/_jsx(CandlesticksChart, {
|
|
1380
|
-
infoTextId: infoTextId,
|
|
1381
|
-
onScrubberPositionChange: setCurrentIndex
|
|
1382
|
-
})]
|
|
1383
|
-
});
|
|
1384
|
-
}
|
|
1385
1180
|
function MonotoneAssetPrice() {
|
|
1386
1181
|
const theme = useTheme();
|
|
1387
1182
|
const prices = sparklineInteractiveData.hour;
|
|
@@ -1455,14 +1250,14 @@ function MonotoneAssetPrice() {
|
|
|
1455
1250
|
dy: -12,
|
|
1456
1251
|
horizontalAlignment: "left"
|
|
1457
1252
|
})), []);
|
|
1458
|
-
const CustomScrubberBeacon = /*#__PURE__*/memo(
|
|
1253
|
+
const CustomScrubberBeacon = /*#__PURE__*/memo(_ref11 => {
|
|
1459
1254
|
let {
|
|
1460
1255
|
dataX,
|
|
1461
1256
|
dataY,
|
|
1462
1257
|
seriesId,
|
|
1463
1258
|
isIdle,
|
|
1464
1259
|
animate = true
|
|
1465
|
-
} =
|
|
1260
|
+
} = _ref11;
|
|
1466
1261
|
const {
|
|
1467
1262
|
getSeries,
|
|
1468
1263
|
getXSerializableScale,
|
|
@@ -1538,10 +1333,10 @@ function MonotoneAssetPrice() {
|
|
|
1538
1333
|
color: theme.color.fg,
|
|
1539
1334
|
gradient: {
|
|
1540
1335
|
axis: 'x',
|
|
1541
|
-
stops:
|
|
1336
|
+
stops: _ref12 => {
|
|
1542
1337
|
let {
|
|
1543
1338
|
min
|
|
1544
|
-
} =
|
|
1339
|
+
} = _ref12;
|
|
1545
1340
|
return [{
|
|
1546
1341
|
offset: min,
|
|
1547
1342
|
color: theme.color.fg,
|
|
@@ -1555,10 +1350,10 @@ function MonotoneAssetPrice() {
|
|
|
1555
1350
|
}
|
|
1556
1351
|
}],
|
|
1557
1352
|
xAxis: {
|
|
1558
|
-
range:
|
|
1353
|
+
range: _ref13 => {
|
|
1559
1354
|
let {
|
|
1560
1355
|
max
|
|
1561
|
-
} =
|
|
1356
|
+
} = _ref13;
|
|
1562
1357
|
return {
|
|
1563
1358
|
min: 96,
|
|
1564
1359
|
max
|
|
@@ -1609,11 +1404,11 @@ function ServiceAvailability() {
|
|
|
1609
1404
|
id: 'availability',
|
|
1610
1405
|
data: availabilityEvents.map(event => event.availability),
|
|
1611
1406
|
gradient: {
|
|
1612
|
-
stops:
|
|
1407
|
+
stops: _ref14 => {
|
|
1613
1408
|
let {
|
|
1614
1409
|
min,
|
|
1615
1410
|
max
|
|
1616
|
-
} =
|
|
1411
|
+
} = _ref14;
|
|
1617
1412
|
return [{
|
|
1618
1413
|
offset: min,
|
|
1619
1414
|
color: theme.color.fgNegative
|
|
@@ -1640,11 +1435,11 @@ function ServiceAvailability() {
|
|
|
1640
1435
|
data: availabilityEvents.map(event => event.date.getTime())
|
|
1641
1436
|
},
|
|
1642
1437
|
yAxis: {
|
|
1643
|
-
domain:
|
|
1438
|
+
domain: _ref15 => {
|
|
1644
1439
|
let {
|
|
1645
1440
|
min,
|
|
1646
1441
|
max
|
|
1647
|
-
} =
|
|
1442
|
+
} = _ref15;
|
|
1648
1443
|
return {
|
|
1649
1444
|
min: Math.max(min - 2, 0),
|
|
1650
1445
|
max: Math.min(max + 2, 100)
|
|
@@ -1804,6 +1599,110 @@ function ForecastAssetPrice() {
|
|
|
1804
1599
|
}), /*#__PURE__*/_jsx(CustomScrubber, {})]
|
|
1805
1600
|
});
|
|
1806
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",
|
|
1628
|
+
children: /*#__PURE__*/_jsx(LineChart, {
|
|
1629
|
+
showArea: true,
|
|
1630
|
+
accessibilityLabel: "Ethereum price chart",
|
|
1631
|
+
areaType: "dotted",
|
|
1632
|
+
height: 120,
|
|
1633
|
+
inset: 0,
|
|
1634
|
+
series: lineChartSeries
|
|
1635
|
+
})
|
|
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
|
+
}),
|
|
1646
|
+
children: /*#__PURE__*/_jsx(LineChart, {
|
|
1647
|
+
showArea: true,
|
|
1648
|
+
accessibilityLabel: "Ethereum price chart",
|
|
1649
|
+
areaType: "dotted",
|
|
1650
|
+
height: 100,
|
|
1651
|
+
inset: 0,
|
|
1652
|
+
series: lineChartSeries
|
|
1653
|
+
})
|
|
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
|
+
}),
|
|
1667
|
+
children: /*#__PURE__*/_jsx(LineChart, {
|
|
1668
|
+
showArea: true,
|
|
1669
|
+
accessibilityLabel: "Ethereum price chart",
|
|
1670
|
+
areaType: "dotted",
|
|
1671
|
+
height: 120,
|
|
1672
|
+
inset: 0,
|
|
1673
|
+
series: lineChartSeries,
|
|
1674
|
+
showXAxis: false,
|
|
1675
|
+
showYAxis: false
|
|
1676
|
+
})
|
|
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
|
+
}),
|
|
1693
|
+
children: /*#__PURE__*/_jsx(LineChart, {
|
|
1694
|
+
showArea: true,
|
|
1695
|
+
accessibilityLabel: "Price chart",
|
|
1696
|
+
areaType: "dotted",
|
|
1697
|
+
height: 100,
|
|
1698
|
+
inset: 0,
|
|
1699
|
+
series: lineChartSeries2,
|
|
1700
|
+
showXAxis: false,
|
|
1701
|
+
showYAxis: false
|
|
1702
|
+
})
|
|
1703
|
+
})]
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1807
1706
|
function ExampleNavigator() {
|
|
1808
1707
|
const theme = useTheme();
|
|
1809
1708
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
@@ -1953,11 +1852,11 @@ function ExampleNavigator() {
|
|
|
1953
1852
|
}],
|
|
1954
1853
|
xAxis: {
|
|
1955
1854
|
// Give space before the end of the chart for the scrubber
|
|
1956
|
-
range:
|
|
1855
|
+
range: _ref16 => {
|
|
1957
1856
|
let {
|
|
1958
1857
|
min,
|
|
1959
1858
|
max
|
|
1960
|
-
} =
|
|
1859
|
+
} = _ref16;
|
|
1961
1860
|
return {
|
|
1962
1861
|
min,
|
|
1963
1862
|
max: max - 24
|
|
@@ -1988,9 +1887,6 @@ function ExampleNavigator() {
|
|
|
1988
1887
|
}, {
|
|
1989
1888
|
title: 'Performance',
|
|
1990
1889
|
component: /*#__PURE__*/_jsx(Performance, {})
|
|
1991
|
-
}, {
|
|
1992
|
-
title: 'Candlesticks',
|
|
1993
|
-
component: /*#__PURE__*/_jsx(Candlesticks, {})
|
|
1994
1890
|
}, {
|
|
1995
1891
|
title: 'Monotone Asset Price',
|
|
1996
1892
|
component: /*#__PURE__*/_jsx(MonotoneAssetPrice, {})
|
|
@@ -2000,17 +1896,19 @@ function ExampleNavigator() {
|
|
|
2000
1896
|
}, {
|
|
2001
1897
|
title: 'Forecast Asset Price',
|
|
2002
1898
|
component: /*#__PURE__*/_jsx(ForecastAssetPrice, {})
|
|
1899
|
+
}, {
|
|
1900
|
+
title: 'In DataCard',
|
|
1901
|
+
component: /*#__PURE__*/_jsx(DataCardWithLineChart, {})
|
|
2003
1902
|
}], [theme.color.fg, theme.color.fgPositive, theme.spectrum.gray50]);
|
|
2004
1903
|
const currentExample = examples[currentIndex];
|
|
2005
|
-
const isFirstExample = currentIndex === 0;
|
|
2006
|
-
const isLastExample = currentIndex === examples.length - 1;
|
|
2007
1904
|
const handlePrevious = useCallback(() => {
|
|
2008
|
-
setCurrentIndex(prev =>
|
|
2009
|
-
}, []);
|
|
1905
|
+
setCurrentIndex(prev => (prev - 1 + examples.length) % examples.length);
|
|
1906
|
+
}, [examples.length]);
|
|
2010
1907
|
const handleNext = useCallback(() => {
|
|
2011
|
-
setCurrentIndex(prev =>
|
|
1908
|
+
setCurrentIndex(prev => (prev + 1 + examples.length) % examples.length);
|
|
2012
1909
|
}, [examples.length]);
|
|
2013
1910
|
return /*#__PURE__*/_jsx(ExampleScreen, {
|
|
1911
|
+
paddingX: 0,
|
|
2014
1912
|
children: /*#__PURE__*/_jsxs(VStack, {
|
|
2015
1913
|
gap: 4,
|
|
2016
1914
|
children: [/*#__PURE__*/_jsxs(HStack, {
|
|
@@ -2020,13 +1918,11 @@ function ExampleNavigator() {
|
|
|
2020
1918
|
children: [/*#__PURE__*/_jsx(IconButton, {
|
|
2021
1919
|
accessibilityHint: "Navigate to previous example",
|
|
2022
1920
|
accessibilityLabel: "Previous",
|
|
2023
|
-
disabled: isFirstExample,
|
|
2024
1921
|
name: "arrowLeft",
|
|
2025
1922
|
onPress: handlePrevious,
|
|
2026
1923
|
variant: "secondary"
|
|
2027
1924
|
}), /*#__PURE__*/_jsxs(VStack, {
|
|
2028
1925
|
alignItems: "center",
|
|
2029
|
-
gap: 1,
|
|
2030
1926
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
2031
1927
|
font: "title3",
|
|
2032
1928
|
children: currentExample.title
|
|
@@ -2038,7 +1934,6 @@ function ExampleNavigator() {
|
|
|
2038
1934
|
}), /*#__PURE__*/_jsx(IconButton, {
|
|
2039
1935
|
accessibilityHint: "Navigate to next example",
|
|
2040
1936
|
accessibilityLabel: "Next",
|
|
2041
|
-
disabled: isLastExample,
|
|
2042
1937
|
name: "arrowRight",
|
|
2043
1938
|
onPress: handleNext,
|
|
2044
1939
|
variant: "secondary"
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
const _excluded = ["accentColor", "yellowColor"];
|
|
2
2
|
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); }
|
|
3
3
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
4
|
-
import { memo, useCallback } from 'react';
|
|
4
|
+
import { memo, useCallback, useMemo } from 'react';
|
|
5
|
+
import { useDerivedValue, withTiming } from 'react-native-reanimated';
|
|
6
|
+
import { sparklineInteractiveData } from '@coinbase/cds-common/internal/visualizations/SparklineInteractiveData';
|
|
5
7
|
import { useTheme } from '@coinbase/cds-mobile';
|
|
6
8
|
import { Example, ExampleScreen } from '@coinbase/cds-mobile/examples/ExampleScreen';
|
|
9
|
+
import { useCartesianChartContext } from '../../ChartProvider';
|
|
10
|
+
import { Scrubber } from '../../scrubber';
|
|
11
|
+
import { getPointOnSerializableScale, useScrubberContext } from '../../utils';
|
|
7
12
|
import { DefaultReferenceLineLabel } from '../DefaultReferenceLineLabel';
|
|
8
13
|
import { DottedLine } from '../DottedLine';
|
|
9
14
|
import { LineChart } from '../LineChart';
|
|
@@ -126,7 +131,96 @@ const ReferenceLineStories = () => {
|
|
|
126
131
|
stroke: theme.color.bgWarning
|
|
127
132
|
})
|
|
128
133
|
})
|
|
134
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
135
|
+
title: "Start Price Reference Line",
|
|
136
|
+
children: /*#__PURE__*/_jsx(StartPriceReferenceLine, {})
|
|
129
137
|
})]
|
|
130
138
|
});
|
|
131
139
|
};
|
|
140
|
+
const FADE_ZONE = 128;
|
|
141
|
+
const StartPriceLabel = /*#__PURE__*/memo(props => {
|
|
142
|
+
const theme = useTheme();
|
|
143
|
+
const {
|
|
144
|
+
scrubberPosition
|
|
145
|
+
} = useScrubberContext();
|
|
146
|
+
const {
|
|
147
|
+
getXSerializableScale,
|
|
148
|
+
drawingArea
|
|
149
|
+
} = useCartesianChartContext();
|
|
150
|
+
const xScale = useMemo(() => getXSerializableScale(), [getXSerializableScale]);
|
|
151
|
+
const opacity = useDerivedValue(() => {
|
|
152
|
+
if (scrubberPosition.value === undefined) return withTiming(0, {
|
|
153
|
+
duration: 250
|
|
154
|
+
});
|
|
155
|
+
if (!xScale) return withTiming(1, {
|
|
156
|
+
duration: 250
|
|
157
|
+
});
|
|
158
|
+
const scrubX = getPointOnSerializableScale(scrubberPosition.value, xScale);
|
|
159
|
+
const rightEdge = drawingArea.x + drawingArea.width;
|
|
160
|
+
const target = rightEdge - scrubX >= FADE_ZONE ? 1 : 0;
|
|
161
|
+
return withTiming(target, {
|
|
162
|
+
duration: 250
|
|
163
|
+
});
|
|
164
|
+
}, [scrubberPosition, xScale, drawingArea]);
|
|
165
|
+
return /*#__PURE__*/_jsx(DefaultReferenceLineLabel, _extends({}, props, {
|
|
166
|
+
background: theme.color.bgSecondary,
|
|
167
|
+
borderRadius: 12.5,
|
|
168
|
+
color: theme.color.fg,
|
|
169
|
+
font: "label1",
|
|
170
|
+
inset: {
|
|
171
|
+
top: 4,
|
|
172
|
+
bottom: 4,
|
|
173
|
+
left: 8,
|
|
174
|
+
right: 8
|
|
175
|
+
},
|
|
176
|
+
opacity: opacity
|
|
177
|
+
}));
|
|
178
|
+
});
|
|
179
|
+
function StartPriceReferenceLine() {
|
|
180
|
+
const theme = useTheme();
|
|
181
|
+
const hourData = useMemo(() => sparklineInteractiveData.hour, []);
|
|
182
|
+
const startPrice = hourData[0].value;
|
|
183
|
+
const endPrice = hourData[hourData.length - 1].value;
|
|
184
|
+
const isPositive = endPrice >= startPrice;
|
|
185
|
+
const seriesColor = isPositive ? theme.color.fgPositive : theme.color.fgNegative;
|
|
186
|
+
return /*#__PURE__*/_jsxs(LineChart, {
|
|
187
|
+
enableScrubbing: true,
|
|
188
|
+
showArea: true,
|
|
189
|
+
areaType: "dotted",
|
|
190
|
+
height: 300,
|
|
191
|
+
inset: 0,
|
|
192
|
+
series: [{
|
|
193
|
+
id: 'hourly-prices',
|
|
194
|
+
data: hourData.map(d => d.value),
|
|
195
|
+
color: seriesColor
|
|
196
|
+
}],
|
|
197
|
+
xAxis: {
|
|
198
|
+
range: _ref2 => {
|
|
199
|
+
let {
|
|
200
|
+
min,
|
|
201
|
+
max
|
|
202
|
+
} = _ref2;
|
|
203
|
+
return {
|
|
204
|
+
min,
|
|
205
|
+
max: max - 24
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
children: [/*#__PURE__*/_jsx(Scrubber, {}), /*#__PURE__*/_jsx(ReferenceLine, {
|
|
210
|
+
LabelComponent: StartPriceLabel,
|
|
211
|
+
LineComponent: props => /*#__PURE__*/_jsx(DottedLine, _extends({}, props, {
|
|
212
|
+
dashIntervals: [0, 16],
|
|
213
|
+
strokeWidth: 3
|
|
214
|
+
})),
|
|
215
|
+
dataY: startPrice,
|
|
216
|
+
label: startPrice.toLocaleString('en-US', {
|
|
217
|
+
minimumFractionDigits: 2,
|
|
218
|
+
maximumFractionDigits: 2
|
|
219
|
+
}),
|
|
220
|
+
labelDx: -12,
|
|
221
|
+
labelHorizontalAlignment: "right",
|
|
222
|
+
stroke: theme.color.fgMuted
|
|
223
|
+
})]
|
|
224
|
+
});
|
|
225
|
+
}
|
|
132
226
|
export default ReferenceLineStories;
|