@widergy/mobile-ui 1.14.6 → 1.15.1
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 +14 -0
- package/lib/components/Button/index.js +1 -1
- package/lib/components/UTBadge/index.js +2 -2
- package/lib/components/UTBadge/theme.js +9 -6
- package/lib/components/UTBaseInputField/README.md +45 -31
- package/lib/components/UTBaseInputField/components/ActionAdornment/index.js +5 -16
- package/lib/components/UTBaseInputField/components/BadgeAdornment/index.js +13 -0
- package/lib/components/UTBaseInputField/components/IconAdornment/constants.js +2 -0
- package/lib/components/UTBaseInputField/components/IconAdornment/index.js +20 -15
- package/lib/components/UTBaseInputField/components/IconAdornment/proptypes.js +20 -0
- package/lib/components/UTBaseInputField/components/IconAdornment/utils.js +7 -2
- package/lib/components/UTBaseInputField/constants.js +18 -3
- package/lib/components/UTBaseInputField/index.js +89 -88
- package/lib/components/UTBaseInputField/proptypes.js +60 -0
- package/lib/components/UTBaseInputField/theme.js +72 -32
- package/lib/components/UTBottomSheet/README.md +53 -0
- package/lib/components/UTBottomSheet/index.js +139 -0
- package/lib/components/UTBottomSheet/styles.js +46 -0
- package/lib/components/UTButton/constants.js +5 -14
- package/lib/components/UTButton/index.js +6 -22
- package/lib/components/UTButton/proptypes.js +29 -0
- package/lib/components/UTButton/theme.js +6 -5
- package/lib/components/UTCheckBox/README.md +4 -30
- package/lib/components/UTCheckBox/constants.js +4 -1
- package/lib/components/UTCheckBox/index.js +33 -22
- package/lib/components/UTCheckBox/proptypes.js +12 -3
- package/lib/components/UTCheckBox/styles.js +7 -0
- package/lib/components/UTCheckBox/theme.js +98 -54
- package/lib/components/UTCheckList/README.MD +14 -10
- package/lib/components/UTCheckList/constants.js +6 -1
- package/lib/components/UTCheckList/index.js +44 -66
- package/lib/components/UTCheckList/proptypes.js +48 -0
- package/lib/components/UTCheckList/styles.js +10 -5
- package/lib/components/UTCheckList/utils.js +5 -0
- package/lib/components/UTFieldLabel/index.js +4 -3
- package/lib/components/UTLabel/constants.js +11 -11
- package/lib/components/UTLabel/index.js +3 -17
- package/lib/components/UTLabel/proptypes.js +19 -0
- package/lib/components/UTLabel/theme.js +2 -2
- package/lib/components/UTMenu/index.js +1 -1
- package/lib/components/UTPasswordField/versions/V0/components/PasswordValidations/styles.js +1 -0
- package/lib/components/UTPasswordField/versions/V1/index.js +3 -2
- package/lib/components/UTPhoneInput/constants.js +303 -0
- package/lib/components/UTPhoneInput/index.js +296 -0
- package/lib/components/UTPhoneInput/styles.js +18 -0
- package/lib/components/UTSearchField/README.md +42 -0
- package/lib/components/UTSearchField/index.js +59 -0
- package/lib/components/UTSearchField/proptypes.js +28 -0
- package/lib/components/UTSelect/index.js +10 -97
- package/lib/components/UTSelect/{componentes → versions/V0/componentes}/MultipleItem/index.js +1 -1
- package/lib/components/UTSelect/versions/V0/index.js +103 -0
- package/lib/components/UTSelect/versions/V1/README.md +82 -0
- package/lib/components/UTSelect/versions/V1/index.js +171 -0
- package/lib/components/UTSelect/versions/V1/proptypes.js +45 -0
- package/lib/components/UTSelect/versions/V1/styles.js +18 -0
- package/lib/components/UTTextArea/index.js +4 -2
- package/lib/components/UTTextInput/versions/V0/components/BaseInput/index.js +3 -3
- package/lib/components/UTTextInput/versions/V1/README.md +36 -35
- package/lib/components/UTTextInput/versions/V1/components/TextInputField/index.js +24 -15
- package/lib/components/UTTextInput/versions/V1/constants.js +3 -5
- package/lib/components/UTTextInput/versions/V1/index.js +25 -20
- package/lib/components/UTTextInput/versions/V1/proptypes.js +25 -7
- package/lib/constants/inputs.js +4 -0
- package/lib/index.js +47 -51
- package/package.json +2 -2
- /package/lib/components/UTSelect/{componentes → versions/V0/componentes}/MultipleItem/styles.js +0 -0
- /package/lib/components/UTSelect/{proptypes.js → versions/V0/proptypes.js} +0 -0
- /package/lib/components/UTSelect/{styles.js → versions/V0/styles.js} +0 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import React, { PureComponent } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import { bool, elementType, func, number, shape, string } from 'prop-types';
|
|
4
|
+
|
|
5
|
+
import UTBaseInputField from '../UTBaseInputField';
|
|
6
|
+
import UTFieldLabel from '../UTFieldLabel';
|
|
7
|
+
import UTLabel from '../UTLabel';
|
|
8
|
+
import UTValidation from '../UTValidation';
|
|
9
|
+
import { formatErrorToValidation } from '../UTValidation/utils';
|
|
10
|
+
import { LABEL_VARIANTS } from '../../constants/inputs';
|
|
11
|
+
import { COMPONENT_KEYS } from '../UTBaseInputField/constants';
|
|
12
|
+
import { validationDataProptypes } from '../UTValidation/constants';
|
|
13
|
+
|
|
14
|
+
import { AREA_CODES } from './constants';
|
|
15
|
+
import styles from './styles';
|
|
16
|
+
|
|
17
|
+
class UTPhoneInput extends PureComponent {
|
|
18
|
+
constructor(props) {
|
|
19
|
+
super(props);
|
|
20
|
+
this.state = {
|
|
21
|
+
areaCode: '',
|
|
22
|
+
bigFocus: false,
|
|
23
|
+
areaCodeError: '',
|
|
24
|
+
firstFocus: false,
|
|
25
|
+
isValidCode: false,
|
|
26
|
+
phoneNumber: '',
|
|
27
|
+
phoneRef: null,
|
|
28
|
+
secondFocus: false
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
this.handleFirstBlur = this.handleBlur('firstFocus');
|
|
32
|
+
this.handleSecondBlur = this.handleBlur('secondFocus');
|
|
33
|
+
this.handleFirstFocus = this.handleFocus('firstFocus');
|
|
34
|
+
this.handleSecondFocus = this.handleFocus('secondFocus');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
componentDidMount() {
|
|
38
|
+
this.updateValue();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
componentDidUpdate(prevProps) {
|
|
42
|
+
const { value } = this.props;
|
|
43
|
+
if (prevProps.value !== value) this.updateValue();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
changeText = updateFunction => {
|
|
47
|
+
const { areaCode, phoneNumber } = this.state;
|
|
48
|
+
const { withAreaCode } = this.props;
|
|
49
|
+
|
|
50
|
+
if (withAreaCode && (areaCode || phoneNumber)) {
|
|
51
|
+
updateFunction(`${areaCode}-${phoneNumber}`);
|
|
52
|
+
} else if (!withAreaCode) {
|
|
53
|
+
updateFunction(phoneNumber);
|
|
54
|
+
} else {
|
|
55
|
+
updateFunction('');
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
getAreaCodeState = value => {
|
|
60
|
+
const {
|
|
61
|
+
translations: { areaCodeWithoutZeroError, invalidAreaCodeError }
|
|
62
|
+
} = this.props;
|
|
63
|
+
let newState = {};
|
|
64
|
+
if (value && value.slice(0, 1) === '0') {
|
|
65
|
+
newState = { areaCodeError: areaCodeWithoutZeroError };
|
|
66
|
+
} else {
|
|
67
|
+
const code = AREA_CODES.find(element => element.code === value);
|
|
68
|
+
newState = {
|
|
69
|
+
areaCodeError: value?.length && !code && invalidAreaCodeError,
|
|
70
|
+
isValidCode: !!code,
|
|
71
|
+
phoneNumber: ''
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return { ...newState, areaCode: value };
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
handleBlur = keyname => async () => {
|
|
79
|
+
this.setState({
|
|
80
|
+
[keyname]: false
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
await new Promise(resolve => setTimeout(resolve, 150));
|
|
84
|
+
|
|
85
|
+
const { secondFocus, firstFocus, bigFocus } = this.state;
|
|
86
|
+
const { onBlur } = this.props;
|
|
87
|
+
|
|
88
|
+
if (!secondFocus && !firstFocus && bigFocus) {
|
|
89
|
+
this.changeText(onBlur);
|
|
90
|
+
this.setState({
|
|
91
|
+
bigFocus: false
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
handleChangeAreaCode = value => {
|
|
97
|
+
this.setState(this.getAreaCodeState(value), () => {
|
|
98
|
+
const { onChange } = this.props;
|
|
99
|
+
this.changeText(onChange);
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
handleChangePhone = value => {
|
|
104
|
+
this.setState({ phoneNumber: value }, () => {
|
|
105
|
+
const { onChange } = this.props;
|
|
106
|
+
this.changeText(onChange);
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
handleFocus = keyname => () => {
|
|
111
|
+
const { onFocus } = this.props;
|
|
112
|
+
const { bigFocus } = this.state;
|
|
113
|
+
|
|
114
|
+
if (!bigFocus) {
|
|
115
|
+
onFocus();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
this.setState({
|
|
119
|
+
[keyname]: true,
|
|
120
|
+
bigFocus: true
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
handleSubmitEditing = () => {
|
|
125
|
+
const { phoneRef, areaCodeError } = this.state;
|
|
126
|
+
if (!areaCodeError) {
|
|
127
|
+
phoneRef.focus();
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
phoneInputRef = ref => this.setState({ phoneRef: ref });
|
|
132
|
+
|
|
133
|
+
updateValue = () => {
|
|
134
|
+
const { value, withAreaCode } = this.props;
|
|
135
|
+
if (value) {
|
|
136
|
+
if (withAreaCode) {
|
|
137
|
+
const phone = value.split('-');
|
|
138
|
+
if (phone.length === 2) {
|
|
139
|
+
const newAreaCodeState = this.getAreaCodeState(phone[0]);
|
|
140
|
+
this.setState({
|
|
141
|
+
...newAreaCodeState,
|
|
142
|
+
phoneNumber: phone[1]
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
this.setState({ phoneNumber: value });
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
this.setState({
|
|
150
|
+
areaCode: '',
|
|
151
|
+
phoneNumber: '',
|
|
152
|
+
areaCodeError: '',
|
|
153
|
+
isValidCode: false
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
render() {
|
|
159
|
+
const {
|
|
160
|
+
areaCodePlaceholder,
|
|
161
|
+
countryCode,
|
|
162
|
+
editable,
|
|
163
|
+
formError,
|
|
164
|
+
helpText,
|
|
165
|
+
InputRef,
|
|
166
|
+
label,
|
|
167
|
+
labelVariant,
|
|
168
|
+
maxLength,
|
|
169
|
+
onSubmitEditing,
|
|
170
|
+
placeholder,
|
|
171
|
+
readOnly,
|
|
172
|
+
required,
|
|
173
|
+
RightIcon,
|
|
174
|
+
validations,
|
|
175
|
+
withAreaCode
|
|
176
|
+
} = this.props;
|
|
177
|
+
const { areaCode, areaCodeError, isValidCode, phoneNumber } = this.state;
|
|
178
|
+
|
|
179
|
+
const labelColorTheme = readOnly ? 'gray' : 'dark';
|
|
180
|
+
|
|
181
|
+
const validationErrors =
|
|
182
|
+
validations ||
|
|
183
|
+
(areaCodeError && formatErrorToValidation(areaCodeError)) ||
|
|
184
|
+
(formError && formatErrorToValidation(formError));
|
|
185
|
+
|
|
186
|
+
const hasError = validationErrors?.length > 0;
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<View style={styles.container}>
|
|
190
|
+
{label && (
|
|
191
|
+
<UTFieldLabel
|
|
192
|
+
colorTheme={labelColorTheme}
|
|
193
|
+
required={required}
|
|
194
|
+
variant={LABEL_VARIANTS[labelVariant]}
|
|
195
|
+
>
|
|
196
|
+
{label}
|
|
197
|
+
</UTFieldLabel>
|
|
198
|
+
)}
|
|
199
|
+
<View style={styles.inputsContainer}>
|
|
200
|
+
{withAreaCode ? (
|
|
201
|
+
<UTBaseInputField
|
|
202
|
+
alwaysShowPlaceholder
|
|
203
|
+
disabled={!editable || readOnly}
|
|
204
|
+
error={hasError}
|
|
205
|
+
leftAdornments={[]}
|
|
206
|
+
maxLength={4}
|
|
207
|
+
onBlur={this.handleFirstBlur}
|
|
208
|
+
onChange={this.handleChangeAreaCode}
|
|
209
|
+
onFocus={this.handleFirstFocus}
|
|
210
|
+
onSubmitEditing={this.handleSubmitEditing}
|
|
211
|
+
placeholder={areaCodePlaceholder}
|
|
212
|
+
ref={InputRef}
|
|
213
|
+
returnKeyType="next"
|
|
214
|
+
rightAdornments={[
|
|
215
|
+
{ name: COMPONENT_KEYS.ICON, props: { Icon: RightIcon, changeOnError: true } }
|
|
216
|
+
]}
|
|
217
|
+
style={{ container: styles.areaCode }}
|
|
218
|
+
type="number"
|
|
219
|
+
value={areaCode}
|
|
220
|
+
/>
|
|
221
|
+
) : null}
|
|
222
|
+
<View style={styles.phoneNumber}>
|
|
223
|
+
<UTBaseInputField
|
|
224
|
+
alwaysShowPlaceholder
|
|
225
|
+
disabled={(withAreaCode && !isValidCode) || !editable || readOnly}
|
|
226
|
+
error={hasError && !areaCodeError}
|
|
227
|
+
leftAdornments={
|
|
228
|
+
countryCode && !withAreaCode
|
|
229
|
+
? [{ name: COMPONENT_KEYS.PREFIX, props: { text: countryCode } }]
|
|
230
|
+
: []
|
|
231
|
+
}
|
|
232
|
+
maxLength={withAreaCode ? maxLength - (areaCode?.length || 0) : maxLength}
|
|
233
|
+
onBlur={this.handleSecondBlur}
|
|
234
|
+
onChange={this.handleChangePhone}
|
|
235
|
+
onFocus={this.handleSecondFocus}
|
|
236
|
+
onSubmitEditing={onSubmitEditing}
|
|
237
|
+
placeholder={placeholder}
|
|
238
|
+
ref={this.phoneInputRef}
|
|
239
|
+
returnKeyType="done"
|
|
240
|
+
rightAdornments={[
|
|
241
|
+
{ name: COMPONENT_KEYS.ICON, props: { Icon: RightIcon, changeOnError: true } }
|
|
242
|
+
]}
|
|
243
|
+
type="number"
|
|
244
|
+
value={phoneNumber}
|
|
245
|
+
/>
|
|
246
|
+
</View>
|
|
247
|
+
</View>
|
|
248
|
+
{helpText && (
|
|
249
|
+
<UTLabel colorTheme="gray" variant="small">
|
|
250
|
+
{helpText}
|
|
251
|
+
</UTLabel>
|
|
252
|
+
)}
|
|
253
|
+
{validationErrors && <UTValidation validationData={validationErrors} />}
|
|
254
|
+
</View>
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
UTPhoneInput.defaultProps = {
|
|
260
|
+
labelVariant: 'large',
|
|
261
|
+
maxLength: 10,
|
|
262
|
+
translations: {
|
|
263
|
+
areaCodeWithoutZeroError: 'Ingrese el código sin 0',
|
|
264
|
+
invalidAreaCodeError: 'Código de área inválido'
|
|
265
|
+
},
|
|
266
|
+
withAreaCode: true
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
UTPhoneInput.propTypes = {
|
|
270
|
+
areaCodePlaceholder: string,
|
|
271
|
+
countryCode: string,
|
|
272
|
+
editable: bool,
|
|
273
|
+
formError: string,
|
|
274
|
+
helpText: string,
|
|
275
|
+
InputRef: func,
|
|
276
|
+
label: string,
|
|
277
|
+
labelVariant: string,
|
|
278
|
+
maxLength: number,
|
|
279
|
+
onBlur: func,
|
|
280
|
+
onChange: func,
|
|
281
|
+
onFocus: func,
|
|
282
|
+
onSubmitEditing: func,
|
|
283
|
+
placeholder: string,
|
|
284
|
+
readOnly: bool,
|
|
285
|
+
required: bool,
|
|
286
|
+
RightIcon: elementType,
|
|
287
|
+
translations: shape({
|
|
288
|
+
areaCodeWithoutZeroError: string,
|
|
289
|
+
invalidAreaCodeError: string
|
|
290
|
+
}),
|
|
291
|
+
validations: validationDataProptypes,
|
|
292
|
+
value: string,
|
|
293
|
+
withAreaCode: bool
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
export default UTPhoneInput;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export default StyleSheet.create({
|
|
4
|
+
areaCode: {
|
|
5
|
+
flex: 1
|
|
6
|
+
},
|
|
7
|
+
container: {
|
|
8
|
+
gap: 12
|
|
9
|
+
},
|
|
10
|
+
inputsContainer: {
|
|
11
|
+
alignItems: 'flex-start',
|
|
12
|
+
flexDirection: 'row',
|
|
13
|
+
gap: 8
|
|
14
|
+
},
|
|
15
|
+
phoneNumber: {
|
|
16
|
+
flex: 2
|
|
17
|
+
}
|
|
18
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# UTSearchField
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
`UTSearchField` is a customizable search field component that includes a search icon on the left and an optional clear button on the right.
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
| Name | Type | Default | Description |
|
|
10
|
+
| --------------- | -------------------------------------------------------------- | --------------------------------- | ------------------------------------------------------------ |
|
|
11
|
+
| inputRef | func | | Reference to the input field. |
|
|
12
|
+
| input | shape({ value: string.isRequired, onChange: func.isRequired }) | { value: '', onChange: () => {} } | Input object containing the value and onChange handler. |
|
|
13
|
+
| onBlur | func | | Function to call when the input field loses focus. |
|
|
14
|
+
| onFocus | func | | Function to call when the input field gains focus. |
|
|
15
|
+
| onSubmitEditing | func | | Function to call when the input field is submitted. |
|
|
16
|
+
| placeholder | string | | Placeholder text for the input field. |
|
|
17
|
+
| returnKeyType | string | | Determines the return key type on the keyboard. |
|
|
18
|
+
| size | string | medium | Size of the input field. One of: `small`, `medium`, `large`. |
|
|
19
|
+
| style | object | | Style object to customize the input field. |
|
|
20
|
+
| type | string | | Type of input (e.g., 'text', 'password', 'email'). |
|
|
21
|
+
| variant | string | white | Variant of the input field. One of: `white`, `gray`. |
|
|
22
|
+
|
|
23
|
+
## Example
|
|
24
|
+
|
|
25
|
+
```jsx
|
|
26
|
+
import React, { useState } from 'react';
|
|
27
|
+
import { View, Text } from 'react-native';
|
|
28
|
+
import UTSearchField from './UTSearchField';
|
|
29
|
+
|
|
30
|
+
const UTSearchFieldExample = () => {
|
|
31
|
+
const [searchValue, setSearchValue] = useState('');
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<View style={{ padding: 20 }}>
|
|
35
|
+
<UTSearchField placeholder="Search..." value={searchValue} onChange={setSearchValue} />
|
|
36
|
+
<Text>Search Value: {searchValue}</Text>
|
|
37
|
+
</View>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default UTSearchFieldExample;
|
|
42
|
+
```
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { COMPONENT_KEYS } from '../UTBaseInputField/constants';
|
|
4
|
+
import UTBaseInputField from '../UTBaseInputField';
|
|
5
|
+
|
|
6
|
+
import { defaultProps, propTypes } from './proptypes';
|
|
7
|
+
|
|
8
|
+
const UTSearchField = ({
|
|
9
|
+
disabled,
|
|
10
|
+
input,
|
|
11
|
+
inputRef,
|
|
12
|
+
onBlur,
|
|
13
|
+
onFocus,
|
|
14
|
+
onSubmitEditing,
|
|
15
|
+
placeholder,
|
|
16
|
+
returnKeyType,
|
|
17
|
+
size,
|
|
18
|
+
style,
|
|
19
|
+
type,
|
|
20
|
+
variant
|
|
21
|
+
}) => {
|
|
22
|
+
const clearText = () => {
|
|
23
|
+
input.onChange('');
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const action = { Icon: 'IconX', onPress: clearText, size: 'small' };
|
|
27
|
+
|
|
28
|
+
const leftAdornments = [
|
|
29
|
+
{ name: COMPONENT_KEYS.ICON, props: { Icon: 'IconSearch', changeOnFocus: true, shade: '02' } }
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const rightAdornments = input.value ? [{ name: COMPONENT_KEYS.ACTION, props: { action } }] : [];
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<UTBaseInputField
|
|
36
|
+
alwaysShowPlaceholder
|
|
37
|
+
disabled={disabled}
|
|
38
|
+
input={input}
|
|
39
|
+
inputSize={size}
|
|
40
|
+
leftAdornments={leftAdornments}
|
|
41
|
+
onBlur={onBlur}
|
|
42
|
+
onFocus={onFocus}
|
|
43
|
+
onSubmitEditing={onSubmitEditing}
|
|
44
|
+
placeholder={placeholder}
|
|
45
|
+
ref={inputRef}
|
|
46
|
+
returnKeyType={returnKeyType}
|
|
47
|
+
rightAdornments={rightAdornments}
|
|
48
|
+
style={{ container: style }}
|
|
49
|
+
type={type}
|
|
50
|
+
variant={variant}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
UTSearchField.defaultProps = defaultProps;
|
|
56
|
+
|
|
57
|
+
UTSearchField.propTypes = propTypes;
|
|
58
|
+
|
|
59
|
+
export default UTSearchField;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { func, oneOf, string, object, shape, instanceOf, oneOfType } from 'prop-types';
|
|
2
|
+
|
|
3
|
+
import { SIZES, VARIANT } from '../UTBaseInputField/constants';
|
|
4
|
+
|
|
5
|
+
export const defaultProps = {
|
|
6
|
+
input: {
|
|
7
|
+
value: [],
|
|
8
|
+
onChange: () => {}
|
|
9
|
+
},
|
|
10
|
+
variant: VARIANT.WHITE
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const propTypes = {
|
|
14
|
+
input: shape({
|
|
15
|
+
value: string,
|
|
16
|
+
onChange: func
|
|
17
|
+
}),
|
|
18
|
+
inputRef: oneOfType([func, instanceOf(Object)]),
|
|
19
|
+
onBlur: func,
|
|
20
|
+
onFocus: func,
|
|
21
|
+
onSubmitEditing: func,
|
|
22
|
+
placeholder: string,
|
|
23
|
+
returnKeyType: string,
|
|
24
|
+
size: oneOf(Object.values(SIZES)),
|
|
25
|
+
style: object,
|
|
26
|
+
type: string,
|
|
27
|
+
variant: oneOf(Object.values(VARIANT))
|
|
28
|
+
};
|
|
@@ -1,103 +1,16 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import {
|
|
3
|
-
import { View } from 'react-native';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { string } from 'prop-types';
|
|
4
3
|
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import UTTextInput from '../UTTextInput';
|
|
4
|
+
import V0 from './versions/V0';
|
|
5
|
+
import V1 from './versions/V1';
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const UTSelect = ({
|
|
14
|
-
options = [],
|
|
15
|
-
value,
|
|
16
|
-
onChange,
|
|
17
|
-
error,
|
|
18
|
-
UTMenuProps,
|
|
19
|
-
label,
|
|
20
|
-
styles: propStyles,
|
|
21
|
-
variant,
|
|
22
|
-
disabled,
|
|
23
|
-
UTTextInputProps,
|
|
24
|
-
isMultiple,
|
|
25
|
-
verticalOffset = 5,
|
|
26
|
-
title,
|
|
27
|
-
titleProps,
|
|
28
|
-
changeOnClose
|
|
29
|
-
}) => {
|
|
30
|
-
const [focused, setFocused] = useState(false);
|
|
31
|
-
|
|
32
|
-
const selectedOption = useMemo(
|
|
33
|
-
() => (!isMultiple ? options.find(option => option.value === value) : value || []),
|
|
34
|
-
[isMultiple, options, value]
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
const handleChange = option => {
|
|
38
|
-
if (!changeOnClose) onChange(option.value);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const handleChangeMultiple = newValue => {
|
|
42
|
-
const newValues = !selectedOption?.find?.(elem => elem === newValue.value)
|
|
43
|
-
? [...(selectedOption || []), newValue.value]
|
|
44
|
-
: selectedOption?.filter(elem => elem !== newValue.value);
|
|
45
|
-
|
|
46
|
-
const finalValue = isEmpty(newValues) ? null : newValues;
|
|
47
|
-
if (!changeOnClose) {
|
|
48
|
-
onChange(finalValue);
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const handleOpen = () => setFocused(true);
|
|
53
|
-
// eslint-disable-next-line consistent-return
|
|
54
|
-
const handleClose = () => {
|
|
55
|
-
setFocused(false);
|
|
56
|
-
if (changeOnClose) {
|
|
57
|
-
return isMultiple
|
|
58
|
-
? onChange(selectedOption)
|
|
59
|
-
: onChange(options.find(_option => _option.id === selectedOption.id).value);
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
return (
|
|
64
|
-
<View style={[styles.container, propStyles]}>
|
|
65
|
-
{title && (
|
|
66
|
-
<Label medium primary {...titleProps}>
|
|
67
|
-
{title}
|
|
68
|
-
</Label>
|
|
69
|
-
)}
|
|
70
|
-
<UTMenu
|
|
71
|
-
options={options}
|
|
72
|
-
selectedOption={isMultiple ? selectedOption : selectedOption?.id}
|
|
73
|
-
fullWidth
|
|
74
|
-
verticalOffset={verticalOffset}
|
|
75
|
-
disabled={disabled}
|
|
76
|
-
onPress={isMultiple ? handleChangeMultiple : handleChange}
|
|
77
|
-
onOpen={handleOpen}
|
|
78
|
-
onClose={handleClose}
|
|
79
|
-
withoutOpacity
|
|
80
|
-
MenuOptionComponent={isMultiple && MultipleItem}
|
|
81
|
-
isMultiple={isMultiple}
|
|
82
|
-
{...UTMenuProps}
|
|
83
|
-
>
|
|
84
|
-
<UTTextInput
|
|
85
|
-
variant={variant}
|
|
86
|
-
value={isMultiple ? value?.join(', ') || '' : selectedOption?.label || selectedOption?.value || ''}
|
|
87
|
-
error={error}
|
|
88
|
-
label={label}
|
|
89
|
-
select
|
|
90
|
-
controlledFocus={focused}
|
|
91
|
-
disabled={disabled}
|
|
92
|
-
version="V0"
|
|
93
|
-
RightIcon={{ type: 'font-awesome', name: 'caret-down' }}
|
|
94
|
-
{...UTTextInputProps}
|
|
95
|
-
/>
|
|
96
|
-
</UTMenu>
|
|
97
|
-
</View>
|
|
98
|
-
);
|
|
7
|
+
const UTSelect = ({ version = 'V0', ...props }) => {
|
|
8
|
+
const Component = { V0, V1 }[version];
|
|
9
|
+
return <Component {...props} />;
|
|
99
10
|
};
|
|
100
11
|
|
|
101
|
-
UTSelect.propTypes =
|
|
12
|
+
UTSelect.propTypes = {
|
|
13
|
+
version: string
|
|
14
|
+
};
|
|
102
15
|
|
|
103
16
|
export default UTSelect;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import React, { useState, useMemo } from 'react';
|
|
2
|
+
import { isEmpty } from '@widergy/web-utils/lib/array';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
|
|
5
|
+
import Label from '../../../Label';
|
|
6
|
+
import UTMenu from '../../../UTMenu';
|
|
7
|
+
import UTTextInput from '../../../UTTextInput';
|
|
8
|
+
|
|
9
|
+
import MultipleItem from './componentes/MultipleItem';
|
|
10
|
+
import styles from './styles';
|
|
11
|
+
import UTSelectTypes from './proptypes';
|
|
12
|
+
|
|
13
|
+
const UTSelect = ({
|
|
14
|
+
options = [],
|
|
15
|
+
value,
|
|
16
|
+
onChange,
|
|
17
|
+
error,
|
|
18
|
+
UTMenuProps,
|
|
19
|
+
label,
|
|
20
|
+
styles: propStyles,
|
|
21
|
+
variant,
|
|
22
|
+
disabled,
|
|
23
|
+
UTTextInputProps,
|
|
24
|
+
isMultiple,
|
|
25
|
+
verticalOffset = 5,
|
|
26
|
+
title,
|
|
27
|
+
titleProps,
|
|
28
|
+
changeOnClose
|
|
29
|
+
}) => {
|
|
30
|
+
const [focused, setFocused] = useState(false);
|
|
31
|
+
|
|
32
|
+
const selectedOption = useMemo(
|
|
33
|
+
() => (!isMultiple ? options.find(option => option.value === value) : value || []),
|
|
34
|
+
[isMultiple, options, value]
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const handleChange = option => {
|
|
38
|
+
if (!changeOnClose) onChange(option.value);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const handleChangeMultiple = newValue => {
|
|
42
|
+
const newValues = !selectedOption?.find?.(elem => elem === newValue.value)
|
|
43
|
+
? [...(selectedOption || []), newValue.value]
|
|
44
|
+
: selectedOption?.filter(elem => elem !== newValue.value);
|
|
45
|
+
|
|
46
|
+
const finalValue = isEmpty(newValues) ? null : newValues;
|
|
47
|
+
if (!changeOnClose) {
|
|
48
|
+
onChange(finalValue);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const handleOpen = () => setFocused(true);
|
|
53
|
+
// eslint-disable-next-line consistent-return
|
|
54
|
+
const handleClose = () => {
|
|
55
|
+
setFocused(false);
|
|
56
|
+
if (changeOnClose) {
|
|
57
|
+
return isMultiple
|
|
58
|
+
? onChange(selectedOption)
|
|
59
|
+
: onChange(options.find(_option => _option.id === selectedOption.id).value);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<View style={[styles.container, propStyles]}>
|
|
65
|
+
{title && (
|
|
66
|
+
<Label medium primary {...titleProps}>
|
|
67
|
+
{title}
|
|
68
|
+
</Label>
|
|
69
|
+
)}
|
|
70
|
+
<UTMenu
|
|
71
|
+
options={options}
|
|
72
|
+
selectedOption={isMultiple ? selectedOption : selectedOption?.id}
|
|
73
|
+
fullWidth
|
|
74
|
+
verticalOffset={verticalOffset}
|
|
75
|
+
disabled={disabled}
|
|
76
|
+
onPress={isMultiple ? handleChangeMultiple : handleChange}
|
|
77
|
+
onOpen={handleOpen}
|
|
78
|
+
onClose={handleClose}
|
|
79
|
+
withoutOpacity
|
|
80
|
+
MenuOptionComponent={isMultiple && MultipleItem}
|
|
81
|
+
isMultiple={isMultiple}
|
|
82
|
+
{...UTMenuProps}
|
|
83
|
+
>
|
|
84
|
+
<UTTextInput
|
|
85
|
+
variant={variant}
|
|
86
|
+
value={isMultiple ? value?.join(', ') || '' : selectedOption?.label || selectedOption?.value || ''}
|
|
87
|
+
error={error}
|
|
88
|
+
label={label}
|
|
89
|
+
select
|
|
90
|
+
controlledFocus={focused}
|
|
91
|
+
disabled={disabled}
|
|
92
|
+
version="V0"
|
|
93
|
+
RightIcon={{ type: 'font-awesome', name: 'caret-down' }}
|
|
94
|
+
{...UTTextInputProps}
|
|
95
|
+
/>
|
|
96
|
+
</UTMenu>
|
|
97
|
+
</View>
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
UTSelect.propTypes = UTSelectTypes;
|
|
102
|
+
|
|
103
|
+
export default UTSelect;
|