@coinbase/cds-mobile-visualization 3.4.0-beta.24 → 3.4.0-beta.25

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 (43) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dts/chart/Path.d.ts +2 -1
  3. package/dts/chart/Path.d.ts.map +1 -1
  4. package/dts/chart/bar/Bar.d.ts +18 -54
  5. package/dts/chart/bar/Bar.d.ts.map +1 -1
  6. package/dts/chart/bar/BarChart.d.ts +2 -2
  7. package/dts/chart/bar/BarPlot.d.ts.map +1 -1
  8. package/dts/chart/bar/BarStack.d.ts +4 -4
  9. package/dts/chart/bar/BarStack.d.ts.map +1 -1
  10. package/dts/chart/bar/DefaultBar.d.ts.map +1 -1
  11. package/dts/chart/bar/DefaultBarStack.d.ts.map +1 -1
  12. package/dts/chart/point/Point.d.ts +2 -1
  13. package/dts/chart/point/Point.d.ts.map +1 -1
  14. package/dts/chart/scrubber/Scrubber.d.ts +4 -2
  15. package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
  16. package/dts/chart/utils/bar.d.ts +155 -0
  17. package/dts/chart/utils/bar.d.ts.map +1 -1
  18. package/dts/chart/utils/chart.d.ts +2 -1
  19. package/dts/chart/utils/chart.d.ts.map +1 -1
  20. package/dts/chart/utils/path.d.ts.map +1 -1
  21. package/dts/sparkline/Sparkline.d.ts +2 -1
  22. package/dts/sparkline/Sparkline.d.ts.map +1 -1
  23. package/dts/sparkline/SparklineArea.d.ts +2 -1
  24. package/dts/sparkline/SparklineArea.d.ts.map +1 -1
  25. package/dts/sparkline/SparklineGradient.d.ts +2 -1
  26. package/dts/sparkline/SparklineGradient.d.ts.map +1 -1
  27. package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts +2 -1
  28. package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts.map +1 -1
  29. package/esm/chart/bar/Bar.js +8 -14
  30. package/esm/chart/bar/BarChart.js +7 -7
  31. package/esm/chart/bar/BarPlot.js +37 -46
  32. package/esm/chart/bar/BarStack.js +71 -604
  33. package/esm/chart/bar/DefaultBar.js +11 -18
  34. package/esm/chart/bar/DefaultBarStack.js +12 -21
  35. package/esm/chart/bar/__stories__/BarChart.stories.js +104 -6
  36. package/esm/chart/utils/bar.js +775 -0
  37. package/esm/chart/utils/chart.js +2 -1
  38. package/esm/chart/utils/path.js +5 -12
  39. package/esm/sparkline/Sparkline.js +2 -1
  40. package/esm/sparkline/SparklineArea.js +2 -1
  41. package/esm/sparkline/SparklineGradient.js +2 -1
  42. package/esm/sparkline/sparkline-interactive/SparklineInteractive.js +2 -1
  43. package/package.json +5 -5
@@ -3,6 +3,7 @@ import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
3
3
  import { useCartesianChartContext } from '../ChartProvider';
4
4
  import { Path } from '../Path';
5
5
  import { defaultBarEnterTransition, getBarPath, withStaggerDelayTransition } from '../utils';
6
+ import { getNormalizedStagger } from '../utils/bar';
6
7
  import { defaultTransition, getTransition } from '../utils/transition';
7
8
  import { jsx as _jsx } from "react/jsx-runtime";
