Skip to content

Commit a2b5665

Browse files
committed
feat: more picker options
1 parent b7c3f25 commit a2b5665

13 files changed

Lines changed: 820 additions & 99 deletions

src/components/Dialog/Dialog.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Opposed to `Dialog` (below), `ConfirmDialog` has predefined styling and handlers
2323
<ConfirmDialog
2424
title="Confirm dialog"
2525
isVisible={on}
26-
onClose={toggle}
26+
onRequestClose={toggle}
2727
cancelLabel="Cancel label"
2828
confirmLabel="Confirm label"
2929
>
@@ -44,7 +44,7 @@ Opposed to `Dialog` (below), `ConfirmDialog` has predefined styling and handlers
4444
<ConfirmDialog
4545
header={null}
4646
isVisible={on}
47-
onClose={toggle}
47+
onRequestClose={toggle}
4848
cancelLabel="Cancel label"
4949
confirmLabel="Confirm label"
5050
>
@@ -72,7 +72,7 @@ Dialog has no predefined styling and handlers. The content, header and footer is
7272
header={<Text>Header</Text>}
7373
footer={<Text>Footer</Text>}
7474
isVisible={on}
75-
onClose={toggle}
75+
onRequestClose={toggle}
7676
>
7777
<Box height={1800}>
7878
<Text>Put any content in the dialog</Text>

