From ea4295ab11a1f7e392842a9e37b0b471410fe67b Mon Sep 17 00:00:00 2001 From: Thinh Trinh Duc Date: Wed, 6 Nov 2024 12:38:07 +0700 Subject: [PATCH] Fix throw errors when encountering a unsupported country --- apps/docs/package.json | 2 +- packages/components/CHANGELOG.md | 7 ++ packages/components/package.json | 4 +- packages/phone-input/CHANGELOG.md | 6 ++ packages/phone-input/package.json | 6 +- .../src/hooks/usePhoneInput.spec.tsx | 71 ++++++++++++++++++- .../phone-input/src/hooks/usePhoneInput.tsx | 31 ++++++-- yarn.lock | 8 +-- 8 files changed, 119 insertions(+), 16 deletions(-) diff --git a/apps/docs/package.json b/apps/docs/package.json index d75f4cb..3ce37b2 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -10,7 +10,7 @@ "clean": "rimraf .turbo && rimraf node_modules && rimraf .next" }, "dependencies": { - "@react-awesome/components": "1.0.21", + "@react-awesome/components": "1.0.22", "@vercel/speed-insights": "^1.0.10", "classnames": "^2.5.1", "lodash": "^4.17.21", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index d0435ff..e9506d5 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -1,5 +1,12 @@ # @react-awesome/components +## 1.0.22 + +### Patch Changes + +- Updated dependencies + - @react-awesome/phone-input@1.1.7 + ## 1.0.21 ### Patch Changes diff --git a/packages/components/package.json b/packages/components/package.json index 1901ea8..0e6217f 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@react-awesome/components", - "version": "1.0.21", + "version": "1.0.22", "main": "./dist/index.cjs", "module": "./dist/index.js", "types": "./dist/index.d.ts", @@ -39,7 +39,7 @@ "access": "public" }, "dependencies": { - "@react-awesome/phone-input": "1.1.6", + "@react-awesome/phone-input": "1.1.7", "@react-awesome/use-click-outside": "0.0.3", "@react-awesome/use-preserve-input-caret-position": "0.0.3", "@react-awesome/use-selection-range": "0.0.3", diff --git a/packages/phone-input/CHANGELOG.md b/packages/phone-input/CHANGELOG.md index 7ae8c36..e89286b 100644 --- a/packages/phone-input/CHANGELOG.md +++ b/packages/phone-input/CHANGELOG.md @@ -1,5 +1,11 @@ # @react-awesome/phone-input +## 1.1.7 + +### Patch Changes + +- Fixed bug throws error when encountering a country is not supported + ## 1.1.6 ### Patch Changes diff --git a/packages/phone-input/package.json b/packages/phone-input/package.json index b6ec190..555ae63 100644 --- a/packages/phone-input/package.json +++ b/packages/phone-input/package.json @@ -1,6 +1,6 @@ { "name": "@react-awesome/phone-input", - "version": "1.1.6", + "version": "1.1.7", "main": "./dist/index.cjs", "module": "./dist/index.js", "types": "./dist/index.d.ts", @@ -34,7 +34,6 @@ "@react-awesome/tsconfig": "*", "@types/react": "^18.2.46", "@types/react-dom": "^18.2.18", - "country-flag-icons": "^1.5.9", "eslint": "^8.56.0", "react": "^18.2.0", "typescript": "^5.3.3" @@ -44,7 +43,8 @@ }, "dependencies": { "classnames": "^2.5.1", - "libphonenumber-js": "^1.10.53" + "libphonenumber-js": "^1.11.12", + "country-flag-icons": "^1.5.9" }, "peerDependencies": { "@react-awesome/use-click-outside": "0.0.3", diff --git a/packages/phone-input/src/hooks/usePhoneInput.spec.tsx b/packages/phone-input/src/hooks/usePhoneInput.spec.tsx index b0b7e8f..7e632dc 100644 --- a/packages/phone-input/src/hooks/usePhoneInput.spec.tsx +++ b/packages/phone-input/src/hooks/usePhoneInput.spec.tsx @@ -1,4 +1,4 @@ -import { usePhoneInput } from './usePhoneInput' +import { usePhoneInput, UsePhoneInput } from './usePhoneInput' import { render } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { act } from 'react-dom/test-utils' @@ -20,7 +20,7 @@ const Comp = ({ onChange = () => {}, }: { country?: CountryCode - supportedCountries?: CountryCode[] + supportedCountries?: UsePhoneInput['supportedCountries'] defaultCountry?: CountryCode smartCaret?: boolean value?: string @@ -503,4 +503,71 @@ describe('usePhoneInput', () => { }) }) }) + + /** + * Unsupported country is being used + */ + describe('Should not throw error when encounters unsupported country is being used as default country', () => { + it('Should not throw error when encounters unsupported country is being used as default country', async () => { + const onChange = vitest.fn() + + const { container } = render( + , + ) + const input = container.querySelector('input') + if (!input) { + throw new Error('input is not a valid element.') + } + + await act(async () => { + input.focus() + await user.paste('+84522369680') + }) + + expect(onChange.mock.calls[0][1]).toEqual({ + country: 'VN', + e164Value: '+84522369680', + formattedValue: '+84 522 369 680', + isPossible: true, + isSupported: true, + isValid: true, + phoneCode: '84', + }) + }) + + it('Should not throw error when encounters unsupported country is being used as default country and supportedCountries is an empty list', async () => { + const onChange = vitest.fn() + + const { container } = render( + , + ) + const input = container.querySelector('input') + if (!input) { + throw new Error('input is not a valid element.') + } + + await act(async () => { + input.focus() + await user.paste('+84522369680') + }) + + expect(onChange.mock.calls[0][1]).toEqual({ + country: 'AQ', + e164Value: '', + formattedValue: '', + isPossible: false, + isSupported: false, + isValid: false, + phoneCode: '', + }) + }) + }) }) diff --git a/packages/phone-input/src/hooks/usePhoneInput.tsx b/packages/phone-input/src/hooks/usePhoneInput.tsx index 5c278bb..26b9f21 100644 --- a/packages/phone-input/src/hooks/usePhoneInput.tsx +++ b/packages/phone-input/src/hooks/usePhoneInput.tsx @@ -6,6 +6,7 @@ import { getCountryCallingCode, formatIncompletePhoneNumber, AsYouType, + isSupportedCountry, } from 'libphonenumber-js' import { usePreserveInputCaretPosition } from '@react-awesome/use-preserve-input-caret-position' import { @@ -19,6 +20,8 @@ import { const INTERNATIONAL_FORMAT = /^[+0-9][0-9]*$/ const LOCAL_FORMAT = /^[0-9][0-9]*$/ +type NonEmptyArray = [T, ...T[]] + export type CountryCode = CCode export type PhoneInputChangeMetadata = { @@ -42,7 +45,7 @@ export type UsePhoneInput = { /** * @description Supported countries */ - supportedCountries?: CountryCode[] + supportedCountries?: NonEmptyArray /** * @description Default selected country */ @@ -139,14 +142,15 @@ export const usePhoneInput = ({ */ const normalizeValue = React.useCallback( (phone: string) => { - if (country && mode === 'national') { + if (country && isSupportedCountry(country) && mode === 'national') { return formatWithFixedCountry(phone, country).replace( '+' + getCountryCallingCode(country), '', ) } - if (country) return formatWithFixedCountry(phone, country) + if (country && isSupportedCountry(country)) + return formatWithFixedCountry(phone, country) switch (mode) { case 'international': @@ -187,6 +191,23 @@ export const usePhoneInput = ({ const guessedCountry = guessCountry(value) || currentCountryCodeRef.current + /** + * If guessedCountry is not supported by the libPhoneNumberJS + * then return the empty metadata + */ + if (!isSupportedCountry(guessedCountry)) { + console.warn(`usePhoneInput - ${guessedCountry} is not supported.`) + return { + isPossible: false, + isValid: false, + e164Value: '', + country: guessedCountry, + phoneCode: '', + formattedValue: '', + isSupported: false, + } + } + const isSupported = checkCountryValidity( guessedCountry, supportedCountries, @@ -370,7 +391,9 @@ export const usePhoneInput = ({ closeCountrySelect, toggleCountrySelect, selectedCountry: currentCountryCodeRef.current, - phoneCode: getCountryCallingCode(currentCountryCodeRef.current), + phoneCode: isSupportedCountry(currentCountryCodeRef.current) + ? getCountryCallingCode(currentCountryCodeRef.current) + : '', setSelectedCountry, } } diff --git a/yarn.lock b/yarn.lock index eb31ad1..577f5a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5276,10 +5276,10 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -libphonenumber-js@^1.10.53: - version "1.10.54" - resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.10.54.tgz#8dfba112f49d1b9c2a160e55f9697f22e50f0841" - integrity sha512-P+38dUgJsmh0gzoRDoM4F5jLbyfztkU6PY6eSK6S5HwTi/LPvnwXqVCQZlAy1FxZ5c48q25QhxGQ0pq+WQcSlQ== +libphonenumber-js@^1.11.12: + version "1.11.12" + resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.11.12.tgz#e108a4632048255f30b872bb1abbb3356f290fbb" + integrity sha512-QkJn9/D7zZ1ucvT++TQSvZuSA2xAWeUytU+DiEQwbPKLyrDpvbul2AFs1CGbRAPpSCCk47aRAb5DX5mmcayp4g== lilconfig@^2.1.0: version "2.1.0"