@coinbase/cds-mobile 9.7.0 → 9.7.2
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/alpha/select/DefaultSelectControl.d.ts.map +1 -1
- package/dts/overlays/modal/Modal.d.ts.map +1 -1
- package/dts/overlays/overlay/Overlay.d.ts +1 -1
- package/dts/overlays/overlay/Overlay.d.ts.map +1 -1
- package/esm/alpha/select/DefaultSelectControl.js +15 -11
- package/esm/alpha/select/__stories__/AlphaSelect.stories.js +13 -0
- package/esm/overlays/modal/Modal.js +7 -1
- package/esm/overlays/overlay/Overlay.js +8 -1
- package/package.json +2 -2
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
|
+
## 9.7.2 (7/23/2026 PST)
|
|
12
|
+
|
|
13
|
+
#### 🐞 Fixes
|
|
14
|
+
|
|
15
|
+
- Fix: adjust select placeholder fallback. [[#805](https://github.com/coinbase/cds/pull/805)]
|
|
16
|
+
|
|
17
|
+
## 9.7.1 (7/22/2026 PST)
|
|
18
|
+
|
|
19
|
+
#### 🐞 Fixes
|
|
20
|
+
|
|
21
|
+
- Prevent Overlay/Modal scrim collapsing to 0x0 under Fabric. [[#804](https://github.com/coinbase/cds/pull/804)]
|
|
22
|
+
|
|
11
23
|
## 9.7.0 (7/22/2026 PST)
|
|
12
24
|
|
|
13
25
|
#### 🚀 Updates
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultSelectControl.d.ts","sourceRoot":"","sources":["../../../src/alpha/select/DefaultSelectControl.tsx"],"names":[],"mappings":"AACA,OAAO,EAA6B,gBAAgB,EAAkB,MAAM,cAAc,CAAC;AAe3F,OAAO,KAAK,EAAE,kBAAkB,EAAgB,UAAU,EAAE,MAAM,UAAU,CAAC;AAY7E,KAAK,6BAA6B,GAAG,CACnC,IAAI,SAAS,UAAU,EACvB,iBAAiB,SAAS,MAAM,GAAG,MAAM,EAEzC,KAAK,EAAE,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,CAAC,GAAG;IACnD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC;CAC9D,KACE,KAAK,CAAC,YAAY,CAAC;AAExB,eAAO,MAAM,6BAA6B,wCACvC,IAAI,SAAS,UAAU,EAAE,iBAAiB,SAAS,MAAM,sfAsCvD,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,CAAC,GAAG;IAC/C,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC;CAC9D,
|
|
1
|
+
{"version":3,"file":"DefaultSelectControl.d.ts","sourceRoot":"","sources":["../../../src/alpha/select/DefaultSelectControl.tsx"],"names":[],"mappings":"AACA,OAAO,EAA6B,gBAAgB,EAAkB,MAAM,cAAc,CAAC;AAe3F,OAAO,KAAK,EAAE,kBAAkB,EAAgB,UAAU,EAAE,MAAM,UAAU,CAAC;AAY7E,KAAK,6BAA6B,GAAG,CACnC,IAAI,SAAS,UAAU,EACvB,iBAAiB,SAAS,MAAM,GAAG,MAAM,EAEzC,KAAK,EAAE,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,CAAC,GAAG;IACnD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC;CAC9D,KACE,KAAK,CAAC,YAAY,CAAC;AAExB,eAAO,MAAM,6BAA6B,wCACvC,IAAI,SAAS,UAAU,EAAE,iBAAiB,SAAS,MAAM,sfAsCvD,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,CAAC,GAAG;IAC/C,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC;CAC9D,8CAuZF,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAoC,6BAA6B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/overlays/modal/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+E,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/overlays/modal/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+E,MAAM,OAAO,CAAC;AAQpG,OAAO,KAAK,EAAE,UAAU,IAAI,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGrF,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAKlG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAC;AAG1E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAKjD,KAAK,wBAAwB,GAAG;IAAE,UAAU,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC;AAE3D;;;GAGG;AACH,KAAK,gBAAgB,GAAG,IAAI,CAC1B,QAAQ,EACN,YAAY,GACZ,OAAO,GACP,aAAa,GACb,aAAa,GACb,cAAc,GACd,qBAAqB,GACrB,sBAAsB,GACtB,wBAAwB,GACxB,yBAAyB,GACzB,gBAAgB,GAChB,mBAAmB,GACnB,kBAAkB,GAClB,gBAAgB,GAChB,UAAU,GACV,aAAa,GACb,gBAAgB,GAChB,eAAe,GACf,aAAa,GACb,oBAAoB,GACpB,kBAAkB,GAClB,WAAW,GACX,SAAS,GACT,UAAU,GACV,UAAU,GACV,YAAY,GACZ,eAAe,GACf,cAAc,GACd,YAAY,GACZ,UAAU,GACV,WAAW,GACX,UAAU,GACV,WAAW,CACd,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,WAAW,GACtC,iBAAiB,GACjB,gBAAgB,GAChB,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,SAAS,GAAG,gBAAgB,GAAG,eAAe,CAAC,GAAG;IAChF,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,wBAAwB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IACpF;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB;;SAEK;IACL,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC7B,yDAAyD;IACzD,MAAM,CAAC,EAAE;QACP,iCAAiC;QACjC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;QAC7B,mDAAmD;QACnD,QAAQ,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;KACjC,CAAC;CACH,CAAC;AAEJ,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;AAEvE,MAAM,MAAM,UAAU,GAAG,cAAc,CAAC;AAMxC,eAAO,MAAM,KAAK,iDAIb,UAAU,GAAG;IACd,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;CACpC,6CAyJF,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type
|
|
2
|
+
import { type Animated } from 'react-native';
|
|
3
3
|
import type { BoxBaseProps } from '../../layout/Box';
|
|
4
4
|
import type { VStackProps } from '../../layout/VStack';
|
|
5
5
|
export type OverlayBaseProps = Omit<BoxBaseProps, 'opacity'> & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Overlay.d.ts","sourceRoot":"","sources":["../../../src/overlays/overlay/Overlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAe,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"Overlay.d.ts","sourceRoot":"","sources":["../../../src/overlays/overlay/Overlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAe,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,KAAK,QAAQ,EAAuB,MAAM,cAAc,CAAC;AAQlE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAOvD,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,GAAG;IAC7D,gIAAgI;IAChI,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AAE3E,eAAO,MAAM,OAAO,qCAAiB,YAAY,6CAyB/C,CAAC"}
|
|
@@ -112,19 +112,23 @@ export const DefaultSelectControlComponent = /*#__PURE__*/memo(_ref => {
|
|
|
112
112
|
});
|
|
113
113
|
return map;
|
|
114
114
|
}, [options]);
|
|
115
|
+
const matchedOption = useMemo(() => {
|
|
116
|
+
if (isMultiSelect || value === null || Array.isArray(value)) return undefined;
|
|
117
|
+
return optionsMap.get(value);
|
|
118
|
+
}, [isMultiSelect, optionsMap, value]);
|
|
119
|
+
const isShowingPlaceholder = matchedOption === undefined;
|
|
115
120
|
const singleValueContent = useMemo(() => {
|
|
116
|
-
var _ref3,
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}, [hasValue, isMultiSelect, optionsMap, placeholder, value]);
|
|
121
|
+
var _ref3, _matchedOption$label;
|
|
122
|
+
if (!matchedOption) return placeholder;
|
|
123
|
+
return (_ref3 = (_matchedOption$label = matchedOption.label) != null ? _matchedOption$label : matchedOption.description) != null ? _ref3 : matchedOption.value;
|
|
124
|
+
}, [matchedOption, placeholder]);
|
|
121
125
|
const computedControlAccessibilityLabel = useMemo(() => {
|
|
122
126
|
// For multi-select, set the label to the content of each selected value and the hidden selected options label
|
|
123
127
|
if (isMultiSelect) {
|
|
124
128
|
const selectedValues = value.map(v => {
|
|
125
|
-
var
|
|
129
|
+
var _ref4, _ref5, _option$label;
|
|
126
130
|
const option = optionsMap.get(v);
|
|
127
|
-
return (
|
|
131
|
+
return (_ref4 = (_ref5 = (_option$label = option == null ? void 0 : option.label) != null ? _option$label : option == null ? void 0 : option.description) != null ? _ref5 : option == null ? void 0 : option.value) != null ? _ref4 : v;
|
|
128
132
|
}).slice(0, maxSelectedOptionsToShow).join(', ');
|
|
129
133
|
return accessibilityLabel + ", " + (value.length > 0 ? selectedValues : placeholder != null ? placeholder : '') + (value.length > maxSelectedOptionsToShow ? ', ' + hiddenSelectedOptionsLabel : '');
|
|
130
134
|
}
|
|
@@ -183,7 +187,7 @@ export const DefaultSelectControlComponent = /*#__PURE__*/memo(_ref => {
|
|
|
183
187
|
maxWidth: "100%",
|
|
184
188
|
minWidth: 0,
|
|
185
189
|
children: [optionsToShow.map(option => {
|
|
186
|
-
var _option$value,
|
|
190
|
+
var _option$value, _ref6, _ref7, _option$label2;
|
|
187
191
|
const accessibilityLabel = typeof option.label === 'string' ? option.label : typeof option.description === 'string' ? option.description : (_option$value = option.value) != null ? _option$value : '';
|
|
188
192
|
return /*#__PURE__*/_jsx(InputChip, {
|
|
189
193
|
compact: true,
|
|
@@ -196,7 +200,7 @@ export const DefaultSelectControlComponent = /*#__PURE__*/memo(_ref => {
|
|
|
196
200
|
event == null || event.stopPropagation();
|
|
197
201
|
onChange == null || onChange(option.value);
|
|
198
202
|
},
|
|
199
|
-
children: (
|
|
203
|
+
children: (_ref6 = (_ref7 = (_option$label2 = option.label) != null ? _option$label2 : option.description) != null ? _ref7 : option.value) != null ? _ref6 : ''
|
|
200
204
|
}, option.value);
|
|
201
205
|
}), value.length - maxSelectedOptionsToShow > 0 && /*#__PURE__*/_jsx(InputChip, {
|
|
202
206
|
compact: true,
|
|
@@ -209,12 +213,12 @@ export const DefaultSelectControlComponent = /*#__PURE__*/memo(_ref => {
|
|
|
209
213
|
}
|
|
210
214
|
return typeof singleValueContent === 'string' ? /*#__PURE__*/_jsx(Text, {
|
|
211
215
|
align: align,
|
|
212
|
-
color:
|
|
216
|
+
color: isShowingPlaceholder ? 'fgMuted' : 'fg',
|
|
213
217
|
ellipsize: "tail",
|
|
214
218
|
font: font,
|
|
215
219
|
children: singleValueContent
|
|
216
220
|
}) : singleValueContent;
|
|
217
|
-
}, [hasValue, isMultiSelect, singleValueContent, font, align, value, maxSelectedOptionsToShow, valueAlignment, hiddenSelectedOptionsLabel, optionsMap, removeSelectedOptionAccessibilityLabel, disabled, onChange, isInteractionBlocked]);
|
|
221
|
+
}, [hasValue, isMultiSelect, isShowingPlaceholder, singleValueContent, font, align, value, maxSelectedOptionsToShow, valueAlignment, hiddenSelectedOptionsLabel, optionsMap, removeSelectedOptionAccessibilityLabel, disabled, onChange, isInteractionBlocked]);
|
|
218
222
|
|
|
219
223
|
// onBlur/onFocus on ViewProps allow null returns but TouchableOpacity's onBlur/onFocus props do not.
|
|
220
224
|
// This appears like a type inconsistency in react-native's type definitions.
|
|
@@ -303,6 +303,16 @@ const DefaultExample = () => {
|
|
|
303
303
|
value: value
|
|
304
304
|
});
|
|
305
305
|
};
|
|
306
|
+
const EmptyStringValueExample = () => {
|
|
307
|
+
const [value, setValue] = useState('');
|
|
308
|
+
return /*#__PURE__*/_jsx(Select, {
|
|
309
|
+
label: "Empty string value",
|
|
310
|
+
onChange: setValue,
|
|
311
|
+
options: exampleOptionsWithoutNull,
|
|
312
|
+
placeholder: "Select an option",
|
|
313
|
+
value: value
|
|
314
|
+
});
|
|
315
|
+
};
|
|
306
316
|
const TypedSelectExample = () => {
|
|
307
317
|
const typedOptions = [{
|
|
308
318
|
value: null,
|
|
@@ -1372,6 +1382,9 @@ const SelectV3Screen = () => {
|
|
|
1372
1382
|
children: [/*#__PURE__*/_jsx(Example, {
|
|
1373
1383
|
title: "Default",
|
|
1374
1384
|
children: /*#__PURE__*/_jsx(DefaultExample, {})
|
|
1385
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
1386
|
+
title: "Empty string value",
|
|
1387
|
+
children: /*#__PURE__*/_jsx(EmptyStringValueExample, {})
|
|
1375
1388
|
}), /*#__PURE__*/_jsx(Example, {
|
|
1376
1389
|
title: "Typed",
|
|
1377
1390
|
children: /*#__PURE__*/_jsx(TypedSelectExample, {})
|
|
@@ -3,7 +3,7 @@ const _excluded = ["ref"],
|
|
|
3
3
|
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); }
|
|
4
4
|
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; }
|
|
5
5
|
import React, { memo, useCallback, useEffect, useImperativeHandle, useMemo, useState } from 'react';
|
|
6
|
-
import { Modal as RNModal, Platform, StatusBar, StyleSheet } from 'react-native';
|
|
6
|
+
import { Modal as RNModal, Platform, StatusBar, StyleSheet, useWindowDimensions } from 'react-native';
|
|
7
7
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
8
8
|
import { usePreviousValue } from '@coinbase/cds-common/hooks/usePreviousValue';
|
|
9
9
|
import { ModalContext } from '@coinbase/cds-common/overlays/ModalContext';
|
|
@@ -76,6 +76,10 @@ export const Modal = /*#__PURE__*/memo(_ref => {
|
|
|
76
76
|
}, animateIn, animateOut] = useModalAnimation();
|
|
77
77
|
const [internalVisible, setInternalVisible] = useState(visible);
|
|
78
78
|
const prevVisible = usePreviousValue(visible);
|
|
79
|
+
const {
|
|
80
|
+
width,
|
|
81
|
+
height
|
|
82
|
+
} = useWindowDimensions();
|
|
79
83
|
const handleClose = useCallback(() => {
|
|
80
84
|
animateOut.start(_ref2 => {
|
|
81
85
|
let {
|
|
@@ -141,6 +145,7 @@ export const Modal = /*#__PURE__*/memo(_ref => {
|
|
|
141
145
|
borderedVertical: borderedVertical,
|
|
142
146
|
color: color,
|
|
143
147
|
elevation: elevation,
|
|
148
|
+
height: height,
|
|
144
149
|
maxHeight: maxHeight,
|
|
145
150
|
maxWidth: maxWidth,
|
|
146
151
|
minHeight: minHeight,
|
|
@@ -159,6 +164,7 @@ export const Modal = /*#__PURE__*/memo(_ref => {
|
|
|
159
164
|
}],
|
|
160
165
|
opacity
|
|
161
166
|
}, customStyles == null ? void 0 : customStyles.modal],
|
|
167
|
+
width: width,
|
|
162
168
|
children: /*#__PURE__*/_jsx(SafeAreaView, {
|
|
163
169
|
style: [styles.safeAreaContainer, customStyles == null ? void 0 : customStyles.safeArea],
|
|
164
170
|
children: /*#__PURE__*/_jsx(ModalContext.Provider, {
|
|
@@ -2,6 +2,7 @@ const _excluded = ["opacity", "style"];
|
|
|
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, { memo } from 'react';
|
|
5
|
+
import { useWindowDimensions } from 'react-native';
|
|
5
6
|
import { OverlayContentContext } from '@coinbase/cds-common/overlays/OverlayContentContext';
|
|
6
7
|
import { useComponentConfig } from '../../hooks/useComponentConfig';
|
|
7
8
|
import { useTheme } from '../../hooks/useTheme';
|
|
@@ -19,17 +20,23 @@ export const Overlay = /*#__PURE__*/memo(_props => {
|
|
|
19
20
|
} = mergedProps,
|
|
20
21
|
props = _objectWithoutPropertiesLoose(mergedProps, _excluded);
|
|
21
22
|
const theme = useTheme();
|
|
23
|
+
const {
|
|
24
|
+
width,
|
|
25
|
+
height
|
|
26
|
+
} = useWindowDimensions();
|
|
22
27
|
return /*#__PURE__*/_jsx(OverlayContentContext.Provider, {
|
|
23
28
|
value: overlayContentContextValue,
|
|
24
29
|
children: /*#__PURE__*/_jsx(VStack, _extends({
|
|
25
30
|
animated: true,
|
|
26
31
|
renderToHardwareTextureAndroid: true,
|
|
27
32
|
background: "bgOverlay",
|
|
33
|
+
height: height,
|
|
28
34
|
opacity: opacity,
|
|
29
35
|
pin: "all",
|
|
30
36
|
style: [theme.activeColorScheme === 'dark' ? {
|
|
31
37
|
backgroundColor: "rgba(" + (theme == null || (_theme$darkSpectrum = theme.darkSpectrum) == null ? void 0 : _theme$darkSpectrum.gray0) + ", 0.5)"
|
|
32
|
-
} : undefined, style]
|
|
38
|
+
} : undefined, style],
|
|
39
|
+
width: width
|
|
33
40
|
}, props))
|
|
34
41
|
});
|
|
35
42
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coinbase/cds-mobile",
|
|
3
|
-
"version": "9.7.
|
|
3
|
+
"version": "9.7.2",
|
|
4
4
|
"description": "Coinbase Design System - Mobile",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -218,7 +218,7 @@
|
|
|
218
218
|
"react-native-worklets": "0.5.2"
|
|
219
219
|
},
|
|
220
220
|
"dependencies": {
|
|
221
|
-
"@coinbase/cds-common": "^9.7.
|
|
221
|
+
"@coinbase/cds-common": "^9.7.2",
|
|
222
222
|
"@coinbase/cds-icons": "^5.21.0",
|
|
223
223
|
"@coinbase/cds-illustrations": "^4.44.0",
|
|
224
224
|
"@coinbase/cds-lottie-files": "^3.3.4",
|