@coinbase/cds-mobile 8.28.2 → 8.30.0

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 (47) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dts/alpha/combobox/Combobox.d.ts +73 -0
  3. package/dts/alpha/combobox/Combobox.d.ts.map +1 -0
  4. package/dts/alpha/combobox/DefaultComboboxControl.d.ts +20 -0
  5. package/dts/alpha/combobox/DefaultComboboxControl.d.ts.map +1 -0
  6. package/dts/alpha/select/DefaultSelectControl.d.ts +1 -0
  7. package/dts/alpha/select/DefaultSelectControl.d.ts.map +1 -1
  8. package/dts/alpha/select/DefaultSelectDropdown.d.ts.map +1 -1
  9. package/dts/alpha/select/types.d.ts +4 -1
  10. package/dts/alpha/select/types.d.ts.map +1 -1
  11. package/dts/alpha/select-chip/SelectChip.d.ts +12 -6
  12. package/dts/alpha/select-chip/SelectChip.d.ts.map +1 -1
  13. package/dts/alpha/select-chip/SelectChipControl.d.ts +1 -0
  14. package/dts/alpha/select-chip/SelectChipControl.d.ts.map +1 -1
  15. package/dts/alpha/tabbed-chips/TabbedChips.d.ts +5 -0
  16. package/dts/alpha/tabbed-chips/TabbedChips.d.ts.map +1 -1
  17. package/dts/chips/Chip.d.ts +1 -1
  18. package/dts/chips/Chip.d.ts.map +1 -1
  19. package/dts/chips/ChipProps.d.ts +1 -1
  20. package/dts/chips/ChipProps.d.ts.map +1 -1
  21. package/dts/chips/InputChip.d.ts +1 -1
  22. package/dts/chips/InputChip.d.ts.map +1 -1
  23. package/dts/chips/MediaChip.d.ts +1 -1
  24. package/dts/chips/MediaChip.d.ts.map +1 -1
  25. package/dts/hooks/useHorizontalScrollToTarget.d.ts +10 -0
  26. package/dts/hooks/useHorizontalScrollToTarget.d.ts.map +1 -1
  27. package/dts/overlays/drawer/Drawer.d.ts.map +1 -1
  28. package/dts/overlays/tray/Tray.d.ts +8 -0
  29. package/dts/overlays/tray/Tray.d.ts.map +1 -1
  30. package/esm/alpha/combobox/Combobox.js +194 -0
  31. package/esm/alpha/combobox/DefaultComboboxControl.js +80 -0
  32. package/esm/alpha/combobox/__stories__/Combobox.stories.js +1019 -0
  33. package/esm/alpha/select/DefaultSelectControl.js +25 -23
  34. package/esm/alpha/select/DefaultSelectDropdown.js +80 -75
  35. package/esm/alpha/select/__stories__/AlphaSelect.stories.js +24 -4
  36. package/esm/alpha/select-chip/SelectChip.js +8 -5
  37. package/esm/alpha/select-chip/SelectChipControl.js +6 -2
  38. package/esm/alpha/select-chip/__stories__/{SelectChip.stories.js → AlphaSelectChip.stories.js} +42 -0
  39. package/esm/alpha/tabbed-chips/TabbedChips.js +12 -5
  40. package/esm/alpha/tabbed-chips/__stories__/AlphaTabbedChips.stories.js +9 -1
  41. package/esm/buttons/__stories__/SlideButton.stories.js +11 -6
  42. package/esm/carousel/__stories__/Carousel.stories.js +5 -4
  43. package/esm/hooks/useHorizontalScrollToTarget.js +16 -5
  44. package/esm/overlays/drawer/Drawer.js +14 -3
  45. package/esm/overlays/tray/Tray.js +17 -5
  46. package/esm/visualizations/__stories__/ProgressCircle.stories.js +3 -3
  47. package/package.json +2 -2
