Skip to content

Commit 083acc7

Browse files
authored
Infra/picker screen ts (#1888)
* Change PickerScreen to TS * Migrate PickerScreen to TS * Remove old Picker typings * Revert changes in globalTypes file
1 parent 2007fe4 commit 083acc7

File tree

7 files changed

+123
-160
lines changed

7 files changed

+123
-160
lines changed

demo/src/screens/componentScreens/PickerScreen.js renamed to demo/src/screens/componentScreens/PickerScreen.tsx

Lines changed: 78 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,17 @@ import {
1111
Avatar,
1212
Assets,
1313
PanningProvider,
14-
Typography
14+
Typography,
15+
PickerProps,
16+
DialogProps
1517
} from 'react-native-ui-lib'; //eslint-disable-line
1618
import contactsData from '../../data/conversations';
17-
import tagIcon from '../../assets/icons/tags.png';
18-
import dropdown from '../../assets/icons/chevronDown.png';
1919
import {longOptions} from './PickerScreenLongOptions';
2020

21-
const contacts = _.map(contactsData, c => ({...c, value: c.name, label: c.name}));
21+
const tagIcon = require('../../assets/icons/tags.png');
22+
const dropdown = require('../../assets/icons/chevronDown.png');
23+
24+
const contacts = _.map(contactsData, (c, index) => ({...c, value: index, label: c.name}));
2225

2326
const options = [
2427
{label: 'JavaScript', value: 'js'},
@@ -35,26 +38,19 @@ const filters = [
3538
];
3639

3740
export default class PickerScreen extends Component {
38-
constructor(props) {
39-
super(props);
40-
41-
this.state = {
42-
itemsCount: 1,
43-
// language: {value: 'java', label: 'Java'},
44-
language: undefined,
45-
language2: options[2].value, // for migrated picker example
46-
languages: [],
47-
nativePickerValue: 'java',
48-
customModalValues: [],
49-
filter: filters[0],
50-
contact: contacts[0],
51-
tags: [{label: 'Amit'}, {label: 'Ethan'}],
52-
tags2: ['Tags', 'Input'],
53-
tags3: ['Non', 'Removable', 'Tags']
54-
};
55-
}
41+
state = {
42+
itemsCount: 1,
43+
// language: {value: 'java', label: 'Java'},
44+
language: undefined,
45+
language2: options[2].value, // for migrated picker example
46+
languages: [],
47+
nativePickerValue: 'java',
48+
customModalValues: [],
49+
filter: filters[0],
50+
contact: 0
51+
};
5652

57-
dialogHeader = props => {
53+
dialogHeader: DialogProps['renderPannableHeader'] = props => {
5854
const {title} = props;
5955
return (
6056
<Text margin-15 text60>
@@ -63,7 +59,7 @@ export default class PickerScreen extends Component {
6359
);
6460
};
6561

66-
renderDialog = modalProps => {
62+
renderDialog: PickerProps['renderCustomModal'] = modalProps => {
6763
const {visible, children, toggleModal, onDone} = modalProps;
6864

6965
return (
@@ -99,19 +95,18 @@ export default class PickerScreen extends Component {
9995
enableModalBlur={false}
10096
onChange={item => this.setState({language: item})}
10197
topBarProps={{title: 'Languages'}}
102-
style={{color: Colors.red20}}
98+
// style={{color: Colors.red20}}
10399
showSearch
104100
searchPlaceholder={'Search a language'}
105101
searchStyle={{color: Colors.blue30, placeholderTextColor: Colors.grey50}}
106102
// onSearchChange={value => console.warn('value', value)}
107103
>
108104
{_.map(longOptions, option => (
109-
<Picker.Item key={option.value} value={option} disabled={option.disabled}/>
105+
<Picker.Item key={option.value} value={option} label={''} disabled={option.disabled}/>
110106
))}
111107
</Picker>
112108

113109
<Picker
114-
marginT-20
115110
placeholder="Favorite Languages (up to 3)"
116111
value={this.state.languages}
117112
onChange={items => this.setState({languages: items})}
@@ -120,7 +115,7 @@ export default class PickerScreen extends Component {
120115
rightIconSource={dropdown}
121116
>
122117
{_.map(options, option => (
123-
<Picker.Item key={option.value} value={option} disabled={option.disabled}/>
118+
<Picker.Item key={option.value} value={option} label={''} disabled={option.disabled}/>
124119
))}
125120
</Picker>
126121

@@ -131,7 +126,7 @@ export default class PickerScreen extends Component {
131126
value={this.state.nativePickerValue}
132127
onChange={nativePickerValue => this.setState({nativePickerValue})}
133128
rightIconSource={dropdown}
134-
containerStyle={{marginTop: 20}}
129+
// containerStyle={{marginTop: 20}}
135130
// renderPicker={() => {
136131
// return (
137132
// <View>
@@ -154,7 +149,6 @@ export default class PickerScreen extends Component {
154149
</Picker>
155150

156151
<Picker
157-
marginT-20
158152
title="Custom modal"
159153
placeholder="Pick multiple Languages"
160154
value={this.state.customModalValues}
@@ -174,13 +168,13 @@ export default class PickerScreen extends Component {
174168
))}
175169
</Picker>
176170

177-
<Text marginT-20 marginB-10 text70 grey60>
171+
<Text marginB-10 text70>
178172
Custom Picker:
179173
</Text>
180174
<Picker
181175
value={this.state.filter}
182176
onChange={filter => this.setState({filter})}
183-
renderPicker={({label}) => {
177+
renderPicker={(_value?: any, label?: string) => {
184178
return (
185179
<View row>
186180
<Icon style={{marginRight: 1, height: 16, resizeMode: 'contain'}} source={tagIcon}/>
@@ -192,62 +186,78 @@ export default class PickerScreen extends Component {
192186
}}
193187
>
194188
{_.map(filters, filter => (
195-
<Picker.Item key={filter.value} value={filter}/>
189+
<Picker.Item key={filter.value} value={filter} label={''}/>
196190
))}
197191
</Picker>
198192

199-
<Text marginT-20 marginB-10 text70 grey60>
193+
<Text text60 marginT-s5>
194+
Migrated Pickers
195+
</Text>
196+
197+
<Text marginT-20 marginB-10 text70>
200198
Custom Picker Items:
201199
</Text>
202200
<Picker
201+
migrate
203202
value={this.state.contact}
204-
onChange={contact => this.setState({contact})}
205-
getItemValue={contact => contact.name}
206-
renderPicker={contact => {
203+
onChange={contact => {
204+
this.setState({contact});
205+
}}
206+
// getItemValue={contact => contact?.value}
207+
renderPicker={(contactValue?: number) => {
208+
const contact = contacts[contactValue!] ?? undefined;
207209
return (
208210
<View row>
209-
<Avatar size={30} source={{uri: contact.thumbnail}}/>
210-
<Text text70 marginL-10>
211-
{contact.name}
212-
</Text>
211+
{contact ? (
212+
<>
213+
<Avatar size={30} source={{uri: contact?.thumbnail}}/>
214+
<Text text70 marginL-10>
215+
{contact?.name}
216+
</Text>
217+
</>
218+
) : (
219+
<Text text70 grey30>
220+
Pick a contact
221+
</Text>
222+
)}
213223
</View>
214224
);
215225
}}
216226
>
217227
{_.map(contacts, contact => (
218228
<Picker.Item
219229
key={contact.name}
220-
value={contact}
221-
renderItem={(item, props) => (
222-
<View
223-
style={{
224-
height: 56,
225-
borderBottomWidth: 1,
226-
borderColor: Colors.grey80
227-
}}
228-
paddingH-15
229-
row
230-
centerV
231-
spread
232-
>
233-
<View row centerV>
234-
<Avatar size={35} source={{uri: item.thumbnail}}/>
235-
<Text marginL-10 text70 grey10>
236-
{item.name}
237-
</Text>
230+
value={contact.value}
231+
label={contact.label}
232+
renderItem={(contactValue, props) => {
233+
const contact = contacts[contactValue as number];
234+
return (
235+
<View
236+
style={{
237+
height: 56,
238+
borderBottomWidth: 1,
239+
borderColor: Colors.grey80
240+
}}
241+
paddingH-15
242+
row
243+
centerV
244+
spread
245+
>
246+
<View row centerV>
247+
<Avatar size={35} source={{uri: contact?.thumbnail}}/>
248+
<Text marginL-10 text70 grey10>
249+
{contact?.name}
250+
</Text>
251+
</View>
252+
{props.isSelected && <Icon source={Assets.icons.check}/>}
238253
</View>
239-
{props.isSelected && <Icon source={Assets.icons.check}/>}
240-
</View>
241-
)}
242-
getItemLabel={item => item.name}
254+
);
255+
}}
256+
getItemLabel={contactValue => contacts[contactValue as number]?.name}
243257
/>
244258
))}
245259
</Picker>
246260

247-
<Text text60 marginT-s5 marginB-s2>
248-
Migrated Picker
249-
</Text>
250-
251261
<Picker
252262
migrate
253263
migrateTextField
@@ -259,6 +269,7 @@ export default class PickerScreen extends Component {
259269
showSearch
260270
searchPlaceholder={'Search a language'}
261271
searchStyle={{color: Colors.blue30, placeholderTextColor: Colors.grey50}}
272+
marginT-s4
262273
// mode={Picker.modes.MULTI}
263274
// useNativePicker
264275
>

demo/src/screens/componentScreens/PickerScreenLongOptions.js renamed to demo/src/screens/componentScreens/PickerScreenLongOptions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ export const longOptions = [
33
{label: 'ABAP2', value: 'ABAP2'},
44
{label: 'ABAP3', value: 'ABAP3'},
55
{label: 'ABAP4', value: 'ABAP4'},
6-
{label: 'ABAP5', value: 'ABAP5'},
6+
{label: 'ABAP5', value: 'ABAP5', disabled: true},
77
{label: 'ActionScript1', value: 'ActionScript1'},
88
{label: 'ActionScript2', value: 'ActionScript2'},
99
{label: 'ActionScript3', value: 'ActionScript3'},
1010
{label: 'ActionScript4', value: 'ActionScript4'},
1111
{label: 'ActionScript5', value: 'ActionScript5'},
12-
{label: 'Ada1', value: 'Ada1'},
12+
{label: 'Ada1', value: 'Ada1', disabled: true},
1313
{label: 'Ada2', value: 'Ada2'},
1414
{label: 'Ada3', value: 'Ada3'},
1515
{label: 'Ada4', value: 'Ada4'},

generatedTypes/src/components/picker/new.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,17 @@ declare const Picker: {
1616
};
1717
export { PickerProps, PickerItemProps, PickerValue, PickerModes, PickerSearchStyle };
1818
export { Picker };
19-
declare const _default: React.ComponentClass<(import("./types").PickerPropsWithSingle | import("./types").PickerPropsWithMulti) & {
19+
declare const _default: React.ComponentClass<PickerProps & {
2020
useCustomTheme?: boolean | undefined;
2121
}, any> & {
22-
(props: React.PropsWithChildren<import("./types").PickerPropsWithSingle | import("./types").PickerPropsWithMulti> & ForwardRefInjectedProps & BaseComponentInjectedProps): JSX.Element;
22+
(props: React.PropsWithChildren<PickerProps> & ForwardRefInjectedProps & BaseComponentInjectedProps): JSX.Element;
2323
Item: {
2424
(props: PickerItemProps): JSX.Element;
2525
displayName: string;
2626
};
2727
defaultProps: any;
2828
modes: typeof PickerModes;
29-
extractPickerItems(props: React.PropsWithChildren<import("./types").PickerPropsWithSingle | import("./types").PickerPropsWithMulti>): {
29+
extractPickerItems(props: React.PropsWithChildren<PickerProps>): {
3030
value: any;
3131
label: any;
3232
}[] | null | undefined;

generatedTypes/src/components/picker/types.d.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { PropsWithChildren } from 'react';
1+
import React, { PropsWithChildren, ReactNode } from 'react';
22
import { FlatListProps, StyleProp, ViewStyle, TextStyle } from 'react-native';
33
import { ExpandableOverlayProps } from '../../incubator/expandableOverlay';
44
import { ModalTopBarProps } from '../modal/TopBar';
@@ -13,7 +13,17 @@ declare type PickerValueDeprecated = {
1313
};
1414
export declare type PickerSingleValue = string | number | PickerValueDeprecated;
1515
export declare type PickerMultiValue = PickerSingleValue[];
16-
export declare type PickerValue = PickerSingleValue | PickerMultiValue;
16+
export declare type PickerValue = PickerSingleValue | PickerMultiValue | undefined;
17+
declare type RenderPickerOverloads<ValueType> = ValueType extends PickerValue ? (value?: ValueType, label?: string) => React.ReactElement : never;
18+
declare type RenderPicker = RenderPickerOverloads<PickerValue>;
19+
declare type RenderCustomModalProps = {
20+
visible: boolean;
21+
toggleModal: (show: boolean) => void;
22+
onSearchChange: (searchValue: string) => void;
23+
children: ReactNode;
24+
onDone: () => void;
25+
onCancel: () => void;
26+
};
1727
export interface PickerSearchStyle {
1828
icon?: number;
1929
color?: string;
@@ -54,7 +64,7 @@ export interface PickerBaseProps extends Omit<TextFieldProps, 'value' | 'onChang
5464
* Example:
5565
* renderPicker = (selectedItem) => {...}
5666
*/
57-
renderPicker?: (value?: PickerValue, label?: string) => React.ReactElement;
67+
renderPicker?: RenderPicker;
5868
/**
5969
* Render custom picker item
6070
*/
@@ -64,7 +74,7 @@ export interface PickerBaseProps extends Omit<TextFieldProps, 'value' | 'onChang
6474
/**
6575
* Render custom picker modal (e.g ({visible, children, toggleModal}) => {...})
6676
*/
67-
renderCustomModal?: (modalProps: ExpandableOverlayProps['modalProps']) => React.ReactElement;
77+
renderCustomModal?: (modalProps: RenderCustomModalProps) => React.ReactElement;
6878
/**
6979
* Custom picker props (when using renderPicker, will apply on the button wrapper)
7080
*/
@@ -142,13 +152,13 @@ export interface PickerBaseProps extends Omit<TextFieldProps, 'value' | 'onChang
142152
}
143153
export interface PickerPropsWithSingle extends PickerBaseProps {
144154
mode?: PickerModes.SINGLE;
145-
value: PickerSingleValue;
155+
value?: PickerSingleValue;
146156
}
147157
export interface PickerPropsWithMulti extends PickerBaseProps {
148158
mode?: PickerModes.MULTI;
149-
value: PickerMultiValue;
159+
value?: PickerMultiValue;
150160
}
151-
export declare type PickerProps = (PickerPropsWithSingle | PickerPropsWithMulti);
161+
export declare type PickerProps = PickerPropsWithSingle | PickerPropsWithMulti;
152162
export interface PickerItemProps {
153163
/**
154164
* Item's value

src/components/picker/new.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ const Picker = (props: PropsWithChildren<PickerProps> & ForwardRefInjectedProps
211211
disabled={editable === false}
212212
>
213213
{renderPicker ? (
214+
// @ts-expect-error TS throws a weird error, might be an issue with TS
214215
renderPicker(value, label)
215216
) : (
216217
<TextFieldMigrator

0 commit comments

Comments
 (0)