Skip to content

Commit 18d09ca

Browse files
committed
feat: exclude unused countries
1 parent 050aeb2 commit 18d09ca

11 files changed

Lines changed: 343 additions & 376 deletions

File tree

README.md

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@
2020
## TODO
2121

2222
- [ ] Fix defaultProp issue with picker library
23-
- [ ] Make similar UI with OTP lib
24-
- [ ] Add Error state
25-
- [ ] Make fully customizable
23+
- [ ] Add custom country picker modal
2624

2725
## Installation
2826

@@ -69,15 +67,15 @@ export default function App() {
6967
callingCode: '+1',
7068
phoneNumber: '',
7169
}}
72-
withShadow
73-
withDarkTheme
70+
theme={{
71+
withShadow: true,
72+
withDarkTheme: true,
73+
containerStyle: styles.phoneContainer,
74+
textInputStyle: styles.input,
75+
flagButtonStyle: styles.flagButton,
76+
}}
7477
autoFocus
7578
placeholder="Enter phone number"
76-
containerStyle={styles.phoneContainer}
77-
textContainerStyle={styles.textInput}
78-
textInputStyle={styles.input}
79-
flagButtonStyle={styles.flagButton}
80-
countryPickerButtonStyle={styles.countryPicker}
8179
layout="second"
8280
onChangeText={(text) => console.log('Phone number:', text)}
8381
onChangeCountry={(country) => console.log('Country:', country)}
@@ -86,26 +84,31 @@ export default function App() {
8684

8785
## Props
8886

89-
| Prop | Type | Description |
90-
| -------------------------- | ---------------------------- | --------------------------------------------------------------- |
91-
| `defaultValues` | `object` | Default values for country code, calling code, and phone number |
92-
| `value` | `string` | Controlled value for the phone number input |
93-
| `onChangeText` | `(text: string) => void` | Callback when phone number changes |
94-
| `onChangeCountry` | `(country: Country) => void` | Callback when selected country changes |
95-
| `withShadow` | `boolean` | Adds shadow to the input container |
96-
| `withDarkTheme` | `boolean` | Enables dark theme |
97-
| `autoFocus` | `boolean` | Automatically focuses the input when mounted |
98-
| `placeholder` | `string` | Placeholder text for the phone number input |
99-
| `disabled` | `boolean` | Disables the input |
100-
| `layout` | `'first' \| 'second'` | Layout style for the country picker and input |
101-
| `containerStyle` | `StyleProp<ViewStyle>` | Style for the main container |
102-
| `textContainerStyle` | `StyleProp<ViewStyle>` | Style for the text input container |
103-
| `textInputStyle` | `StyleProp<TextStyle>` | Style for the text input |
104-
| `flagButtonStyle` | `StyleProp<ViewStyle>` | Style for the flag button |
105-
| `countryPickerButtonStyle` | `StyleProp<ViewStyle>` | Style for the country picker button |
106-
| `countryPickerProps` | `CountryPickerProps` | Props for the country picker modal |
107-
| `filterProps` | `object` | Props for the country filter |
108-
| `maskInputProps` | `MaskInputProps` | Props for the masked input component |
87+
| Prop | Type | Description |
88+
| -------------------- | ---------------------------- | --------------------------------------------------------------- |
89+
| `defaultValues` | `object` | Default values for country code, calling code, and phone number |
90+
| `value` | `string` | Controlled value for the phone number input |
91+
| `onChangeText` | `(text: string) => void` | Callback when phone number changes |
92+
| `onChangeCountry` | `(country: Country) => void` | Callback when selected country changes |
93+
| `autoFocus` | `boolean` | Automatically focuses the input when mounted |
94+
| `placeholder` | `string` | Placeholder text for the phone number input |
95+
| `disabled` | `boolean` | Disables the input |
96+
| `layout` | `'first' \| 'second'` | Layout style for the country picker and input |
97+
| `countryPickerProps` | `CountryPickerProps` | Props for the country picker modal |
98+
| `filterProps` | `object` | Props for the country filter |
99+
| `maskInputProps` | `MaskInputProps` | Props for the masked input component |
100+
| `theme` | `Theme` | Theme configuration for styling the component |
101+
102+
### Theme Properties
103+
104+
| Property | Type | Description |
105+
| ----------------- | ---------------------- | ------------------------------------ |
106+
| `containerStyle` | `StyleProp<ViewStyle>` | Style for the main container |
107+
| `textInputStyle` | `StyleProp<TextStyle>` | Style for the text input |
108+
| `codeTextStyle` | `StyleProp<TextStyle>` | Style for the calling code text |
109+
| `flagButtonStyle` | `StyleProp<ViewStyle>` | Style for the flag button |
110+
| `withDarkTheme` | `boolean` | Enables dark theme for the component |
111+
| `withShadow` | `boolean` | Adds shadow to the input container |
109112

110113
## Contributing
111114

example/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"react": "18.3.1",
1616
"react-dom": "18.3.1",
1717
"react-native": "0.76.6",
18+
"react-native-otp-entry": "~1.8.2",
1819
"react-native-web": "~0.19.13"
1920
},
2021
"devDependencies": {

example/src/App.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ export default function App() {
77
<PhoneInput
88
onChangeCountry={(country) => console.log('country changed:', country)}
99
onChangeText={(text) => console.log('text changed:', text)}
10-
callingCodeEditable={false}
11-
theme={{
12-
withShadow: true,
13-
}}
10+
// callingCodeEditable={false}
11+
theme={
12+
{
13+
// withShadow: true,
14+
}
15+
}
1416
/>
17+
{/* <OtpInput /> */}
1518
</View>
1619
);
1720
}
@@ -21,6 +24,6 @@ const styles = StyleSheet.create({
2124
flex: 1,
2225
alignItems: 'center',
2326
justifyContent: 'center',
24-
backgroundColor: 'white',
27+
// backgroundColor: 'black',
2528
},
2629
});

