Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: exposes utils #529

Merged
merged 3 commits into from
Jul 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ export default function MyComponent() {
| :--------------- | :------------------------------------------------- | :---------------------------- | -----------------------------------------------------------------------: |
| `defaultCountry` | Default country displayed for the country selector | First country _(Afghanistan)_ | Country [ISO2 code](https://en.wikipedia.org/wiki/ISO_3166-2) _(fr, us)_ |

## Utils

| Name | Description |
| :----------------- | :------------------------------------------------- |
| `countries` | List of all countries. |
| `getCountryByIso` | Returns the country object for a given ISO code. |
| `applyMask` | Apply the mask to a given phone number. |
| `splitPhoneNumber` | Split a phone number into country code and number. |
| `replaceDialCode` | Replace the dial code of a phone number. |

## Contributors

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
Expand Down
17 changes: 12 additions & 5 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const PhoneContext = React.createContext<
>([
DEFAULT_PHONE_NUMBER,
// eslint-disable-next-line @typescript-eslint/no-empty-function
() => {},
() => { },
]);

const usePhoneContext = () => React.useContext(PhoneContext);
Expand All @@ -42,10 +42,10 @@ export const _Phone = React.forwardRef<HTMLInputElement, PhoneProps>(
(_defaultValue
? splitPhoneNumber(_defaultValue)
: defaultCountry && {
raw: '',
formatted: '',
country: getCountryByIso(defaultCountry),
}) || DEFAULT_PHONE_NUMBER;
raw: '',
formatted: '',
country: getCountryByIso(defaultCountry),
}) || DEFAULT_PHONE_NUMBER;

const [_value, setValue] = React.useState<PhoneNumber>(defaultPhoneNumber);

Expand Down Expand Up @@ -160,3 +160,10 @@ const _Number = React.forwardRef<
_Number.displayName = DISPLAY_NAME + '.Number';

export const Phone = Object.assign(_Phone, { Country, Number: _Number });
export {
countries,
applyMask,
getCountryByIso,
replaceDialCode,
splitPhoneNumber,
};
60 changes: 53 additions & 7 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,32 @@
import countries from './countries';

/**
* Type representing a country object.
*/
export type Country = typeof countries[number];

export const getCountryByIso = (code: Country[2]) =>
/**
* Returns the country object for a given ISO code.
* @param {string} code - The ISO code of the country.
* @returns {Country} The country object.
*/
export const getCountryByIso = (code: Country[2]): Country =>
countries.find((c) => c[2] === code) as Country;

export const removeMask = (value: string) => value.replace(/\D/g, '');
export const getMaskDigit = (value: string, mask?: string) => {
/**
* Removes all non-digit characters from a string.
* @param {string} value - The string to remove non-digit characters from.
* @returns {string} The string with all non-digit characters removed.
*/
export const removeMask = (value: string): string => value.replace(/\D/g, '');

/**
* Returns the digits of a string that match the mask.
* @param {string} value - The string to extract digits from.
* @param {string} mask - The mask to match against.
* @returns {string} The digits of the string that match the mask.
*/
export const getMaskDigit = (value: string, mask?: string): string => {
const v = removeMask(value);
if (!mask) return v;

Expand All @@ -15,7 +35,13 @@ export const getMaskDigit = (value: string, mask?: string) => {
return v.substring(0, numberOfDigits);
};

export const applyMask = (value = '', mask?: string) => {
/**
* Applies a mask to a string.
* @param {string} value - The string to apply the mask to.
* @param {string} mask - The mask to apply.
* @returns {string} The string with the mask applied.
*/
export const applyMask = (value = '', mask?: string): string => {
if (!mask || !value) return value;
const flatValue = removeMask(value).split('');
return (
Expand All @@ -24,15 +50,28 @@ export const applyMask = (value = '', mask?: string) => {
);
};

export const isE164Compliant = (value: string) =>
/**
* Checks if a phone number is E.164 compliant.
* @param {string} value - The phone number to check.
* @returns {boolean} True if the phone number is E.164 compliant, false otherwise.
*/
export const isE164Compliant = (value: string): boolean =>
/^\+[1-9]\d{1,14}$/.test(value);

/**
* Type representing a phone number object.
*/
export interface PhoneNumber {
raw: string;
formatted: string;
country: Country;
}

/**
* Splits a phone number into its raw, formatted, and country components.
* @param {string} value - The phone number to split.
* @returns {PhoneNumber | undefined} The phone number object.
*/
export const splitPhoneNumber = (value: string): PhoneNumber | undefined => {
if (!isE164Compliant(value)) {
console.log('[react-telephone] phone number should follow E.164');
Expand All @@ -45,7 +84,7 @@ export const splitPhoneNumber = (value: string): PhoneNumber | undefined => {
const [country] = countries.filter(
(c) =>
dial.startsWith(c[3]) &&
(c[6] ? c[6].some((a:string) => dial.startsWith(`${c[3]}${a}`)) : true)
(c[6] ? c[6].some((a: string) => dial.startsWith(`${c[3]}${a}`)) : true)
);

return {
Expand All @@ -55,8 +94,15 @@ export const splitPhoneNumber = (value: string): PhoneNumber | undefined => {
};
};

/**
* Replaces the dial code in a phone number with a given string.
* @param {string} value - The phone number to replace the dial code in.
* @param {string} dialCode - The dial code to replace.
* @param {string} replacer - The string to replace the dial code with.
* @returns {string} The phone number with the dial code replaced.
*/
export const replaceDialCode = (
value: string,
dialCode: string,
replacer: string
) => value.replace('+' + dialCode, replacer);
): string => value.replace('+' + dialCode, replacer);