Skip to content

Commit ee21567

Browse files
authored
Feat/picker custom top element (#3465)
* Picker types - customTopElement, onItemSelection * add customTopElement support in Picker component * PickerScreen example * refactor: rename customTopElement, types fix * remove onItemSelection prop * remove unused setValue from Picker context * use optional chaining for renderCustomTopElement * renderCustomTopElement added to api.json
1 parent c2bc66c commit ee21567

File tree

5 files changed

+60
-2
lines changed

5 files changed

+60
-2
lines changed

demo/src/screens/componentScreens/PickerScreen.tsx

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ const dialogOptions = [
8383
{label: 'Option 8', value: 6}
8484
];
8585

86+
const statusOptions = [
87+
{label: 'Overview', value: 'overview'},
88+
{label: 'In Progress', value: 'inProgress'},
89+
{label: 'Completed', value: 'completed'},
90+
{label: 'Pending Review', value: 'pendingReview'},
91+
{label: 'Approved', value: 'approved'},
92+
{label: 'Rejected', value: 'rejected'}
93+
];
94+
8695
export default class PickerScreen extends Component {
8796
picker = React.createRef<PickerMethods>();
8897
state = {
@@ -96,6 +105,7 @@ export default class PickerScreen extends Component {
96105
dialogPickerValue: 'java',
97106
customModalValues: [],
98107
filter: undefined,
108+
statOption: [],
99109
scheme: undefined,
100110
contact: 0
101111
};
@@ -122,6 +132,15 @@ export default class PickerScreen extends Component {
122132
);
123133
};
124134

135+
onTopElementPress = (allOptionsSelected: boolean) => {
136+
if (allOptionsSelected) {
137+
this.setState({statOption: []});
138+
} else {
139+
const allValues = statusOptions.map(option => option.value);
140+
this.setState({statOption: allValues});
141+
}
142+
};
143+
125144
render() {
126145
return (
127146
<ScrollView keyboardShouldPersistTaps="always">
@@ -195,7 +214,32 @@ export default class PickerScreen extends Component {
195214
searchPlaceholder={'Search a language'}
196215
items={dialogOptions}
197216
/>
198-
217+
218+
<Text text70 $textDefault>
219+
Custom Top Element:
220+
</Text>
221+
<Picker
222+
placeholder="Status"
223+
floatingPlaceholder
224+
value={this.state.statOption}
225+
onChange={items => this.setState({statOption: items})}
226+
topBarProps={{title: 'Status'}}
227+
mode={Picker.modes.MULTI}
228+
items={statusOptions}
229+
renderCustomTopElement={value => {
230+
const allOptionsSelected = Array.isArray(value) && value.length === statusOptions.length;
231+
return (
232+
<View margin-s3>
233+
<Button
234+
label={allOptionsSelected ? 'Unselect All' : 'Select All'}
235+
onPress={() => this.onTopElementPress(allOptionsSelected)}
236+
size="small"
237+
/>
238+
</View>
239+
);
240+
}}
241+
/>
242+
199243
<Text marginB-10 text70 $textDefault>
200244
Custom Picker:
201245
</Text>

src/components/picker/PickerItemsList.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ const PickerItemsList = (props: PickerItemsListProps) => {
3434
mode,
3535
testID,
3636
showLoader,
37-
customLoaderElement
37+
customLoaderElement,
38+
renderCustomTopElement
3839
} = props;
3940
const context = useContext(PickerContext);
4041

@@ -167,6 +168,7 @@ const PickerItemsList = (props: PickerItemsListProps) => {
167168
) : (
168169
<>
169170
{renderSearchInput()}
171+
{renderCustomTopElement?.(context.value)}
170172
{renderList()}
171173
</>
172174
);

src/components/picker/api/picker.api.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@
4747
"type": "(value, {{...props, isSelected}}, itemLabel) => void",
4848
"description": "Render custom picker item"
4949
},
50+
{
51+
"name": "renderCustomTopElement",
52+
"type": "(value?: PickerValue) => React.ReactElement",
53+
"description": "Render custom top element"
54+
},
5055
{
5156
"name": "renderCustomModal",
5257
"type": "({visible, children, toggleModal}) => void)",

src/components/picker/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ const Picker = React.forwardRef((props: PickerProps, ref) => {
7878
items: propItems,
7979
showLoader,
8080
customLoaderElement,
81+
renderCustomTopElement,
8182
...others
8283
} = themeProps;
8384
const {preset, placeholder, style, trailingAccessory, label: propsLabel} = others;
@@ -245,6 +246,7 @@ const Picker = React.forwardRef((props: PickerProps, ref) => {
245246
useSafeArea={useSafeArea}
246247
showLoader={showLoader}
247248
customLoaderElement={customLoaderElement}
249+
renderCustomTopElement={renderCustomTopElement}
248250
>
249251
{filteredItems}
250252
</PickerItemsList>

src/components/picker/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ export type PickerBaseProps = Omit<TextFieldProps, 'value' | 'onChange'> &
206206
itemProps: PickerItemProps & {isSelected: boolean; isItemDisabled: boolean},
207207
label?: string
208208
) => React.ReactElement;
209+
/**
210+
* Render custom top element
211+
*/
212+
renderCustomTopElement?: (value?: PickerValue) => React.ReactElement;
209213
/**
210214
* Add onPress callback for when pressing the picker
211215
*/
@@ -315,6 +319,7 @@ export type PickerItemsListProps = Pick<
315319
| 'useSafeArea'
316320
| 'showLoader'
317321
| 'customLoaderElement'
322+
| 'renderCustomTopElement'
318323
| 'showSearch'
319324
| 'searchStyle'
320325
| 'searchPlaceholder'

0 commit comments

Comments
 (0)