fix(phone): блокировать ввод не-цифр на уровне keyDown
Some checks failed
CI / POS (WPF, Windows) (push) Waiting to run
CI / Backend (.NET 8) (push) Successful in 1m4s
CI / Web (React + Vite) (push) Failing after 37s
Docker Public / Build + push Public (push) Successful in 26s
Docker Web / Build + push Web (push) Failing after 26s
Docker Web / Deploy Web on stage (push) Has been skipped
Docker Public / Deploy Public on stage (push) Successful in 10s
Some checks failed
CI / POS (WPF, Windows) (push) Waiting to run
CI / Backend (.NET 8) (push) Successful in 1m4s
CI / Web (React + Vite) (push) Failing after 37s
Docker Public / Build + push Public (push) Successful in 26s
Docker Web / Build + push Web (push) Failing after 26s
Docker Web / Deploy Web on stage (push) Has been skipped
Docker Public / Deploy Public on stage (push) Successful in 10s
Предыдущий fix не покрывал кейс когда курсор оказывался не сразу после «+7 » (в начале строки или в середине). parseRawInput не находил префикс на нужной позиции и «7» снова попадала в подсчёт. Корректное решение: блокировать любой не-цифровой символ через preventDefault в onKeyDown — тогда он вообще не доходит до input, парсер видит только валидные цифры. Сохранены: Backspace/Delete (с защитой префикса), стрелки и навигация, Cmd/Ctrl+A/C/V/X для копи-пасты, Enter для submit. Paste произвольной строки по-прежнему работает через onChange.
This commit is contained in:
parent
47c349818f
commit
16fe7580af
|
|
@ -43,11 +43,21 @@ export function PhoneInput({ value, onChange, className, disabled, ...rest }: Ph
|
|||
}
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.metaKey || e.ctrlKey || e.altKey) return
|
||||
if (['Tab', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End', 'Enter', 'Escape'].includes(e.key)) return
|
||||
const el = e.currentTarget
|
||||
const start = el.selectionStart ?? 0
|
||||
const end = el.selectionEnd ?? 0
|
||||
if (e.key === 'Backspace' && start <= 3 && end === start) e.preventDefault()
|
||||
if (e.key === 'Delete' && start < 3) e.preventDefault()
|
||||
if (e.key === 'Backspace') {
|
||||
if (start <= 3 && end === start) e.preventDefault()
|
||||
return
|
||||
}
|
||||
if (e.key === 'Delete') {
|
||||
if (start < 3) e.preventDefault()
|
||||
return
|
||||
}
|
||||
// Только цифры — иначе появляется фантомная «7» из префикса.
|
||||
if (!/^\d$/.test(e.key)) e.preventDefault()
|
||||
}
|
||||
|
||||
const handleFocus = () => {
|
||||
|
|
|
|||
|
|
@ -59,13 +59,31 @@ export function PhoneInput({ value, onChange, className, disabled, ...rest }: Ph
|
|||
}
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
// Cmd/Ctrl + что-то — copy/paste/select-all и прочие шорткаты, пропускаем.
|
||||
if (e.metaKey || e.ctrlKey || e.altKey) return
|
||||
// Навигация и форм-сабмит — пропускаем.
|
||||
if (['Tab', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End', 'Enter', 'Escape'].includes(e.key)) return
|
||||
|
||||
const el = e.currentTarget
|
||||
const start = el.selectionStart ?? 0
|
||||
const end = el.selectionEnd ?? 0
|
||||
// Не позволяем удалить префикс "+7 " (3 символа). Backspace на позиции
|
||||
// ≤3 без выделения, либо Delete на позиции <3.
|
||||
if (e.key === 'Backspace' && start <= 3 && end === start) e.preventDefault()
|
||||
if (e.key === 'Delete' && start < 3) e.preventDefault()
|
||||
|
||||
// Backspace/Delete — разрешаем, но не даём удалить префикс «+7 » (3 символа).
|
||||
if (e.key === 'Backspace') {
|
||||
if (start <= 3 && end === start) e.preventDefault()
|
||||
return
|
||||
}
|
||||
if (e.key === 'Delete') {
|
||||
if (start < 3) e.preventDefault()
|
||||
return
|
||||
}
|
||||
|
||||
// Дальше — только цифры. Любой другой символ блокируем, чтобы он не
|
||||
// попал в input и не запутал парсер. Без этого нажатие буквы при курсоре
|
||||
// в любом месте ломает раскладку и приводит к появлению фантомной «7».
|
||||
if (!/^\d$/.test(e.key)) {
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue