@lets-events/react 12.3.10 → 12.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +2 -2
- package/.turbo/turbo-build.log +19 -21
- package/CHANGELOG.md +12 -0
- package/dist/index.d.mts +35 -3
- package/dist/index.d.ts +35 -3
- package/dist/index.js +562 -344
- package/dist/index.mjs +535 -319
- package/package.json +1 -1
- package/src/components/Alert.tsx +303 -303
- package/src/components/Avatar.tsx +55 -55
- package/src/components/Badge.tsx +125 -125
- package/src/components/Box.tsx +3 -3
- package/src/components/Button/index.tsx +45 -45
- package/src/components/Button/styledComponents.ts +313 -313
- package/src/components/ButtonGroup.tsx +484 -484
- package/src/components/Calendar/index.tsx +148 -148
- package/src/components/Calendar/styledComponents.ts +259 -250
- package/src/components/Card.tsx +67 -67
- package/src/components/CheckboxGroup.tsx +176 -176
- package/src/components/Container.tsx +39 -39
- package/src/components/Divider.tsx +7 -7
- package/src/components/DoubleCalendar/index.tsx +166 -0
- package/src/components/Drawer/index.tsx +98 -98
- package/src/components/Drawer/styledComponents.ts +103 -103
- package/src/components/Dropdown.tsx +302 -302
- package/src/components/Filter.tsx +164 -164
- package/src/components/Flex.tsx +118 -118
- package/src/components/FormFields/AddressFormFields/CityFormField.tsx +111 -111
- package/src/components/FormFields/AddressFormFields/CountryFormField.tsx +33 -33
- package/src/components/FormFields/AddressFormFields/PostalCodeFormField.tsx +39 -39
- package/src/components/FormFields/AddressFormFields/StateFormField.tsx +32 -32
- package/src/components/FormFields/AddressFormFields/index.tsx +141 -141
- package/src/components/FormFields/BirthDateFormField.tsx +84 -84
- package/src/components/FormFields/CNPJFormField.tsx +87 -87
- package/src/components/FormFields/CPFFormField.tsx +78 -78
- package/src/components/FormFields/CalendarFormField.tsx +95 -95
- package/src/components/FormFields/CheckboxGroupFormField.tsx +91 -91
- package/src/components/FormFields/DoubleCalendarFormField.tsx +90 -0
- package/src/components/FormFields/EmailFormField.tsx +27 -27
- package/src/components/FormFields/Form.tsx +39 -39
- package/src/components/FormFields/IdentityDocumentNumberFormField.tsx +32 -32
- package/src/components/FormFields/MultiSelectFormField.tsx +64 -64
- package/src/components/FormFields/PhoneFormField.tsx +40 -40
- package/src/components/FormFields/RadioGroupFormField.tsx +84 -84
- package/src/components/FormFields/RichEditorFormField.tsx +103 -103
- package/src/components/FormFields/SelectFormField.tsx +93 -93
- package/src/components/FormFields/SwitchFormField.tsx +46 -46
- package/src/components/FormFields/TextAreaFormField.tsx +59 -57
- package/src/components/FormFields/TextFormField.tsx +112 -112
- package/src/components/FormFields/TimePickerFormField.tsx +88 -88
- package/src/components/FormFields/subComponents/ErrorFormMessage.tsx +36 -36
- package/src/components/FormFields/subComponents/FormLabel.tsx +29 -29
- package/src/components/FormFields/utils/validation.ts +23 -23
- package/src/components/Grid.tsx +137 -137
- package/src/components/Icon.tsx +47 -47
- package/src/components/MenuDropdown/index.tsx +38 -38
- package/src/components/MenuDropdown/styledComponents.ts +31 -31
- package/src/components/Modal.tsx +110 -110
- package/src/components/MultiSelect/index.tsx +243 -243
- package/src/components/MultiSelect/styledComponents.ts +160 -160
- package/src/components/RadioGroup.tsx +210 -210
- package/src/components/RichEditor/QuillComponent.tsx +457 -457
- package/src/components/RichEditor/RichEditor.tsx +49 -49
- package/src/components/RichEditor/index.ts +2 -2
- package/src/components/RichEditor/styledComponents.ts +1151 -1151
- package/src/components/Section.tsx +33 -33
- package/src/components/Step.tsx +164 -164
- package/src/components/Switch.tsx +108 -108
- package/src/components/Text.tsx +38 -38
- package/src/components/TextField.tsx +372 -372
- package/src/components/TextareaField.tsx +138 -127
- package/src/components/TimePicker.tsx +328 -328
- package/src/components/Toast/components/ToastItem.tsx +41 -41
- package/src/components/Toast/components/ToastProvider.tsx +63 -63
- package/src/components/Toast/hooks/useToast.ts +12 -12
- package/src/components/Toast/index.tsx +5 -5
- package/src/components/Toast/styles/index.ts +135 -135
- package/src/components/Toast/types/index.ts +46 -46
- package/src/components/Tooltip/index.tsx +66 -66
- package/src/components/Tooltip/styles.ts +77 -77
- package/src/hooks/useCountries.ts +41 -41
- package/src/hooks/useImageUpload.ts +139 -139
- package/src/hooks/useOnClickOutside.tsx +42 -42
- package/src/index.tsx +71 -69
- package/src/styles/index.ts +41 -41
- package/src/types/typographyValues.ts +178 -178
- package/src/utils/getNestedValue.ts +3 -3
- package/src/utils/states.ts +29 -29
- package/src/utils/uploadService.ts +180 -180
- package/tsconfig.json +3 -3
- package/tsup.config.ts +38 -38
|
@@ -1,141 +1,141 @@
|
|
|
1
|
-
import { useEffect } from "react";
|
|
2
|
-
import { useFormContext, useWatch, useFormState } from "react-hook-form";
|
|
3
|
-
import { CountryFormField } from "./CountryFormField";
|
|
4
|
-
import { PostalCodeFormField } from "./PostalCodeFormField";
|
|
5
|
-
import { StateFormField } from "./StateFormField";
|
|
6
|
-
import { CityFormField } from "./CityFormField";
|
|
7
|
-
import { FormLabel } from "../subComponents/FormLabel";
|
|
8
|
-
import { TextFormField } from "../TextFormField";
|
|
9
|
-
import { styled } from "../../../styles";
|
|
10
|
-
|
|
11
|
-
type AddressFormFieldsProps = {
|
|
12
|
-
name: string;
|
|
13
|
-
label: string;
|
|
14
|
-
required?: boolean;
|
|
15
|
-
layout?: "column" | "grid";
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
function getNestedValue(obj: any, path: string): any {
|
|
19
|
-
return path.split(".").reduce((acc, key) => acc?.[key], obj);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const AddressContainerStyled = styled("div", {
|
|
23
|
-
variants: {
|
|
24
|
-
layout: {
|
|
25
|
-
column: {
|
|
26
|
-
display: "flex",
|
|
27
|
-
flexDirection: "column",
|
|
28
|
-
gap: "$4",
|
|
29
|
-
},
|
|
30
|
-
grid: {
|
|
31
|
-
display: "grid",
|
|
32
|
-
gap: "$8 $16",
|
|
33
|
-
gridTemplateColumns: "repeat(2, 1fr)",
|
|
34
|
-
|
|
35
|
-
"& > *:nth-child(1)": {
|
|
36
|
-
gridColumn: "span 2",
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
});
|
|
42
|
-
export function AddressFormFields({
|
|
43
|
-
name,
|
|
44
|
-
label,
|
|
45
|
-
required,
|
|
46
|
-
layout = "column",
|
|
47
|
-
}: AddressFormFieldsProps) {
|
|
48
|
-
const { control, setValue } = useFormContext();
|
|
49
|
-
const { errors } = useFormState({ control });
|
|
50
|
-
|
|
51
|
-
const selectedCountry = useWatch({ control, name: `${name}.country` });
|
|
52
|
-
const isBrazil = selectedCountry === "Brasil";
|
|
53
|
-
|
|
54
|
-
const addressErrors = getNestedValue(errors, name);
|
|
55
|
-
const haveError = !!addressErrors;
|
|
56
|
-
|
|
57
|
-
const handleCEPChange = (cep: string) => {
|
|
58
|
-
if (!isBrazil) return;
|
|
59
|
-
|
|
60
|
-
const cleanedCep = cep?.replace(/\D/g, "");
|
|
61
|
-
|
|
62
|
-
if (cleanedCep?.length !== 8) return;
|
|
63
|
-
|
|
64
|
-
fetch(`https://viacep.com.br/ws/${cleanedCep}/json`)
|
|
65
|
-
.then((res) => res.json())
|
|
66
|
-
.then((data) => {
|
|
67
|
-
if (!data.erro) {
|
|
68
|
-
setValue(`${name}.street`, data.logradouro || "");
|
|
69
|
-
setValue(`${name}.neighborhood`, data.bairro || "");
|
|
70
|
-
setValue(`${name}.city`, data.localidade || "");
|
|
71
|
-
setValue(`${name}.state`, data.uf || "");
|
|
72
|
-
}
|
|
73
|
-
})
|
|
74
|
-
.catch(() => {
|
|
75
|
-
console.error("Erro ao buscar CEP");
|
|
76
|
-
});
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
return (
|
|
80
|
-
<AddressContainerStyled layout={layout}>
|
|
81
|
-
<FormLabel
|
|
82
|
-
name={name}
|
|
83
|
-
label={label}
|
|
84
|
-
required={required}
|
|
85
|
-
haveError={haveError}
|
|
86
|
-
/>
|
|
87
|
-
|
|
88
|
-
<CountryFormField
|
|
89
|
-
name={`${name}.country`}
|
|
90
|
-
label="País"
|
|
91
|
-
required={required}
|
|
92
|
-
language="pt-BR"
|
|
93
|
-
/>
|
|
94
|
-
|
|
95
|
-
{isBrazil ? (
|
|
96
|
-
<PostalCodeFormField
|
|
97
|
-
name={`${name}.zip_code`}
|
|
98
|
-
label="CEP"
|
|
99
|
-
required={required}
|
|
100
|
-
placeholder="00000-000"
|
|
101
|
-
validationErrorMessage="CEP inválido"
|
|
102
|
-
onChange={handleCEPChange}
|
|
103
|
-
/>
|
|
104
|
-
) : (
|
|
105
|
-
<TextFormField
|
|
106
|
-
name={`${name}.zip_code`}
|
|
107
|
-
label="Código Postal"
|
|
108
|
-
required={required}
|
|
109
|
-
/>
|
|
110
|
-
)}
|
|
111
|
-
|
|
112
|
-
<StateFormField
|
|
113
|
-
name={`${name}.state`}
|
|
114
|
-
label="Estado"
|
|
115
|
-
required={required}
|
|
116
|
-
isBrazil={isBrazil}
|
|
117
|
-
/>
|
|
118
|
-
|
|
119
|
-
<CityFormField
|
|
120
|
-
name={`${name}.city`}
|
|
121
|
-
stateName={`${name}.state`}
|
|
122
|
-
label="Cidade"
|
|
123
|
-
required={required}
|
|
124
|
-
isBrazil={isBrazil}
|
|
125
|
-
/>
|
|
126
|
-
|
|
127
|
-
<TextFormField name={`${name}.street`} label="Rua" required={required} />
|
|
128
|
-
<TextFormField
|
|
129
|
-
name={`${name}.number`}
|
|
130
|
-
label="Número"
|
|
131
|
-
required={required}
|
|
132
|
-
/>
|
|
133
|
-
<TextFormField
|
|
134
|
-
name={`${name}.neighborhood`}
|
|
135
|
-
label="Bairro"
|
|
136
|
-
required={required}
|
|
137
|
-
/>
|
|
138
|
-
<TextFormField name={`${name}.complement`} label="Complemento" />
|
|
139
|
-
</AddressContainerStyled>
|
|
140
|
-
);
|
|
141
|
-
}
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import { useFormContext, useWatch, useFormState } from "react-hook-form";
|
|
3
|
+
import { CountryFormField } from "./CountryFormField";
|
|
4
|
+
import { PostalCodeFormField } from "./PostalCodeFormField";
|
|
5
|
+
import { StateFormField } from "./StateFormField";
|
|
6
|
+
import { CityFormField } from "./CityFormField";
|
|
7
|
+
import { FormLabel } from "../subComponents/FormLabel";
|
|
8
|
+
import { TextFormField } from "../TextFormField";
|
|
9
|
+
import { styled } from "../../../styles";
|
|
10
|
+
|
|
11
|
+
type AddressFormFieldsProps = {
|
|
12
|
+
name: string;
|
|
13
|
+
label: string;
|
|
14
|
+
required?: boolean;
|
|
15
|
+
layout?: "column" | "grid";
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function getNestedValue(obj: any, path: string): any {
|
|
19
|
+
return path.split(".").reduce((acc, key) => acc?.[key], obj);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const AddressContainerStyled = styled("div", {
|
|
23
|
+
variants: {
|
|
24
|
+
layout: {
|
|
25
|
+
column: {
|
|
26
|
+
display: "flex",
|
|
27
|
+
flexDirection: "column",
|
|
28
|
+
gap: "$4",
|
|
29
|
+
},
|
|
30
|
+
grid: {
|
|
31
|
+
display: "grid",
|
|
32
|
+
gap: "$8 $16",
|
|
33
|
+
gridTemplateColumns: "repeat(2, 1fr)",
|
|
34
|
+
|
|
35
|
+
"& > *:nth-child(1)": {
|
|
36
|
+
gridColumn: "span 2",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
export function AddressFormFields({
|
|
43
|
+
name,
|
|
44
|
+
label,
|
|
45
|
+
required,
|
|
46
|
+
layout = "column",
|
|
47
|
+
}: AddressFormFieldsProps) {
|
|
48
|
+
const { control, setValue } = useFormContext();
|
|
49
|
+
const { errors } = useFormState({ control });
|
|
50
|
+
|
|
51
|
+
const selectedCountry = useWatch({ control, name: `${name}.country` });
|
|
52
|
+
const isBrazil = selectedCountry === "Brasil";
|
|
53
|
+
|
|
54
|
+
const addressErrors = getNestedValue(errors, name);
|
|
55
|
+
const haveError = !!addressErrors;
|
|
56
|
+
|
|
57
|
+
const handleCEPChange = (cep: string) => {
|
|
58
|
+
if (!isBrazil) return;
|
|
59
|
+
|
|
60
|
+
const cleanedCep = cep?.replace(/\D/g, "");
|
|
61
|
+
|
|
62
|
+
if (cleanedCep?.length !== 8) return;
|
|
63
|
+
|
|
64
|
+
fetch(`https://viacep.com.br/ws/${cleanedCep}/json`)
|
|
65
|
+
.then((res) => res.json())
|
|
66
|
+
.then((data) => {
|
|
67
|
+
if (!data.erro) {
|
|
68
|
+
setValue(`${name}.street`, data.logradouro || "");
|
|
69
|
+
setValue(`${name}.neighborhood`, data.bairro || "");
|
|
70
|
+
setValue(`${name}.city`, data.localidade || "");
|
|
71
|
+
setValue(`${name}.state`, data.uf || "");
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
.catch(() => {
|
|
75
|
+
console.error("Erro ao buscar CEP");
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<AddressContainerStyled layout={layout}>
|
|
81
|
+
<FormLabel
|
|
82
|
+
name={name}
|
|
83
|
+
label={label}
|
|
84
|
+
required={required}
|
|
85
|
+
haveError={haveError}
|
|
86
|
+
/>
|
|
87
|
+
|
|
88
|
+
<CountryFormField
|
|
89
|
+
name={`${name}.country`}
|
|
90
|
+
label="País"
|
|
91
|
+
required={required}
|
|
92
|
+
language="pt-BR"
|
|
93
|
+
/>
|
|
94
|
+
|
|
95
|
+
{isBrazil ? (
|
|
96
|
+
<PostalCodeFormField
|
|
97
|
+
name={`${name}.zip_code`}
|
|
98
|
+
label="CEP"
|
|
99
|
+
required={required}
|
|
100
|
+
placeholder="00000-000"
|
|
101
|
+
validationErrorMessage="CEP inválido"
|
|
102
|
+
onChange={handleCEPChange}
|
|
103
|
+
/>
|
|
104
|
+
) : (
|
|
105
|
+
<TextFormField
|
|
106
|
+
name={`${name}.zip_code`}
|
|
107
|
+
label="Código Postal"
|
|
108
|
+
required={required}
|
|
109
|
+
/>
|
|
110
|
+
)}
|
|
111
|
+
|
|
112
|
+
<StateFormField
|
|
113
|
+
name={`${name}.state`}
|
|
114
|
+
label="Estado"
|
|
115
|
+
required={required}
|
|
116
|
+
isBrazil={isBrazil}
|
|
117
|
+
/>
|
|
118
|
+
|
|
119
|
+
<CityFormField
|
|
120
|
+
name={`${name}.city`}
|
|
121
|
+
stateName={`${name}.state`}
|
|
122
|
+
label="Cidade"
|
|
123
|
+
required={required}
|
|
124
|
+
isBrazil={isBrazil}
|
|
125
|
+
/>
|
|
126
|
+
|
|
127
|
+
<TextFormField name={`${name}.street`} label="Rua" required={required} />
|
|
128
|
+
<TextFormField
|
|
129
|
+
name={`${name}.number`}
|
|
130
|
+
label="Número"
|
|
131
|
+
required={required}
|
|
132
|
+
/>
|
|
133
|
+
<TextFormField
|
|
134
|
+
name={`${name}.neighborhood`}
|
|
135
|
+
label="Bairro"
|
|
136
|
+
required={required}
|
|
137
|
+
/>
|
|
138
|
+
<TextFormField name={`${name}.complement`} label="Complemento" />
|
|
139
|
+
</AddressContainerStyled>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
import { TextFormField } from "./TextFormField";
|
|
2
|
-
|
|
3
|
-
type Language = "pt-BR" | "en" | "es";
|
|
4
|
-
|
|
5
|
-
type BirthDateFormFieldProps = {
|
|
6
|
-
name: string;
|
|
7
|
-
label: string;
|
|
8
|
-
required?: boolean;
|
|
9
|
-
placeholder?: string;
|
|
10
|
-
validationErrorMessage: string;
|
|
11
|
-
language: Language;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const isValidDate = (day: number, month: number, year: number): boolean => {
|
|
15
|
-
const date = new Date(year, month - 1, day);
|
|
16
|
-
return (
|
|
17
|
-
date.getFullYear() === year &&
|
|
18
|
-
date.getMonth() === month - 1 &&
|
|
19
|
-
date.getDate() === day
|
|
20
|
-
);
|
|
21
|
-
};
|
|
22
|
-
const isValidBirthDate = (value: string, language: Language): boolean => {
|
|
23
|
-
if (!/^\d{8}$/.test(value)) return false;
|
|
24
|
-
|
|
25
|
-
let day = 0;
|
|
26
|
-
let month = 0;
|
|
27
|
-
let year = 0;
|
|
28
|
-
if (language === "en") {
|
|
29
|
-
month = Number(value.slice(0, 2));
|
|
30
|
-
day = Number(value.slice(2, 4));
|
|
31
|
-
year = Number(value.slice(4));
|
|
32
|
-
} else {
|
|
33
|
-
day = Number(value.slice(0, 2));
|
|
34
|
-
month = Number(value.slice(2, 4));
|
|
35
|
-
year = Number(value.slice(4));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (!isValidDate(day, month, year)) return false;
|
|
39
|
-
|
|
40
|
-
const today = new Date();
|
|
41
|
-
const birthDate = new Date(year, month - 1, day);
|
|
42
|
-
|
|
43
|
-
if (birthDate > today) return false;
|
|
44
|
-
|
|
45
|
-
const age = today.getFullYear() - birthDate.getFullYear();
|
|
46
|
-
const beforeBirthday =
|
|
47
|
-
today.getMonth() < birthDate.getMonth() ||
|
|
48
|
-
(today.getMonth() === birthDate.getMonth() &&
|
|
49
|
-
today.getDate() < birthDate.getDate());
|
|
50
|
-
|
|
51
|
-
const realAge = beforeBirthday ? age - 1 : age;
|
|
52
|
-
|
|
53
|
-
return realAge <= 100;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
export const BirthDateFormField = ({
|
|
57
|
-
name,
|
|
58
|
-
label,
|
|
59
|
-
required,
|
|
60
|
-
placeholder,
|
|
61
|
-
validationErrorMessage,
|
|
62
|
-
language,
|
|
63
|
-
}: BirthDateFormFieldProps) => {
|
|
64
|
-
const inputPlaceholder =
|
|
65
|
-
placeholder || (language === "pt-BR" ? "DD/MM/AAAA" : "MM/DD/YYYY");
|
|
66
|
-
|
|
67
|
-
return (
|
|
68
|
-
<TextFormField
|
|
69
|
-
name={name}
|
|
70
|
-
label={label}
|
|
71
|
-
required={required}
|
|
72
|
-
placeholder={inputPlaceholder}
|
|
73
|
-
mask={{
|
|
74
|
-
mask: "__/__/____",
|
|
75
|
-
replacement: { _: /[0-9]/ },
|
|
76
|
-
}}
|
|
77
|
-
validate={(value: string) => {
|
|
78
|
-
const isEmpty = value.replace(/[^\d]+/g, "").length === 0;
|
|
79
|
-
if (!required && isEmpty) return true;
|
|
80
|
-
return isValidBirthDate(value, language) || validationErrorMessage;
|
|
81
|
-
}}
|
|
82
|
-
/>
|
|
83
|
-
);
|
|
84
|
-
};
|
|
1
|
+
import { TextFormField } from "./TextFormField";
|
|
2
|
+
|
|
3
|
+
type Language = "pt-BR" | "en" | "es";
|
|
4
|
+
|
|
5
|
+
type BirthDateFormFieldProps = {
|
|
6
|
+
name: string;
|
|
7
|
+
label: string;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
validationErrorMessage: string;
|
|
11
|
+
language: Language;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const isValidDate = (day: number, month: number, year: number): boolean => {
|
|
15
|
+
const date = new Date(year, month - 1, day);
|
|
16
|
+
return (
|
|
17
|
+
date.getFullYear() === year &&
|
|
18
|
+
date.getMonth() === month - 1 &&
|
|
19
|
+
date.getDate() === day
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
const isValidBirthDate = (value: string, language: Language): boolean => {
|
|
23
|
+
if (!/^\d{8}$/.test(value)) return false;
|
|
24
|
+
|
|
25
|
+
let day = 0;
|
|
26
|
+
let month = 0;
|
|
27
|
+
let year = 0;
|
|
28
|
+
if (language === "en") {
|
|
29
|
+
month = Number(value.slice(0, 2));
|
|
30
|
+
day = Number(value.slice(2, 4));
|
|
31
|
+
year = Number(value.slice(4));
|
|
32
|
+
} else {
|
|
33
|
+
day = Number(value.slice(0, 2));
|
|
34
|
+
month = Number(value.slice(2, 4));
|
|
35
|
+
year = Number(value.slice(4));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!isValidDate(day, month, year)) return false;
|
|
39
|
+
|
|
40
|
+
const today = new Date();
|
|
41
|
+
const birthDate = new Date(year, month - 1, day);
|
|
42
|
+
|
|
43
|
+
if (birthDate > today) return false;
|
|
44
|
+
|
|
45
|
+
const age = today.getFullYear() - birthDate.getFullYear();
|
|
46
|
+
const beforeBirthday =
|
|
47
|
+
today.getMonth() < birthDate.getMonth() ||
|
|
48
|
+
(today.getMonth() === birthDate.getMonth() &&
|
|
49
|
+
today.getDate() < birthDate.getDate());
|
|
50
|
+
|
|
51
|
+
const realAge = beforeBirthday ? age - 1 : age;
|
|
52
|
+
|
|
53
|
+
return realAge <= 100;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const BirthDateFormField = ({
|
|
57
|
+
name,
|
|
58
|
+
label,
|
|
59
|
+
required,
|
|
60
|
+
placeholder,
|
|
61
|
+
validationErrorMessage,
|
|
62
|
+
language,
|
|
63
|
+
}: BirthDateFormFieldProps) => {
|
|
64
|
+
const inputPlaceholder =
|
|
65
|
+
placeholder || (language === "pt-BR" ? "DD/MM/AAAA" : "MM/DD/YYYY");
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<TextFormField
|
|
69
|
+
name={name}
|
|
70
|
+
label={label}
|
|
71
|
+
required={required}
|
|
72
|
+
placeholder={inputPlaceholder}
|
|
73
|
+
mask={{
|
|
74
|
+
mask: "__/__/____",
|
|
75
|
+
replacement: { _: /[0-9]/ },
|
|
76
|
+
}}
|
|
77
|
+
validate={(value: string) => {
|
|
78
|
+
const isEmpty = value.replace(/[^\d]+/g, "").length === 0;
|
|
79
|
+
if (!required && isEmpty) return true;
|
|
80
|
+
return isValidBirthDate(value, language) || validationErrorMessage;
|
|
81
|
+
}}
|
|
82
|
+
/>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
import { TextFormField } from "./TextFormField";
|
|
2
|
-
|
|
3
|
-
type CNPJFormFieldProps = {
|
|
4
|
-
name: string;
|
|
5
|
-
label: string;
|
|
6
|
-
required?: boolean;
|
|
7
|
-
placeholder?: string;
|
|
8
|
-
validationErrorMessage: string;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const matchesNonDigit = new RegExp(/\D+/g);
|
|
12
|
-
|
|
13
|
-
const getWeights = (size: number, start: number, end: number) => {
|
|
14
|
-
const weights = [];
|
|
15
|
-
for (let i = size - 1; i >= 0; i--) {
|
|
16
|
-
weights.push((end ? i % (end - start + 1) : i) + start);
|
|
17
|
-
}
|
|
18
|
-
return weights;
|
|
19
|
-
};
|
|
20
|
-
const calcValidatorDigit = (basicDigits: number[], weights: number[]) => {
|
|
21
|
-
const sum = basicDigits.reduce(
|
|
22
|
-
(sum, digit, index) => sum + digit * weights[index],
|
|
23
|
-
0
|
|
24
|
-
);
|
|
25
|
-
const mod = sum % 11;
|
|
26
|
-
return mod < 2 ? 0 : 11 - mod;
|
|
27
|
-
};
|
|
28
|
-
const cnpjWeights1 = getWeights(12, 2, 9);
|
|
29
|
-
const cnpjWeights2 = getWeights(13, 2, 9);
|
|
30
|
-
export const isValidCNPJ = (cnpj: string) => {
|
|
31
|
-
const digitsOnlyCnpj = cnpj.replace(matchesNonDigit, "");
|
|
32
|
-
|
|
33
|
-
if (digitsOnlyCnpj.length !== 14) {
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
// Elimina CNPJs com todos os dígitos iguais (ex: 11.111.111/1111-11)
|
|
37
|
-
if (/^(\d)\1+$/.test(digitsOnlyCnpj)) return false;
|
|
38
|
-
|
|
39
|
-
const cnpjArray = digitsOnlyCnpj
|
|
40
|
-
.split("")
|
|
41
|
-
.map((digit) => Number.parseInt(digit));
|
|
42
|
-
|
|
43
|
-
const validatorDigit1 = cnpjArray[12];
|
|
44
|
-
const validatorDigit2 = cnpjArray[13];
|
|
45
|
-
const basicDigits = cnpjArray.slice(0, 12);
|
|
46
|
-
|
|
47
|
-
const expectedValidator1 = calcValidatorDigit(basicDigits, cnpjWeights1);
|
|
48
|
-
if (expectedValidator1 !== validatorDigit1) {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const expectedValidator2 = calcValidatorDigit(
|
|
53
|
-
[...basicDigits, validatorDigit1],
|
|
54
|
-
cnpjWeights2
|
|
55
|
-
);
|
|
56
|
-
if (expectedValidator2 !== validatorDigit2) {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return true;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export const CNPJFormField = ({
|
|
64
|
-
name,
|
|
65
|
-
label,
|
|
66
|
-
required,
|
|
67
|
-
placeholder,
|
|
68
|
-
validationErrorMessage,
|
|
69
|
-
}: CNPJFormFieldProps) => {
|
|
70
|
-
return (
|
|
71
|
-
<TextFormField
|
|
72
|
-
name={name}
|
|
73
|
-
label={label}
|
|
74
|
-
required={required}
|
|
75
|
-
placeholder={placeholder || "00.000.000/0000-00"}
|
|
76
|
-
mask={{
|
|
77
|
-
mask: "__.___.___/____-__",
|
|
78
|
-
replacement: { _: /[0-9]/ },
|
|
79
|
-
}}
|
|
80
|
-
validate={(value: string) => {
|
|
81
|
-
const isEmpty = value.replace(matchesNonDigit, "").length === 0;
|
|
82
|
-
if (!required && isEmpty) return true;
|
|
83
|
-
return isValidCNPJ(value) || validationErrorMessage;
|
|
84
|
-
}}
|
|
85
|
-
/>
|
|
86
|
-
);
|
|
87
|
-
};
|
|
1
|
+
import { TextFormField } from "./TextFormField";
|
|
2
|
+
|
|
3
|
+
type CNPJFormFieldProps = {
|
|
4
|
+
name: string;
|
|
5
|
+
label: string;
|
|
6
|
+
required?: boolean;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
validationErrorMessage: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const matchesNonDigit = new RegExp(/\D+/g);
|
|
12
|
+
|
|
13
|
+
const getWeights = (size: number, start: number, end: number) => {
|
|
14
|
+
const weights = [];
|
|
15
|
+
for (let i = size - 1; i >= 0; i--) {
|
|
16
|
+
weights.push((end ? i % (end - start + 1) : i) + start);
|
|
17
|
+
}
|
|
18
|
+
return weights;
|
|
19
|
+
};
|
|
20
|
+
const calcValidatorDigit = (basicDigits: number[], weights: number[]) => {
|
|
21
|
+
const sum = basicDigits.reduce(
|
|
22
|
+
(sum, digit, index) => sum + digit * weights[index],
|
|
23
|
+
0
|
|
24
|
+
);
|
|
25
|
+
const mod = sum % 11;
|
|
26
|
+
return mod < 2 ? 0 : 11 - mod;
|
|
27
|
+
};
|
|
28
|
+
const cnpjWeights1 = getWeights(12, 2, 9);
|
|
29
|
+
const cnpjWeights2 = getWeights(13, 2, 9);
|
|
30
|
+
export const isValidCNPJ = (cnpj: string) => {
|
|
31
|
+
const digitsOnlyCnpj = cnpj.replace(matchesNonDigit, "");
|
|
32
|
+
|
|
33
|
+
if (digitsOnlyCnpj.length !== 14) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
// Elimina CNPJs com todos os dígitos iguais (ex: 11.111.111/1111-11)
|
|
37
|
+
if (/^(\d)\1+$/.test(digitsOnlyCnpj)) return false;
|
|
38
|
+
|
|
39
|
+
const cnpjArray = digitsOnlyCnpj
|
|
40
|
+
.split("")
|
|
41
|
+
.map((digit) => Number.parseInt(digit));
|
|
42
|
+
|
|
43
|
+
const validatorDigit1 = cnpjArray[12];
|
|
44
|
+
const validatorDigit2 = cnpjArray[13];
|
|
45
|
+
const basicDigits = cnpjArray.slice(0, 12);
|
|
46
|
+
|
|
47
|
+
const expectedValidator1 = calcValidatorDigit(basicDigits, cnpjWeights1);
|
|
48
|
+
if (expectedValidator1 !== validatorDigit1) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const expectedValidator2 = calcValidatorDigit(
|
|
53
|
+
[...basicDigits, validatorDigit1],
|
|
54
|
+
cnpjWeights2
|
|
55
|
+
);
|
|
56
|
+
if (expectedValidator2 !== validatorDigit2) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return true;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const CNPJFormField = ({
|
|
64
|
+
name,
|
|
65
|
+
label,
|
|
66
|
+
required,
|
|
67
|
+
placeholder,
|
|
68
|
+
validationErrorMessage,
|
|
69
|
+
}: CNPJFormFieldProps) => {
|
|
70
|
+
return (
|
|
71
|
+
<TextFormField
|
|
72
|
+
name={name}
|
|
73
|
+
label={label}
|
|
74
|
+
required={required}
|
|
75
|
+
placeholder={placeholder || "00.000.000/0000-00"}
|
|
76
|
+
mask={{
|
|
77
|
+
mask: "__.___.___/____-__",
|
|
78
|
+
replacement: { _: /[0-9]/ },
|
|
79
|
+
}}
|
|
80
|
+
validate={(value: string) => {
|
|
81
|
+
const isEmpty = value.replace(matchesNonDigit, "").length === 0;
|
|
82
|
+
if (!required && isEmpty) return true;
|
|
83
|
+
return isValidCNPJ(value) || validationErrorMessage;
|
|
84
|
+
}}
|
|
85
|
+
/>
|
|
86
|
+
);
|
|
87
|
+
};
|