src/components/Dialog/Dialog.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ import {
1717
export interface DialogProps {
1818
children: React.ReactNode;
1919
theme: Theme;
20+
/** Prop to be passed to Modal */
21+
useHistory?: boolean;
2022
/** To show dialog or not */
2123
isVisible?: boolean;
22-
/** Called when clicking on overlay or pressing Esc */
23-
onClose?: () => void;
24+
/** Called when clicking on overlay or pressing Esc, or using back button (requires useHistory to be true) */
25+
onRequestClose?: () => void;
2426
/** In ConfirmDialog, you can pass null to render nothing. If it is undefined, it will use default value */
2527
header?: React.ReactNode;
2628
/** In ConfirmDialog, you can pass null to render nothing. If it is undefined, it will use default value */
@@ -37,9 +39,10 @@ const DialogBase = (props: DialogProps) => {
3739
footer,
3840
header,
3941
isVisible,
40-
onClose = () => null,
42+
onRequestClose = () => null,
4143
theme,
4244
getStyles,
45+
useHistory,
4346
} = props;
4447

4548
const { modalContainerStyle, containerStyle, bodyStyle } = mergeStyles(
@@ -48,14 +51,19 @@ const DialogBase = (props: DialogProps) => {
4851
)(theme);
4952

5053
return (
51-
<Modal visible={isVisible} transparent onRequestClose={onClose}>
54+
<Modal
55+
useHistory={useHistory}
56+
visible={isVisible}
57+
transparent
58+
onRequestClose={onRequestClose}
59+
>
5260
<View style={modalContainerStyle}>
5361
<View style={containerStyle}>
5462
{header}
5563
<View style={bodyStyle}>{children}</View>
5664
{footer}
5765
</View>
58-
<Overlay onPress={onClose} />
66+
<Overlay onPress={onRequestClose} />
5967
</View>
6068
</Modal>
6169
);
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import * as React from 'react';
2+
import { PickerProps as RNPickerProps } from 'react-native';
3+
4+
import { Dialog } from '../Dialog';
5+
import { SelectList, SelectListItemBaseProps } from '../SelectList';
6+
import PickerButton, { GetPickerButtonStylesProp } from './PickerButton';
7+
import { PickerButtonSize } from './PickerButton.styles';
8+
9+
export interface DialogPickerProps extends RNPickerProps {
10+
children: Array<React.ReactElement<SelectListItemBaseProps>>;
11+
/** Prop to be passed to Dialog */
12+
useHistory?: boolean;
13+
/** Label displayed when showing country selection */
14+
header?: React.ReactNode;
15+
getStyles?: GetPickerButtonStylesProp;
16+
size?: PickerButtonSize;
17+
}
18+
19+
const DialogPickerBase = (props: DialogPickerProps) => {
20+
const {
21+
header,
22+
getStyles,
23+
useHistory = false,
24+
selectedValue = null,
25+
onValueChange,
26+
children,
27+
size = 'medium',
28+
} = props;
29+
const [isDialogOpen, setIsDialogOpen] = React.useState(false);
30+
31+
const childrenArray = React.Children.toArray(children);
32+
const data = childrenArray.map(child => child.props);
33+
const selectedData = data.find(d => d.value === selectedValue);
34+
const selectedLabel = selectedData ? selectedData.label : null;
35+
36+
return (
37+
<>
38+
<PickerButton
39+
onPress={() => setIsDialogOpen(true)}
40+
getStyles={getStyles}
41+
size={size}
42+
title={selectedLabel}
43+
/>
44+
<Dialog
45+
header={header}
46+
isVisible={isDialogOpen}
47+
useHistory={useHistory}
48+
onRequestClose={() => setIsDialogOpen(false)}
49+
>
50+
<SelectList
51+
selectedValue={selectedValue}
52+
onValueChange={(value, index) => {
53+
if (onValueChange) onValueChange(value, index);
54+
setIsDialogOpen(false);
55+
}}
56+
>
57+
{children}
58+
</SelectList>
59+
</Dialog>
60+
</>
61+
);
62+
};
63+
64+
export const DialogPicker = DialogPickerBase;
65+
66+
export default DialogPicker;
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import * as React from 'react';
2+
import { PickerProps as RNPickerProps } from 'react-native';
3+
4+
import { Modal } from '../Modal';
5+
import ModalContent from '../Modal/ModalContent';
6+
import { SelectList, SelectListItemBaseProps } from '../SelectList';
7+
import PickerButton, { GetPickerButtonStylesProp } from './PickerButton';
8+
import { PickerButtonSize } from './PickerButton.styles';
9+
10+
export interface ModalPickerProps extends RNPickerProps {
11+
children: Array<React.ReactElement<SelectListItemBaseProps>>;
12+
/** Prop to be passed to modal */
13+
useHistory?: boolean;
14+
/** Label displayed when showing country selection */
15+
header?: React.ReactNode;
16+
getStyles?: GetPickerButtonStylesProp;
17+
size?: PickerButtonSize;
18+
}
19+
20+
const ModalPickerBase = (props: ModalPickerProps) => {
21+
const {
22+
header,
23+
getStyles,
24+
useHistory = false,
25+
selectedValue = null,
26+
onValueChange,
27+
children,
28+
size = 'medium',
29+
} = props;
30+
const [isModalOpen, setIsModalOpen] = React.useState(false);
31+
32+
const childrenArray = React.Children.toArray(children);
33+
const data = childrenArray.map(child => child.props);
34+
const selectedData = data.find(d => d.value === selectedValue);
35+
const selectedLabel = selectedData ? selectedData.label : null;
36+
37+
return (
38+
<>
39+
<PickerButton
40+
onPress={() => setIsModalOpen(true)}
41+
getStyles={getStyles}
42+
size={size}
43+
title={selectedLabel}
44+
/>
45+
<Modal
46+
visible={isModalOpen}
47+
useHistory={useHistory}
48+
onRequestClose={() => setIsModalOpen(false)}
49+
>
50+
<ModalContent onClose={() => setIsModalOpen(false)}>
51+
{header}
52+
<SelectList
53+
selectedValue={selectedValue}
54+
onValueChange={(value, index) => {
55+
if (onValueChange) onValueChange(value, index);
56+
setIsModalOpen(false);
57+
}}
58+
>
59+
{children}
60+
</SelectList>
61+
</ModalContent>
62+
</Modal>
63+
</>
64+
);
65+
};
66+
67+
export const ModalPicker = ModalPickerBase;
68+
69+
export default ModalPicker;

src/components/Pickers/NativePicker.tsx

Lines changed: 13 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,20 @@
11
import * as React from 'react';
2-
import {
3-
Picker as RNPicker,
4-
PickerProps as RNPickerProps,
5-
View,
6-
} from 'react-native';
7-
import { DeepPartial } from 'ts-essentials';
2+
import { Picker as RNPicker, PickerProps as RNPickerProps } from 'react-native';
83

9-
import { Icon } from '../../icons';
104
import { ThemeContext } from '../../theme';
11-
import { mergeStyles, ReplaceReturnType } from '../../utils/mergeStyles';
12-
import {
13-
GetNativePickerStyles,
14-
getNativePickerStyles,
15-
NativePickerSize,
16-
NativePickerStyles,
17-
} from './NativePicker.styles';
5+
import { mergeStyles } from '../../utils/mergeStyles';
6+
import { GetPickerButtonStylesProp } from './PickerButton';
7+
import { getPickerButtonStyles, PickerButtonSize } from './PickerButton.styles';
8+
import PickerButtonWrapper from './PickerButtonWrapper';
189

1910
export interface NativePickerProps extends RNPickerProps {
20-
size?: NativePickerSize;
11+
size?: PickerButtonSize;
2112
innerRef?: React.Ref<RNPicker>;
2213
rightIcon?: React.ReactNode;
2314
/**
2415
* Inline styles for components
2516
*/
26-
getStyles?: ReplaceReturnType<
27-
GetNativePickerStyles,
28-
DeepPartial<NativePickerStyles>
29-
>;
17+
getStyles?: GetPickerButtonStylesProp;
3018
}
3119

3220
const NativePickerBase = (props: NativePickerProps) => {
@@ -39,31 +27,20 @@ const NativePickerBase = (props: NativePickerProps) => {
3927
} = props;
4028
const theme = React.useContext(ThemeContext);
4129

42-
const {
43-
containerStyle,
44-
rightContainerStyle,
45-
pickerStyle,
46-
itemStyle,
47-
} = mergeStyles(getNativePickerStyles, getStyles)({ size }, theme);
30+
const { pickerStyle, itemStyle } = mergeStyles(
31+
getPickerButtonStyles,
32+
getStyles,
33+
)({ size }, theme);
4834

4935
return (
50-
<View style={containerStyle}>
36+
<PickerButtonWrapper getStyles={getStyles}>
5137
<RNPicker
5238
ref={innerRef}
5339
itemStyle={itemStyle}
5440
style={pickerStyle}
5541
{...pickerProps}
5642
/>
57-
<View style={rightContainerStyle}>
58-
{rightIcon || (
59-
<Icon
60-
name="chevron-down"
61-
size={32}
62-
color={theme.colors.text.default}
63-
/>
64-
)}
65-
</View>
66-
</View>
43+
</PickerButtonWrapper>
6744
);
6845
};
6946

0 commit comments

Comments
 (0)