@lets-events/react 12.7.2 → 12.8.0

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.
Files changed (93) hide show
  1. package/.eslintrc.json +2 -2
  2. package/.turbo/turbo-build.log +21 -19
  3. package/CHANGELOG.md +12 -0
  4. package/dist/index.d.mts +13 -1
  5. package/dist/index.d.ts +13 -1
  6. package/dist/index.js +147 -9
  7. package/dist/index.mjs +143 -6
  8. package/package.json +1 -1
  9. package/src/components/Alert.tsx +303 -303
  10. package/src/components/Avatar.tsx +55 -55
  11. package/src/components/Badge.tsx +123 -123
  12. package/src/components/Box.tsx +3 -3
  13. package/src/components/Button/index.tsx +62 -62
  14. package/src/components/Button/styledComponents.ts +320 -320
  15. package/src/components/ButtonGroup.tsx +484 -484
  16. package/src/components/Calendar/index.tsx +148 -148
  17. package/src/components/Calendar/styledComponents.ts +274 -259
  18. package/src/components/Card.tsx +67 -67
  19. package/src/components/CheckboxGroup.tsx +176 -176
  20. package/src/components/Container.tsx +39 -39
  21. package/src/components/Divider.tsx +7 -7
  22. package/src/components/DoubleCalendar/index.tsx +170 -170
  23. package/src/components/Drawer/index.tsx +100 -100
  24. package/src/components/Drawer/styledComponents.ts +103 -103
  25. package/src/components/Dropdown.tsx +302 -302
  26. package/src/components/Filter.tsx +164 -164
  27. package/src/components/Flex.tsx +118 -118
  28. package/src/components/FormFields/AddressFormFields/CityFormField.tsx +111 -111
  29. package/src/components/FormFields/AddressFormFields/CountryFormField.tsx +33 -33
  30. package/src/components/FormFields/AddressFormFields/PostalCodeFormField.tsx +39 -39
  31. package/src/components/FormFields/AddressFormFields/StateFormField.tsx +32 -32
  32. package/src/components/FormFields/AddressFormFields/index.tsx +141 -141
  33. package/src/components/FormFields/BirthDateFormField.tsx +84 -84
  34. package/src/components/FormFields/CNPJFormField.tsx +87 -87
  35. package/src/components/FormFields/CPFFormField.tsx +78 -78
  36. package/src/components/FormFields/CalendarFormField.tsx +95 -95
  37. package/src/components/FormFields/CheckboxGroupFormField.tsx +91 -91
  38. package/src/components/FormFields/DateAndTimeFormField.tsx +154 -0
  39. package/src/components/FormFields/DoubleCalendarFormField.tsx +93 -93
  40. package/src/components/FormFields/EmailFormField.tsx +27 -27
  41. package/src/components/FormFields/Form.tsx +39 -39
  42. package/src/components/FormFields/IdentityDocumentNumberFormField.tsx +32 -32
  43. package/src/components/FormFields/MultiSelectFormField.tsx +64 -64
  44. package/src/components/FormFields/PhoneFormField.tsx +40 -40
  45. package/src/components/FormFields/RadioGroupFormField.tsx +86 -86
  46. package/src/components/FormFields/RichEditorFormField.tsx +103 -103
  47. package/src/components/FormFields/SelectFormField.tsx +93 -93
  48. package/src/components/FormFields/SwitchFormField.tsx +46 -46
  49. package/src/components/FormFields/TextAreaFormField.tsx +61 -61
  50. package/src/components/FormFields/TextFormField.tsx +112 -112
  51. package/src/components/FormFields/TimePickerFormField.tsx +88 -88
  52. package/src/components/FormFields/subComponents/ErrorFormMessage.tsx +36 -36
  53. package/src/components/FormFields/subComponents/FormLabel.tsx +36 -36
  54. package/src/components/FormFields/utils/validation.ts +23 -23
  55. package/src/components/Grid.tsx +137 -137
  56. package/src/components/Icon.tsx +47 -47
  57. package/src/components/MenuDropdown/index.tsx +38 -38
  58. package/src/components/MenuDropdown/styledComponents.ts +31 -31
  59. package/src/components/Modal.tsx +110 -110
  60. package/src/components/MultiSelect/index.tsx +268 -268
  61. package/src/components/MultiSelect/styledComponents.ts +160 -160
  62. package/src/components/RadioGroup.tsx +210 -210
  63. package/src/components/RichEditor/QuillComponent.tsx +468 -468
  64. package/src/components/RichEditor/RichEditor.tsx +49 -49
  65. package/src/components/RichEditor/RichTextPresenter.tsx +18 -18
  66. package/src/components/RichEditor/index.ts +3 -3
  67. package/src/components/RichEditor/styledComponents.ts +1170 -1170
  68. package/src/components/Section.tsx +33 -33
  69. package/src/components/Step.tsx +164 -164
  70. package/src/components/Switch.tsx +108 -108
  71. package/src/components/Text.tsx +38 -38
  72. package/src/components/TextField.tsx +372 -372
  73. package/src/components/TextareaField.tsx +116 -116
  74. package/src/components/TimePicker.tsx +328 -328
  75. package/src/components/Toast/components/ToastItem.tsx +41 -41
  76. package/src/components/Toast/components/ToastProvider.tsx +63 -63
  77. package/src/components/Toast/hooks/useToast.ts +12 -12
  78. package/src/components/Toast/index.tsx +5 -5
  79. package/src/components/Toast/styles/index.ts +135 -135
  80. package/src/components/Toast/types/index.ts +46 -46
  81. package/src/components/Tooltip/index.tsx +73 -73
  82. package/src/components/Tooltip/styles.ts +77 -77
  83. package/src/hooks/useCountries.ts +41 -41
  84. package/src/hooks/useImageUpload.ts +139 -139
  85. package/src/hooks/useOnClickOutside.tsx +42 -42
  86. package/src/index.tsx +72 -71
  87. package/src/styles/index.ts +41 -41
  88. package/src/types/typographyValues.ts +178 -178
  89. package/src/utils/getNestedValue.ts +3 -3
  90. package/src/utils/states.ts +29 -29
  91. package/src/utils/uploadService.ts +180 -180
  92. package/tsconfig.json +3 -3
  93. package/tsup.config.ts +38 -38
