fix: add phone-input
This commit is contained in:
48
package-lock.json
generated
48
package-lock.json
generated
@@ -9,6 +9,10 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hookform/resolvers": "^5.1.1",
|
"@hookform/resolvers": "^5.1.1",
|
||||||
|
"@maskito/core": "^3.9.0",
|
||||||
|
"@maskito/phone": "^3.9.0",
|
||||||
|
"@maskito/react": "^3.9.0",
|
||||||
|
"libphonenumber-js": "^1.12.9",
|
||||||
"next": "15.3.2",
|
"next": "15.3.2",
|
||||||
"nodemailer": "^7.0.3",
|
"nodemailer": "^7.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
@@ -682,6 +686,44 @@
|
|||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@maskito/core": {
|
||||||
|
"version": "3.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@maskito/core/-/core-3.9.0.tgz",
|
||||||
|
"integrity": "sha512-OgzzgzJTXFZH79mqyHFVUZ5/bUhSW147+JzYVX+DdmQ5zc+mxmFQqsUS5ffVxd2C7/bnEmC7+savYbcae2IhBw==",
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
|
"node_modules/@maskito/kit": {
|
||||||
|
"version": "3.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@maskito/kit/-/kit-3.9.0.tgz",
|
||||||
|
"integrity": "sha512-CD7TQ7WUMtZ8jkhOsislbqht1gMuNHVQsLJG9tXcGvZbegkgJ6wdkggkol1y1/0F5eh/fT+RzzKD9dVjSQon2g==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
|
"peerDependencies": {
|
||||||
|
"@maskito/core": "^3.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@maskito/phone": {
|
||||||
|
"version": "3.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@maskito/phone/-/phone-3.9.0.tgz",
|
||||||
|
"integrity": "sha512-EUCOmOscoQM+vnJwOAiBXVpZVVYkHc7rhnqLqfkslXsZCg5VLNNpzAb8SuFQMxYJYM2NnMawErvL7CjOdVDmvQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@maskito/core": "^3.9.0",
|
||||||
|
"@maskito/kit": "^3.9.0",
|
||||||
|
"libphonenumber-js": ">=1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@maskito/react": {
|
||||||
|
"version": "3.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@maskito/react/-/react-3.9.0.tgz",
|
||||||
|
"integrity": "sha512-qYGncdyaPbi50rDkg0gwh64DHPBCT6YMdkWsMbqG57bVjE1S0X9zbZQICieRQXGVkRjlgJenoMu3b5svdH4ysQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@maskito/core": "^3.9.0",
|
||||||
|
"react": ">=16.8",
|
||||||
|
"react-dom": ">=16.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@napi-rs/wasm-runtime": {
|
"node_modules/@napi-rs/wasm-runtime": {
|
||||||
"version": "0.2.10",
|
"version": "0.2.10",
|
||||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.10.tgz",
|
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.10.tgz",
|
||||||
@@ -4025,6 +4067,12 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/libphonenumber-js": {
|
||||||
|
"version": "1.12.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.9.tgz",
|
||||||
|
"integrity": "sha512-VWwAdNeJgN7jFOD+wN4qx83DTPMVPPAUyx9/TUkBXKLiNkuWWk6anV0439tgdtwaJDrEdqkvdN22iA6J4bUCZg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/lilconfig": {
|
"node_modules/lilconfig": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
|
||||||
|
|||||||
@@ -12,6 +12,10 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hookform/resolvers": "^5.1.1",
|
"@hookform/resolvers": "^5.1.1",
|
||||||
|
"@maskito/core": "^3.9.0",
|
||||||
|
"@maskito/phone": "^3.9.0",
|
||||||
|
"@maskito/react": "^3.9.0",
|
||||||
|
"libphonenumber-js": "^1.12.9",
|
||||||
"next": "15.3.2",
|
"next": "15.3.2",
|
||||||
"nodemailer": "^7.0.3",
|
"nodemailer": "^7.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
|
|||||||
@@ -3,3 +3,4 @@ export { Mark } from './mark';
|
|||||||
export { Input } from './input';
|
export { Input } from './input';
|
||||||
export { AdvancedPhoneInput } from './advanced-phone-input';
|
export { AdvancedPhoneInput } from './advanced-phone-input';
|
||||||
export { TextArea } from './text-area';
|
export { TextArea } from './text-area';
|
||||||
|
export { PhoneInput } from './phone-input';
|
||||||
|
|||||||
@@ -41,6 +41,10 @@
|
|||||||
transition: border-color ease .5s;
|
transition: border-color ease .5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&_error {
|
||||||
|
border-color: $color-error;
|
||||||
|
}
|
||||||
|
|
||||||
&_fullWidth{
|
&_fullWidth{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,17 @@ type InputProps = {
|
|||||||
className?: string;
|
className?: string;
|
||||||
fullWidth?: boolean;
|
fullWidth?: boolean;
|
||||||
variant?: 'default' | 'ghost';
|
variant?: 'default' | 'ghost';
|
||||||
|
error?: string | boolean;
|
||||||
} & DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>;
|
} & DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>;
|
||||||
|
|
||||||
const Input = forwardRef(function Input(
|
const Input = forwardRef(function Input(
|
||||||
{ className, fullWidth = false, variant = 'default', ...props }: InputProps,
|
{
|
||||||
|
className,
|
||||||
|
fullWidth = false,
|
||||||
|
variant = 'default',
|
||||||
|
error = false,
|
||||||
|
...props
|
||||||
|
}: InputProps,
|
||||||
ref: Ref<HTMLInputElement>,
|
ref: Ref<HTMLInputElement>,
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
@@ -24,6 +31,7 @@ const Input = forwardRef(function Input(
|
|||||||
s.Input,
|
s.Input,
|
||||||
s['Input_' + variant],
|
s['Input_' + variant],
|
||||||
fullWidth && s.Input_fullWidth,
|
fullWidth && s.Input_fullWidth,
|
||||||
|
error && s.Input_error,
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default as PhoneInput } from './phone-input';
|
||||||
|
|||||||
@@ -1,10 +1,25 @@
|
|||||||
//import s from './phone-input.module.scss';
|
//import s from './phone-input.module.scss';
|
||||||
import { Input } from '@shared/ui';
|
import { Input } from '@shared/ui';
|
||||||
|
import { useMaskito } from '@maskito/react';
|
||||||
|
|
||||||
|
import { maskitoPhoneOptionsGenerator } from '@maskito/phone';
|
||||||
|
import metadata from 'libphonenumber-js/min/metadata';
|
||||||
|
import { DetailedHTMLProps, InputHTMLAttributes } from 'react';
|
||||||
|
|
||||||
|
type PhoneInput = {
|
||||||
|
className?: string;
|
||||||
|
} & DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>;
|
||||||
|
|
||||||
|
export default function PhoneInput({ ...props }: PhoneInput) {
|
||||||
|
const options = maskitoPhoneOptionsGenerator({
|
||||||
|
countryIsoCode: 'RU',
|
||||||
|
metadata,
|
||||||
|
});
|
||||||
|
const maskedInputRef = useMaskito({ options });
|
||||||
|
|
||||||
export default function PhoneInput() {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Input />
|
<Input {...props} ref={maskedInputRef} type='tel' />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import s from './styles.module.scss';
|
import s from './styles.module.scss';
|
||||||
import { Button, Input } from '@shared/ui';
|
import { Button, Input, PhoneInput } from '@shared/ui';
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import { sendFormFn } from '@shared/api/api.service';
|
import { sendFormFn } from '@shared/api/api.service';
|
||||||
|
import { isValidPhoneNumber } from 'libphonenumber-js/min';
|
||||||
|
|
||||||
const FormSchema = z.object({
|
const FormSchema = z.object({
|
||||||
name: z.string().min(3),
|
name: z
|
||||||
phone: z.string(),
|
.string()
|
||||||
|
.min(3, { message: 'Поле должно содержать не менее 3-х букв' })
|
||||||
|
.regex(/^[A-Za-zА-Яа-яЁё]+(?:[ '-][A-Za-zА-Яа-яЁё]+)*$/, {
|
||||||
|
message: 'Поле содержит некорректные символы',
|
||||||
|
}),
|
||||||
|
phone: z.string().refine(isValidPhoneNumber, 'Некорректный номер телефона'),
|
||||||
});
|
});
|
||||||
type TForm = z.infer<typeof FormSchema>;
|
type TForm = z.infer<typeof FormSchema>;
|
||||||
|
|
||||||
@@ -67,11 +73,11 @@ export default function OfferForm() {
|
|||||||
control={control}
|
control={control}
|
||||||
name={'phone'}
|
name={'phone'}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<Input
|
<PhoneInput
|
||||||
{...field}
|
{...field}
|
||||||
className={s.Unit}
|
className={s.Unit}
|
||||||
type='text'
|
type='text'
|
||||||
placeholder='+7 (999) 123 45 67'
|
placeholder='+7 999 123-45-67'
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user