diff --git a/package-lock.json b/package-lock.json index 072f28b..2a0e18f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,14 @@ { "name": "no-copy-frontend", - "version": "0.9.0", + "version": "0.10.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "no-copy-frontend", - "version": "0.9.0", + "version": "0.10.0", "dependencies": { + "@react-input/mask": "^2.0.4", "@tailwindcss/postcss": "^4.1.17", "@tanstack/match-sorter-utils": "^8.19.4", "@tanstack/react-query": "^5.90.11", @@ -1652,6 +1653,49 @@ "node": ">=0.10" } }, + "node_modules/@react-input/core": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@react-input/core/-/core-2.0.2.tgz", + "integrity": "sha512-xLLBueYFbant9308uv3cIJQz5NYSixeGspjP3Nt6jogRHTcHYMRmlVFUuSzQiP8Z8/5BdnPkudRSsN0/AJ1fbw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-input" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "react": ">=16.8 || ^19.0.0-rc", + "react-dom": ">=16.8 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@react-input/mask": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@react-input/mask/-/mask-2.0.4.tgz", + "integrity": "sha512-NOielvQSBOlGLVuEcxtkjaGneC0GJFXjC7KOF99ed9H9XSDruWnQirjht5uSbWqLeeiOup0VD2YjM+6FH+aWBg==", + "license": "MIT", + "dependencies": { + "@react-input/core": "^2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-input" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "react": ">=16.8 || ^19.0.0-rc", + "react-dom": ">=16.8 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@reduxjs/toolkit": { "version": "2.11.1", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.1.tgz", diff --git a/package.json b/package.json index 12ddfe5..9f95a93 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "lint": "eslint" }, "dependencies": { + "@react-input/mask": "^2.0.4", "@tailwindcss/postcss": "^4.1.17", "@tanstack/match-sorter-utils": "^8.19.4", "@tanstack/react-query": "^5.90.11", diff --git a/src/app/ui/inputs/phone-input.tsx b/src/app/ui/inputs/phone-input.tsx index 9eacad3..cb3a4cf 100644 --- a/src/app/ui/inputs/phone-input.tsx +++ b/src/app/ui/inputs/phone-input.tsx @@ -1,6 +1,7 @@ 'use client' -import { useState, ChangeEvent, useEffect, useRef, KeyboardEvent } from 'react'; +import { useState, ChangeEvent } from 'react'; +import { InputMask } from '@react-input/mask'; import styles from '@/app/styles/module/login.module.scss'; interface PhoneInputProps { @@ -10,104 +11,21 @@ interface PhoneInputProps { export default function PhoneInput({ phoneState, validateHandler }: PhoneInputProps) { const [phone, setPhone] = useState(phoneState ? phoneState : ''); - const inputRef = useRef(null); - - const formatPhoneNumber = (value: string, isBackspace: boolean): string => { - if (value === '+') { - return value; - } - - const digitsOnly = value.replace(/\D/g, ''); - - if (!digitsOnly) { - return ''; - } - - const limitedDigits = digitsOnly.slice(0, 11); - const countryCode = 7; - const phoneNumber = limitedDigits.startsWith('7') - ? limitedDigits.slice(1) - : limitedDigits; - - let formatted = `+${countryCode}`; - - if (phoneNumber.length > 0) { - formatted += ` (${phoneNumber.slice(0, 3)}`; - } - if (phoneNumber.length >= 3) { - formatted += `) ${phoneNumber.slice(3, 6)}`; - } - if (phoneNumber.length >= 6) { - formatted += `-${phoneNumber.slice(6, 8)}`; - } - if (phoneNumber.length >= 8) { - formatted += `-${phoneNumber.slice(8, 10)}`; - } - - if (isBackspace) { - const lastChar = formatted[formatted.length - 1]; - const specialChars = ['-', '(', ')', ' ']; - - if (specialChars.includes(lastChar)) { - if (lastChar === ' ' && formatted[formatted.length - 2] === ')') { - return formatted.slice(0, -2); - } - return formatted.slice(0, -1); - } - } - - return formatted; - }; - - const handleChange = (e: ChangeEvent): void => { - const input = e.target.value; - const nativeEvent = e.nativeEvent as InputEvent; - const isBackspace = nativeEvent.inputType === 'deleteContentBackward'; - const formatted = formatPhoneNumber(input, isBackspace); - setPhone(formatted); - }; - - const range = useRef<{ - start: number | null, - key: string; - } | null>(null); - - const handleKeyDown = (e: KeyboardEvent): void => { - const input = e.currentTarget; - range.current = { - start: input.selectionStart, - key: e.key - }; - }; - - useEffect(() => { - console.log('use'); - if (range.current?.key === 'Backspace' && inputRef.current) { - const startPos = range.current.start ?? 0; - const newPosition = Math.max(0, startPos - 1); - inputRef.current.setSelectionRange(newPosition, newPosition); - } else if (range.current?.key === 'Delete' && inputRef.current) { - inputRef.current.setSelectionRange(range.current.start, range.current.start); - } - - }, [phone]); return ( - { - handleChange(e); + setPhone(e.target.value); validateHandler(e); }} - onKeyDown={(e) => { - handleKeyDown(e); - }} + placeholder="+7 (999) 123-45-67" /> ) } \ No newline at end of file