8
9
  /**
@@ -23,6 +24,7 @@ export const DefaultBar = /*#__PURE__*/memo(_ref => {
23
24
  stroke,
24
25
  strokeWidth,
25
26
  origin,
27
+ minSize = 1,
26
28
  transitions,
27
29
  transition
28
30
  } = _ref;
@@ -33,28 +35,19 @@ export const DefaultBar = /*#__PURE__*/memo(_ref => {
33
35
  } = useCartesianChartContext();
34
36
  const theme = useTheme();
35
37
  const defaultFill = fill || theme.color.fgPrimary;
36
-
37
- // For vertical layout, stagger by x (category axis). For horizontal, stagger by y (category axis).
38
- const normalizedStagger = useMemo(() => {
39
- const barsGrowVertically = layout !== 'horizontal';
40
- if (barsGrowVertically) {
41
- return drawingArea.width > 0 ? (x - drawingArea.x) / drawingArea.width : 0;
42
- }
43
- return drawingArea.height > 0 ? (y - drawingArea.y) / drawingArea.height : 0;
44
- }, [layout, x, y, drawingArea.x, drawingArea.y, drawingArea.width, drawingArea.height]);
38
+ const normalizedStagger = useMemo(() => getNormalizedStagger(layout, x, y, drawingArea), [layout, x, y, drawingArea]);
45
39
  const enterTransition = useMemo(() => withStaggerDelayTransition(getTransition(transitions == null ? void 0 : transitions.enter, animate, defaultBarEnterTransition), normalizedStagger), [transitions == null ? void 0 : transitions.enter, animate, normalizedStagger]);
46
40
  const updateTransition = useMemo(() => withStaggerDelayTransition(getTransition((transitions == null ? void 0 : transitions.update) !== undefined ? transitions.update : transition, animate, defaultTransition), normalizedStagger), [transitions == null ? void 0 : transitions.update, transition, animate, normalizedStagger]);
47
41
  const initialPath = useMemo(() => {
48
- if (!animate) return undefined;
49
- const minSize = 1;
50
- const barsGrowVertically = layout !== 'horizontal';
51
- const baseline = origin != null ? origin : barsGrowVertically ? y + height : x;
52
- const initialX = barsGrowVertically ? x : baseline;
53
- const initialY = barsGrowVertically ? baseline : y;
54
- const initialWidth = barsGrowVertically ? width : minSize;
55
- const initialHeight = barsGrowVertically ? minSize : height;
42
+ if (!animate) return;
43
+ const isHorizontalLayout = layout === 'horizontal';
44
+ const baseline = origin != null ? origin : isHorizontalLayout ? x : y + height;
45
+ const initialX = isHorizontalLayout ? baseline : x;
46
+ const initialY = isHorizontalLayout ? y : baseline;
47
+ const initialWidth = isHorizontalLayout ? minSize : width;
48
+ const initialHeight = isHorizontalLayout ? height : minSize;
56
49
  return getBarPath(initialX, initialY, initialWidth, initialHeight, borderRadius, !!roundTop, !!roundBottom, layout);
57
- }, [animate, layout, x, y, origin, width, height, borderRadius, roundTop, roundBottom]);
50
+ }, [animate, layout, x, y, origin, width, height, borderRadius, roundTop, roundBottom, minSize]);
58
51
  return /*#__PURE__*/_jsx(Path, {
59
52
  animate: animate,
60
53
  clipPath: null,
@@ -2,7 +2,7 @@ import { memo, useMemo } from 'react';
2
2
  import { Group } from '@shopify/react-native-skia';
3
3
  import { useCartesianChartContext } from '../ChartProvider';
4
4
  import { getBarPath } from '../utils';
5
- import { defaultBarEnterTransition, withStaggerDelayTransition } from '../utils/bar';
5
+ import { defaultBarEnterTransition, getNormalizedStagger, getStackInitialClipRect, withStaggerDelayTransition } from '../utils/bar';
6
6
  import { defaultTransition, getTransition, usePathTransition } from '../utils/transition';
7
7
  import { jsx as _jsx } from "react/jsx-runtime";
8
8
  /**
@@ -18,7 +18,7 @@ export const DefaultBarStack = /*#__PURE__*/memo(_ref => {
18
18
  borderRadius = 4,
19
19
  roundTop = true,
20
20
  roundBottom = true,
21
- yOrigin,
21
+ origin,
22
22
  transitions,
23
23
  transition
24
24
  } = _ref;
@@ -27,15 +27,7 @@ export const DefaultBarStack = /*#__PURE__*/memo(_ref => {
27
27
  drawingArea,
28
28
  layout
29
29
  } = useCartesianChartContext();
30
-
31
- // For vertical layout, stagger by x (category axis). For horizontal, stagger by y (category axis).
32
- const normalizedStagger = useMemo(() => {
33
- const barsGrowVertically = layout !== 'horizontal';
34
- if (barsGrowVertically) {
35
- return drawingArea.width > 0 ? (x - drawingArea.x) / drawingArea.width : 0;
36
- }
37
- return drawingArea.height > 0 ? (y - drawingArea.y) / drawingArea.height : 0;
38
- }, [layout, x, y, drawingArea.x, drawingArea.y, drawingArea.width, drawingArea.height]);
30
+ const normalizedStagger = useMemo(() => getNormalizedStagger(layout, x, y, drawingArea), [layout, x, y, drawingArea]);
39
31
  const enterTransition = useMemo(() => withStaggerDelayTransition(getTransition(transitions == null ? void 0 : transitions.enter, animate, defaultBarEnterTransition), normalizedStagger), [animate, transitions == null ? void 0 : transitions.enter, normalizedStagger]);
40
32
  const updateTransition = useMemo(() => withStaggerDelayTransition(getTransition((transitions == null ? void 0 : transitions.update) !== undefined ? transitions.update : transition, animate, defaultTransition), normalizedStagger), [animate, transitions == null ? void 0 : transitions.update, transition, normalizedStagger]);
41
33
 
@@ -46,16 +38,15 @@ export const DefaultBarStack = /*#__PURE__*/memo(_ref => {
46
38
 
47
39
  // Initial clip path for entry animation (bar at baseline with minimal height)
48
40
  const initialPath = useMemo(() => {
49
- if (!animate) return undefined;
50
- const barsGrowVertically = layout !== 'horizontal';
51
- const baseline = yOrigin != null ? yOrigin : barsGrowVertically ? y + height : x;
52
- const minSize = 1;
53
- const initialX = barsGrowVertically ? x : baseline;
54
- const initialY = barsGrowVertically ? baseline : y;
55
- const initialWidth = barsGrowVertically ? width : minSize;
56
- const initialHeight = barsGrowVertically ? minSize : height;
57
- return getBarPath(initialX, initialY, initialWidth, initialHeight, borderRadius, roundTop, roundBottom, layout);
58
- }, [animate, layout, x, yOrigin, y, height, width, borderRadius, roundTop, roundBottom]);
41
+ if (!animate) return;
42
+ const initialClipRect = getStackInitialClipRect({
43
+ x,
44
+ y,
45
+ width,
46
+ height
47
+ }, layout, origin);
48
+ return getBarPath(initialClipRect.x, initialClipRect.y, initialClipRect.width, initialClipRect.height, borderRadius, roundTop, roundBottom, layout);
49
+ }, [animate, layout, x, y, height, width, borderRadius, roundTop, roundBottom, origin]);
59
50
  const animatedClipPath = usePathTransition({
60
51
  currentPath: targetPath,
61
52
  initialPath,
@@ -1,7 +1,8 @@
1
1
  const _excluded = ["children"],
2
2
  _excluded2 = ["animate"],
3
3
  _excluded3 = ["x", "y", "width", "height", "dataX"],
4
- _excluded4 = ["data", "height"];
4
+ _excluded4 = ["data", "height"],
5
+ _excluded5 = ["buy", "sell", "animate", "borderRadius", "height", "inset", "layout", "stackGap", "xAxis", "yAxis", "barMinSize"];
5
6
  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
7
  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 { memo, useCallback, useEffect, useId, useMemo, useState } from 'react';
@@ -17,6 +18,7 @@ import { Line as SkiaLine, Rect } from '@shopify/react-native-skia';
17
18
  import { XAxis, YAxis } from '../../axis';
18
19
  import { CartesianChart } from '../../CartesianChart';
19
20
  import { useCartesianChartContext } from '../../ChartProvider';
21
+ import { DefaultLegendEntry } from '../../legend';
20
22
  import { ReferenceLine, SolidLine } from '../../line';
21
23
  import { Scrubber } from '../../scrubber';
22
24
  import { getPointOnSerializableScale, unwrapAnimatedValue, useScrubberContext } from '../../utils';
@@ -125,6 +127,7 @@ const CustomBarStackComponent = /*#__PURE__*/memo(_ref => {
125
127
  }));
126
128
  });
127
129
  const MonthlyRewards = () => {
130
+ const theme = useTheme();
128
131
  const months = ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'];
129
132
  const purple = [null, 6, 8, 10, 7, 6, 6, 8, null, null, null, null];
130
133
  const blue = [null, 10, 12, 11, 10, 9, 10, 11, null, null, null, null];
@@ -134,19 +137,19 @@ const MonthlyRewards = () => {
134
137
  const series = [{
135
138
  id: 'purple',
136
139
  data: purple,
137
- color: '#b399ff'
140
+ color: "rgb(" + theme.spectrum.purple30 + ")"
138
141
  }, {
139
142
  id: 'blue',
140
143
  data: blue,
141
- color: '#4f7cff'
144
+ color: "rgb(" + theme.spectrum.blue30 + ")"
142
145
  }, {
143
146
  id: 'cyan',
144
147
  data: cyan,
145
- color: '#00c2df'
148
+ color: "rgb(" + theme.spectrum.teal30 + ")"
146
149
  }, {
147
150
  id: 'green',
148
151
  data: green,
149
- color: '#33c481'
152
+ color: "rgb(" + theme.spectrum.green30 + ")"
150
153
  }];
151
154
  return /*#__PURE__*/_jsxs(VStack, {
152
155
  gap: 2,
@@ -165,7 +168,7 @@ const MonthlyRewards = () => {
165
168
  tickLabelFormatter: index => {
166
169
  return months[index];
167
170
  },
168
- categoryPadding: 0.27
171
+ categoryPadding: 0.25
169
172
  }
170
173
  }), /*#__PURE__*/_jsx(Button, {
171
174
  onPress: () => setRoundBaseline(!roundBaseline),
@@ -1061,6 +1064,98 @@ const HorizontalBarChart = () => {
1061
1064
  }
1062
1065
  });
1063
1066
  };
1067
+ function BuyVsSellExample() {
1068
+ function BuyVsSellLegend(_ref15) {
1069
+ let {
1070
+ buy,
1071
+ sell
1072
+ } = _ref15;
1073
+ const theme = useTheme();
1074
+ return /*#__PURE__*/_jsxs(HStack, {
1075
+ gap: 1,
1076
+ justifyContent: "space-between",
1077
+ children: [/*#__PURE__*/_jsx(DefaultLegendEntry, {
1078
+ color: theme.color.fgPositive,
1079
+ label: /*#__PURE__*/_jsxs(Text, {
1080
+ color: "fgMuted",
1081
+ font: "legal",
1082
+ children: [buy, "% bought"]
1083
+ }),
1084
+ seriesId: "buy"
1085
+ }), /*#__PURE__*/_jsx(DefaultLegendEntry, {
1086
+ color: theme.color.fgNegative,
1087
+ label: /*#__PURE__*/_jsxs(Text, {
1088
+ color: "fgMuted",
1089
+ font: "legal",
1090
+ children: [sell, "% sold"]
1091
+ }),
1092
+ seriesId: "sell"
1093
+ })]
1094
+ });
1095
+ }
1096
+ function BuyVsSellChart(_ref16) {
1097
+ let {
1098
+ buy,
1099
+ sell,
1100
+ animate = true,
1101
+ borderRadius = 3,
1102
+ height = 6,
1103
+ inset = 0,
1104
+ layout = 'horizontal',
1105
+ stackGap = 4,
1106
+ xAxis,
1107
+ yAxis,
1108
+ barMinSize = height
1109
+ } = _ref16,
1110
+ props = _objectWithoutPropertiesLoose(_ref16, _excluded5);
1111
+ const theme = useTheme();
1112
+ return /*#__PURE__*/_jsxs(VStack, {
1113
+ gap: 1.5,
1114
+ children: [/*#__PURE__*/_jsx(BarChart, _extends({
1115
+ roundBaseline: true,
1116
+ stacked: true,
1117
+ animate: animate,
1118
+ barMinSize: barMinSize,
1119
+ borderRadius: borderRadius,
1120
+ height: height,
1121
+ inset: inset,
1122
+ layout: layout,
1123
+ series: [{
1124
+ id: 'buy',
1125
+ data: [buy],
1126
+ color: theme.color.fgPositive,
1127
+ legendShape: 'circle'
1128
+ }, {
1129
+ id: 'sell',
1130
+ data: [sell],
1131
+ color: theme.color.fgNegative,
1132
+ legendShape: 'circle'
1133
+ }],
1134
+ stackGap: stackGap,
1135
+ transitions: {
1136
+ enter: {
1137
+ type: 'timing',
1138
+ duration: 5000,
1139
+ delay: 2000
1140
+ }
1141
+ },
1142
+ xAxis: _extends({
1143
+ domainLimit: 'strict'
1144
+ }, xAxis),
1145
+ yAxis: _extends({
1146
+ categoryPadding: 0
1147
+ }, yAxis)
1148
+ }, props)), /*#__PURE__*/_jsx(BuyVsSellLegend, {
1149
+ buy: buy,
1150
+ sell: sell
1151
+ })]
1152
+ });
1153
+ }
1154
+ return /*#__PURE__*/_jsx(BuyVsSellChart, {
1155
+ buy: 76,
1156
+ sell: 24
1157
+ });
1158
+ }
1064
1159
  const PopulationPyramid = () => {
1065
1160
  const theme = useTheme();
1066
1161
  const ageGroups = ['100+ yrs', '95-99 yrs', '90-94 yrs', '85-89 yrs', '80-84 yrs', '75-79 yrs', '70-74 yrs', '65-69 yrs', '60-64 yrs', '55-59 yrs', '50-54 yrs', '45-49 yrs', '40-44 yrs', '35-39 yrs', '30-34 yrs', '25-29 yrs', '20-24 yrs', '15-19 yrs', '10-14 yrs', '5-9 yrs', '0-4 yrs'];
@@ -1192,6 +1287,9 @@ function ExampleNavigator() {
1192
1287
  }, {
1193
1288
  title: 'Horizontal Layout',
1194
1289
  component: /*#__PURE__*/_jsx(HorizontalBarChart, {})
1290
+ }, {
1291
+ title: 'Buy vs Sell',
1292
+ component: /*#__PURE__*/_jsx(BuyVsSellExample, {})
1195
1293
  }, {
1196
1294
  title: 'Population Pyramid',
1197
1295
  component: /*#__PURE__*/_jsx(PopulationPyramid, {})