@@ -1,78 +1,78 @@
1
- import { useFormContext, useWatch } from "react-hook-form";
2
- import { CheckboxGroup, CheckboxItem } from "../CheckboxGroup";
3
- import { Flex } from "../Flex";
4
- import { TextFormField } from "./TextFormField";
5
-
6
- type CPFFormFieldProps = {
7
- name: string;
8
- label: string;
9
- required?: boolean;
10
- placeholder?: string;
11
- validationErrorMessage: string;
12
- foreignerLabel: string;
13
- };
14
-
15
- const isValidCPF = (cpf: string) => {
16
- cpf = cpf.replace(/[^\d]+/g, "");
17
- if (cpf.length !== 11 || /^(\d)\1{10}$/.test(cpf)) return false;
18
-
19
- let sum = 0;
20
- for (let i = 0; i < 9; i++) sum += parseInt(cpf.charAt(i)) * (10 - i);
21
- let rest = (sum * 10) % 11;
22
- if (rest === 10 || rest === 11) rest = 0;
23
- if (rest !== parseInt(cpf.charAt(9))) return false;
24
-
25
- sum = 0;
26
- for (let i = 0; i < 10; i++) sum += parseInt(cpf.charAt(i)) * (11 - i);
27
- rest = (sum * 10) % 11;
28
- if (rest === 10 || rest === 11) rest = 0;
29
- if (rest !== parseInt(cpf.charAt(10))) return false;
30
-
31
- return true;
32
- };
33
-
34
- export const CPFFormField = ({
35
- name,
36
- label,
37
- required,
38
- placeholder,
39
- validationErrorMessage,
40
- foreignerLabel,
41
- }: CPFFormFieldProps) => {
42
- const { control, setValue } = useFormContext();
43
- const foreigner = useWatch({ name: "foreigner", control });
44
-
45
- return (
46
- <Flex direction="column">
47
- <TextFormField
48
- name={name}
49
- label={label}
50
- required={required && !foreigner}
51
- placeholder={placeholder || "000.000.000-00"}
52
- mask={{
53
- mask: "___.___.___-__",
54
- replacement: { _: /[0-9]/ },
55
- }}
56
- validate={(value: string) => {
57
- if (!required || foreigner) return true;
58
- return isValidCPF(value) || validationErrorMessage;
59
- }}
60
- disabled={foreigner}
61
- />
62
-
63
- <CheckboxGroup
64
- value={foreigner ? ["true"] : []}
65
- name="foreigner"
66
- onValueChange={(value) => {
67
- const isForeigner = value.includes("true");
68
- setValue("foreigner", isForeigner);
69
- if (isForeigner) {
70
- setValue(name, "");
71
- }
72
- }}
73
- >
74
- <CheckboxItem value="true">{foreignerLabel}</CheckboxItem>
75
- </CheckboxGroup>
76
- </Flex>
77
- );
78
- };
1
+ import { useFormContext, useWatch } from "react-hook-form";
2
+ import { CheckboxGroup, CheckboxItem } from "../CheckboxGroup";
3
+ import { Flex } from "../Flex";
4
+ import { TextFormField } from "./TextFormField";
5
+
6
+ type CPFFormFieldProps = {
7
+ name: string;
8
+ label: string;
9
+ required?: boolean;
10
+ placeholder?: string;
11
+ validationErrorMessage: string;
12
+ foreignerLabel: string;
13
+ };
14
+
15
+ const isValidCPF = (cpf: string) => {
16
+ cpf = cpf.replace(/[^\d]+/g, "");
17
+ if (cpf.length !== 11 || /^(\d)\1{10}$/.test(cpf)) return false;
18
+
19
+ let sum = 0;
20
+ for (let i = 0; i < 9; i++) sum += parseInt(cpf.charAt(i)) * (10 - i);
21
+ let rest = (sum * 10) % 11;
22
+ if (rest === 10 || rest === 11) rest = 0;
23
+ if (rest !== parseInt(cpf.charAt(9))) return false;
24
+
25
+ sum = 0;
26
+ for (let i = 0; i < 10; i++) sum += parseInt(cpf.charAt(i)) * (11 - i);
27
+ rest = (sum * 10) % 11;
28
+ if (rest === 10 || rest === 11) rest = 0;
29
+ if (rest !== parseInt(cpf.charAt(10))) return false;
30
+
31
+ return true;
32
+ };
33
+
34
+ export const CPFFormField = ({
35
+ name,
36
+ label,
37
+ required,
38
+ placeholder,
39
+ validationErrorMessage,
40
+ foreignerLabel,
41
+ }: CPFFormFieldProps) => {
42
+ const { control, setValue } = useFormContext();
43
+ const foreigner = useWatch({ name: "foreigner", control });
44
+
45
+ return (
46
+ <Flex direction="column">
47
+ <TextFormField
48
+ name={name}
49
+ label={label}
50
+ required={required && !foreigner}
51
+ placeholder={placeholder || "000.000.000-00"}
52
+ mask={{
53
+ mask: "___.___.___-__",
54
+ replacement: { _: /[0-9]/ },
55
+ }}
56
+ validate={(value: string) => {
57
+ if (!required || foreigner) return true;
58
+ return isValidCPF(value) || validationErrorMessage;
59
+ }}
60
+ disabled={foreigner}
61
+ />
62
+
63
+ <CheckboxGroup
64
+ value={foreigner ? ["true"] : []}
65
+ name="foreigner"
66
+ onValueChange={(value) => {
67
+ const isForeigner = value.includes("true");
68
+ setValue("foreigner", isForeigner);
69
+ if (isForeigner) {
70
+ setValue(name, "");
71
+ }
72
+ }}
73
+ >
74
+ <CheckboxItem value="true">{foreignerLabel}</CheckboxItem>
75
+ </CheckboxGroup>
76
+ </Flex>
77
+ );
78
+ };
@@ -1,95 +1,95 @@
1
- import React from "react";
2
- import { FieldValues, useController, RegisterOptions } from "react-hook-form";
3
- import { Flex } from "../Flex";
4
- import { FormLabel } from "./subComponents/FormLabel";
5
- import { ErrorFormMessage } from "./subComponents/ErrorFormMessage";
6
- import { Calendar, CalendarProps } from "../Calendar";
7
- import { useCallback } from "react";
8
-
9
- export type CalendarFormFieldProps = Omit<
10
- CalendarProps,
11
- "selected" | "setSelected"
12
- > & {
13
- name: string;
14
- label?: string;
15
- required?: boolean;
16
- validate?: (value: Date | undefined) => boolean | string;
17
- validationErrorMessage?: string;
18
- rules?: Omit<
19
- RegisterOptions<FieldValues, string>,
20
- "valueAsNumber" | "valueAsDate" | "setValueAs" | "disabled"
21
- >;
22
- allowPastDates?: boolean;
23
- maxYearsFromNow?: number;
24
- };
25
-
26
- export const CalendarFormField = ({
27
- name,
28
- label,
29
- required,
30
- validate,
31
- validationErrorMessage = "Este campo é obrigatório.",
32
- rules,
33
- onChange,
34
- allowPastDates,
35
- maxYearsFromNow = 20,
36
- ...calendarProps
37
- }: CalendarFormFieldProps) => {
38
- const handleValidate = useCallback(
39
- (value?: Date) => {
40
- if (value === undefined || value === null) {
41
- if (required) return validationErrorMessage;
42
- return true;
43
- }
44
- return validate?.(value) ?? true;
45
- },
46
- [validate, required, validationErrorMessage]
47
- );
48
-
49
- const { field, fieldState } = useController({
50
- name,
51
- rules: {
52
- required: required ? validationErrorMessage : false,
53
- validate: handleValidate,
54
- ...rules,
55
- },
56
- defaultValue: undefined,
57
- });
58
-
59
- const fieldError = fieldState.error;
60
- const haveError = !!fieldError;
61
- const errorMsg = fieldError?.message;
62
-
63
- const { value: selected, onChange: setSelected } = field;
64
-
65
- const handleCalendarChange = (date: Date | undefined) => {
66
- setSelected(date);
67
- };
68
-
69
- return (
70
- <Flex direction="column" style={{ flex: "1" }}>
71
- {label && (
72
- <FormLabel
73
- name={name}
74
- label={label}
75
- required={required}
76
- haveError={haveError}
77
- />
78
- )}
79
-
80
- <Calendar
81
- selected={selected}
82
- setSelected={(value) => {
83
- const date = typeof value === "function" ? value(selected) : value;
84
- handleCalendarChange(date);
85
- }}
86
- hasError={haveError}
87
- allowPastDates={allowPastDates}
88
- maxYearsFromNow={maxYearsFromNow}
89
- {...calendarProps}
90
- />
91
-
92
- <ErrorFormMessage message={errorMsg} />
93
- </Flex>
94
- );
95
- };
1
+ import React from "react";
2
+ import { FieldValues, useController, RegisterOptions } from "react-hook-form";
3
+ import { Flex } from "../Flex";
4
+ import { FormLabel } from "./subComponents/FormLabel";
5
+ import { ErrorFormMessage } from "./subComponents/ErrorFormMessage";
6
+ import { Calendar, CalendarProps } from "../Calendar";
7
+ import { useCallback } from "react";
8
+
9
+ export type CalendarFormFieldProps = Omit<
10
+ CalendarProps,
11
+ "selected" | "setSelected"
12
+ > & {
13
+ name: string;
14
+ label?: string;
15
+ required?: boolean;
16
+ validate?: (value: Date | undefined) => boolean | string;
17
+ validationErrorMessage?: string;
18
+ rules?: Omit<
19
+ RegisterOptions<FieldValues, string>,
20
+ "valueAsNumber" | "valueAsDate" | "setValueAs" | "disabled"
21
+ >;
22
+ allowPastDates?: boolean;
23
+ maxYearsFromNow?: number;
24
+ };
25
+
26
+ export const CalendarFormField = ({
27
+ name,
28
+ label,
29
+ required,
30
+ validate,
31
+ validationErrorMessage = "Este campo é obrigatório.",
32
+ rules,
33
+ onChange,
34
+ allowPastDates,
35
+ maxYearsFromNow = 20,
36
+ ...calendarProps
37
+ }: CalendarFormFieldProps) => {
38
+ const handleValidate = useCallback(
39
+ (value?: Date) => {
40
+ if (value === undefined || value === null) {
41
+ if (required) return validationErrorMessage;
42
+ return true;
43
+ }
44
+ return validate?.(value) ?? true;
45
+ },
46
+ [validate, required, validationErrorMessage]
47
+ );
48
+
49
+ const { field, fieldState } = useController({
50
+ name,
51
+ rules: {
52
+ required: required ? validationErrorMessage : false,
53
+ validate: handleValidate,
54
+ ...rules,
55
+ },
56
+ defaultValue: undefined,
57
+ });
58
+
59
+ const fieldError = fieldState.error;
60
+ const haveError = !!fieldError;
61
+ const errorMsg = fieldError?.message;
62
+
63
+ const { value: selected, onChange: setSelected } = field;
64
+
65
+ const handleCalendarChange = (date: Date | undefined) => {
66
+ setSelected(date);
67
+ };
68
+
69
+ return (
70
+ <Flex direction="column" style={{ flex: "1" }}>
71
+ {label && (
72
+ <FormLabel
73
+ name={name}
74
+ label={label}
75
+ required={required}
76
+ haveError={haveError}
77
+ />
78
+ )}
79
+
80
+ <Calendar
81
+ selected={selected}
82
+ setSelected={(value) => {
83
+ const date = typeof value === "function" ? value(selected) : value;
84
+ handleCalendarChange(date);
85
+ }}
86
+ hasError={haveError}
87
+ allowPastDates={allowPastDates}
88
+ maxYearsFromNow={maxYearsFromNow}
89
+ {...calendarProps}
90
+ />
91
+
92
+ <ErrorFormMessage message={errorMsg} />
93
+ </Flex>
94
+ );
95
+ };
@@ -1,91 +1,91 @@
1
- import { Controller, useFormContext } from "react-hook-form";
2
- import { Flex } from "../Flex";
3
- import { FormLabel } from "./subComponents/FormLabel";
4
- import { ErrorFormMessage } from "./subComponents/ErrorFormMessage";
5
- import { CheckboxGroup, CheckboxItem } from "../CheckboxGroup";
6
- import { getNestedValue } from "../../utils/getNestedValue";
7
-
8
- type Option = {
9
- label: string;
10
- value: string;
11
- };
12
-
13
- export type CheckboxGroupFormFieldProps = {
14
- name: string;
15
- label: string;
16
- options: Option[];
17
- required?: boolean;
18
- validationErrorMessage?: string;
19
- defaultValue?: string[];
20
- color?: "blue" | "success" | "error";
21
- fontWeight?: "regular" | "medium" | "semibold" | "bold";
22
- disabled?: boolean;
23
- };
24
-
25
- export const CheckboxGroupFormField = ({
26
- name,
27
- label,
28
- options,
29
- required,
30
- validationErrorMessage = "Selecione pelo menos uma opção.",
31
- defaultValue = [],
32
- color = "blue",
33
- fontWeight = "regular",
34
- disabled = false,
35
- }: CheckboxGroupFormFieldProps) => {
36
- const {
37
- control,
38
- formState: { errors },
39
- } = useFormContext();
40
-
41
- const fieldError = getNestedValue(errors, name);
42
- const haveError = !!fieldError;
43
- const errorMsg = fieldError?.message;
44
-
45
- const validationRules = {
46
- required: required ? validationErrorMessage : false,
47
- validate: required
48
- ? (value: string[]) => value?.length > 0 || validationErrorMessage
49
- : undefined,
50
- };
51
-
52
- return (
53
- <Flex direction="column">
54
- <FormLabel
55
- name={name}
56
- label={label}
57
- required={required}
58
- haveError={haveError}
59
- />
60
-
61
- <Controller
62
- name={name}
63
- control={control}
64
- rules={validationRules}
65
- defaultValue={defaultValue}
66
- render={({ field }) => (
67
- <CheckboxGroup
68
- name={name}
69
- value={field.value}
70
- onValueChange={field.onChange}
71
- color={haveError ? "error" : color}
72
- fontWeight={fontWeight}
73
- disabled={disabled}
74
- >
75
- {options.map((option) => (
76
- <CheckboxItem
77
- key={option.value}
78
- value={option.value}
79
- disabled={disabled}
80
- >
81
- {option.label}
82
- </CheckboxItem>
83
- ))}
84
- </CheckboxGroup>
85
- )}
86
- />
87
-
88
- <ErrorFormMessage message={errorMsg} />
89
- </Flex>
90
- );
91
- };
1
+ import { Controller, useFormContext } from "react-hook-form";
2
+ import { Flex } from "../Flex";
3
+ import { FormLabel } from "./subComponents/FormLabel";
4
+ import { ErrorFormMessage } from "./subComponents/ErrorFormMessage";
5
+ import { CheckboxGroup, CheckboxItem } from "../CheckboxGroup";
6
+ import { getNestedValue } from "../../utils/getNestedValue";
7
+
8
+ type Option = {
9
+ label: string;
10
+ value: string;
11
+ };
12
+
13
+ export type CheckboxGroupFormFieldProps = {
14
+ name: string;
15
+ label: string;
16
+ options: Option[];
17
+ required?: boolean;
18
+ validationErrorMessage?: string;
19
+ defaultValue?: string[];
20
+ color?: "blue" | "success" | "error";
21
+ fontWeight?: "regular" | "medium" | "semibold" | "bold";
22
+ disabled?: boolean;
23
+ };
24
+
25
+ export const CheckboxGroupFormField = ({
26
+ name,
27
+ label,
28
+ options,
29
+ required,
30
+ validationErrorMessage = "Selecione pelo menos uma opção.",
31
+ defaultValue = [],
32
+ color = "blue",
33
+ fontWeight = "regular",
34
+ disabled = false,
35
+ }: CheckboxGroupFormFieldProps) => {
36
+ const {
37
+ control,
38
+ formState: { errors },
39
+ } = useFormContext();
40
+
41
+ const fieldError = getNestedValue(errors, name);
42
+ const haveError = !!fieldError;
43
+ const errorMsg = fieldError?.message;
44
+
45
+ const validationRules = {
46
+ required: required ? validationErrorMessage : false,
47
+ validate: required
48
+ ? (value: string[]) => value?.length > 0 || validationErrorMessage
49
+ : undefined,
50
+ };
51
+
52
+ return (
53
+ <Flex direction="column">
54
+ <FormLabel
55
+ name={name}
56
+ label={label}
57
+ required={required}
58
+ haveError={haveError}
59
+ />
60
+
61
+ <Controller
62
+ name={name}
63
+ control={control}
64
+ rules={validationRules}
65
+ defaultValue={defaultValue}
66
+ render={({ field }) => (
67
+ <CheckboxGroup
68
+ name={name}
69
+ value={field.value}
70
+ onValueChange={field.onChange}
71
+ color={haveError ? "error" : color}
72
+ fontWeight={fontWeight}
73
+ disabled={disabled}
74
+ >
75
+ {options.map((option) => (
76
+ <CheckboxItem
77
+ key={option.value}
78
+ value={option.value}
79
+ disabled={disabled}
80
+ >
81
+ {option.label}
82
+ </CheckboxItem>
83
+ ))}
84
+ </CheckboxGroup>
85
+ )}
86
+ />
87
+
88
+ <ErrorFormMessage message={errorMsg} />
89
+ </Flex>
90
+ );
91
+ };
@@ -0,0 +1,154 @@
1
+ import { FieldValues, useController, RegisterOptions } from "react-hook-form";
2
+ import { Flex } from "../Flex";
3
+ import { FormLabel } from "./subComponents/FormLabel";
4
+ import { ErrorFormMessage } from "./subComponents/ErrorFormMessage";
5
+ import { Calendar, CalendarProps } from "../Calendar";
6
+ import { TimePicker, TimePickerProps } from "../TimePicker";
7
+ import { useCallback, useMemo } from "react";
8
+
9
+ export type DateAndTimeFormFieldProps = Omit<
10
+ CalendarProps,
11
+ "selected" | "setSelected"
12
+ > & Omit<
13
+ TimePickerProps,
14
+ "selected" | "setSelected"
15
+ > & {
16
+ name: string;
17
+ label?: string;
18
+ required?: boolean;
19
+ validate?: (value: string | undefined) => boolean | string;
20
+ validationErrorMessage?: string;
21
+ rules?: Omit<
22
+ RegisterOptions<FieldValues, string>,
23
+ "valueAsNumber" | "valueAsDate" | "setValueAs" | "disabled"
24
+ >;
25
+ allowPastDates?: boolean;
26
+ maxYearsFromNow?: number;
27
+ };
28
+
29
+ export const DateAndTimeFormField = ({
30
+ name,
31
+ label,
32
+ required,
33
+ validate,
34
+ validationErrorMessage = "Este campo é obrigatório.",
35
+ rules,
36
+ allowPastDates,
37
+ maxYearsFromNow = 20,
38
+ ...props
39
+ }: DateAndTimeFormFieldProps) => {
40
+ const handleValidate = useCallback(
41
+ (value?: string) => {
42
+ if (value === undefined || value === null || value === "") {
43
+ if (required) return validationErrorMessage;
44
+ return true;
45
+ }
46
+ return validate?.(value) ?? true;
47
+ },
48
+ [validate, required, validationErrorMessage]
49
+ );
50
+
51
+ const { field, fieldState } = useController({
52
+ name,
53
+ rules: {
54
+ required: required ? validationErrorMessage : false,
55
+ validate: handleValidate,
56
+ ...rules,
57
+ },
58
+ defaultValue: "",
59
+ });
60
+
61
+ const fieldError = fieldState.error;
62
+ const haveError = !!fieldError;
63
+ const errorMsg = fieldError?.message;
64
+
65
+ const { value: isoValue, onChange: setIsoValue } = field;
66
+
67
+ const { selectedDate, selectedTime } = useMemo(() => {
68
+ if (!isoValue) return { selectedDate: undefined, selectedTime: undefined };
69
+
70
+ try {
71
+ const date = new Date(isoValue);
72
+ if (isNaN(date.getTime())) {
73
+ return { selectedDate: undefined, selectedTime: undefined };
74
+ }
75
+
76
+ const hours = String(date.getHours()).padStart(2, "0");
77
+ const minutes = String(date.getMinutes()).padStart(2, "0");
78
+ const time = `${hours}:${minutes}`;
79
+
80
+ return { selectedDate: date, selectedTime: time };
81
+ } catch {
82
+ return { selectedDate: undefined, selectedTime: undefined };
83
+ }
84
+ }, [isoValue]);
85
+
86
+ const combineDateTime = useCallback(
87
+ (date?: Date, time?: string) => {
88
+ if (!date || !time) {
89
+ setIsoValue("");
90
+ return;
91
+ }
92
+
93
+ const [hours, minutes] = time.split(":").map(Number);
94
+ const combined = new Date(date);
95
+ combined.setHours(hours || 0, minutes || 0, 0, 0);
96
+
97
+ setIsoValue(combined.toISOString());
98
+ },
99
+ [setIsoValue]
100
+ );
101
+
102
+ const handleDateChange = (date: Date | undefined) => {
103
+ combineDateTime(date, selectedTime);
104
+ };
105
+
106
+ const handleTimeChange = (time: string | undefined) => {
107
+ combineDateTime(selectedDate, time);
108
+ };
109
+
110
+ return (
111
+ <Flex direction="column">
112
+ {label && (
113
+ <FormLabel
114
+ name={name}
115
+ label={label}
116
+ required={required}
117
+ haveError={haveError}
118
+ />
119
+ )}
120
+
121
+ <Flex gap={12} align="start">
122
+ <Flex direction="column">
123
+ <Calendar
124
+ selected={selectedDate}
125
+ setSelected={(date) => {
126
+ const d = typeof date === "function" ? date(selectedDate) : date;
127
+ handleDateChange(d);
128
+ }}
129
+ hasError={haveError}
130
+ allowPastDates={allowPastDates}
131
+ maxYearsFromNow={maxYearsFromNow}
132
+ {...(props as Omit<CalendarProps, "selected" | "setSelected">)}
133
+ />
134
+ </Flex>
135
+
136
+ <Flex direction="column">
137
+ <TimePicker
138
+ selected={selectedTime}
139
+ setSelected={(value) => {
140
+ const time = typeof value === "function" ? value(selectedTime) : value;
141
+ handleTimeChange(time);
142
+ }}
143
+ hasError={haveError}
144
+ {...(props as Omit<TimePickerProps, "selected" | "setSelected">)}
145
+ />
146
+ </Flex>
147
+ </Flex>
148
+
149
+ <ErrorFormMessage message={errorMsg} />
150
+ </Flex>
151
+ );
152
+ };
153
+
154
+ export default DateAndTimeFormField