@@ -0,0 +1,194 @@
1
+ const _excluded = ["ComboboxControlComponent"],
2
+ _excluded2 = ["type", "value", "onChange", "options", "open", "setOpen", "label", "placeholder", "disabled", "variant", "startNode", "endNode", "accessibilityLabel", "defaultOpen", "searchText", "onSearch", "defaultSearchText", "closeButtonLabel", "filterFunction", "SelectControlComponent", "ComboboxControlComponent", "SelectDropdownComponent", "hideSearchInput"];
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
+ 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
+ import { createContext, forwardRef, memo, useCallback, useContext, useImperativeHandle, useMemo, useRef, useState } from 'react';
6
+ import { KeyboardAvoidingView, Platform, View } from 'react-native';
7
+ import Fuse from 'fuse.js';
8
+ import { Button } from '../../buttons/Button';
9
+ import { Box } from '../../layout';
10
+ import { StickyFooter } from '../../sticky-footer/StickyFooter';
11
+ import { DefaultSelectControl } from '../select/DefaultSelectControl';
12
+ import { DefaultSelectDropdown } from '../select/DefaultSelectDropdown';
13
+ import { Select } from '../select/Select';
14
+ import { DefaultComboboxControl } from './DefaultComboboxControl';
15
+ import { jsx as _jsx } from "react/jsx-runtime";
16
+ /**
17
+ * Context used for Combobox props needed to render to the ComboboxControlComponent.
18
+ * We use the any type here because the concrete type is not known at this point.
19
+ * The unknown type does not satisfy the SelectType type.
20
+ */
21
+ const ComboboxContext = /*#__PURE__*/createContext(null);
22
+ const useComboboxContext = () => {
23
+ const context = useContext(ComboboxContext);
24
+ if (!context) {
25
+ throw new Error('Combobox components must be used within ComboboxContext.Provider');
26
+ }
27
+ return context;
28
+ };
29
+ /**
30
+ * Wraps the ComboboxControlComponent with passed in props and the ComboboxContext values.
31
+ * This allows the usage of all props when wanting to use a custom SelectControlComponent in Combobox.
32
+ * Otherwise, a customer using a custom component would need to use props and context to get the
33
+ * <ComboboxControlComponent> rendering correctly.
34
+ */
35
+ const ComboboxControlContextAdapter = /*#__PURE__*/memo(_ref => {
36
+ let {
37
+ ComboboxControlComponent
38
+ } = _ref,
39
+ props = _objectWithoutPropertiesLoose(_ref, _excluded);
40
+ const {
41
+ searchText,
42
+ onSearch,
43
+ hideSearchInput,
44
+ options
45
+ } = useComboboxContext();
46
+ return /*#__PURE__*/_jsx(ComboboxControlComponent, _extends({}, props, {
47
+ hideSearchInput: hideSearchInput,
48
+ onSearch: onSearch,
49
+ options: options,
50
+ searchText: searchText
51
+ }));
52
+ });
53
+ const ComboboxBase = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref2, ref) => {
54
+ let {
55
+ type = 'single',
56
+ value,
57
+ onChange,
58
+ options,
59
+ open: openProp,
60
+ setOpen: setOpenProp,
61
+ label,
62
+ placeholder,
63
+ disabled,
64
+ variant,
65
+ startNode,
66
+ endNode,
67
+ accessibilityLabel = 'Combobox control',
68
+ defaultOpen,
69
+ searchText: searchTextProp,
70
+ onSearch: onSearchProp,
71
+ defaultSearchText = '',
72
+ closeButtonLabel = 'Done',
73
+ filterFunction,
74
+ SelectControlComponent = DefaultSelectControl,
75
+ ComboboxControlComponent = DefaultComboboxControl,
76
+ SelectDropdownComponent = DefaultSelectDropdown,
77
+ hideSearchInput
78
+ } = _ref2,
79
+ props = _objectWithoutPropertiesLoose(_ref2, _excluded2);
80
+ const [searchTextInternal, setSearchTextInternal] = useState(defaultSearchText);
81
+ const searchText = searchTextProp != null ? searchTextProp : searchTextInternal;
82
+ const setSearchText = onSearchProp != null ? onSearchProp : setSearchTextInternal;
83
+ if (typeof searchTextProp === 'undefined' !== (typeof onSearchProp === 'undefined')) {
84
+ throw Error('Combobox component must be fully controlled or uncontrolled: "searchText" and "onSearch" props must be provided together or not at all');
85
+ }
86
+ const [openInternal, setOpenInternal] = useState(defaultOpen != null ? defaultOpen : false);
87
+ const open = openProp != null ? openProp : openInternal;
88
+ const setOpen = setOpenProp != null ? setOpenProp : setOpenInternal;
89
+ if (typeof openProp === 'undefined' !== (typeof setOpenProp === 'undefined')) throw Error('Combobox component must be fully controlled or uncontrolled: "open" and "setOpen" props must be provided together or not at all');
90
+ const fuse = useMemo(() => new Fuse(options, {
91
+ keys: ['label', 'description'],
92
+ threshold: 0.3
93
+ }), [options]);
94
+ const filteredOptions = useMemo(() => {
95
+ if (searchText.length === 0) return options;
96
+ if (filterFunction) return filterFunction(options, searchText);
97
+ return fuse.search(searchText).map(result => result.item);
98
+ }, [filterFunction, fuse, options, searchText]);
99
+ const handleChange = useCallback(value => {
100
+ onChange == null || onChange(value);
101
+ }, [onChange]);
102
+ const controlRef = useRef(null);
103
+ useImperativeHandle(ref, () => Object.assign(controlRef.current, {
104
+ open,
105
+ setOpen
106
+ }));
107
+ const searchInputRef = useRef(null);
108
+ const handleTrayVisibilityChange = useCallback(visibility => {
109
+ if (visibility === 'visible') {
110
+ var _searchInputRef$curre;
111
+ (_searchInputRef$curre = searchInputRef.current) == null || _searchInputRef$curre.focus();
112
+ }
113
+ }, []);
114
+ const ComboboxControl = useCallback(props => {
115
+ return /*#__PURE__*/_jsx(ComboboxControlContextAdapter, _extends({}, props, {
116
+ ComboboxControlComponent: ComboboxControlComponent,
117
+ SelectControlComponent: SelectControlComponent,
118
+ controlRef: controlRef,
119
+ searchInputRef: searchInputRef
120
+ }));
121
+ }, [ComboboxControlComponent, SelectControlComponent, searchInputRef]);
122
+ const ComboboxDropdown = useCallback(props => /*#__PURE__*/_jsx(SelectDropdownComponent, _extends({
123
+ label: label,
124
+ minHeight: 500
125
+ }, props, {
126
+ footer: /*#__PURE__*/_jsx(KeyboardAvoidingView, {
127
+ behavior: "padding",
128
+ keyboardVerticalOffset: Platform.OS === 'ios' ? 86 : 0,
129
+ children: /*#__PURE__*/_jsx(View, {
130
+ style: Platform.OS === 'android' ? {
131
+ overflow: 'hidden',
132
+ paddingTop: 4
133
+ } : undefined,
134
+ children: /*#__PURE__*/_jsx(StickyFooter, {
135
+ background: "bg",
136
+ elevation: 2,
137
+ style: {
138
+ shadowOffset: {
139
+ width: 0,
140
+ height: -32
141
+ },
142
+ shadowOpacity: 0.05
143
+ },
144
+ children: /*#__PURE__*/_jsx(Button, {
145
+ compact: true,
146
+ onPress: () => setOpen(false),
147
+ children: closeButtonLabel
148
+ })
149
+ })
150
+ })
151
+ }),
152
+ header: /*#__PURE__*/_jsx(Box, {
153
+ paddingX: 3,
154
+ children: /*#__PURE__*/_jsx(ComboboxControl, _extends({
155
+ endNode: endNode,
156
+ placeholder: placeholder,
157
+ startNode: startNode,
158
+ variant: variant
159
+ }, props, {
160
+ label: null,
161
+ styles: undefined
162
+ }))
163
+ }),
164
+ onVisibilityChange: handleTrayVisibilityChange
165
+ })), [ComboboxControl, SelectDropdownComponent, closeButtonLabel, endNode, handleTrayVisibilityChange, label, placeholder, setOpen, startNode, variant]);
166
+ return /*#__PURE__*/_jsx(ComboboxContext.Provider, {
167
+ value: {
168
+ searchText,
169
+ onSearch: setSearchText,
170
+ hideSearchInput: hideSearchInput != null ? hideSearchInput : false,
171
+ options
172
+ },
173
+ children: /*#__PURE__*/_jsx(Select, _extends({
174
+ ref: controlRef,
175
+ SelectControlComponent: ComboboxControl,
176
+ SelectDropdownComponent: ComboboxDropdown,
177
+ accessibilityLabel: accessibilityLabel,
178
+ defaultOpen: defaultOpen,
179
+ disabled: disabled,
180
+ endNode: endNode,
181
+ label: label,
182
+ onChange: handleChange,
183
+ open: open,
184
+ options: filteredOptions,
185
+ placeholder: placeholder,
186
+ setOpen: setOpen,
187
+ startNode: startNode,
188
+ type: type,
189
+ value: value,
190
+ variant: variant
191
+ }, props))
192
+ });
193
+ }));
194
+ export const Combobox = ComboboxBase;
@@ -0,0 +1,80 @@
1
+ const _excluded = ["SelectControlComponent", "value", "placeholder", "open", "setOpen", "disabled", "options", "searchText", "onSearch", "searchInputRef", "hideSearchInput"];
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
+ 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 { StyleSheet } from 'react-native';
5
+ import { NativeInput } from '../../controls/NativeInput';
6
+ import { useTheme } from '../../hooks/useTheme';
7
+ import { HStack } from '../../layout';
8
+ import { Text } from '../../typography/Text';
9
+ import { DefaultSelectControl } from '../select/DefaultSelectControl';
10
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
11
+ const hasSelectedValue = currentValue => currentValue !== null && typeof currentValue !== 'undefined' && !(Array.isArray(currentValue) && currentValue.length === 0);
12
+ export const DefaultComboboxControl = _ref => {
13
+ var _props$styles, _props$styles2;
14
+ let {
15
+ SelectControlComponent = DefaultSelectControl,
16
+ value,
17
+ placeholder,
18
+ open,
19
+ setOpen,
20
+ disabled,
21
+ options,
22
+ searchText,
23
+ onSearch,
24
+ searchInputRef,
25
+ hideSearchInput
26
+ } = _ref,
27
+ props = _objectWithoutPropertiesLoose(_ref, _excluded);
28
+ const theme = useTheme();
29
+ const hasValue = hasSelectedValue(value);
30
+ const shouldRenderSearchInput = !hideSearchInput && (!hasValue || open);
31
+ return /*#__PURE__*/_jsx(SelectControlComponent, _extends({
32
+ disabled: disabled,
33
+ open: open,
34
+ options: options,
35
+ setOpen: setOpen,
36
+ value: value
37
+ }, props, {
38
+ contentNode: shouldRenderSearchInput ? /*#__PURE__*/_jsx(HStack, {
39
+ flexWrap: "wrap",
40
+ children: /*#__PURE__*/_jsx(NativeInput, {
41
+ ref: searchInputRef,
42
+ disabled: disabled || !open,
43
+ onChangeText: onSearch,
44
+ onPress: () => !disabled && setOpen(true),
45
+ placeholder: typeof placeholder === 'string' ? placeholder : undefined,
46
+ style: {
47
+ flex: 0,
48
+ flexGrow: 1,
49
+ flexShrink: 1,
50
+ minWidth: 0,
51
+ padding: 0,
52
+ height: hasValue ? 24 : 48,
53
+ marginTop: hasValue ? 0 : -24,
54
+ marginBottom: hasValue ? -12 : -24,
55
+ paddingTop: hasValue ? 8 : 0,
56
+ // This is constrained by the parent container's width. The width is large
57
+ // to ensure it grows to fill the control
58
+ width: open ? '100%' : undefined
59
+ },
60
+ value: searchText
61
+ })
62
+ }) : /*#__PURE__*/_jsx(_Fragment, {
63
+ children: hasValue ? null : /*#__PURE__*/_jsx(Text, {
64
+ color: "fgMuted",
65
+ font: "body",
66
+ paddingY: 0,
67
+ children: typeof placeholder === 'string' ? placeholder : ''
68
+ })
69
+ }),
70
+ placeholder: null,
71
+ styles: _extends({}, props.styles, {
72
+ controlEndNode: _extends({}, StyleSheet.flatten((_props$styles = props.styles) == null ? void 0 : _props$styles.controlEndNode), {
73
+ alignItems: hasValue && shouldRenderSearchInput ? 'flex-end' : 'center'
74
+ }),
75
+ controlValueNode: _extends({}, StyleSheet.flatten((_props$styles2 = props.styles) == null ? void 0 : _props$styles2.controlValueNode), {
76
+ paddingBottom: hasValue && shouldRenderSearchInput ? theme.space[1.5] : 0
77
+ })
78
+ })
79
+ }));
80
+ };