src/PhoneInput/PhoneInput.tsx

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import CountryPicker, {
77
Flag,
88
} from 'react-native-country-picker-modal';
99
import MaskInput from 'react-native-mask-input';
10+
import { EXCLUDED_COUNTRIES } from './constants';
1011
import type { PhoneInputProps } from './PhoneInput.types';
1112
import styles from './styles';
1213
import { usePhoneInput } from './usePhoneInput';
@@ -28,7 +29,6 @@ export const PhoneInput: React.FC<PhoneInputProps> = (props) => {
2829
textInputStyle,
2930
flagButtonStyle,
3031
containerStyle,
31-
countryPickerButtonStyle,
3232
} = {},
3333
maskInputProps,
3434
autoFocus,
@@ -50,12 +50,16 @@ export const PhoneInput: React.FC<PhoneInputProps> = (props) => {
5050
);
5151
}, []);
5252

53-
const renderFlagButton = useCallback(() => {
54-
const flagSize = flagProps?.flagSize || DEFAULT_THEME.flagSize;
55-
return (
56-
<Flag countryCode={countryCode} flagSize={flagSize} {...flagProps} />
57-
);
58-
}, [countryCode, flagProps]);
53+
const renderFlagButton = useCallback(
54+
() => (
55+
<Flag
56+
countryCode={countryCode}
57+
flagSize={flagProps?.flagSize || DEFAULT_THEME.flagSize}
58+
{...flagProps}
59+
/>
60+
),
61+
[countryCode, flagProps]
62+
);
5963

6064
return (
6165
<CountryModalProvider>
@@ -69,11 +73,7 @@ export const PhoneInput: React.FC<PhoneInputProps> = (props) => {
6973
>
7074
<TouchableOpacity
7175
testID="country-picker-button"
72-
style={[
73-
styles.flagButtonView,
74-
flagButtonStyle,
75-
countryPickerButtonStyle,
76-
]}
76+
style={[styles.flagButtonView, flagButtonStyle]}
7777
disabled={disabled}
7878
onPress={showModal}
7979
>
@@ -82,37 +82,37 @@ export const PhoneInput: React.FC<PhoneInputProps> = (props) => {
8282
withEmoji
8383
withFilter
8484
withFlag
85+
withAlphaFilter
8586
filterProps={countryPickerProps?.filterProps}
8687
countryCode={countryCode}
8788
withCallingCode
8889
disableNativeModal={disabled}
8990
visible={modalVisible}
9091
theme={withDarkTheme ? DARK_THEME : DEFAULT_THEME}
9192
renderFlagButton={renderFlagButton}
93+
excludeCountries={EXCLUDED_COUNTRIES}
9294
onClose={hideModal}
9395
{...countryPickerProps}
9496
/>
9597
{!disableArrowIcon &&
9698
(renderDropdownImage || <>{_renderDropdownImage}</>)}
9799
</TouchableOpacity>
98-
<View style={styles.textInputWrapper}>
99-
<MaskInput
100-
testID="phone-input"
101-
ref={(ref) => {
102-
inputRef.current = ref;
103-
}}
104-
style={[styles.numberText, textInputStyle]}
105-
mask={mask}
106-
onChangeText={handleChangeText}
107-
value={phoneNumber}
108-
editable={!disabled}
109-
selectionColor="black"
110-
keyboardAppearance={withDarkTheme ? 'dark' : 'default'}
111-
keyboardType="number-pad"
112-
autoFocus={autoFocus}
113-
{...maskInputProps}
114-
/>
115-
</View>
100+
<MaskInput
101+
testID="phone-input"
102+
ref={(ref) => {
103+
inputRef.current = ref;
104+
}}
105+
style={[styles.numberText, textInputStyle]}
106+
mask={mask}
107+
onChangeText={handleChangeText}
108+
value={phoneNumber}
109+
editable={!disabled}
110+
selectionColor="black"
111+
keyboardAppearance={withDarkTheme ? 'dark' : 'default'}
112+
keyboardType="number-pad"
113+
autoFocus={autoFocus}
114+
{...maskInputProps}
115+
/>
116116
</View>
117117
</CountryModalProvider>
118118
);

src/PhoneInput/PhoneInput.types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ interface Theme {
3333
textInputStyle?: StyleProp<TextStyle>;
3434
codeTextStyle?: StyleProp<TextStyle>;
3535
flagButtonStyle?: StyleProp<ViewStyle>;
36-
countryPickerButtonStyle?: StyleProp<ViewStyle>;
3736
withDarkTheme?: boolean;
3837
withShadow?: boolean;
3938
}

0 commit comments

Comments
 (0)