@coinbase/cds-mobile 8.13.2 → 8.13.5

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 CHANGED
@@ -8,6 +8,24 @@ All notable changes to this project will be documented in this file.
8
8
 
9
9
  <!-- template-start -->
10
10
 
11
+ ## 8.13.5 (10/3/2025 PST)
12
+
13
+ #### 🐞 Fixes
14
+
15
+ - Support custom font in SegmentedTab. [[#65](https://github.com/coinbase/cds/pull/65)]
16
+
17
+ ## 8.13.4 (10/1/2025 PST)
18
+
19
+ #### 🐞 Fixes
20
+
21
+ - Fix tour position flickering issue.
22
+
23
+ ## 8.13.3 (10/1/2025 PST)
24
+
25
+ #### 🐞 Fixes
26
+
27
+ - Remove alignSelf="start" from mobile RollingNumber, keeping it the same behavior with web. [[#55](https://github.com/coinbase/cds/pull/55)]
28
+
11
29
  ## 8.13.2 (10/1/2025 PST)
12
30
 
13
31
  #### 🐞 Fixes
@@ -8,22 +8,24 @@ import {
8
8
  } from 'react-native';
9
9
  import type { ThemeVars } from '@coinbase/cds-common/core/theme';
10
10
  import { type TabValue } from '@coinbase/cds-common/tabs/useTabs';
11
- export type SegmentedTabProps<T extends string = string> = {
12
- /**
13
- * Text color when the SegmentedTab is active.
14
- * @default negativeForeground
15
- */
16
- activeColor?: ThemeVars.Color;
17
- /**
18
- * Text color when the SegmentedTab is inactive.
19
- * @default foreground
20
- */
21
- color?: ThemeVars.Color;
22
- /** Callback that is fired when the SegmentedTab is pressed. */
23
- onPress?: (id: string, event: GestureResponderEvent) => void;
24
- style?: StyleProp<ViewStyle>;
25
- } & TabValue<T> &
26
- Omit<PressableProps, 'children' | 'disabled' | 'onPress' | 'style'>;
11
+ import { type TextBaseProps } from '../typography/Text';
12
+ export type SegmentedTabProps<T extends string = string> = TabValue<T> &
13
+ Pick<TextBaseProps, 'font' | 'fontFamily' | 'fontSize' | 'fontWeight' | 'lineHeight'> &
14
+ Omit<PressableProps, 'children' | 'disabled' | 'onPress' | 'style'> & {
15
+ /**
16
+ * Text color when the SegmentedTab is active.
17
+ * @default negativeForeground
18
+ */
19
+ activeColor?: ThemeVars.Color;
20
+ /**
21
+ * Text color when the SegmentedTab is inactive.
22
+ * @default foreground
23
+ */
24
+ color?: ThemeVars.Color;
25
+ /** Callback that is fired when the SegmentedTab is pressed. */
26
+ onPress?: (id: string, event: GestureResponderEvent) => void;
27
+ style?: StyleProp<ViewStyle>;
28
+ };
27
29
  type SegmentedTabFC = <T extends string = string>(
28
30
  props: SegmentedTabProps<T> & {
29
31
  ref?: React.ForwardedRef<View>;
@@ -1 +1 @@
1
- {"version":3,"file":"SegmentedTab.d.ts","sourceRoot":"","sources":["../../src/tabs/SegmentedTab.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AACtE,OAAO,EACL,KAAK,qBAAqB,EAE1B,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,IAAI,EACT,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AASlE,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IACzD;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC;IAC9B;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC;IACxB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC7D,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B,GAAG,QAAQ,CAAC,CAAC,CAAC,GACb,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC;AAItE,KAAK,cAAc,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC9C,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;CAAE,KAC7D,KAAK,CAAC,YAAY,CAAC;AA0FxB,eAAO,MAAM,YAAY,EAA4B,cAAc,CAAC"}
1
+ {"version":3,"file":"SegmentedTab.d.ts","sourceRoot":"","sources":["../../src/tabs/SegmentedTab.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AACtE,OAAO,EACL,KAAK,qBAAqB,EAE1B,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,IAAI,EACT,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAKlE,OAAO,EAAQ,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAI9D,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,GACpE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,YAAY,GAAG,UAAU,GAAG,YAAY,GAAG,YAAY,CAAC,GACrF,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,GAAG;IACpE;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC;IAC9B;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC;IACxB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC7D,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B,CAAC;AAIJ,KAAK,cAAc,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC9C,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;CAAE,KAC7D,KAAK,CAAC,YAAY,CAAC;AAmGxB,eAAO,MAAM,YAAY,EAA4B,cAAc,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tour.d.ts","sourceRoot":"","sources":["../../src/tour/Tour.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAC9D,OAAO,EAAS,IAAI,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAQxD,OAAO,KAAK,EACV,WAAW,EACX,sBAAsB,EAEvB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qDAAqD,CAAC;AACpG,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,mBAAmB,CAAC;AAmB3B,MAAM,MAAM,sBAAsB,GAAG;IACnC;;OAEG;IACH,oBAAoB,EAAE,IAAI,CAAC;IAC3B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAAC,CAAC;AAEjE,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG;IAClE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;IAChD;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,oBAAoB,CAAC;IAC7C;;OAEG;IACH,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACxC,GAAG,IAAI,CAAC,wBAAwB,EAAE,oBAAoB,GAAG,yBAAyB,GAAG,IAAI,CAAC,GACzF,WAAW,CAAC;AAEd,KAAK,MAAM,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;AA2HlF,eAAO,MAAM,IAAI,EAAoB,MAAM,CAAC"}
1
+ {"version":3,"file":"Tour.d.ts","sourceRoot":"","sources":["../../src/tour/Tour.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,EAAS,IAAI,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAMxD,OAAO,KAAK,EACV,WAAW,EACX,sBAAsB,EAEvB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qDAAqD,CAAC;AACpG,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,mBAAmB,CAAC;AAmB3B,MAAM,MAAM,sBAAsB,GAAG;IACnC;;OAEG;IACH,oBAAoB,EAAE,IAAI,CAAC;IAC3B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAAC,CAAC;AAEjE,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG;IAClE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;IAChD;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,oBAAoB,CAAC;IAC7C;;OAEG;IACH,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACxC,GAAG,IAAI,CAAC,wBAAwB,EAAE,oBAAoB,GAAG,yBAAyB,GAAG,IAAI,CAAC,GACzF,WAAW,CAAC;AAEd,KAAK,MAAM,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;AA2IlF,eAAO,MAAM,IAAI,EAAoB,MAAM,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"TourStep.d.ts","sourceRoot":"","sources":["../../src/tour/TourStep.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsB,MAAM,OAAO,CAAC;AAI3C,KAAK,aAAa,GAAG;IACnB,iDAAiD;IACjD,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,kBAAkB,aAAa,4CAQvD,CAAC"}
1
+ {"version":3,"file":"TourStep.d.ts","sourceRoot":"","sources":["../../src/tour/TourStep.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsB,MAAM,OAAO,CAAC;AAI3C,KAAK,aAAa,GAAG;IACnB,iDAAiD;IACjD,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,kBAAkB,aAAa,4CAWvD,CAAC"}
@@ -256,7 +256,6 @@ export const RollingNumber = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, re
256
256
  }, [accessibilityLiveRegion, textProps, accessibilityLabelPrefix, accessibilityLabel, formatted, prefix, suffix, accessibilityLabelSuffix, styles == null ? void 0 : styles.text]);
257
257
  return /*#__PURE__*/_jsxs(HStack, {
258
258
  ref: ref,
259
- alignSelf: "flex-start",
260
259
  style: rootStyle,
261
260
  testID: testID,
262
261
  children: [invisibleMeasuredDigits, screenReaderOnlySection, /*#__PURE__*/_jsxs(HStack, {
@@ -470,7 +470,8 @@ const StyleOverrides = () => {
470
470
  paddingVertical: 4,
471
471
  paddingHorizontal: 8,
472
472
  borderRadius: 8,
473
- backgroundColor: theme.color.bgSecondaryWash
473
+ backgroundColor: theme.color.bgSecondaryWash,
474
+ alignSelf: 'flex-start'
474
475
  },
475
476
  fraction: {
476
477
  opacity: 0.2,
@@ -1,4 +1,4 @@
1
- const _excluded = ["id", "label", "disabled", "onPress", "color", "activeColor", "style", "aria-selected", "accessibilityRole", "testID"];
1
+ const _excluded = ["id", "label", "disabled", "onPress", "color", "activeColor", "style", "aria-selected", "accessibilityRole", "testID", "font", "fontFamily", "fontSize", "fontWeight", "lineHeight"];
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
4
  import React, { forwardRef, memo, useCallback, useMemo } from 'react';
@@ -23,7 +23,12 @@ const SegmentedTabComponent = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
23
23
  style,
24
24
  'aria-selected': ariaSelected,
25
25
  accessibilityRole = 'button',
26
- testID
26
+ testID,
27
+ font = 'headline',
28
+ fontFamily,
29
+ fontSize,
30
+ fontWeight,
31
+ lineHeight
27
32
  } = _ref,
28
33
  props = _objectWithoutPropertiesLoose(_ref, _excluded);
29
34
  const {
@@ -64,7 +69,11 @@ const SegmentedTabComponent = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
64
69
  paddingY: 1,
65
70
  children: typeof label === 'string' ? /*#__PURE__*/_jsx(AnimatedTextHeadline, {
66
71
  animated: true,
67
- font: "headline",
72
+ font: font,
73
+ fontFamily: fontFamily,
74
+ fontSize: fontSize,
75
+ fontWeight: fontWeight,
76
+ lineHeight: lineHeight,
68
77
  style: animatedTextStyles,
69
78
  testID: testID + "-label",
70
79
  children: label
@@ -57,6 +57,14 @@ const AnotherCustomSegmentedTab = _ref2 => {
57
57
  })
58
58
  });
59
59
  };
60
+ const CustomSegmentedTabColor = props => /*#__PURE__*/_jsx(SegmentedTab, _extends({}, props, {
61
+ activeColor: "fgWarning",
62
+ color: "bgPrimary",
63
+ font: "label2"
64
+ }));
65
+ const CustomSegmentedTabFont = props => /*#__PURE__*/_jsx(SegmentedTab, _extends({}, props, {
66
+ font: "label2"
67
+ }));
60
68
  const basicSegments = [{
61
69
  id: 'buy',
62
70
  label: 'Buy'
@@ -124,6 +132,19 @@ const customSegments = [{
124
132
  id: 'convert',
125
133
  label: 'Convert'
126
134
  }];
135
+ const mixedCustomSegments = [{
136
+ id: 'buy',
137
+ label: 'Buy',
138
+ Component: CustomSegmentedTabColor
139
+ }, {
140
+ id: 'sell',
141
+ label: 'Sell',
142
+ Component: CustomSegmentedTabFont
143
+ }, {
144
+ id: 'convert',
145
+ label: 'Convert',
146
+ Component: CustomSegmentedTabColor
147
+ }];
127
148
  const SegmentedTabsExample = _ref3 => {
128
149
  let {
129
150
  title,
@@ -179,6 +200,10 @@ const SegmentedTabsScreen = () => /*#__PURE__*/_jsxs(ExampleScreen, {
179
200
  defaultActiveTab: customSegments[0],
180
201
  tabs: customSegments,
181
202
  title: "Custom Single Segment"
203
+ }), /*#__PURE__*/_jsx(SegmentedTabsExample, {
204
+ defaultActiveTab: mixedCustomSegments[0],
205
+ tabs: mixedCustomSegments,
206
+ title: "Mixed Custom Segments"
182
207
  }), /*#__PURE__*/_jsx(SegmentedTabsExample, {
183
208
  TabComponent: AnotherCustomSegmentedTab,
184
209
  TabsActiveIndicatorComponent: CustomActiveIndicator,
package/esm/tour/Tour.js CHANGED
@@ -1,9 +1,7 @@
1
1
  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); }
2
- import React, { useCallback, useEffect, useRef } from 'react';
2
+ import React, { useCallback, useRef } from 'react';
3
3
  import { Modal, View } from 'react-native';
4
- import { useRefMap } from '@coinbase/cds-common/hooks/useRefMap';
5
4
  import { OverlayContentContext } from '@coinbase/cds-common/overlays/OverlayContentContext';
6
- import { RefMapContext } from '@coinbase/cds-common/system/RefMapContext';
7
5
  import { TourContext } from '@coinbase/cds-common/tour/TourContext';
8
6
  import { useTour } from '@coinbase/cds-common/tour/useTour';
9
7
  import { arrow as arrowMiddleware, autoPlacement, offset, shift, useFloating } from '@floating-ui/react-native';
@@ -35,13 +33,17 @@ const TourComponent = _ref => {
35
33
  testID
36
34
  } = _ref;
37
35
  const theme = useTheme();
38
- const refMap = useRefMap();
36
+ const defaultTourStepOffset = theme.space[3];
37
+ const defaultTourStepShiftPadding = theme.space[4];
39
38
  const tourStepArrowRef = useRef(null);
40
39
  const RenderedTourStep = activeTourStep == null ? void 0 : activeTourStep.Component;
41
40
  const RenderedTourStepArrow = (_activeTourStep$Arrow = activeTourStep == null ? void 0 : activeTourStep.ArrowComponent) != null ? _activeTourStep$Arrow : TourStepArrowComponent;
42
- const activeTourStepTarget = activeTourStep ? refMap.getRef(activeTourStep.id) : null;
43
- const defaultTourStepOffset = theme.space[3];
44
- const defaultTourStepShiftPadding = theme.space[4];
41
+ const [animation, animationApi] = useSpring(() => ({
42
+ from: {
43
+ opacity: 0
44
+ },
45
+ config: springConfig.slow
46
+ }), []);
45
47
  const {
46
48
  refs,
47
49
  floatingStyles,
@@ -56,25 +58,43 @@ const TourComponent = _ref => {
56
58
  element: tourStepArrowRef
57
59
  })]
58
60
  });
59
- const [animation, animationApi] = useSpring(() => ({
60
- from: {
61
- opacity: 0
62
- },
63
- config: springConfig.slow
64
- }), []);
65
61
  const handleChange = useCallback(tourStep => {
66
- // If the opacity is already 0, animating it to 0 does not trigger `onRest`
67
- if (animation.opacity.get() === 0) return onChange(tourStep);
68
62
  void animationApi.start({
69
63
  to: {
70
64
  opacity: 0
71
65
  },
72
66
  config: springConfig.stiff,
73
- onRest: () => onChange(tourStep)
67
+ onResolve: () => {
68
+ onChange(tourStep);
69
+ }
74
70
  });
75
- }, [animation.opacity, animationApi, onChange]);
76
- const revealTourStep = useCallback(() => {
77
- activeTourStepTarget == null || activeTourStepTarget.measureInWindow((x, y, width, height) => {
71
+ }, [animationApi, onChange]);
72
+ const api = useTour({
73
+ steps,
74
+ activeTourStep,
75
+ onChange: handleChange
76
+ });
77
+ const {
78
+ activeTourStepTarget,
79
+ setActiveTourStepTarget
80
+ } = api;
81
+
82
+ // Component Lifecycle & Side Effects
83
+ // ---------------------------------------------------------------------------
84
+ // This component's visual side effects (animations) are driven by a single
85
+ // callback, `handleSetActiveTourStepTarget`.
86
+ //
87
+ // This function is called from the `TourStep` component's ref callback
88
+ // whenever the active step changes. Because the ref callback is tied to the
89
+ // lifecycle of the `TourStep`, it reliably fires whenever a new step becomes
90
+ // active.
91
+ //
92
+ // This centralizes the logic for revealing a step: when the callback fires,
93
+ // we measure the target element's position on screen and then kick off the
94
+ // fade-in animation, all in one sequential, event-driven flow.
95
+
96
+ const handleActiveTourStepTargetChange = useCallback(target => {
97
+ target == null || target.measureInWindow((x, y, width, height) => {
78
98
  refs.setReference({
79
99
  measure: callback => {
80
100
  callback(x, y, width, height);
@@ -87,53 +107,44 @@ const TourComponent = _ref => {
87
107
  }
88
108
  });
89
109
  });
90
- }, [activeTourStepTarget, animationApi, refs]);
91
- const api = useTour({
92
- steps,
93
- activeTourStep,
94
- onChange: handleChange
95
- });
96
- useEffect(() => {
97
- if (!activeTourStep) return;
98
- revealTourStep();
99
- }, [activeTourStep, revealTourStep]);
110
+ setActiveTourStepTarget(target);
111
+ }, [animationApi, refs, setActiveTourStepTarget]);
100
112
  return /*#__PURE__*/_jsx(OverlayContentContext.Provider, {
101
113
  value: overlayContentContextValue,
102
- children: /*#__PURE__*/_jsx(RefMapContext.Provider, {
103
- value: refMap,
104
- children: /*#__PURE__*/_jsxs(TourContext.Provider, {
105
- value: api,
106
- children: [children, !!RenderedTourStep && /*#__PURE__*/_jsxs(Modal, {
107
- transparent: true,
108
- accessibilityLabel: accessibilityLabel,
109
- accessibilityLabelledBy: accessibilityLabelledBy,
110
- animationType: "none",
111
- id: id,
112
- presentationStyle: "overFullScreen",
113
- testID: testID,
114
- children: [!((_activeTourStep$hideO = activeTourStep.hideOverlay) != null ? _activeTourStep$hideO : hideOverlay) && !!activeTourStepTarget && /*#__PURE__*/_jsx(animated.View, {
114
+ children: /*#__PURE__*/_jsxs(TourContext.Provider, {
115
+ value: _extends({}, api, {
116
+ setActiveTourStepTarget: handleActiveTourStepTargetChange
117
+ }),
118
+ children: [children, !!RenderedTourStep && /*#__PURE__*/_jsxs(Modal, {
119
+ transparent: true,
120
+ accessibilityLabel: accessibilityLabel,
121
+ accessibilityLabelledBy: accessibilityLabelledBy,
122
+ animationType: "none",
123
+ id: id,
124
+ presentationStyle: "overFullScreen",
125
+ testID: testID,
126
+ children: [!((_activeTourStep$hideO = activeTourStep.hideOverlay) != null ? _activeTourStep$hideO : hideOverlay) && !!activeTourStepTarget && /*#__PURE__*/_jsx(animated.View, {
127
+ style: animation,
128
+ children: /*#__PURE__*/_jsx(TourMaskComponent, {
129
+ activeTourStepTarget: activeTourStepTarget,
130
+ borderRadius: (_activeTourStep$tourM = activeTourStep.tourMaskBorderRadius) != null ? _activeTourStep$tourM : tourMaskBorderRadius,
131
+ padding: (_activeTourStep$tourM2 = activeTourStep.tourMaskPadding) != null ? _activeTourStep$tourM2 : tourMaskPadding
132
+ })
133
+ }), /*#__PURE__*/_jsx(View, {
134
+ ref: refs.setFloating,
135
+ collapsable: false,
136
+ style: floatingStyles,
137
+ children: /*#__PURE__*/_jsxs(animated.View, {
115
138
  style: animation,
116
- children: /*#__PURE__*/_jsx(TourMaskComponent, {
117
- activeTourStepTarget: activeTourStepTarget,
118
- borderRadius: (_activeTourStep$tourM = activeTourStep.tourMaskBorderRadius) != null ? _activeTourStep$tourM : tourMaskBorderRadius,
119
- padding: (_activeTourStep$tourM2 = activeTourStep.tourMaskPadding) != null ? _activeTourStep$tourM2 : tourMaskPadding
120
- })
121
- }), /*#__PURE__*/_jsx(View, {
122
- ref: refs.setFloating,
123
- collapsable: false,
124
- style: floatingStyles,
125
- children: /*#__PURE__*/_jsxs(animated.View, {
126
- style: animation,
127
- children: [/*#__PURE__*/_jsx(RenderedTourStepArrow, {
128
- ref: tourStepArrowRef,
129
- arrow: arrow,
130
- placement: placement,
131
- style: activeTourStep == null ? void 0 : activeTourStep.arrowStyle
132
- }), /*#__PURE__*/_jsx(RenderedTourStep, _extends({}, activeTourStep))]
133
- })
134
- })]
139
+ children: [/*#__PURE__*/_jsx(RenderedTourStepArrow, {
140
+ ref: tourStepArrowRef,
141
+ arrow: arrow,
142
+ placement: placement,
143
+ style: activeTourStep == null ? void 0 : activeTourStep.arrowStyle
144
+ }), /*#__PURE__*/_jsx(RenderedTourStep, _extends({}, activeTourStep))]
145
+ })
135
146
  })]
136
- })
147
+ })]
137
148
  })
138
149
  });
139
150
  };
@@ -1,6 +1,6 @@
1
1
  import React, { useCallback } from 'react';
2
2
  import { View } from 'react-native';
3
- import { useRefMapContext } from '@coinbase/cds-common/system/RefMapContext';
3
+ import { useTourContext } from '@coinbase/cds-common/tour/TourContext';
4
4
  import { jsx as _jsx } from "react/jsx-runtime";
5
5
  /**
6
6
  * The TourStep component wraps the target element (children) that you want to highlight during a step
@@ -13,9 +13,10 @@ export const TourStep = _ref => {
13
13
  children
14
14
  } = _ref;
15
15
  const {
16
- registerRef
17
- } = useRefMapContext();
18
- const refCallback = useCallback(ref => ref && registerRef(id, ref), [id, registerRef]);
16
+ activeTourStep,
17
+ setActiveTourStepTarget
18
+ } = useTourContext();
19
+ const refCallback = useCallback(ref => (activeTourStep == null ? void 0 : activeTourStep.id) === id && ref && setActiveTourStepTarget(ref), [activeTourStep, id, setActiveTourStepTarget]);
19
20
  return /*#__PURE__*/_jsx(View, {
20
21
  ref: refCallback,
21
22
  collapsable: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coinbase/cds-mobile",
3
- "version": "8.13.2",
3
+ "version": "8.13.5",
4
4
  "description": "Coinbase Design System - Mobile",
5
5
  "repository": {
6
6
  "type": "git",
@@ -150,9 +150,9 @@
150
150
  "react-native-svg": "^14.1.0"
151
151
  },
152
152
  "dependencies": {
153
- "@coinbase/cds-common": "^8.13.2",
153
+ "@coinbase/cds-common": "^8.13.5",
154
154
  "@coinbase/cds-icons": "^5.4.1",
155
- "@coinbase/cds-illustrations": "^4.22.1",
155
+ "@coinbase/cds-illustrations": "^4.23.0",
156
156
  "@coinbase/cds-lottie-files": "^3.3.1",
157
157
  "@coinbase/cds-utils": "^2.3.2",
158
158
  "@floating-ui/react-native": "^0.10.5",