Skip to content

Commit

Permalink
fix(core-components-phone-input): fix controlled value bug (#248)
Browse files Browse the repository at this point in the history
* fix(core-components-phone-input): fix controlled value bug

* feat(core-components-phone-input): add useCallback

#253

Co-authored-by: Кононенко Артем Игоревич <AIKononenko@alfabank.ru>
  • Loading branch information
reme3d2y and Кононенко Артем Игоревич committed Aug 28, 2020
1 parent c474a89 commit 62c3cd2
Showing 1 changed file with 60 additions and 56 deletions.
116 changes: 60 additions & 56 deletions packages/phone-input/src/Component.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useImperativeHandle, useRef } from 'react';
import React, { useImperativeHandle, useCallback, useRef } from 'react';
import { conformToMask, TextMaskConfig } from 'text-mask-core';
import { MaskedInput, MaskedInputProps } from '@alfalab/core-components-masked-input';

Expand Down Expand Up @@ -32,67 +32,71 @@ export const PhoneInput = React.forwardRef<HTMLInputElement, PhoneInputProps>(
// Оставляет возможность прокинуть ref извне
useImperativeHandle(ref, () => inputRef.current as HTMLInputElement);

const handleBeforeDisplay = (conformedValue: string, config: TextMaskConfig) => {
const { rawValue, previousConformedValue, currentCaretPosition } = config;
const handleBeforeDisplay = useCallback(
(conformedValue: string, config: TextMaskConfig) => {
const { rawValue, previousConformedValue, currentCaretPosition } = config;

/*
* код ниже нужен для фикса следующих багов библиотеки text-mask:
* 1) так как код страны указан в маске жестко как "+7",
* то при удалении цифры перед ним каретку устанавливается перед кодом страны
* 2) в номере телефона есть пробелы и дефисы,
* при редактировании цифр рядом с этими символами каретка перескакивает через них,
* а не остается на том же месте, на котором была до редактирования
*/
const previousValueWithoutFormatting = previousConformedValue
? deleteFormatting(previousConformedValue)
: '';
const currentValueWithoutFormatting = deleteFormatting(conformedValue) || '';
if (
(previousConformedValue &&
Math.abs(
previousValueWithoutFormatting.length -
currentValueWithoutFormatting.length,
) === 1 &&
[3, 6, 11].includes(currentCaretPosition)) ||
([7, 10, 13].includes(currentCaretPosition) &&
previousConformedValue.length > currentCaretPosition)
) {
const caret = currentCaretPosition;
window.requestAnimationFrame(() => {
if (inputRef !== null && inputRef.current) {
inputRef.current.selectionStart = caret;
inputRef.current.selectionEnd = caret;
}
});
}
/*
* код ниже нужен для фикса следующих багов библиотеки text-mask:
* 1) так как код страны указан в маске жестко как "+7",
* то при удалении цифры перед ним каретка устанавливается перед кодом страны
* 2) в номере телефона есть пробелы и дефисы,
* при редактировании цифр рядом с этими символами каретка перескакивает через них,
* а не остается на том же месте, на котором была до редактирования
*/
const previousValueWithoutFormatting = previousConformedValue
? deleteFormatting(previousConformedValue)
: '';
const currentValueWithoutFormatting = deleteFormatting(conformedValue) || '';

// Удаление цифры перед кодом страны удаляет только саму цифру, код остается ("+7 1" -> "+7 ")
if (rawValue === '+7 ') {
return rawValue;
}
if (
previousConformedValue &&
(([3, 6, 11].includes(currentCaretPosition) &&
Math.abs(
previousValueWithoutFormatting.length -
currentValueWithoutFormatting.length,
) === 1) ||
([7, 10, 13].includes(currentCaretPosition) &&
previousConformedValue.length > currentCaretPosition))
) {
const caret = currentCaretPosition;
window.requestAnimationFrame(() => {
if (inputRef !== null && inputRef.current) {
inputRef.current.selectionStart = caret;
inputRef.current.selectionEnd = caret;
}
});
}

// Вставка номера с 10 цифрами без кода страны
if (rawValue.length === 10 && conformedValue.length === mask.length) {
const masked = conformToMask(`+7${rawValue}`, mask, config);
return masked.conformedValue;
}
// Удаление цифры перед кодом страны удаляет только саму цифру, код остается ("+7 1" -> "+7 ")
if (rawValue === '+7 ') {
return rawValue;
}

// Вставка номера, начинающегося с 8 или 7: 89990313131, 71112223344
if (
conformedValue.length === mask.length &&
(rawValue.startsWith('8') || rawValue.startsWith('7'))
) {
const masked = conformToMask(`+7${rawValue.slice(1)}`, mask, config);
return masked.conformedValue;
}
// Вставка номера с 10 цифрами без кода страны
if (rawValue.length === 10 && conformedValue.length === mask.length) {
const masked = conformToMask(`+7${rawValue}`, mask, config);
return masked.conformedValue;
}

// Если ввод начат с 7 или 8 - выводит "+7 " и дает продолжить ввод со след. цифры
if (rawValue.length === 1 && ['7', '8'].includes(rawValue[0])) {
return '+7 ';
}
// Вставка номера, начинающегося с 8 или 7: 89990313131, 71112223344
if (
conformedValue.length === mask.length &&
(rawValue.startsWith('8') || rawValue.startsWith('7'))
) {
const masked = conformToMask(`+7${rawValue.slice(1)}`, mask, config);
return masked.conformedValue;
}

return conformedValue;
};
// Если ввод начат с 7 или 8 - выводит "+7 " и дает продолжить ввод со след. цифры
if (rawValue.length === 1 && ['7', '8'].includes(rawValue[0])) {
return '+7 ';
}

return conformedValue;
},
[],
);

return (
<MaskedInput
Expand Down

0 comments on commit 62c3cd2

Please sign in to comment.