@coinbase/cds-mobile 8.75.2 → 8.75.4

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,18 @@ All notable changes to this project will be documented in this file.
8
8
 
9
9
  <!-- template-start -->
10
10
 
11
+ ## 8.75.4 (6/10/2026 PST)
12
+
13
+ #### 🐞 Fixes
14
+
15
+ - Fix: custom Switch sizes now center in the background track correctly.
16
+
17
+ ## 8.75.3 (5/22/2026 PST)
18
+
19
+ #### 🐞 Fixes
20
+
21
+ - Fix: update tray drag position live on iOS during swipe. [[#719](https://github.com/coinbase/cds/pull/719)]
22
+
11
23
  ## 8.75.2 ((5/19/2026, 01:13 PM PST))
12
24
 
13
25
  This is an artificial version bump with no new change.
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.d.ts","sourceRoot":"","sources":["../../src/controls/Switch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoC,MAAM,OAAO,CAAC;AACzD,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,cAAc,CAAC;AAOrD,OAAO,EAAW,KAAK,gBAAgB,EAAyB,MAAM,WAAW,CAAC;AAElF,MAAM,MAAM,eAAe,CAAC,WAAW,SAAS,MAAM,IAAI,IAAI,CAC5D,gBAAgB,CAAC,WAAW,CAAC,EAC7B,OAAO,GAAG,aAAa,GAAG,SAAS,CACpC,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,WAAW,SAAS,MAAM,IAAI,eAAe,CAAC,WAAW,CAAC,CAAC;AAiHnF,eAAO,MAAM,MAAM,6GAAsB,CAAC"}
1
+ {"version":3,"file":"Switch.d.ts","sourceRoot":"","sources":["../../src/controls/Switch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoC,MAAM,OAAO,CAAC;AACzD,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,cAAc,CAAC;AAOrD,OAAO,EAAW,KAAK,gBAAgB,EAAyB,MAAM,WAAW,CAAC;AAElF,MAAM,MAAM,eAAe,CAAC,WAAW,SAAS,MAAM,IAAI,IAAI,CAC5D,gBAAgB,CAAC,WAAW,CAAC,EAC7B,OAAO,GAAG,aAAa,GAAG,SAAS,CACpC,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,WAAW,SAAS,MAAM,IAAI,eAAe,CAAC,WAAW,CAAC,CAAC;AAqHnF,eAAO,MAAM,MAAM,6GAAsB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useDrawerPanResponder.d.ts","sourceRoot":"","sources":["../../../src/overlays/drawer/useDrawerPanResponder.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAmD,MAAM,cAAc,CAAC;AAC9F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAgB7D,KAAK,2BAA2B,GAAG;IACjC,eAAe,EAAE,QAAQ,CAAC,KAAK,CAAC;IAChC,eAAe,EAAE,QAAQ,CAAC,kBAAkB,CAAC;IAC7C,GAAG,EAAE,gBAAgB,CAAC;IACtB,iCAAiC,EAAE,OAAO,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,gBAAgB,EAAE,QAAQ,CAAC,KAAK,CAAC;IACjC,8BAA8B,EAAE,MAAM,CAAC;CACxC,CAAC;AASF,eAAO,MAAM,qBAAqB,GAAI,6JASnC,2BAA2B,gDAiN7B,CAAC"}
1
+ {"version":3,"file":"useDrawerPanResponder.d.ts","sourceRoot":"","sources":["../../../src/overlays/drawer/useDrawerPanResponder.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAmD,MAAM,cAAc,CAAC;AAC9F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAgB7D,KAAK,2BAA2B,GAAG;IACjC,eAAe,EAAE,QAAQ,CAAC,KAAK,CAAC;IAChC,eAAe,EAAE,QAAQ,CAAC,kBAAkB,CAAC;IAC7C,GAAG,EAAE,gBAAgB,CAAC;IACtB,iCAAiC,EAAE,OAAO,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,gBAAgB,EAAE,QAAQ,CAAC,KAAK,CAAC;IACjC,8BAA8B,EAAE,MAAM,CAAC;CACxC,CAAC;AASF,eAAO,MAAM,qBAAqB,GAAI,6JASnC,2BAA2B,gDA4N7B,CAAC"}
@@ -31,6 +31,10 @@ const SwitchIcon = _ref => {
31
31
  switchHeight,
32
32
  switchThumbSize
33
33
  } = theme.controlSize;
34
+
35
+ // Inset that keeps the thumb centered within the track regardless of the
36
+ // configured track/thumb sizes (built-in themes use a 1px inset).
37
+ const thumbInset = (switchHeight - switchThumbSize) / 2;
34
38
  const trackStyle = useMemo(() => [{
35
39
  width: switchWidth,
36
40
  height: switchHeight
@@ -39,16 +43,16 @@ const SwitchIcon = _ref => {
39
43
  width: switchThumbSize,
40
44
  height: switchThumbSize,
41
45
  position: 'absolute',
42
- top: 1 - borderSize,
43
- left: 1 - borderSize
46
+ top: thumbInset - borderSize,
47
+ left: thumbInset - borderSize
44
48
  }, {
45
49
  transform: [{
46
50
  translateX: animatedScaleValue.interpolate({
47
51
  inputRange: [0.9, 1],
48
- outputRange: [0, switchWidth - switchThumbSize - 2]
52
+ outputRange: [0, switchWidth - switchThumbSize - thumbInset * 2]
49
53
  })
50
54
  }]
51
- }], [animatedScaleValue, borderSize, switchThumbSize, switchWidth]);
55
+ }], [animatedScaleValue, borderSize, thumbInset, switchThumbSize, switchWidth]);
52
56
  return /*#__PURE__*/_jsx(Interactable, {
53
57
  background: background,
54
58
  borderColor: borderColor,
@@ -1,12 +1,16 @@
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); }
1
2
  import React, { useState } from 'react';
2
3
  import { Example, ExampleScreen } from '../../examples/ExampleScreen';
3
4
  import { VStack } from '../../layout';
5
+ import { ThemeProvider } from '../../system/ThemeProvider';
6
+ import { defaultTheme } from '../../themes/defaultTheme';
4
7
  import { Switch } from '../Switch';
5
8
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
9
  const SwitchScreen = () => {
7
10
  const [isChecked, setIsChecked] = useState(false);
8
11
  const [isChecked2, setIsChecked2] = useState(true);
9
12
  const [isChecked3, setIsChecked3] = useState(false);
13
+ const [isChecked4, setIsChecked4] = useState(false);
10
14
  return /*#__PURE__*/_jsxs(ExampleScreen, {
11
15
  children: [/*#__PURE__*/_jsx(Example, {
12
16
  inline: true,
@@ -64,6 +68,37 @@ const SwitchScreen = () => {
64
68
  })]
65
69
  });
66
70
  }
71
+ }), /*#__PURE__*/_jsx(Example, {
72
+ inline: true,
73
+ title: "Custom Theme",
74
+ children: () => {
75
+ const toggleChecked = () => setIsChecked4(prevChecked => !prevChecked);
76
+ const customTheme = _extends({}, defaultTheme, {
77
+ controlSize: _extends({}, defaultTheme.controlSize, {
78
+ switchHeight: 24,
79
+ switchThumbSize: 20,
80
+ switchWidth: 44
81
+ })
82
+ });
83
+ return /*#__PURE__*/_jsx(ThemeProvider, {
84
+ activeColorScheme: "light",
85
+ theme: customTheme,
86
+ children: /*#__PURE__*/_jsxs(VStack, {
87
+ gap: 2,
88
+ children: [/*#__PURE__*/_jsx(Switch, {
89
+ checked: isChecked4,
90
+ onChange: toggleChecked,
91
+ children: "Interactive"
92
+ }), /*#__PURE__*/_jsx(Switch, {
93
+ checked: false,
94
+ children: "Off"
95
+ }), /*#__PURE__*/_jsx(Switch, {
96
+ checked: true,
97
+ children: "On"
98
+ })]
99
+ })
100
+ });
101
+ }
67
102
  }), /*#__PURE__*/_jsx(Example, {
68
103
  inline: true,
69
104
  title: "Elevation",
@@ -127,11 +127,20 @@ export const useDrawerPanResponder = _ref => {
127
127
  }
128
128
  return false;
129
129
  }, [isTryingToDismiss, parseGestureState, isFlingToDismiss, isSwipeToDismiss]);
130
+ const initializeDragAnimation = useCallback(() => {
131
+ // On iOS, setOffset during pan move does not flush to native; capture the current
132
+ // position as offset via extractOffset() so setValue in onPanResponderMove updates the UI.
133
+ drawerAnimation.stopAnimation();
134
+ opacityAnimation.stopAnimation();
135
+ drawerAnimation.extractOffset();
136
+ opacityAnimation.extractOffset();
137
+ }, [drawerAnimation, opacityAnimation]);
130
138
  const panGestureHandlers = useMemo(() => {
131
139
  return PanResponder.create({
132
140
  onStartShouldSetPanResponder: () => true,
133
141
  onMoveShouldSetPanResponder: shouldCaptureGestures,
134
142
  onMoveShouldSetPanResponderCapture: shouldCaptureGestures,
143
+ onPanResponderGrant: initializeDragAnimation,
135
144
  onPanResponderMove: (_, gestureState) => {
136
145
  const {
137
146
  isDragging,
@@ -148,20 +157,20 @@ export const useDrawerPanResponder = _ref => {
148
157
  outputRange: [0, 0.1],
149
158
  clamp: true
150
159
  });
151
- drawerAnimation.setOffset(calculateDragOffset(normalizedDistance));
160
+ drawerAnimation.setValue(calculateDragOffset(normalizedDistance));
152
161
  } else {
153
162
  const normalizedDrawerTransition = modulate(distance, {
154
163
  inputRange: [0, isHorizontalDrawer ? horizontalDrawerMaxPanDistance : verticalDrawerMaxPanDistance],
155
164
  outputRange: [0, normalizeDrawerPanDistanceMultiplier],
156
165
  clamp: false
157
166
  });
158
- drawerAnimation.setOffset(normalizedDrawerTransition);
167
+ drawerAnimation.setValue(normalizedDrawerTransition);
159
168
  const normalizedOpacityTransition = modulate(distance, {
160
169
  inputRange: [0, isHorizontalDrawer ? horizontalDrawerMaxPanDistance : verticalDrawerMaxPanDistance],
161
170
  outputRange: [0, 1],
162
171
  clamp: false
163
172
  });
164
- opacityAnimation.setOffset(normalizedOpacityTransition);
173
+ opacityAnimation.setValue(normalizedOpacityTransition);
165
174
  }
166
175
  }
167
176
  },
@@ -176,6 +185,6 @@ export const useDrawerPanResponder = _ref => {
176
185
  }
177
186
  }
178
187
  });
179
- }, [drawerAnimation, animateSnapBack, parseGestureState, shouldCaptureGestures, shouldDismiss, drawerWidth, drawerHeight, pin, isHorizontalDrawer, onBlur, handleSwipeToClose, opacityAnimation]);
188
+ }, [drawerAnimation, animateSnapBack, initializeDragAnimation, parseGestureState, shouldCaptureGestures, shouldDismiss, drawerWidth, drawerHeight, pin, isHorizontalDrawer, onBlur, handleSwipeToClose, opacityAnimation]);
180
189
  return panGestureHandlers;
181
190
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coinbase/cds-mobile",
3
- "version": "8.75.2",
3
+ "version": "8.75.4",
4
4
  "description": "Coinbase Design System - Mobile",
5
5
  "repository": {
6
6
  "type": "git",
@@ -196,7 +196,7 @@
196
196
  "react-native-svg": "^14.1.0"
197
197
  },
198
198
  "dependencies": {
199
- "@coinbase/cds-common": "^8.75.2",
199
+ "@coinbase/cds-common": "^8.75.4",
200
200
  "@coinbase/cds-icons": "^5.16.0",
201
201
  "@coinbase/cds-illustrations": "^4.40.1",
202
202
  "@coinbase/cds-lottie-files": "^3.3.4",