From 16fe7580af65c985ce80f6e194c3d90fb0b07105 Mon Sep 17 00:00:00 2001 From: nurdotnet <278048682+nurdotnet@users.noreply.github.com> Date: Sun, 3 May 2026 16:15:27 +0500 Subject: [PATCH] =?UTF-8?q?fix(phone):=20=D0=B1=D0=BB=D0=BE=D0=BA=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20=D0=B2=D0=B2=D0=BE=D0=B4?= =?UTF-8?q?=20=D0=BD=D0=B5-=D1=86=D0=B8=D1=84=D1=80=20=D0=BD=D0=B0=20?= =?UTF-8?q?=D1=83=D1=80=D0=BE=D0=B2=D0=BD=D0=B5=20keyDown?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Предыдущий fix не покрывал кейс когда курсор оказывался не сразу после «+7 » (в начале строки или в середине). parseRawInput не находил префикс на нужной позиции и «7» снова попадала в подсчёт. Корректное решение: блокировать любой не-цифровой символ через preventDefault в onKeyDown — тогда он вообще не доходит до input, парсер видит только валидные цифры. Сохранены: Backspace/Delete (с защитой префикса), стрелки и навигация, Cmd/Ctrl+A/C/V/X для копи-пасты, Enter для submit. Paste произвольной строки по-прежнему работает через onChange. --- .../src/components/PhoneInput.tsx | 14 ++++++++-- .../src/components/PhoneInput.tsx | 26 ++++++++++++++++--- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/food-market.public/src/components/PhoneInput.tsx b/src/food-market.public/src/components/PhoneInput.tsx index 3a146cc..0b58aef 100644 --- a/src/food-market.public/src/components/PhoneInput.tsx +++ b/src/food-market.public/src/components/PhoneInput.tsx @@ -43,11 +43,21 @@ export function PhoneInput({ value, onChange, className, disabled, ...rest }: Ph } const handleKeyDown = (e: React.KeyboardEvent) => { + 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 = () => { diff --git a/src/food-market.web/src/components/PhoneInput.tsx b/src/food-market.web/src/components/PhoneInput.tsx index 7ecabd1..df05d76 100644 --- a/src/food-market.web/src/components/PhoneInput.tsx +++ b/src/food-market.web/src/components/PhoneInput.tsx @@ -59,13 +59,31 @@ export function PhoneInput({ value, onChange, className, disabled, ...rest }: Ph } const handleKeyDown = (e: React.KeyboardEvent) => { + // 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) => {