@widergy/mobile-ui 1.47.0 → 1.48.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.
- package/CHANGELOG.md +7 -0
- package/lib/components/CaptionLabel/README.md +30 -8
- package/lib/components/CaptionLabel/index.js +2 -1
- package/lib/components/CaptionLabel/propTypes.js +1 -0
- package/lib/components/Checkbox/README.md +93 -25
- package/lib/components/Checkbox/index.js +14 -1
- package/lib/components/Checkbox/propTypes.js +1 -0
- package/lib/components/Label/index.js +2 -1
- package/lib/components/Label/propTypes.js +1 -0
- package/lib/components/RadioGroup/components/RadioButton/index.js +29 -18
- package/lib/components/RadioGroup/index.js +19 -5
- package/lib/components/Touchable/index.js +3 -1
- package/lib/components/Touchable/propTypes.js +1 -0
- package/lib/components/UTBadge/index.js +3 -1
- package/lib/components/UTBaseInputField/README.md +41 -19
- package/lib/components/UTBaseInputField/components/ActionAdornment/index.js +10 -3
- package/lib/components/UTBaseInputField/components/BadgeAdornment/index.js +6 -1
- package/lib/components/UTBaseInputField/components/IconAdornment/index.js +8 -1
- package/lib/components/UTBaseInputField/components/PrefixAdornment/index.js +8 -2
- package/lib/components/UTBaseInputField/components/SuffixAdornment/index.js +6 -1
- package/lib/components/UTBaseInputField/components/TooltipAdornment/index.js +16 -3
- package/lib/components/UTBaseInputField/index.js +15 -4
- package/lib/components/UTBottomSheet/README.md +94 -23
- package/lib/components/UTBottomSheet/index.js +27 -4
- package/lib/components/UTButton/index.js +18 -4
- package/lib/components/UTButton/proptypes.js +1 -0
- package/lib/components/UTCheckBox/README.md +47 -0
- package/lib/components/UTCheckBox/index.js +24 -3
- package/lib/components/UTCheckBox/proptypes.js +1 -0
- package/lib/components/UTCheckList/README.MD +63 -0
- package/lib/components/UTCheckList/index.js +25 -2
- package/lib/components/UTCheckList/proptypes.js +1 -0
- package/lib/components/UTDetailDrawer/README.md +60 -10
- package/lib/components/UTDetailDrawer/index.js +11 -1
- package/lib/components/UTDetailDrawer/propTypes.js +1 -0
- package/lib/components/UTFieldLabel/README.md +99 -0
- package/lib/components/UTFieldLabel/index.js +19 -2
- package/lib/components/UTIcon/README.md +25 -2
- package/lib/components/UTIcon/index.js +3 -1
- package/lib/components/UTLabel/README.md +26 -0
- package/lib/components/UTLabel/index.js +2 -0
- package/lib/components/UTLabel/proptypes.js +1 -0
- package/lib/components/UTMenu/README.md +275 -0
- package/lib/components/UTMenu/components/ListView/index.js +5 -3
- package/lib/components/UTMenu/components/ListView/proptypes.js +2 -1
- package/lib/components/UTMenu/components/MenuOption/index.js +5 -3
- package/lib/components/UTMenu/index.js +18 -3
- package/lib/components/UTMenu/proptypes.js +2 -1
- package/lib/components/UTModal/README.md +193 -0
- package/lib/components/UTModal/index.js +22 -2
- package/lib/components/UTModal/proptypes.js +1 -0
- package/lib/components/UTPhoneInput/index.js +25 -2
- package/lib/components/UTRoundView/README.md +158 -0
- package/lib/components/UTRoundView/index.js +12 -1
- package/lib/components/UTRoundView/propTypes.js +4 -2
- package/lib/components/UTSearchField/README.md +64 -14
- package/lib/components/UTSearchField/index.js +3 -1
- package/lib/components/UTSearchField/proptypes.js +2 -1
- package/lib/components/UTSelect/versions/V0/README.md +216 -0
- package/lib/components/UTSelect/versions/V0/componentes/MultipleItem/index.js +4 -2
- package/lib/components/UTSelect/versions/V0/index.js +5 -2
- package/lib/components/UTSelect/versions/V0/proptypes.js +2 -1
- package/lib/components/UTSelect/versions/V1/README.md +94 -0
- package/lib/components/UTSelect/versions/V1/index.js +28 -6
- package/lib/components/UTSelect/versions/V1/proptypes.js +1 -0
- package/lib/components/UTSelectableCard/README.md +85 -0
- package/lib/components/UTSelectableCard/index.js +52 -4
- package/lib/components/UTTextInput/versions/V0/components/BaseInput/index.js +5 -1
- package/lib/components/UTTextInput/versions/V0/components/InputLabel/index.js +4 -1
- package/lib/components/UTTextInput/versions/V0/flavors/FilledInput/index.js +9 -1
- package/lib/components/UTTextInput/versions/V0/flavors/OutlinedInput/index.js +9 -1
- package/lib/components/UTTextInput/versions/V0/flavors/StandardInput/index.js +9 -1
- package/lib/components/UTTextInput/versions/V1/components/TextInputField/index.js +3 -0
- package/lib/components/UTTextInput/versions/V1/index.js +20 -3
- package/lib/components/UTTooltip/README.md +99 -0
- package/lib/components/UTTooltip/index.js +2 -0
- package/lib/components/UTTooltip/proptypes.js +2 -1
- package/lib/components/UTValidation/index.js +26 -4
- package/lib/constants/testIds.js +44 -0
- package/package.json +1 -1
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# UTSelect V0
|
|
2
|
+
|
|
3
|
+
> **⚠️ AI-Generated Documentation Disclaimer**
|
|
4
|
+
> This documentation has been generated with AI assistance and has not been thoroughly reviewed by a developer. Please verify implementation details and usage examples before relying on them in production code.
|
|
5
|
+
|
|
6
|
+
A customizable select/dropdown component with support for single and multiple selection modes. Features autocomplete functionality, custom styling, and comprehensive test ID support.
|
|
7
|
+
|
|
8
|
+
## Props
|
|
9
|
+
|
|
10
|
+
| NAME | TYPE | REQUIRED | DESCRIPTION |
|
|
11
|
+
| ---------------- | ------ | -------- | ----------------------------------------------------------------------------------------- |
|
|
12
|
+
| options | array | Yes | Array of option objects. Each option must have `id`, `label`, and `value` properties. |
|
|
13
|
+
| value | any | No | Selected value(s). For single select: option value. For multiple: array of values. |
|
|
14
|
+
| onChange | func | No | Callback function called when selection changes. Receives the selected value(s). |
|
|
15
|
+
| label | string | No | Label text for the input field. |
|
|
16
|
+
| error | string | No | Error message to display. |
|
|
17
|
+
| disabled | bool | No | Whether the select is disabled. |
|
|
18
|
+
| variant | string | No | Visual variant for the text input. |
|
|
19
|
+
| isMultiple | bool | No | Enables multiple selection mode with checkboxes. |
|
|
20
|
+
| title | string | No | Title text displayed above the select. |
|
|
21
|
+
| titleProps | object | No | Additional props to pass to the title Label component. |
|
|
22
|
+
| changeOnClose | bool | No | When true, onChange is only called when the menu closes, not on each selection. |
|
|
23
|
+
| verticalOffset | number | No | Vertical offset for the dropdown menu positioning. Default: 5. |
|
|
24
|
+
| UTMenuProps | object | No | Additional props to pass to the underlying UTMenu component. |
|
|
25
|
+
| UTTextInputProps | object | No | Additional props to pass to the underlying UTTextInput component. |
|
|
26
|
+
| styles | object | No | Custom styles for the container. |
|
|
27
|
+
| dataTestId | string | No | Unique identifier for testing purposes. Creates hierarchical test IDs for child elements. |
|
|
28
|
+
|
|
29
|
+
## Option Object Structure
|
|
30
|
+
|
|
31
|
+
Each option in the `options` array should have the following structure:
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
{
|
|
35
|
+
id: string | number, // Unique identifier for the option
|
|
36
|
+
label: string, // Display text for the option
|
|
37
|
+
value: any, // Value to be passed to onChange when selected
|
|
38
|
+
action?: function // Optional custom action function
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Usage Examples
|
|
43
|
+
|
|
44
|
+
### Basic Single Select
|
|
45
|
+
|
|
46
|
+
```jsx
|
|
47
|
+
import React, { useState } from 'react';
|
|
48
|
+
import UTSelect from '@widergy/mobile-ui/lib/components/UTSelect/versions/V0';
|
|
49
|
+
|
|
50
|
+
const BasicExample = () => {
|
|
51
|
+
const [selectedValue, setSelectedValue] = useState(null);
|
|
52
|
+
|
|
53
|
+
const options = [
|
|
54
|
+
{ id: '1', label: 'Option 1', value: 'value1' },
|
|
55
|
+
{ id: '2', label: 'Option 2', value: 'value2' },
|
|
56
|
+
{ id: '3', label: 'Option 3', value: 'value3' }
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<UTSelect options={options} value={selectedValue} onChange={setSelectedValue} label="Choose an option" />
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Multiple Select with Title
|
|
66
|
+
|
|
67
|
+
```jsx
|
|
68
|
+
const MultipleSelectExample = () => {
|
|
69
|
+
const [selectedValues, setSelectedValues] = useState([]);
|
|
70
|
+
|
|
71
|
+
const options = [
|
|
72
|
+
{ id: 'red', label: 'Red', value: 'red' },
|
|
73
|
+
{ id: 'green', label: 'Green', value: 'green' },
|
|
74
|
+
{ id: 'blue', label: 'Blue', value: 'blue' }
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<UTSelect
|
|
79
|
+
options={options}
|
|
80
|
+
value={selectedValues}
|
|
81
|
+
onChange={setSelectedValues}
|
|
82
|
+
label="Select colors"
|
|
83
|
+
title="Color Selection"
|
|
84
|
+
isMultiple
|
|
85
|
+
/>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### With Error State
|
|
91
|
+
|
|
92
|
+
```jsx
|
|
93
|
+
const ValidationExample = () => {
|
|
94
|
+
const [value, setValue] = useState(null);
|
|
95
|
+
const [error, setError] = useState('');
|
|
96
|
+
|
|
97
|
+
const handleChange = newValue => {
|
|
98
|
+
setValue(newValue);
|
|
99
|
+
if (newValue) {
|
|
100
|
+
setError('');
|
|
101
|
+
} else {
|
|
102
|
+
setError('Please select an option');
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<UTSelect options={options} value={value} onChange={handleChange} label="Required Field" error={error} />
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Testing
|
|
113
|
+
|
|
114
|
+
The `UTSelect` component supports comprehensive test ID assignment through the `dataTestId` prop. When provided, it creates a hierarchical structure of test IDs for all interactive and meaningful elements.
|
|
115
|
+
|
|
116
|
+
### Test ID Structure
|
|
117
|
+
|
|
118
|
+
When you provide `dataTestId="provided.testId"`, the following test IDs are automatically generated:
|
|
119
|
+
|
|
120
|
+
| Element | Test ID | When Available |
|
|
121
|
+
| ----------------------- | ------------------------ | ------------------------------------------------------- |
|
|
122
|
+
| Text input field | `provided.testId` | Always (when dataTestId is provided) |
|
|
123
|
+
| Title text | `provided.testId.title` | When title prop is provided |
|
|
124
|
+
| Menu (all sub-elements) | `provided.testId.menu.*` | When menu is open - inherits UTMenu's test ID structure |
|
|
125
|
+
|
|
126
|
+
**Note:**
|
|
127
|
+
|
|
128
|
+
- The text input field test ID (`provided.testId`) creates additional hierarchical test IDs based on the UTTextInput component's own test ID structure.
|
|
129
|
+
- The menu test ID (`provided.testId.menu`) creates a hierarchical structure based on UTMenu's streamlined test ID implementation, including:
|
|
130
|
+
- `provided.testId.menu.anchor` (menu trigger)
|
|
131
|
+
- `provided.testId.menu.modal` (when open)
|
|
132
|
+
- `provided.testId.menu.searchInput` (when autocomplete is enabled)
|
|
133
|
+
- `provided.testId.menu.list` (options container)
|
|
134
|
+
- `provided.testId.menu.list.option.{index}` (each option by index)
|
|
135
|
+
- `provided.testId.menu.list.option.{index}.label` (each option label)
|
|
136
|
+
- For multiple selection: each checkbox inherits the option's test ID structure
|
|
137
|
+
|
|
138
|
+
### Test ID Examples
|
|
139
|
+
|
|
140
|
+
```jsx
|
|
141
|
+
// Basic single select with test IDs
|
|
142
|
+
<UTSelect
|
|
143
|
+
dataTestId="countrySelect"
|
|
144
|
+
options={countries}
|
|
145
|
+
value={selectedCountry}
|
|
146
|
+
onChange={setSelectedCountry}
|
|
147
|
+
label="Select Country"
|
|
148
|
+
/>
|
|
149
|
+
|
|
150
|
+
// Creates test IDs:
|
|
151
|
+
// - countrySelect (text input field and its sub-elements)
|
|
152
|
+
// - countrySelect.menu.anchor (menu trigger - same as text input area)
|
|
153
|
+
// - countrySelect.menu.modal (when menu is open)
|
|
154
|
+
// - countrySelect.menu.list (options container when open)
|
|
155
|
+
// - countrySelect.menu.list.option.0 (first option when open)
|
|
156
|
+
// - countrySelect.menu.list.option.0.label (first option label when open)
|
|
157
|
+
// - countrySelect.menu.list.option.1 (second option when open)
|
|
158
|
+
// - countrySelect.menu.list.option.1.label (second option label when open)
|
|
159
|
+
// ... etc for each option
|
|
160
|
+
|
|
161
|
+
// Multiple select with title and test IDs
|
|
162
|
+
<UTSelect
|
|
163
|
+
dataTestId="skillsSelect"
|
|
164
|
+
options={skillOptions}
|
|
165
|
+
value={selectedSkills}
|
|
166
|
+
onChange={setSelectedSkills}
|
|
167
|
+
title="Technical Skills"
|
|
168
|
+
label="Choose your skills"
|
|
169
|
+
isMultiple
|
|
170
|
+
/>
|
|
171
|
+
|
|
172
|
+
// Creates test IDs:
|
|
173
|
+
// - skillsSelect (text input field and its sub-elements)
|
|
174
|
+
// - skillsSelect.title (title label)
|
|
175
|
+
// - skillsSelect.menu.anchor (menu trigger)
|
|
176
|
+
// - skillsSelect.menu.modal (when menu is open)
|
|
177
|
+
// - skillsSelect.menu.list (options container when open)
|
|
178
|
+
// - skillsSelect.menu.list.option.0 (first checkbox option when open)
|
|
179
|
+
// - skillsSelect.menu.list.option.0.label (first option label when open)
|
|
180
|
+
// - skillsSelect.menu.list.option.1 (second checkbox option when open)
|
|
181
|
+
// - skillsSelect.menu.list.option.1.label (second option label when open)
|
|
182
|
+
// - skillsSelect.menu.list.option.2 (third checkbox option when open)
|
|
183
|
+
// - skillsSelect.menu.list.option.2.label (third option label when open)
|
|
184
|
+
// ... etc for each option
|
|
185
|
+
|
|
186
|
+
// Complex example with searchable menu
|
|
187
|
+
const options = [
|
|
188
|
+
{ id: 'beginner', label: 'Beginner Level', value: 'beginner' },
|
|
189
|
+
{ id: 'intermediate', label: 'Intermediate Level', value: 'intermediate' },
|
|
190
|
+
{ id: 'advanced', label: 'Advanced Level', value: 'advanced' }
|
|
191
|
+
];
|
|
192
|
+
|
|
193
|
+
<UTSelect
|
|
194
|
+
dataTestId="userLevel"
|
|
195
|
+
options={options}
|
|
196
|
+
value={userLevel}
|
|
197
|
+
onChange={setUserLevel}
|
|
198
|
+
title="Experience Level"
|
|
199
|
+
label="Select your level"
|
|
200
|
+
UTMenuProps={{ withAutocomplete: true, autoCompletePlaceholder: "Search levels..." }}
|
|
201
|
+
/>
|
|
202
|
+
|
|
203
|
+
// Creates test IDs:
|
|
204
|
+
// - userLevel (text input field and its sub-elements)
|
|
205
|
+
// - userLevel.title (title label)
|
|
206
|
+
// - userLevel.menu.anchor (menu trigger)
|
|
207
|
+
// - userLevel.menu.modal (when menu is open)
|
|
208
|
+
// - userLevel.menu.searchInput (search input when menu is open)
|
|
209
|
+
// - userLevel.menu.list (options container when open)
|
|
210
|
+
// - userLevel.menu.list.option.0 (first option when open)
|
|
211
|
+
// - userLevel.menu.list.option.0.label (first option label when open)
|
|
212
|
+
// - userLevel.menu.list.option.1 (second option when open)
|
|
213
|
+
// - userLevel.menu.list.option.1.label (second option label when open)
|
|
214
|
+
// - userLevel.menu.list.option.2 (third option when open)
|
|
215
|
+
// - userLevel.menu.list.option.2.label (third option label when open)
|
|
216
|
+
```
|
|
@@ -6,12 +6,13 @@ import Checkbox from '../../../../../Checkbox';
|
|
|
6
6
|
|
|
7
7
|
import styles from './styles';
|
|
8
8
|
|
|
9
|
-
const MultipleItem = ({ onPress, label, selected, checkboxProps, item }) => (
|
|
9
|
+
const MultipleItem = ({ onPress, label, selected, checkboxProps, item, dataTestId }) => (
|
|
10
10
|
<Checkbox
|
|
11
11
|
label={label}
|
|
12
12
|
onPress={() => onPress(item)}
|
|
13
13
|
checked={selected}
|
|
14
14
|
style={styles.checkbox}
|
|
15
|
+
dataTestId={dataTestId}
|
|
15
16
|
{...checkboxProps}
|
|
16
17
|
/>
|
|
17
18
|
);
|
|
@@ -21,7 +22,8 @@ MultipleItem.propTypes = {
|
|
|
21
22
|
label: string,
|
|
22
23
|
selected: bool,
|
|
23
24
|
checkboxProps: shape(any),
|
|
24
|
-
item: shape(any)
|
|
25
|
+
item: shape(any),
|
|
26
|
+
dataTestId: string
|
|
25
27
|
};
|
|
26
28
|
|
|
27
29
|
export default memo(MultipleItem);
|
|
@@ -25,7 +25,8 @@ const UTSelect = ({
|
|
|
25
25
|
verticalOffset = 5,
|
|
26
26
|
title,
|
|
27
27
|
titleProps,
|
|
28
|
-
changeOnClose
|
|
28
|
+
changeOnClose,
|
|
29
|
+
dataTestId
|
|
29
30
|
}) => {
|
|
30
31
|
const [focused, setFocused] = useState(false);
|
|
31
32
|
|
|
@@ -63,7 +64,7 @@ const UTSelect = ({
|
|
|
63
64
|
return (
|
|
64
65
|
<View style={[styles.container, propStyles]}>
|
|
65
66
|
{title && (
|
|
66
|
-
<Label medium primary {...titleProps}>
|
|
67
|
+
<Label medium primary {...titleProps} dataTestId={dataTestId ? `${dataTestId}.title` : undefined}>
|
|
67
68
|
{title}
|
|
68
69
|
</Label>
|
|
69
70
|
)}
|
|
@@ -79,6 +80,7 @@ const UTSelect = ({
|
|
|
79
80
|
withoutOpacity
|
|
80
81
|
MenuOptionComponent={isMultiple && MultipleItem}
|
|
81
82
|
isMultiple={isMultiple}
|
|
83
|
+
dataTestId={dataTestId ? `${dataTestId}.menu` : undefined}
|
|
82
84
|
{...UTMenuProps}
|
|
83
85
|
>
|
|
84
86
|
<UTTextInput
|
|
@@ -91,6 +93,7 @@ const UTSelect = ({
|
|
|
91
93
|
disabled={disabled}
|
|
92
94
|
version="V0"
|
|
93
95
|
RightIcon={{ type: 'font-awesome', name: 'caret-down' }}
|
|
96
|
+
dataTestId={dataTestId}
|
|
94
97
|
{...UTTextInputProps}
|
|
95
98
|
/>
|
|
96
99
|
</UTMenu>
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
| action | shape | | Action object containing `Icon`, `onPress`, and `size` for the action button. |
|
|
10
10
|
| alwaysShowPlaceholder | bool | true | Determines if the placeholder should always be shown. |
|
|
11
11
|
| clearable | bool | false | Determines whether a button to clear the current selection should be shown. |
|
|
12
|
+
| dataTestId | string | | Test ID for automated testing. Enables hierarchical test ID structure. |
|
|
12
13
|
| helpText | string | | Help text displayed below the input field. |
|
|
13
14
|
| title | string | | Title for the select field. |
|
|
14
15
|
| multiple | bool | false | Allows multiple selection if true. |
|
|
@@ -27,6 +28,47 @@
|
|
|
27
28
|
| value | oneOfType([string, array]) | null | The value of the input field. It can be a string for single selection or an array for multiple selection. |
|
|
28
29
|
| withAutoReset | bool | true | Determines whether the select should automatically reset when the selected value is no longer available in the options. |
|
|
29
30
|
|
|
31
|
+
## Test IDs
|
|
32
|
+
|
|
33
|
+
When `dataTestId` is provided, the component creates a hierarchical test ID structure:
|
|
34
|
+
|
|
35
|
+
| Element | Test ID | Condition |
|
|
36
|
+
| ------------------ | -------------------------------- | --------------------------------- |
|
|
37
|
+
| Select trigger | `${dataTestId}` | Always when `dataTestId` provided |
|
|
38
|
+
| Title | `${dataTestId}.title` | When `title` prop is provided |
|
|
39
|
+
| Input field | `${dataTestId}.input` | Always when `dataTestId` provided |
|
|
40
|
+
| Help text | `${dataTestId}.helpText` | When `helpText` prop is provided |
|
|
41
|
+
| Validation | `${dataTestId}.validation` | When `error` prop is provided |
|
|
42
|
+
| Bottom sheet | `${dataTestId}.bottomSheet` | When bottom sheet is open |
|
|
43
|
+
| Search field | `${dataTestId}.searchField` | When bottom sheet is open |
|
|
44
|
+
| No options message | `${dataTestId}.noOptionsMessage` | When no options to display |
|
|
45
|
+
| Options list | `${dataTestId}.optionsList` | When options are available |
|
|
46
|
+
|
|
47
|
+
### Child Component Test IDs
|
|
48
|
+
|
|
49
|
+
UTSelect V1 uses several child components that have their own test ID hierarchies:
|
|
50
|
+
|
|
51
|
+
- **UTBaseInputField**: Creates test IDs for input field and adornments (badge, prefix, suffix, clear action, chevron icon)
|
|
52
|
+
- **UTBottomSheet**: Creates test IDs for modal, title, description, close button, and action buttons
|
|
53
|
+
- **UTSearchField**: Creates test IDs for search input, search icon, and clear button
|
|
54
|
+
- **UTCheckList**: Creates test IDs for checkboxes, labels, and select all functionality
|
|
55
|
+
|
|
56
|
+
### Test ID Structure Details
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
${dataTestId} // Select trigger (Pressable)
|
|
60
|
+
${dataTestId}.title // Title label
|
|
61
|
+
${dataTestId}.input // Input field (+ UTBaseInputField hierarchy)
|
|
62
|
+
${dataTestId}.input.left // Badge (when multiple selection has values)
|
|
63
|
+
${dataTestId}.input.right // Clear action, chevron icon, custom action
|
|
64
|
+
${dataTestId}.helpText // Help text
|
|
65
|
+
${dataTestId}.validation // Validation message
|
|
66
|
+
${dataTestId}.bottomSheet // Bottom sheet (+ UTBottomSheet hierarchy)
|
|
67
|
+
${dataTestId}.searchField // Search field (+ UTSearchField hierarchy)
|
|
68
|
+
${dataTestId}.noOptionsMessage // No options message
|
|
69
|
+
${dataTestId}.optionsList // Options list (+ UTCheckList hierarchy)
|
|
70
|
+
```
|
|
71
|
+
|
|
30
72
|
### Option Object
|
|
31
73
|
|
|
32
74
|
The `options` prop is an array of objects, each representing an option:
|
|
@@ -42,6 +84,8 @@ The `options` prop is an array of objects, each representing an option:
|
|
|
42
84
|
|
|
43
85
|
## Usage
|
|
44
86
|
|
|
87
|
+
### Basic Example
|
|
88
|
+
|
|
45
89
|
```jsx
|
|
46
90
|
import React, { useState } from 'react';
|
|
47
91
|
import { View, Text } from 'react-native';
|
|
@@ -75,3 +119,53 @@ const UTSelectExample = () => {
|
|
|
75
119
|
|
|
76
120
|
export default UTSelectExample;
|
|
77
121
|
```
|
|
122
|
+
|
|
123
|
+
### With Test IDs
|
|
124
|
+
|
|
125
|
+
```jsx
|
|
126
|
+
import React, { useState } from 'react';
|
|
127
|
+
import { View, Text } from 'react-native';
|
|
128
|
+
import UTSelect from './UTSelect';
|
|
129
|
+
|
|
130
|
+
const options = [
|
|
131
|
+
{ label: 'React', value: 'react' },
|
|
132
|
+
{ label: 'JavaScript', value: 'javascript' },
|
|
133
|
+
{ label: 'TypeScript', value: 'typescript' },
|
|
134
|
+
{ label: 'Node.js', value: 'nodejs' }
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
const TestableSelectExample = () => {
|
|
138
|
+
const [selectedSkills, setSelectedSkills] = useState([]);
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<View style={{ padding: 20 }}>
|
|
142
|
+
<UTSelect
|
|
143
|
+
dataTestId="skillsSelect"
|
|
144
|
+
title="Select Skills"
|
|
145
|
+
helpText="Choose your programming skills"
|
|
146
|
+
multiple={true}
|
|
147
|
+
clearable={true}
|
|
148
|
+
noMatchesText="No skills found"
|
|
149
|
+
noOptionsText="No skills available"
|
|
150
|
+
onChange={setSelectedSkills}
|
|
151
|
+
options={options}
|
|
152
|
+
placeholder="Choose skills..."
|
|
153
|
+
searchPlaceholder="Search skills..."
|
|
154
|
+
selectAllLabel="Select All Skills"
|
|
155
|
+
showSelectAll={true}
|
|
156
|
+
value={selectedSkills}
|
|
157
|
+
/>
|
|
158
|
+
<Text>Selected Skills: {selectedSkills.join(', ')}</Text>
|
|
159
|
+
</View>
|
|
160
|
+
);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// Generated test IDs include:
|
|
164
|
+
// skillsSelect (select trigger)
|
|
165
|
+
// skillsSelect.title
|
|
166
|
+
// skillsSelect.input (+ UTBaseInputField hierarchy)
|
|
167
|
+
// skillsSelect.helpText
|
|
168
|
+
// skillsSelect.bottomSheet (when open + UTBottomSheet hierarchy)
|
|
169
|
+
// skillsSelect.searchField (when open + UTSearchField hierarchy)
|
|
170
|
+
// skillsSelect.optionsList (when open + UTCheckList hierarchy)
|
|
171
|
+
```
|
|
@@ -41,7 +41,8 @@ const UTSelect = ({
|
|
|
41
41
|
value,
|
|
42
42
|
onChangeSearchTerm,
|
|
43
43
|
disableFilterOptions,
|
|
44
|
-
withAutoReset
|
|
44
|
+
withAutoReset,
|
|
45
|
+
dataTestId
|
|
45
46
|
}) => {
|
|
46
47
|
const [bottomSheetVisible, setBottomSheetVisible] = useState(false);
|
|
47
48
|
const [searchTerm, setSearchTerm] = useState('');
|
|
@@ -146,11 +147,15 @@ const UTSelect = ({
|
|
|
146
147
|
<Fragment>
|
|
147
148
|
<View style={[styles.container, style]}>
|
|
148
149
|
{title && (
|
|
149
|
-
<UTFieldLabel
|
|
150
|
+
<UTFieldLabel
|
|
151
|
+
required={required}
|
|
152
|
+
variant="body"
|
|
153
|
+
dataTestId={dataTestId ? `${dataTestId}.title` : undefined}
|
|
154
|
+
>
|
|
150
155
|
{title}
|
|
151
156
|
</UTFieldLabel>
|
|
152
157
|
)}
|
|
153
|
-
<Pressable disabled={disabled} onPress={handleOpenBottomSheet}>
|
|
158
|
+
<Pressable disabled={disabled} onPress={handleOpenBottomSheet} testID={dataTestId}>
|
|
154
159
|
<UTBaseInputField
|
|
155
160
|
alwaysShowPlaceholder={alwaysShowPlaceholder}
|
|
156
161
|
disabled={disabled}
|
|
@@ -162,14 +167,24 @@ const UTSelect = ({
|
|
|
162
167
|
rightAdornments={rightAdornments}
|
|
163
168
|
value={displayValue}
|
|
164
169
|
variant="button"
|
|
170
|
+
dataTestId={dataTestId ? `${dataTestId}.input` : undefined}
|
|
165
171
|
/>
|
|
166
172
|
</Pressable>
|
|
167
173
|
{helpText && (
|
|
168
|
-
<UTLabel
|
|
174
|
+
<UTLabel
|
|
175
|
+
colorTheme="gray"
|
|
176
|
+
variant="small"
|
|
177
|
+
dataTestId={dataTestId ? `${dataTestId}.helpText` : undefined}
|
|
178
|
+
>
|
|
169
179
|
{helpText}
|
|
170
180
|
</UTLabel>
|
|
171
181
|
)}
|
|
172
|
-
{validationData &&
|
|
182
|
+
{validationData && (
|
|
183
|
+
<UTValidation
|
|
184
|
+
validationData={validationData}
|
|
185
|
+
dataTestId={dataTestId ? `${dataTestId}.validation` : undefined}
|
|
186
|
+
/>
|
|
187
|
+
)}
|
|
173
188
|
</View>
|
|
174
189
|
<UTBottomSheet
|
|
175
190
|
title={title}
|
|
@@ -177,6 +192,7 @@ const UTSelect = ({
|
|
|
177
192
|
visible={bottomSheetVisible}
|
|
178
193
|
onClose={handleCloseBottomSheet}
|
|
179
194
|
buttonText={closeButtonText}
|
|
195
|
+
dataTestId={dataTestId ? `${dataTestId}.bottomSheet` : undefined}
|
|
180
196
|
>
|
|
181
197
|
<View style={styles.bottomSheetBodyContainer}>
|
|
182
198
|
<UTSearchField
|
|
@@ -184,9 +200,14 @@ const UTSelect = ({
|
|
|
184
200
|
placeholder={searchPlaceholder}
|
|
185
201
|
value={searchTerm}
|
|
186
202
|
variant="gray"
|
|
203
|
+
dataTestId={dataTestId ? `${dataTestId}.searchField` : undefined}
|
|
187
204
|
/>
|
|
188
205
|
{isEmpty(filteredOptions) ? (
|
|
189
|
-
<UTLabel
|
|
206
|
+
<UTLabel
|
|
207
|
+
colorTheme="gray"
|
|
208
|
+
style={styles.noMatchesText}
|
|
209
|
+
dataTestId={dataTestId ? `${dataTestId}.noOptionsMessage` : undefined}
|
|
210
|
+
>
|
|
190
211
|
{!searchTerm ? noOptionsText : noMatchesText}
|
|
191
212
|
</UTLabel>
|
|
192
213
|
) : (
|
|
@@ -200,6 +221,7 @@ const UTSelect = ({
|
|
|
200
221
|
value={value ? (multiple ? value : [value]) : []}
|
|
201
222
|
variant="button"
|
|
202
223
|
style={{ item: { title: styles.checklistTitles } }}
|
|
224
|
+
dataTestId={dataTestId ? `${dataTestId}.optionsList` : undefined}
|
|
203
225
|
/>
|
|
204
226
|
</ScrollView>
|
|
205
227
|
)}
|
|
@@ -11,9 +11,11 @@
|
|
|
11
11
|
| `additionalInfo` | `additionalInfoType` | `{}` | Contains `description` and `title` to display supplementary information in the card. |
|
|
12
12
|
| `appearance` | `string` | `'white'` | Defines the card's appearance. Supported values: `white`, `gray`. |
|
|
13
13
|
| `checkIcon` | `bool` | `true` | Whether to show a check icon when the card is selected. |
|
|
14
|
+
| `dataTestId` | `string` | | Unique identifier for testing purposes. Creates hierarchical test IDs for child elements. |
|
|
14
15
|
| `description` | `string` | | Secondary text shown below the title. |
|
|
15
16
|
| `disabled` | `bool` | `false` | Disables the card, preventing interactions and applying a disabled style. |
|
|
16
17
|
| `Icon` | `iconType` | | Icon configuration. Supports `url`, `name`, `shade`, `size`, or a custom `Component`. |
|
|
18
|
+
| `iconDataTestId` | `string` | | Override test ID for Icon.Component. If not provided, uses `${dataTestId}.icon`. |
|
|
17
19
|
| `numberOfLines` | `number` | | Determines the amount of lines the text can span. If the text overflows it will be ellipsized |
|
|
18
20
|
| `onPress` | `func` | | Function triggered when the card is pressed. |
|
|
19
21
|
| `selected` | `bool` | `false` | Indicates whether the card is selected. |
|
|
@@ -82,6 +84,89 @@ export default Example;
|
|
|
82
84
|
/>
|
|
83
85
|
```
|
|
84
86
|
|
|
87
|
+
## Testing
|
|
88
|
+
|
|
89
|
+
The `UTSelectableCard` component supports comprehensive test ID assignment through the `dataTestId` prop. When provided, it creates a hierarchical structure of test IDs for all interactive and meaningful elements.
|
|
90
|
+
|
|
91
|
+
### Test ID Structure
|
|
92
|
+
|
|
93
|
+
When you provide `dataTestId="provided.testId"`, the following test IDs are automatically generated:
|
|
94
|
+
|
|
95
|
+
| Element | Test ID | When Available |
|
|
96
|
+
| --------------------------- | -------------------------------------------- | ------------------------------------------- |
|
|
97
|
+
| Card container (touchable) | `provided.testId` | Always (when dataTestId is provided) |
|
|
98
|
+
| Icon | `provided.testId.icon` | When Icon prop is provided |
|
|
99
|
+
| Title text | `provided.testId.titleText` | When titleText prop is provided |
|
|
100
|
+
| Description text | `provided.testId.description` | When description prop is provided |
|
|
101
|
+
| Tooltip | `provided.testId.tooltip` | When tooltip prop is provided |
|
|
102
|
+
| Tooltip content | `provided.testId.tooltip.content` | When tooltip prop is provided |
|
|
103
|
+
| Additional info title | `provided.testId.additionalInfo.title` | When additionalInfo.title is provided |
|
|
104
|
+
| Additional info description | `provided.testId.additionalInfo.description` | When additionalInfo.description is provided |
|
|
105
|
+
| Check icon | `provided.testId.checkIcon` | When selected=true and checkIcon=true |
|
|
106
|
+
|
|
107
|
+
**Note:** If `Icon.Component` is used, the `iconDataTestId` prop can be used to override the default `${dataTestId}.icon` test ID. This prop only applies to custom icon components and has no effect when using `Icon.url` or `Icon.name`.
|
|
108
|
+
|
|
109
|
+
**Children Test IDs:** The `children` prop renders React components directly without wrapping them. If child components need test IDs, it's the responsibility of the developer creating those components to add appropriate `dataTestId` props.
|
|
110
|
+
|
|
111
|
+
### Example Usage
|
|
112
|
+
|
|
113
|
+
```jsx
|
|
114
|
+
// Basic test ID usage
|
|
115
|
+
<UTSelectableCard
|
|
116
|
+
dataTestId="addressCard.1"
|
|
117
|
+
titleText="Home Address"
|
|
118
|
+
description="123 Main Street"
|
|
119
|
+
selected={true}
|
|
120
|
+
onPress={() => selectAddress(1)}
|
|
121
|
+
/>
|
|
122
|
+
|
|
123
|
+
// Creates the following test IDs:
|
|
124
|
+
// - addressCard.1 (main container)
|
|
125
|
+
// - addressCard.1.titleText (title text)
|
|
126
|
+
// - addressCard.1.description (description text)
|
|
127
|
+
// - addressCard.1.checkIcon (check icon when selected)
|
|
128
|
+
|
|
129
|
+
// With all features enabled
|
|
130
|
+
<UTSelectableCard
|
|
131
|
+
dataTestId="paymentCard.visa"
|
|
132
|
+
titleText="Visa ****1234"
|
|
133
|
+
description="Expires 12/25"
|
|
134
|
+
additionalInfo={{ title: "Primary", description: "Default card" }}
|
|
135
|
+
Icon={{ name: "IconCreditCard" }}
|
|
136
|
+
tooltip="Secure payment method"
|
|
137
|
+
selected={false}
|
|
138
|
+
onPress={() => selectCard('visa')}
|
|
139
|
+
/>
|
|
140
|
+
|
|
141
|
+
// Creates test IDs:
|
|
142
|
+
// - paymentCard.visa
|
|
143
|
+
// - paymentCard.visa.icon
|
|
144
|
+
// - paymentCard.visa.titleText
|
|
145
|
+
// - paymentCard.visa.description
|
|
146
|
+
// - paymentCard.visa.tooltip
|
|
147
|
+
// - paymentCard.visa.tooltip.content
|
|
148
|
+
// - paymentCard.visa.additionalInfo.title
|
|
149
|
+
// - paymentCard.visa.additionalInfo.description
|
|
150
|
+
|
|
151
|
+
// Custom icon test ID override
|
|
152
|
+
<UTSelectableCard
|
|
153
|
+
dataTestId="productCard.featured"
|
|
154
|
+
iconDataTestId="customProductIcon.primary"
|
|
155
|
+
titleText="Premium Product"
|
|
156
|
+
description="High-quality item"
|
|
157
|
+
Icon={{ Component: CustomIconComponent }}
|
|
158
|
+
selected={true}
|
|
159
|
+
onPress={() => selectProduct('featured')}
|
|
160
|
+
/>
|
|
161
|
+
|
|
162
|
+
// Creates test IDs:
|
|
163
|
+
// - productCard.featured (main container)
|
|
164
|
+
// - customProductIcon.primary (custom icon test ID)
|
|
165
|
+
// - productCard.featured.titleText
|
|
166
|
+
// - productCard.featured.description
|
|
167
|
+
// - productCard.featured.checkIcon
|
|
168
|
+
```
|
|
169
|
+
|
|
85
170
|
## Notes
|
|
86
171
|
|
|
87
172
|
- Ensure to define custom styles through the `style` prop or the project theme.
|