Skip to content

Commit 32fddbe

Browse files
committed
refactor: replace svg with image
1 parent facc029 commit 32fddbe

10 files changed

Lines changed: 50 additions & 218 deletions

File tree

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ export default function App() {
6868
phoneNumber: '',
6969
}}
7070
theme={{
71-
withShadow: true,
72-
withDarkTheme: true,
71+
enableShadow: true,
72+
enableDarkTheme: true,
7373
containerStyle: styles.phoneContainer,
7474
textInputStyle: styles.input,
7575
flagButtonStyle: styles.flagButton,
@@ -107,8 +107,8 @@ export default function App() {
107107
| `textInputStyle` | `StyleProp<TextStyle>` | Style for the text input |
108108
| `codeTextStyle` | `StyleProp<TextStyle>` | Style for the calling code text |
109109
| `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 |
110+
| `enableDarkTheme` | `boolean` | Enables dark theme for the component |
111+
| `enableShadow` | `boolean` | Adds shadow to the input container |
112112

113113
## Contributing
114114

example/src/App.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export default function App() {
1010
// callingCodeEditable={false}
1111
theme={
1212
{
13-
// withShadow: true,
13+
// enableShadow: true,
1414
}
1515
}
1616
/>
@@ -24,6 +24,7 @@ const styles = StyleSheet.create({
2424
flex: 1,
2525
alignItems: 'center',
2626
justifyContent: 'center',
27+
paddingHorizontal: 16,
2728
// backgroundColor: 'black',
2829
},
2930
});

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@
9393
"react-native-builder-bob": "^0.35.2",
9494
"react-native-country-picker-modal": "^2.0.0",
9595
"react-native-mask-input": "^1.2.3",
96-
"react-native-svg": "^15.11.1",
9796
"react-test-renderer": "18.3.1",
9897
"release-it": "^17.10.0",
9998
"typescript": "^5.2.2"

src/PhoneInput/PhoneInput.tsx

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useCallback, useMemo } from 'react';
1+
import React, { useCallback } from 'react';
22
import { Appearance, Image, TouchableOpacity, View } from 'react-native';
33
import CountryPicker, {
44
CountryModalProvider,
@@ -13,7 +13,7 @@ import styles from './styles';
1313
import { usePhoneInput } from './usePhoneInput';
1414

1515
const isDarkTheme = Appearance.getColorScheme() === 'dark';
16-
const dropDown =
16+
const dropDownImage =
1717
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAi0lEQVRYR+3WuQ6AIBRE0eHL1T83FBqU5S1szdiY2NyTKcCAzU/Y3AcBXIALcIF0gRPAsehgugDEXnYQrUC88RIgfpuJ+MRrgFmILN4CjEYU4xJgFKIa1wB6Ec24FuBFiHELwIpQxa0ALUId9wAkhCnuBdQQ5ngP4I9wxXsBDyJ9m+8y/g9wAS7ABW4giBshQZji3AAAAABJRU5ErkJggg==';
1818

1919
export const PhoneInput: React.FC<PhoneInputProps> = (props) => {
@@ -25,32 +25,22 @@ export const PhoneInput: React.FC<PhoneInputProps> = (props) => {
2525

2626
const {
2727
theme: {
28-
withDarkTheme = isDarkTheme,
29-
withShadow,
28+
enableDarkTheme = isDarkTheme,
3029
textInputStyle,
3130
flagButtonStyle,
3231
containerStyle,
32+
dropDownImageStyle,
3333
} = {},
3434
maskInputProps,
3535
autoFocus,
36-
disableArrowIcon,
37-
renderDropdownImage,
36+
hideDropdownIcon,
37+
renderCustomDropdown,
3838
countryPickerProps,
3939
flagProps,
4040
disabled,
41+
dropDownImageProps,
4142
} = props;
4243

43-
const _renderDropdownImage = useMemo(() => {
44-
return (
45-
<Image
46-
testID="dropdown-icon"
47-
source={{ uri: dropDown }}
48-
resizeMode="contain"
49-
style={styles.dropDownImage}
50-
/>
51-
);
52-
}, []);
53-
5444
const renderFlagButton = useCallback(
5545
() => (
5646
<Flag
@@ -66,11 +56,7 @@ export const PhoneInput: React.FC<PhoneInputProps> = (props) => {
6656
<CountryModalProvider>
6757
<View
6858
testID="phone-input-container"
69-
style={[
70-
styles.container,
71-
withShadow ? styles.shadow : {},
72-
containerStyle,
73-
]}
59+
style={[styles.container, containerStyle]}
7460
>
7561
<TouchableOpacity
7662
testID="country-picker-button"
@@ -89,14 +75,22 @@ export const PhoneInput: React.FC<PhoneInputProps> = (props) => {
8975
withCallingCode
9076
disableNativeModal={disabled}
9177
visible={modalVisible}
92-
theme={withDarkTheme ? DARK_THEME : DEFAULT_THEME}
78+
theme={enableDarkTheme ? DARK_THEME : DEFAULT_THEME}
9379
renderFlagButton={renderFlagButton}
9480
excludeCountries={EXCLUDED_COUNTRIES}
9581
onClose={hideModal}
9682
{...countryPickerProps}
9783
/>
98-
{!disableArrowIcon &&
99-
(renderDropdownImage || <>{_renderDropdownImage}</>)}
84+
{!hideDropdownIcon &&
85+
(renderCustomDropdown || (
86+
<Image
87+
testID="dropdown-icon"
88+
source={{ uri: dropDownImage }}
89+
resizeMode="contain"
90+
style={[styles.dropDownImage, dropDownImageStyle]}
91+
{...dropDownImageProps}
92+
/>
93+
))}
10094
</TouchableOpacity>
10195
<MaskInput
10296
testID="phone-input"
@@ -109,7 +103,7 @@ export const PhoneInput: React.FC<PhoneInputProps> = (props) => {
109103
value={phoneNumber}
110104
editable={!disabled}
111105
selectionColor="black"
112-
keyboardAppearance={withDarkTheme ? 'dark' : 'default'}
106+
keyboardAppearance={enableDarkTheme ? 'dark' : 'default'}
113107
keyboardType="number-pad"
114108
autoFocus={autoFocus}
115109
{...maskInputProps}

src/PhoneInput/PhoneInput.types.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import type { StyleProp, TextStyle, ViewStyle } from 'react-native';
1+
import type {
2+
ImageProps,
3+
ImageStyle,
4+
StyleProp,
5+
TextStyle,
6+
ViewStyle,
7+
} from 'react-native';
28
import type {
39
CallingCode,
410
Country,
@@ -18,21 +24,22 @@ export type PhoneInputProps = {
1824
phoneNumber: string;
1925
};
2026
disabled?: boolean;
21-
disableArrowIcon?: boolean;
27+
hideDropdownIcon?: boolean;
2228
onChangeCountry?: (country: Country) => void;
2329
onChangeText?: (text: string) => void;
24-
renderDropdownImage?: JSX.Element;
30+
renderCustomDropdown?: JSX.Element;
2531
theme?: Theme;
2632
maskInputProps?: MaskInputProps;
2733
countryPickerProps?: Parameters<typeof CountryPicker>[0];
2834
flagProps?: Parameters<typeof Flag>[0];
2935
callingCodeEditable?: boolean;
36+
dropDownImageProps?: ImageProps;
3037
};
3138
interface Theme {
3239
containerStyle?: StyleProp<ViewStyle>;
3340
textInputStyle?: StyleProp<TextStyle>;
3441
codeTextStyle?: StyleProp<TextStyle>;
3542
flagButtonStyle?: StyleProp<ViewStyle>;
36-
withDarkTheme?: boolean;
37-
withShadow?: boolean;
43+
dropDownImageStyle?: StyleProp<ImageStyle>;
44+
enableDarkTheme?: boolean;
3845
}

src/PhoneInput/dropdown-icon.tsx

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/PhoneInput/styles.ts

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,12 @@
1-
import { Dimensions, StyleSheet } from 'react-native';
2-
const { width: viewportWidth, height: viewportHeight } =
3-
Dimensions.get('window');
4-
function wp(percentage: number) {
5-
const value = (percentage * viewportWidth) / 100;
6-
return Math.round(value);
7-
}
8-
function hp(percentage: number) {
9-
const value = (percentage * viewportHeight) / 100;
10-
return Math.round(value);
11-
}
1+
import { Platform, StyleSheet } from 'react-native';
2+
123
const styles = StyleSheet.create({
134
container: {
14-
width: wp(90),
155
backgroundColor: 'white',
166
flexDirection: 'row',
177
borderRadius: 12,
188
overflow: 'hidden',
19-
height: hp(7),
20-
minHeight: 56,
9+
height: 60,
2110
borderWidth: 1,
2211
borderColor: '#DFDFDE',
2312
},
@@ -31,20 +20,10 @@ const styles = StyleSheet.create({
3120
borderRightColor: '#E5E7EB',
3221
paddingHorizontal: 8,
3322
},
34-
shadow: {
35-
shadowColor: '#000000',
36-
shadowOffset: {
37-
width: 0,
38-
height: 2,
39-
},
40-
shadowOpacity: 0.1,
41-
shadowRadius: 4,
42-
elevation: 3,
43-
},
4423
dropDownImage: {
4524
height: 16,
4625
width: 16,
47-
marginLeft: 4,
26+
marginLeft: Platform.select({ android: 0, default: 2 }),
4827
opacity: 0.9,
4928
},
5029
codeText: {
@@ -56,7 +35,7 @@ const styles = StyleSheet.create({
5635
},
5736
numberText: {
5837
flex: 1,
59-
paddingHorizontal: wp(4),
38+
paddingHorizontal: 16,
6039
fontSize: 15,
6140
color: '#1F2937',
6241
letterSpacing: 0.3,

src/__tests__/PhoneInput.test.tsx

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -85,30 +85,13 @@ describe('PhoneInput', () => {
8585

8686
it('handles dark theme correctly', () => {
8787
const { getByTestId } = render(
88-
<PhoneInput {...defaultProps} theme={{ withDarkTheme: true }} />
88+
<PhoneInput {...defaultProps} theme={{ enableDarkTheme: true }} />
8989
);
9090

9191
const input = getByTestId('phone-input');
9292
expect(input.props.keyboardAppearance).toBe('dark');
9393
});
9494

95-
it('handles shadow style correctly', () => {
96-
const { getByTestId } = render(
97-
<PhoneInput {...defaultProps} theme={{ withShadow: true }} />
98-
);
99-
100-
const container = getByTestId('phone-input-container');
101-
expect(container.props.style).toContainEqual(
102-
expect.objectContaining({
103-
shadowColor: '#000000',
104-
shadowOffset: expect.any(Object),
105-
shadowOpacity: expect.any(Number),
106-
shadowRadius: expect.any(Number),
107-
elevation: expect.any(Number),
108-
})
109-
);
110-
});
111-
11295
it('handles country picker modal visibility', () => {
11396
const { getByTestId } = render(<PhoneInput {...defaultProps} />);
11497

@@ -121,7 +104,7 @@ describe('PhoneInput', () => {
121104
it('renders custom dropdown image when provided', () => {
122105
const customDropdown = <View testID="custom-dropdown" />;
123106
const { getByTestId } = render(
124-
<PhoneInput {...defaultProps} renderDropdownImage={customDropdown} />
107+
<PhoneInput {...defaultProps} renderCustomDropdown={customDropdown} />
125108
);
126109

127110
expect(getByTestId('custom-dropdown')).toBeTruthy();
@@ -151,9 +134,9 @@ describe('PhoneInput', () => {
151134
);
152135
});
153136

154-
it('hides arrow icon when disableArrowIcon is true', () => {
137+
it('hides arrow icon when hideDropdownIcon is true', () => {
155138
const { queryByTestId } = render(
156-
<PhoneInput {...defaultProps} disableArrowIcon />
139+
<PhoneInput {...defaultProps} hideDropdownIcon />
157140
);
158141

159142
expect(queryByTestId('dropdown-icon')).toBeNull();

src/__tests__/setup.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ jest.mock('react-native-country-picker-modal', () => ({
2525

2626
// Mock react-native
2727
jest.mock('react-native', () => ({
28-
Dimensions: {
29-
get: jest.fn().mockReturnValue({ width: 375, height: 812 }),
30-
},
3128
TextInput: 'TextInput',
3229
Image: 'Image',
3330
TouchableOpacity: 'TouchableOpacity',
@@ -44,4 +41,7 @@ jest.mock('react-native', () => ({
4441
return style || {};
4542
},
4643
},
44+
Platform: {
45+
select: jest.fn(),
46+
},
4747
}));

0 commit comments

Comments
 (0)