Skip to content

fix(intl-phone-input): remove changing unclearable country code #730

Merged
merged 7 commits into from
Jul 19, 2021
26 changes: 26 additions & 0 deletions packages/intl-phone-input/src/component.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,30 @@ describe('IntlPhoneInput', () => {
expect(input).toHaveValue('+7');
});
});

it('should ignore changing country code', async () => {
const onChange = jest.fn();
render(<IntlPhoneInput value='+7' onChange={onChange} clearableCountryCode={false} />);

const input = await screen.findByDisplayValue('+7');
fireEvent.change(input, { target: { value: '+17' } });

waitFor(() => {
expect(onChange).not.toHaveBeenCalled();
expect(input).toHaveValue('+71');
});
});

it('should move chars before country code', async () => {
const onChange = jest.fn();
render(<IntlPhoneInput value='+7' onChange={onChange} clearableCountryCode={false} />);

const input = await screen.findByDisplayValue('+7');
fireEvent.change(input, { target: { value: '9+7' } });

waitFor(() => {
expect(onChange).not.toHaveBeenCalled();
expect(input).toHaveValue('+79');
});
});
});
15 changes: 15 additions & 0 deletions packages/intl-phone-input/src/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { CountriesSelect } from './components';
import styles from './index.module.css';
import { formatPhoneWithUnclearableCountryCode } from './utils/format-phone-with-unclearable-country-code';
import { permitCaretOnCountryCode } from './utils/permit-caret-on-country-code';

const countriesHash = getCountriesHash();

Expand Down Expand Up @@ -233,6 +234,20 @@ export const IntlPhoneInput = forwardRef<HTMLInputElement, IntlPhoneInputProps>(
}
}, [countryIso2, loadPhoneUtils, setCountryByDialCode, value]);

useEffect(() => {
const input = inputRef.current;

if (!input || clearableCountryCode) {
return;
}

const country = countriesHash[countryIso2];

if (input) {
permitCaretOnCountryCode(input, `+${country.dialCode}`.length);
}
});

return (
<InputAutocomplete
{...restProps}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,25 @@ import { Country } from '@alfalab/utils';
import { formatPhoneWithUnclearableCountryCode } from './format-phone-with-unclearable-country-code';

describe('formatPhoneWithUnclearableCountryCode', () => {
it('should work', () => {
it('shoul change 8 to +7 at russian country code', () => {
const ru = {
dialCode: '7',
} as Country;

expect(formatPhoneWithUnclearableCountryCode('8171', ru)).toEqual('+7171');
});

it('should work with long country code', () => {
const az = {
dialCode: '994',
} as Country;
expect(formatPhoneWithUnclearableCountryCode('', ru)).toEqual('+7');
expect(formatPhoneWithUnclearableCountryCode('+', ru)).toEqual('+7');
expect(formatPhoneWithUnclearableCountryCode('7', ru)).toEqual('+7');
expect(formatPhoneWithUnclearableCountryCode('+7', ru)).toEqual('+7');
expect(formatPhoneWithUnclearableCountryCode('+17', ru)).toEqual('+71');
expect(formatPhoneWithUnclearableCountryCode('+71', ru)).toEqual('+71');
expect(formatPhoneWithUnclearableCountryCode('1+7', ru)).toEqual('+71');

expect(formatPhoneWithUnclearableCountryCode('', az)).toEqual('+994');
expect(formatPhoneWithUnclearableCountryCode('+', az)).toEqual('+994');
expect(formatPhoneWithUnclearableCountryCode('+9', az)).toEqual('+994');
expect(formatPhoneWithUnclearableCountryCode('+99', az)).toEqual('+994');
expect(formatPhoneWithUnclearableCountryCode('+994', az)).toEqual('+994');
expect(formatPhoneWithUnclearableCountryCode('1+994', az)).toEqual('+9941');
expect(formatPhoneWithUnclearableCountryCode('+1994', az)).toEqual('+9941');
expect(formatPhoneWithUnclearableCountryCode('+9194', az)).toEqual('+9941');
expect(formatPhoneWithUnclearableCountryCode('+9914', az)).toEqual('+9941');
expect(formatPhoneWithUnclearableCountryCode('1+994', az)).toEqual('+994');
expect(formatPhoneWithUnclearableCountryCode('+9941', az)).toEqual('+9941');
});
});
Original file line number Diff line number Diff line change
@@ -1,32 +1,21 @@
import { Country } from '@alfalab/utils';
import { getPhoneDiff } from './get-phone-diff';

const RUSSIAN_DIAL_CODE = '7';
const RUSSIAN_NATIONAL_DIAL_CODE = '8';

/**
* Форматирует телефон с неудаляемым кодом страны
*/
export const formatPhoneWithUnclearableCountryCode = (phone: string, country: Country) => {
const defaultValue = `+${country.dialCode}`;
// При попытке стереть код страны возвращаем дефолтное значение
if (phone.length < defaultValue.length) {
return defaultValue;
}
const countryPrefix = `+${country.dialCode}`;

// Если код страны совпадает, даем вводить значение
if (phone.substr(1, country.dialCode.length) === country.dialCode) {
if (phone.startsWith(countryPrefix)) {
return phone;
}

const lengthDiff = phone.substr(1).length - country.dialCode.length;
// Если разница длины нового значения и длины кода страны равна 1, то определяем отличающийся символ и ставим его после кода
if (lengthDiff === 1) {
const diff = getPhoneDiff(phone, country);
// Если не смогли вычислить отличающийся символ, то возвращаем дефолтное значение
if (!diff) {
return defaultValue;
}

return `+${country.dialCode}${diff}`;
if (country.dialCode === RUSSIAN_DIAL_CODE && phone.startsWith(RUSSIAN_NATIONAL_DIAL_CODE)) {
return phone.replace(RUSSIAN_NATIONAL_DIAL_CODE, countryPrefix);
}

return phone;
return countryPrefix;
};
30 changes: 0 additions & 30 deletions packages/intl-phone-input/src/utils/get-phone-diff.test.ts

This file was deleted.

23 changes: 0 additions & 23 deletions packages/intl-phone-input/src/utils/get-phone-diff.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export function permitCaretOnCountryCode(input: HTMLInputElement, countryCodeLength: number) {
function resetCaret() {
const selectionStart = input.selectionStart || 0;

if (selectionStart < countryCodeLength) {
input.focus();
input.setSelectionRange(countryCodeLength, countryCodeLength);
}
}

input.addEventListener('keyup', resetCaret);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Обработчики тогда ведь при каждом ререндере будут создаваться?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

да похоже

input.addEventListener('click', resetCaret);
}