@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.
Files changed (68) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dts/chart/Path.d.ts +35 -13
  3. package/dts/chart/Path.d.ts.map +1 -1
  4. package/dts/chart/area/Area.d.ts +7 -11
  5. package/dts/chart/area/Area.d.ts.map +1 -1
  6. package/dts/chart/area/AreaChart.d.ts +1 -1
  7. package/dts/chart/area/DottedArea.d.ts.map +1 -1
  8. package/dts/chart/area/GradientArea.d.ts.map +1 -1
  9. package/dts/chart/area/SolidArea.d.ts.map +1 -1
  10. package/dts/chart/bar/Bar.d.ts +32 -2
  11. package/dts/chart/bar/Bar.d.ts.map +1 -1
  12. package/dts/chart/bar/BarChart.d.ts +2 -0
  13. package/dts/chart/bar/BarChart.d.ts.map +1 -1
  14. package/dts/chart/bar/BarPlot.d.ts +2 -1
  15. package/dts/chart/bar/BarPlot.d.ts.map +1 -1
  16. package/dts/chart/bar/BarStack.d.ts +5 -10
  17. package/dts/chart/bar/BarStack.d.ts.map +1 -1
  18. package/dts/chart/bar/BarStackGroup.d.ts +1 -0
  19. package/dts/chart/bar/BarStackGroup.d.ts.map +1 -1
  20. package/dts/chart/bar/DefaultBar.d.ts.map +1 -1
  21. package/dts/chart/bar/DefaultBarStack.d.ts.map +1 -1
  22. package/dts/chart/line/DottedLine.d.ts.map +1 -1
  23. package/dts/chart/line/Line.d.ts +4 -9
  24. package/dts/chart/line/Line.d.ts.map +1 -1
  25. package/dts/chart/line/LineChart.d.ts +1 -1
  26. package/dts/chart/line/SolidLine.d.ts.map +1 -1
  27. package/dts/chart/point/Point.d.ts +18 -2
  28. package/dts/chart/point/Point.d.ts.map +1 -1
  29. package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts +9 -1
  30. package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts.map +1 -1
  31. package/dts/chart/scrubber/Scrubber.d.ts +45 -24
  32. package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
  33. package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts +9 -1
  34. package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts.map +1 -1
  35. package/dts/chart/utils/bar.d.ts +34 -0
  36. package/dts/chart/utils/bar.d.ts.map +1 -1
  37. package/dts/chart/utils/path.d.ts +6 -0
  38. package/dts/chart/utils/path.d.ts.map +1 -1
  39. package/dts/chart/utils/transition.d.ts +59 -21
  40. package/dts/chart/utils/transition.d.ts.map +1 -1
  41. package/esm/chart/Path.js +18 -17
  42. package/esm/chart/__stories__/CartesianChart.stories.js +3 -77
  43. package/esm/chart/__stories__/ChartTransitions.stories.js +629 -0
  44. package/esm/chart/area/Area.js +2 -0
  45. package/esm/chart/area/DottedArea.js +7 -3
  46. package/esm/chart/area/GradientArea.js +4 -2
  47. package/esm/chart/area/SolidArea.js +4 -2
  48. package/esm/chart/bar/Bar.js +2 -0
  49. package/esm/chart/bar/BarChart.js +4 -2
  50. package/esm/chart/bar/BarPlot.js +2 -0
  51. package/esm/chart/bar/BarStack.js +3 -0
  52. package/esm/chart/bar/DefaultBar.js +15 -15
  53. package/esm/chart/bar/DefaultBarStack.js +14 -3
  54. package/esm/chart/bar/__stories__/BarChart.stories.js +448 -52
  55. package/esm/chart/line/DottedLine.js +4 -2
  56. package/esm/chart/line/Line.js +6 -17
  57. package/esm/chart/line/SolidLine.js +4 -2
  58. package/esm/chart/line/__stories__/LineChart.stories.js +130 -235
  59. package/esm/chart/line/__stories__/ReferenceLine.stories.js +95 -1
  60. package/esm/chart/point/Point.js +33 -35
  61. package/esm/chart/scrubber/DefaultScrubberBeacon.js +2 -5
  62. package/esm/chart/scrubber/Scrubber.js +15 -14
  63. package/esm/chart/scrubber/ScrubberBeaconLabelGroup.js +29 -7
  64. package/esm/chart/utils/bar.js +43 -0
  65. package/esm/chart/utils/path.js +8 -0
  66. package/esm/chart/utils/transition.js +96 -61
  67. package/package.json +5 -5
  68. 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, useId, useMemo, useRef, useState } from 'react';
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, Line as SkiaLine, Rect, Skia, TextAlign } from '@shopify/react-native-skia';
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, getPointOnSerializableScale, projectPointWithSerializableScale, unwrapAnimatedValue, useScrubberContext } from '../../utils';
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(_ref16 => {
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
- } = _ref16;
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: _ref17 => {
1336
+ stops: _ref12 => {
1542
1337
  let {
1543
1338
  min
1544
- } = _ref17;
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: _ref18 => {
1353
+ range: _ref13 => {
1559
1354
  let {
1560
1355
  max
1561
- } = _ref18;
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: _ref19 => {
1407
+ stops: _ref14 => {
1613
1408
  let {
1614
1409
  min,
1615
1410
  max
1616
- } = _ref19;
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: _ref20 => {
1438
+ domain: _ref15 => {
1644
1439
  let {
1645
1440
  min,
1646
1441
  max
1647
- } = _ref20;
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: _ref21 => {
1855
+ range: _ref16 => {
1957
1856
  let {
1958
1857
  min,
1959
1858
  max
1960
- } = _ref21;
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 => Math.max(0, prev - 1));
2009
- }, []);
1905
+ setCurrentIndex(prev => (prev - 1 + examples.length) % examples.length);
1906
+ }, [examples.length]);
2010
1907
  const handleNext = useCallback(() => {
2011
- setCurrentIndex(prev => Math.min(examples.length - 1, prev + 1));
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;