@lets-events/react 12.7.3 → 12.8.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.
@@ -1,6 +1,6 @@
1
1
 
2
2
 
3
- > @lets-events/react@12.7.3 build
3
+ > @lets-events/react@12.8.1 build
4
4
  > tsup src/index.tsx --format esm,cjs --dts --external react
5
5
 
6
6
  CLI Building entry: src/index.tsx
@@ -10,12 +10,12 @@
10
10
  CLI Target: es6
11
11
  ESM Build start
12
12
  CJS Build start
13
- CJS dist/index.js 405.05 KB
14
- CJS ⚡️ Build success in 411ms
15
- ESM dist/index.mjs 389.96 KB
16
- ESM ⚡️ Build success in 412ms
13
+ ESM dist/index.mjs 394.44 KB
14
+ ESM ⚡️ Build success in 296ms
15
+ CJS dist/index.js 409.79 KB
16
+ CJS ⚡️ Build success in 296ms
17
17
  DTS Build start
18
- DTS ⚡️ Build success in 7518ms
19
- DTS dist/index.d.mts 403.02 KB
20
- DTS dist/index.d.ts 403.02 KB
18
+ DTS ⚡️ Build success in 6147ms
19
+ DTS dist/index.d.mts 403.74 KB
20
+ DTS dist/index.d.ts 403.74 KB
21
21
  ⠙
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @lets-events/react
2
2
 
3
+ ## 12.8.1
4
+
5
+ ### Patch Changes
6
+
7
+ - TimePicker Initial Value
8
+
9
+ ## 12.8.0
10
+
11
+ ### Minor Changes
12
+
13
+ - DateAndTimeFormField
14
+
3
15
  ## 12.7.3
4
16
 
5
17
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -15351,6 +15351,18 @@ type TimePickerFormFieldProps = Omit<TimePickerProps, "selected" | "setSelected"
15351
15351
  };
15352
15352
  declare const TimePickerFormField: ({ name, label, required, validate, validationErrorMessage, rules, ...timePickerProps }: TimePickerFormFieldProps) => react_jsx_runtime.JSX.Element;
15353
15353
 
15354
+ type DateAndTimeFormFieldProps = Omit<CalendarProps, "selected" | "setSelected"> & Omit<TimePickerProps, "selected" | "setSelected"> & {
15355
+ name: string;
15356
+ label?: string;
15357
+ required?: boolean;
15358
+ validate?: (value: string | undefined) => boolean | string;
15359
+ validationErrorMessage?: string;
15360
+ rules?: Omit<RegisterOptions<FieldValues, string>, "valueAsNumber" | "valueAsDate" | "setValueAs" | "disabled">;
15361
+ allowPastDates?: boolean;
15362
+ maxYearsFromNow?: number;
15363
+ };
15364
+ declare const DateAndTimeFormField: ({ name, label, required, validate, validationErrorMessage, rules, allowPastDates, maxYearsFromNow, ...props }: DateAndTimeFormFieldProps) => react_jsx_runtime.JSX.Element;
15365
+
15354
15366
  interface UploadConfig {
15355
15367
  apiUrl: string;
15356
15368
  s3Bucket: string;
@@ -15405,4 +15417,4 @@ declare const useImageUpload: (options: UseImageUploadOptions) => {
15405
15417
  reset: () => void;
15406
15418
  };
15407
15419
 
15408
- export { AddressFormFields, Alert, AlertDialogCompleteStyled, AlertDialogDescriptionStyled, AlertDialogRowStyled, AlertDialogSimpleStyled, AlertDialogSubtitleStyled, AlertDialogTitleStyled, AlertDialoghrStyled, type AlertProps, Avatar, type AvatarProps, AvatarStyled, Badge, type BadgeProps, BadgeStyled, BirthDateFormField, Box, Button, ButtonGroup, type ButtonGroupProps, ButtonGroupStyled, ButtonItem, type ButtonItemProps, ButtonItemStyled, type ButtonProps, CNPJFormField, CPFFormField, Calendar, CalendarFormField, type CalendarFormFieldProps, type CalendarProps, Card, type CardProps, CardStyled, CheckboxGroup, CheckboxGroupFormField, type CheckboxGroupFormFieldProps, type CheckboxGroupProps, CheckboxGroupStyled, CheckboxItem, type CheckboxItemProps, Container, type ContainerProps, ContainerStyled, CountryFormField, type DateRange, Divider, DoubleCalendar, DoubleCalendarFormField, type DoubleCalendarFormFieldProps, type DoubleCalendarProps, Drawer, type DrawerProps, DropdownMenu, DropdownMenuItem, type DropdownMenuItemProps, type DropdownMenuProps, EmailFormField, type EmailFormFieldProps, ErrorFormMessage, type ErrorFormMessageProps, Filter, FilterItem, type FilterItemProps, type FilterProps, Flex, type FlexProps, FlexStyled, Form, FormLabel, type FormLabelProps, type FormProps, Grid, type GridProps, GridStyled, Icon, type IconProps, IdentityDocumentNumberFormField, InputStyled, MenuDropdown, type MenuDropdownProps, Modal, type ModalProps, MultiSelect, MultiSelectFormField, type MultiSelectFormFieldProps, type MultiSelectProps, PhoneFormField, type PhoneFormFieldProps, RadioGroup, RadioGroupFormField, type RadioGroupFormFieldProps, type RadioGroupProps, RadioGroupStyled, RadioItem, type RadioItemProps, RichEditor, RichEditorFormField, type RichEditorFormFieldProps, type RichEditorProps, RichTextPresenter, Section, type SectionProps, SectionStyled, SelectFormField, type SelectFormFieldProps, Step, StepContent, StepList, type StepProps, StepStyled, StepTrigger, StepWrapper, Switch, SwitchFormField, type SwitchFormFieldProps, type SwitchProps, SwitchStyled, Text, TextAreaFormField, type TextAreaFormFieldProps, TextField, type TextFieldProps, TextFieldSlot, type TextFieldSlotProps, TextFieldSlotStyled, TextFieldStyled, TextFormField, type TextFormFieldProps, type TextProps, TextStyle, TextareaField, type TextareaFieldProps, TextareaFieldStyle, TimePicker, TimePickerButtonStyled, TimePickerDropdownStyled, TimePickerFooterStyled, TimePickerFormField, type TimePickerFormFieldProps, TimePickerIconButton, type TimePickerProps, TimePickerStyled, TimerPickerContentStyled, type Toast, type ToastComponentProps, type ToastConfig, type ToastContextType, ToastItem, type ToastOptions, ToastProvider, type ToastProviderProps, type ToastType, type ToasterShowOptions, Tooltip, TooltipContent, type TooltipProps, TooltipProvider, TooltipRoot, TooltipTrigger, type UploadConfig, UploadService, isValidCNPJ, maskFormat, maskUnformat, useImageUpload, useToast };
15420
+ export { AddressFormFields, Alert, AlertDialogCompleteStyled, AlertDialogDescriptionStyled, AlertDialogRowStyled, AlertDialogSimpleStyled, AlertDialogSubtitleStyled, AlertDialogTitleStyled, AlertDialoghrStyled, type AlertProps, Avatar, type AvatarProps, AvatarStyled, Badge, type BadgeProps, BadgeStyled, BirthDateFormField, Box, Button, ButtonGroup, type ButtonGroupProps, ButtonGroupStyled, ButtonItem, type ButtonItemProps, ButtonItemStyled, type ButtonProps, CNPJFormField, CPFFormField, Calendar, CalendarFormField, type CalendarFormFieldProps, type CalendarProps, Card, type CardProps, CardStyled, CheckboxGroup, CheckboxGroupFormField, type CheckboxGroupFormFieldProps, type CheckboxGroupProps, CheckboxGroupStyled, CheckboxItem, type CheckboxItemProps, Container, type ContainerProps, ContainerStyled, CountryFormField, DateAndTimeFormField, type DateAndTimeFormFieldProps, type DateRange, Divider, DoubleCalendar, DoubleCalendarFormField, type DoubleCalendarFormFieldProps, type DoubleCalendarProps, Drawer, type DrawerProps, DropdownMenu, DropdownMenuItem, type DropdownMenuItemProps, type DropdownMenuProps, EmailFormField, type EmailFormFieldProps, ErrorFormMessage, type ErrorFormMessageProps, Filter, FilterItem, type FilterItemProps, type FilterProps, Flex, type FlexProps, FlexStyled, Form, FormLabel, type FormLabelProps, type FormProps, Grid, type GridProps, GridStyled, Icon, type IconProps, IdentityDocumentNumberFormField, InputStyled, MenuDropdown, type MenuDropdownProps, Modal, type ModalProps, MultiSelect, MultiSelectFormField, type MultiSelectFormFieldProps, type MultiSelectProps, PhoneFormField, type PhoneFormFieldProps, RadioGroup, RadioGroupFormField, type RadioGroupFormFieldProps, type RadioGroupProps, RadioGroupStyled, RadioItem, type RadioItemProps, RichEditor, RichEditorFormField, type RichEditorFormFieldProps, type RichEditorProps, RichTextPresenter, Section, type SectionProps, SectionStyled, SelectFormField, type SelectFormFieldProps, Step, StepContent, StepList, type StepProps, StepStyled, StepTrigger, StepWrapper, Switch, SwitchFormField, type SwitchFormFieldProps, type SwitchProps, SwitchStyled, Text, TextAreaFormField, type TextAreaFormFieldProps, TextField, type TextFieldProps, TextFieldSlot, type TextFieldSlotProps, TextFieldSlotStyled, TextFieldStyled, TextFormField, type TextFormFieldProps, type TextProps, TextStyle, TextareaField, type TextareaFieldProps, TextareaFieldStyle, TimePicker, TimePickerButtonStyled, TimePickerDropdownStyled, TimePickerFooterStyled, TimePickerFormField, type TimePickerFormFieldProps, TimePickerIconButton, type TimePickerProps, TimePickerStyled, TimerPickerContentStyled, type Toast, type ToastComponentProps, type ToastConfig, type ToastContextType, ToastItem, type ToastOptions, ToastProvider, type ToastProviderProps, type ToastType, type ToasterShowOptions, Tooltip, TooltipContent, type TooltipProps, TooltipProvider, TooltipRoot, TooltipTrigger, type UploadConfig, UploadService, isValidCNPJ, maskFormat, maskUnformat, useImageUpload, useToast };
package/dist/index.d.ts CHANGED
@@ -15351,6 +15351,18 @@ type TimePickerFormFieldProps = Omit<TimePickerProps, "selected" | "setSelected"
15351
15351
  };
15352
15352
  declare const TimePickerFormField: ({ name, label, required, validate, validationErrorMessage, rules, ...timePickerProps }: TimePickerFormFieldProps) => react_jsx_runtime.JSX.Element;
15353
15353
 
15354
+ type DateAndTimeFormFieldProps = Omit<CalendarProps, "selected" | "setSelected"> & Omit<TimePickerProps, "selected" | "setSelected"> & {
15355
+ name: string;
15356
+ label?: string;
15357
+ required?: boolean;
15358
+ validate?: (value: string | undefined) => boolean | string;
15359
+ validationErrorMessage?: string;
15360
+ rules?: Omit<RegisterOptions<FieldValues, string>, "valueAsNumber" | "valueAsDate" | "setValueAs" | "disabled">;
15361
+ allowPastDates?: boolean;
15362
+ maxYearsFromNow?: number;
15363
+ };
15364
+ declare const DateAndTimeFormField: ({ name, label, required, validate, validationErrorMessage, rules, allowPastDates, maxYearsFromNow, ...props }: DateAndTimeFormFieldProps) => react_jsx_runtime.JSX.Element;
15365
+
15354
15366
  interface UploadConfig {
15355
15367
  apiUrl: string;
15356
15368
  s3Bucket: string;
@@ -15405,4 +15417,4 @@ declare const useImageUpload: (options: UseImageUploadOptions) => {
15405
15417
  reset: () => void;
15406
15418
  };
15407
15419
 
15408
- export { AddressFormFields, Alert, AlertDialogCompleteStyled, AlertDialogDescriptionStyled, AlertDialogRowStyled, AlertDialogSimpleStyled, AlertDialogSubtitleStyled, AlertDialogTitleStyled, AlertDialoghrStyled, type AlertProps, Avatar, type AvatarProps, AvatarStyled, Badge, type BadgeProps, BadgeStyled, BirthDateFormField, Box, Button, ButtonGroup, type ButtonGroupProps, ButtonGroupStyled, ButtonItem, type ButtonItemProps, ButtonItemStyled, type ButtonProps, CNPJFormField, CPFFormField, Calendar, CalendarFormField, type CalendarFormFieldProps, type CalendarProps, Card, type CardProps, CardStyled, CheckboxGroup, CheckboxGroupFormField, type CheckboxGroupFormFieldProps, type CheckboxGroupProps, CheckboxGroupStyled, CheckboxItem, type CheckboxItemProps, Container, type ContainerProps, ContainerStyled, CountryFormField, type DateRange, Divider, DoubleCalendar, DoubleCalendarFormField, type DoubleCalendarFormFieldProps, type DoubleCalendarProps, Drawer, type DrawerProps, DropdownMenu, DropdownMenuItem, type DropdownMenuItemProps, type DropdownMenuProps, EmailFormField, type EmailFormFieldProps, ErrorFormMessage, type ErrorFormMessageProps, Filter, FilterItem, type FilterItemProps, type FilterProps, Flex, type FlexProps, FlexStyled, Form, FormLabel, type FormLabelProps, type FormProps, Grid, type GridProps, GridStyled, Icon, type IconProps, IdentityDocumentNumberFormField, InputStyled, MenuDropdown, type MenuDropdownProps, Modal, type ModalProps, MultiSelect, MultiSelectFormField, type MultiSelectFormFieldProps, type MultiSelectProps, PhoneFormField, type PhoneFormFieldProps, RadioGroup, RadioGroupFormField, type RadioGroupFormFieldProps, type RadioGroupProps, RadioGroupStyled, RadioItem, type RadioItemProps, RichEditor, RichEditorFormField, type RichEditorFormFieldProps, type RichEditorProps, RichTextPresenter, Section, type SectionProps, SectionStyled, SelectFormField, type SelectFormFieldProps, Step, StepContent, StepList, type StepProps, StepStyled, StepTrigger, StepWrapper, Switch, SwitchFormField, type SwitchFormFieldProps, type SwitchProps, SwitchStyled, Text, TextAreaFormField, type TextAreaFormFieldProps, TextField, type TextFieldProps, TextFieldSlot, type TextFieldSlotProps, TextFieldSlotStyled, TextFieldStyled, TextFormField, type TextFormFieldProps, type TextProps, TextStyle, TextareaField, type TextareaFieldProps, TextareaFieldStyle, TimePicker, TimePickerButtonStyled, TimePickerDropdownStyled, TimePickerFooterStyled, TimePickerFormField, type TimePickerFormFieldProps, TimePickerIconButton, type TimePickerProps, TimePickerStyled, TimerPickerContentStyled, type Toast, type ToastComponentProps, type ToastConfig, type ToastContextType, ToastItem, type ToastOptions, ToastProvider, type ToastProviderProps, type ToastType, type ToasterShowOptions, Tooltip, TooltipContent, type TooltipProps, TooltipProvider, TooltipRoot, TooltipTrigger, type UploadConfig, UploadService, isValidCNPJ, maskFormat, maskUnformat, useImageUpload, useToast };
15420
+ export { AddressFormFields, Alert, AlertDialogCompleteStyled, AlertDialogDescriptionStyled, AlertDialogRowStyled, AlertDialogSimpleStyled, AlertDialogSubtitleStyled, AlertDialogTitleStyled, AlertDialoghrStyled, type AlertProps, Avatar, type AvatarProps, AvatarStyled, Badge, type BadgeProps, BadgeStyled, BirthDateFormField, Box, Button, ButtonGroup, type ButtonGroupProps, ButtonGroupStyled, ButtonItem, type ButtonItemProps, ButtonItemStyled, type ButtonProps, CNPJFormField, CPFFormField, Calendar, CalendarFormField, type CalendarFormFieldProps, type CalendarProps, Card, type CardProps, CardStyled, CheckboxGroup, CheckboxGroupFormField, type CheckboxGroupFormFieldProps, type CheckboxGroupProps, CheckboxGroupStyled, CheckboxItem, type CheckboxItemProps, Container, type ContainerProps, ContainerStyled, CountryFormField, DateAndTimeFormField, type DateAndTimeFormFieldProps, type DateRange, Divider, DoubleCalendar, DoubleCalendarFormField, type DoubleCalendarFormFieldProps, type DoubleCalendarProps, Drawer, type DrawerProps, DropdownMenu, DropdownMenuItem, type DropdownMenuItemProps, type DropdownMenuProps, EmailFormField, type EmailFormFieldProps, ErrorFormMessage, type ErrorFormMessageProps, Filter, FilterItem, type FilterItemProps, type FilterProps, Flex, type FlexProps, FlexStyled, Form, FormLabel, type FormLabelProps, type FormProps, Grid, type GridProps, GridStyled, Icon, type IconProps, IdentityDocumentNumberFormField, InputStyled, MenuDropdown, type MenuDropdownProps, Modal, type ModalProps, MultiSelect, MultiSelectFormField, type MultiSelectFormFieldProps, type MultiSelectProps, PhoneFormField, type PhoneFormFieldProps, RadioGroup, RadioGroupFormField, type RadioGroupFormFieldProps, type RadioGroupProps, RadioGroupStyled, RadioItem, type RadioItemProps, RichEditor, RichEditorFormField, type RichEditorFormFieldProps, type RichEditorProps, RichTextPresenter, Section, type SectionProps, SectionStyled, SelectFormField, type SelectFormFieldProps, Step, StepContent, StepList, type StepProps, StepStyled, StepTrigger, StepWrapper, Switch, SwitchFormField, type SwitchFormFieldProps, type SwitchProps, SwitchStyled, Text, TextAreaFormField, type TextAreaFormFieldProps, TextField, type TextFieldProps, TextFieldSlot, type TextFieldSlotProps, TextFieldSlotStyled, TextFieldStyled, TextFormField, type TextFormFieldProps, type TextProps, TextStyle, TextareaField, type TextareaFieldProps, TextareaFieldStyle, TimePicker, TimePickerButtonStyled, TimePickerDropdownStyled, TimePickerFooterStyled, TimePickerFormField, type TimePickerFormFieldProps, TimePickerIconButton, type TimePickerProps, TimePickerStyled, TimerPickerContentStyled, type Toast, type ToastComponentProps, type ToastConfig, type ToastContextType, ToastItem, type ToastOptions, ToastProvider, type ToastProviderProps, type ToastType, type ToasterShowOptions, Tooltip, TooltipContent, type TooltipProps, TooltipProvider, TooltipRoot, TooltipTrigger, type UploadConfig, UploadService, isValidCNPJ, maskFormat, maskUnformat, useImageUpload, useToast };
package/dist/index.js CHANGED
@@ -895,6 +895,7 @@ __export(index_exports, {
895
895
  Container: () => Container,
896
896
  ContainerStyled: () => ContainerStyled,
897
897
  CountryFormField: () => CountryFormField,
898
+ DateAndTimeFormField: () => DateAndTimeFormField,
898
899
  Divider: () => Divider,
899
900
  DoubleCalendar: () => DoubleCalendar,
900
901
  DoubleCalendarFormField: () => DoubleCalendarFormField,
@@ -7939,7 +7940,8 @@ var DayPickerWrapperStyled = styled("div", {
7939
7940
  },
7940
7941
  ".rdp-nav": {
7941
7942
  position: "absolute",
7942
- width: "98%",
7943
+ width: "100%",
7944
+ left: "0",
7943
7945
  display: "flex",
7944
7946
  justifyContent: "space-between"
7945
7947
  },
@@ -8614,6 +8616,21 @@ var TimePickerIconButton = styled(Button, {
8614
8616
  padding: "0 !important"
8615
8617
  });
8616
8618
  var pad = (num) => String(num).padStart(2, "0");
8619
+ var parseTime = (value) => {
8620
+ if (!value) {
8621
+ return {
8622
+ parsedHours: "00",
8623
+ parsedMinutes: "00"
8624
+ };
8625
+ }
8626
+ const [hours, minutes] = value.split(":");
8627
+ const nextHours = Math.min(Math.max(parseInt(hours || "0", 10), 0), 23);
8628
+ const nextMinutes = Math.min(Math.max(parseInt(minutes || "0", 10), 0), 59);
8629
+ return {
8630
+ parsedHours: Number.isNaN(nextHours) ? "00" : pad(nextHours),
8631
+ parsedMinutes: Number.isNaN(nextMinutes) ? "00" : pad(nextMinutes)
8632
+ };
8633
+ };
8617
8634
  function TimePicker({
8618
8635
  selected,
8619
8636
  setSelected,
@@ -8628,6 +8645,13 @@ function TimePicker({
8628
8645
  const [isOpen, setIsOpen] = (0, import_react11.useState)(false);
8629
8646
  const dropdownRef = (0, import_react11.useRef)(null);
8630
8647
  useOnClickOutside(dropdownRef, () => setIsOpen(false));
8648
+ (0, import_react11.useEffect)(() => {
8649
+ const { parsedHours, parsedMinutes } = parseTime(selected);
8650
+ setHours(parsedHours);
8651
+ setMinutes(parsedMinutes);
8652
+ setRawHours(parsedHours);
8653
+ setRawMinutes(parsedMinutes);
8654
+ }, [selected]);
8631
8655
  const handleIncrement = (0, import_react11.useCallback)(
8632
8656
  (type) => {
8633
8657
  if (type === "hours") {
@@ -13250,12 +13274,133 @@ var TimePickerFormField = (_a) => {
13250
13274
  ] });
13251
13275
  };
13252
13276
 
13253
- // src/hooks/useImageUpload.ts
13277
+ // src/components/FormFields/DateAndTimeFormField.tsx
13278
+ var import_react_hook_form16 = require("react-hook-form");
13254
13279
  var import_react28 = require("react");
13280
+ var import_jsx_runtime59 = require("react/jsx-runtime");
13281
+ var DateAndTimeFormField = (_a) => {
13282
+ var _b = _a, {
13283
+ name,
13284
+ label,
13285
+ required,
13286
+ validate,
13287
+ validationErrorMessage = "Este campo \xE9 obrigat\xF3rio.",
13288
+ rules,
13289
+ allowPastDates,
13290
+ maxYearsFromNow = 20
13291
+ } = _b, props = __objRest(_b, [
13292
+ "name",
13293
+ "label",
13294
+ "required",
13295
+ "validate",
13296
+ "validationErrorMessage",
13297
+ "rules",
13298
+ "allowPastDates",
13299
+ "maxYearsFromNow"
13300
+ ]);
13301
+ const handleValidate = (0, import_react28.useCallback)(
13302
+ (value) => {
13303
+ var _a2;
13304
+ if (value === void 0 || value === null || value === "") {
13305
+ if (required) return validationErrorMessage;
13306
+ return true;
13307
+ }
13308
+ return (_a2 = validate == null ? void 0 : validate(value)) != null ? _a2 : true;
13309
+ },
13310
+ [validate, required, validationErrorMessage]
13311
+ );
13312
+ const { field, fieldState } = (0, import_react_hook_form16.useController)({
13313
+ name,
13314
+ rules: __spreadValues({
13315
+ required: required ? validationErrorMessage : false,
13316
+ validate: handleValidate
13317
+ }, rules),
13318
+ defaultValue: ""
13319
+ });
13320
+ const fieldError = fieldState.error;
13321
+ const haveError = !!fieldError;
13322
+ const errorMsg = fieldError == null ? void 0 : fieldError.message;
13323
+ const { value: isoValue, onChange: setIsoValue } = field;
13324
+ const { selectedDate, selectedTime } = (0, import_react28.useMemo)(() => {
13325
+ if (!isoValue) return { selectedDate: void 0, selectedTime: void 0 };
13326
+ try {
13327
+ const date = new Date(isoValue);
13328
+ if (isNaN(date.getTime())) {
13329
+ return { selectedDate: void 0, selectedTime: void 0 };
13330
+ }
13331
+ const hours = String(date.getHours()).padStart(2, "0");
13332
+ const minutes = String(date.getMinutes()).padStart(2, "0");
13333
+ const time = `${hours}:${minutes}`;
13334
+ return { selectedDate: date, selectedTime: time };
13335
+ } catch (e) {
13336
+ return { selectedDate: void 0, selectedTime: void 0 };
13337
+ }
13338
+ }, [isoValue]);
13339
+ const combineDateTime = (0, import_react28.useCallback)(
13340
+ (date, time) => {
13341
+ if (!date || !time) {
13342
+ setIsoValue("");
13343
+ return;
13344
+ }
13345
+ const [hours, minutes] = time.split(":").map(Number);
13346
+ const combined = new Date(date);
13347
+ combined.setHours(hours || 0, minutes || 0, 0, 0);
13348
+ setIsoValue(combined.toISOString());
13349
+ },
13350
+ [setIsoValue]
13351
+ );
13352
+ const handleDateChange = (date) => {
13353
+ combineDateTime(date, selectedTime);
13354
+ };
13355
+ const handleTimeChange = (time) => {
13356
+ combineDateTime(selectedDate, time);
13357
+ };
13358
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(Flex, { direction: "column", children: [
13359
+ label && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
13360
+ FormLabel,
13361
+ {
13362
+ name,
13363
+ label,
13364
+ required,
13365
+ haveError
13366
+ }
13367
+ ),
13368
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(Flex, { gap: 12, align: "start", children: [
13369
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Flex, { direction: "column", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
13370
+ Calendar,
13371
+ __spreadValues({
13372
+ selected: selectedDate,
13373
+ setSelected: (date) => {
13374
+ const d = typeof date === "function" ? date(selectedDate) : date;
13375
+ handleDateChange(d);
13376
+ },
13377
+ hasError: haveError,
13378
+ allowPastDates,
13379
+ maxYearsFromNow
13380
+ }, props)
13381
+ ) }),
13382
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Flex, { direction: "column", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
13383
+ TimePicker,
13384
+ __spreadValues({
13385
+ selected: selectedTime,
13386
+ setSelected: (value) => {
13387
+ const time = typeof value === "function" ? value(selectedTime) : value;
13388
+ handleTimeChange(time);
13389
+ },
13390
+ hasError: haveError
13391
+ }, props)
13392
+ ) })
13393
+ ] }),
13394
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(ErrorFormMessage, { message: errorMsg })
13395
+ ] });
13396
+ };
13397
+
13398
+ // src/hooks/useImageUpload.ts
13399
+ var import_react29 = require("react");
13255
13400
  var useImageUpload = (options) => {
13256
- const [isUploading, setIsUploading] = (0, import_react28.useState)(false);
13257
- const [progress, setProgress] = (0, import_react28.useState)(null);
13258
- const [error, setError] = (0, import_react28.useState)(null);
13401
+ const [isUploading, setIsUploading] = (0, import_react29.useState)(false);
13402
+ const [progress, setProgress] = (0, import_react29.useState)(null);
13403
+ const [error, setError] = (0, import_react29.useState)(null);
13259
13404
  const {
13260
13405
  onSuccess,
13261
13406
  onError,
@@ -13265,7 +13410,7 @@ var useImageUpload = (options) => {
13265
13410
  allowedTypes = ["image/jpeg", "image/png", "image/gif", "image/webp"],
13266
13411
  uploadConfig
13267
13412
  } = options;
13268
- const validateFile = (0, import_react28.useCallback)(
13413
+ const validateFile = (0, import_react29.useCallback)(
13269
13414
  (file) => {
13270
13415
  if (!allowedTypes.includes(file.type)) {
13271
13416
  const errorMsg = "Tipo de arquivo n\xE3o suportado";
@@ -13283,7 +13428,7 @@ var useImageUpload = (options) => {
13283
13428
  },
13284
13429
  [allowedTypes, maxFileSize, onError]
13285
13430
  );
13286
- const uploadFile = (0, import_react28.useCallback)(
13431
+ const uploadFile = (0, import_react29.useCallback)(
13287
13432
  (file) => __async(null, null, function* () {
13288
13433
  if (!validateFile(file)) {
13289
13434
  return null;
@@ -13336,7 +13481,7 @@ var useImageUpload = (options) => {
13336
13481
  }),
13337
13482
  [validateFile, onSuccess, onError, onProgress]
13338
13483
  );
13339
- const reset = (0, import_react28.useCallback)(() => {
13484
+ const reset = (0, import_react29.useCallback)(() => {
13340
13485
  setIsUploading(false);
13341
13486
  setProgress(null);
13342
13487
  setError(null);
@@ -13384,6 +13529,7 @@ var useImageUpload = (options) => {
13384
13529
  Container,
13385
13530
  ContainerStyled,
13386
13531
  CountryFormField,
13532
+ DateAndTimeFormField,
13387
13533
  Divider,
13388
13534
  DoubleCalendar,
13389
13535
  DoubleCalendarFormField,
package/dist/index.mjs CHANGED
@@ -7824,7 +7824,8 @@ var DayPickerWrapperStyled = styled("div", {
7824
7824
  },
7825
7825
  ".rdp-nav": {
7826
7826
  position: "absolute",
7827
- width: "98%",
7827
+ width: "100%",
7828
+ left: "0",
7828
7829
  display: "flex",
7829
7830
  justifyContent: "space-between"
7830
7831
  },
@@ -8383,7 +8384,7 @@ function Drawer({
8383
8384
  }
8384
8385
 
8385
8386
  // src/components/TimePicker.tsx
8386
- import { useCallback, useRef as useRef6, useState as useState4 } from "react";
8387
+ import { useCallback, useEffect as useEffect6, useRef as useRef6, useState as useState4 } from "react";
8387
8388
  import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
8388
8389
  var TimePickerStyled = styled("div", {
8389
8390
  position: "relative",
@@ -8499,6 +8500,21 @@ var TimePickerIconButton = styled(Button, {
8499
8500
  padding: "0 !important"
8500
8501
  });
8501
8502
  var pad = (num) => String(num).padStart(2, "0");
8503
+ var parseTime = (value) => {
8504
+ if (!value) {
8505
+ return {
8506
+ parsedHours: "00",
8507
+ parsedMinutes: "00"
8508
+ };
8509
+ }
8510
+ const [hours, minutes] = value.split(":");
8511
+ const nextHours = Math.min(Math.max(parseInt(hours || "0", 10), 0), 23);
8512
+ const nextMinutes = Math.min(Math.max(parseInt(minutes || "0", 10), 0), 59);
8513
+ return {
8514
+ parsedHours: Number.isNaN(nextHours) ? "00" : pad(nextHours),
8515
+ parsedMinutes: Number.isNaN(nextMinutes) ? "00" : pad(nextMinutes)
8516
+ };
8517
+ };
8502
8518
  function TimePicker({
8503
8519
  selected,
8504
8520
  setSelected,
@@ -8513,6 +8529,13 @@ function TimePicker({
8513
8529
  const [isOpen, setIsOpen] = useState4(false);
8514
8530
  const dropdownRef = useRef6(null);
8515
8531
  useOnClickOutside(dropdownRef, () => setIsOpen(false));
8532
+ useEffect6(() => {
8533
+ const { parsedHours, parsedMinutes } = parseTime(selected);
8534
+ setHours(parsedHours);
8535
+ setMinutes(parsedMinutes);
8536
+ setRawHours(parsedHours);
8537
+ setRawMinutes(parsedMinutes);
8538
+ }, [selected]);
8516
8539
  const handleIncrement = useCallback(
8517
8540
  (type) => {
8518
8541
  if (type === "hours") {
@@ -9246,7 +9269,7 @@ function Card(_a) {
9246
9269
 
9247
9270
  // src/components/TextareaField.tsx
9248
9271
  import { TextArea as TextAreaRadix } from "@radix-ui/themes";
9249
- import React9, { useRef as useRef7, useState as useState5, useEffect as useEffect6 } from "react";
9272
+ import React9, { useRef as useRef7, useState as useState5, useEffect as useEffect7 } from "react";
9250
9273
  import { jsx as jsx23, jsxs as jsxs12 } from "react/jsx-runtime";
9251
9274
  var TextareaFieldStyle = styled(TextAreaRadix, {
9252
9275
  display: "flex",
@@ -9301,7 +9324,7 @@ var TextareaField = React9.forwardRef((_a, forwardedRef) => {
9301
9324
  var _b = _a, { maxLength, color, top = "-1.75rem" } = _b, props = __objRest(_b, ["maxLength", "color", "top"]);
9302
9325
  const inputRef = useRef7(null);
9303
9326
  const [remaining, setRemaining] = useState5(maxLength);
9304
- useEffect6(() => {
9327
+ useEffect7(() => {
9305
9328
  var _a2;
9306
9329
  if (maxLength && inputRef.current) {
9307
9330
  setRemaining(maxLength - ((_a2 = inputRef.current.value.length) != null ? _a2 : 0));
@@ -10937,7 +10960,7 @@ function StateFormField({
10937
10960
  }
10938
10961
 
10939
10962
  // src/components/FormFields/AddressFormFields/CityFormField.tsx
10940
- import { useEffect as useEffect7, useState as useState9 } from "react";
10963
+ import { useEffect as useEffect8, useState as useState9 } from "react";
10941
10964
  import { useFormContext as useFormContext5, Controller as Controller2 } from "react-hook-form";
10942
10965
  import { Fragment as Fragment4, jsx as jsx46 } from "react/jsx-runtime";
10943
10966
  function CityFormField({
@@ -10952,7 +10975,7 @@ function CityFormField({
10952
10975
  const selectedState = watch(stateName);
10953
10976
  const [cities, setCities] = useState9([]);
10954
10977
  const [loading, setLoading] = useState9(false);
10955
- useEffect7(() => {
10978
+ useEffect8(() => {
10956
10979
  if (!isBrazil) {
10957
10980
  setCities([]);
10958
10981
  return;
@@ -11337,10 +11360,10 @@ var EmailFormField = ({
11337
11360
  import { useController as useController3 } from "react-hook-form";
11338
11361
 
11339
11362
  // src/components/RichEditor/RichEditor.tsx
11340
- import { useEffect as useEffect9, useState as useState11 } from "react";
11363
+ import { useEffect as useEffect10, useState as useState11 } from "react";
11341
11364
 
11342
11365
  // src/components/RichEditor/QuillComponent.tsx
11343
- import { useState as useState10, useRef as useRef9, useEffect as useEffect8, useCallback as useCallback4 } from "react";
11366
+ import { useState as useState10, useRef as useRef9, useEffect as useEffect9, useCallback as useCallback4 } from "react";
11344
11367
  import { useQuill } from "react-quilljs";
11345
11368
 
11346
11369
  // src/utils/uploadService.ts
@@ -12520,7 +12543,7 @@ var QuillComponent = ({
12520
12543
  }),
12521
12544
  [disabled, quill, addToast, removeToast, uploadConfig, onChange]
12522
12545
  );
12523
- useEffect8(() => {
12546
+ useEffect9(() => {
12524
12547
  if (quill && value) {
12525
12548
  const currentContent = quill.root.innerHTML;
12526
12549
  if (currentContent !== value) {
@@ -12534,7 +12557,7 @@ var QuillComponent = ({
12534
12557
  }
12535
12558
  }
12536
12559
  }, [quill, value]);
12537
- useEffect8(() => {
12560
+ useEffect9(() => {
12538
12561
  if (quill) {
12539
12562
  quill.on("text-change", (delta, oldDelta, source) => {
12540
12563
  if (source === "user") {
@@ -12589,7 +12612,7 @@ var QuillComponent = ({
12589
12612
  }, 2e3);
12590
12613
  }
12591
12614
  }, [quill, onChange, handleImageUpload, onCharacterCountChange]);
12592
- useEffect8(() => {
12615
+ useEffect9(() => {
12593
12616
  if (quill) {
12594
12617
  quill.enable(!disabled);
12595
12618
  if (!disabled) {
@@ -12656,7 +12679,7 @@ var QuillComponent = ({
12656
12679
  setVideoUrl("");
12657
12680
  setShowVideoModal(false);
12658
12681
  }, [videoUrl, quill]);
12659
- useEffect8(() => {
12682
+ useEffect9(() => {
12660
12683
  const handleClickOutside = (event) => {
12661
12684
  if (showVideoModal && videoModalRef.current && !videoModalRef.current.contains(event.target)) {
12662
12685
  handleVideoCancel();
@@ -12819,7 +12842,7 @@ var QuillComponent_default = QuillComponent;
12819
12842
  import { jsx as jsx53 } from "react/jsx-runtime";
12820
12843
  var RichEditor = (props) => {
12821
12844
  const [isClient, setIsClient] = useState11(false);
12822
- useEffect9(() => {
12845
+ useEffect10(() => {
12823
12846
  setIsClient(typeof window !== "undefined");
12824
12847
  }, []);
12825
12848
  if (!isClient) return null;
@@ -13144,8 +13167,129 @@ var TimePickerFormField = (_a) => {
13144
13167
  ] });
13145
13168
  };
13146
13169
 
13170
+ // src/components/FormFields/DateAndTimeFormField.tsx
13171
+ import { useController as useController7 } from "react-hook-form";
13172
+ import { useCallback as useCallback8, useMemo as useMemo4 } from "react";
13173
+ import { jsx as jsx59, jsxs as jsxs33 } from "react/jsx-runtime";
13174
+ var DateAndTimeFormField = (_a) => {
13175
+ var _b = _a, {
13176
+ name,
13177
+ label,
13178
+ required,
13179
+ validate,
13180
+ validationErrorMessage = "Este campo \xE9 obrigat\xF3rio.",
13181
+ rules,
13182
+ allowPastDates,
13183
+ maxYearsFromNow = 20
13184
+ } = _b, props = __objRest(_b, [
13185
+ "name",
13186
+ "label",
13187
+ "required",
13188
+ "validate",
13189
+ "validationErrorMessage",
13190
+ "rules",
13191
+ "allowPastDates",
13192
+ "maxYearsFromNow"
13193
+ ]);
13194
+ const handleValidate = useCallback8(
13195
+ (value) => {
13196
+ var _a2;
13197
+ if (value === void 0 || value === null || value === "") {
13198
+ if (required) return validationErrorMessage;
13199
+ return true;
13200
+ }
13201
+ return (_a2 = validate == null ? void 0 : validate(value)) != null ? _a2 : true;
13202
+ },
13203
+ [validate, required, validationErrorMessage]
13204
+ );
13205
+ const { field, fieldState } = useController7({
13206
+ name,
13207
+ rules: __spreadValues({
13208
+ required: required ? validationErrorMessage : false,
13209
+ validate: handleValidate
13210
+ }, rules),
13211
+ defaultValue: ""
13212
+ });
13213
+ const fieldError = fieldState.error;
13214
+ const haveError = !!fieldError;
13215
+ const errorMsg = fieldError == null ? void 0 : fieldError.message;
13216
+ const { value: isoValue, onChange: setIsoValue } = field;
13217
+ const { selectedDate, selectedTime } = useMemo4(() => {
13218
+ if (!isoValue) return { selectedDate: void 0, selectedTime: void 0 };
13219
+ try {
13220
+ const date = new Date(isoValue);
13221
+ if (isNaN(date.getTime())) {
13222
+ return { selectedDate: void 0, selectedTime: void 0 };
13223
+ }
13224
+ const hours = String(date.getHours()).padStart(2, "0");
13225
+ const minutes = String(date.getMinutes()).padStart(2, "0");
13226
+ const time = `${hours}:${minutes}`;
13227
+ return { selectedDate: date, selectedTime: time };
13228
+ } catch (e) {
13229
+ return { selectedDate: void 0, selectedTime: void 0 };
13230
+ }
13231
+ }, [isoValue]);
13232
+ const combineDateTime = useCallback8(
13233
+ (date, time) => {
13234
+ if (!date || !time) {
13235
+ setIsoValue("");
13236
+ return;
13237
+ }
13238
+ const [hours, minutes] = time.split(":").map(Number);
13239
+ const combined = new Date(date);
13240
+ combined.setHours(hours || 0, minutes || 0, 0, 0);
13241
+ setIsoValue(combined.toISOString());
13242
+ },
13243
+ [setIsoValue]
13244
+ );
13245
+ const handleDateChange = (date) => {
13246
+ combineDateTime(date, selectedTime);
13247
+ };
13248
+ const handleTimeChange = (time) => {
13249
+ combineDateTime(selectedDate, time);
13250
+ };
13251
+ return /* @__PURE__ */ jsxs33(Flex, { direction: "column", children: [
13252
+ label && /* @__PURE__ */ jsx59(
13253
+ FormLabel,
13254
+ {
13255
+ name,
13256
+ label,
13257
+ required,
13258
+ haveError
13259
+ }
13260
+ ),
13261
+ /* @__PURE__ */ jsxs33(Flex, { gap: 12, align: "start", children: [
13262
+ /* @__PURE__ */ jsx59(Flex, { direction: "column", children: /* @__PURE__ */ jsx59(
13263
+ Calendar,
13264
+ __spreadValues({
13265
+ selected: selectedDate,
13266
+ setSelected: (date) => {
13267
+ const d = typeof date === "function" ? date(selectedDate) : date;
13268
+ handleDateChange(d);
13269
+ },
13270
+ hasError: haveError,
13271
+ allowPastDates,
13272
+ maxYearsFromNow
13273
+ }, props)
13274
+ ) }),
13275
+ /* @__PURE__ */ jsx59(Flex, { direction: "column", children: /* @__PURE__ */ jsx59(
13276
+ TimePicker,
13277
+ __spreadValues({
13278
+ selected: selectedTime,
13279
+ setSelected: (value) => {
13280
+ const time = typeof value === "function" ? value(selectedTime) : value;
13281
+ handleTimeChange(time);
13282
+ },
13283
+ hasError: haveError
13284
+ }, props)
13285
+ ) })
13286
+ ] }),
13287
+ /* @__PURE__ */ jsx59(ErrorFormMessage, { message: errorMsg })
13288
+ ] });
13289
+ };
13290
+
13147
13291
  // src/hooks/useImageUpload.ts
13148
- import { useState as useState13, useCallback as useCallback8 } from "react";
13292
+ import { useState as useState13, useCallback as useCallback9 } from "react";
13149
13293
  var useImageUpload = (options) => {
13150
13294
  const [isUploading, setIsUploading] = useState13(false);
13151
13295
  const [progress, setProgress] = useState13(null);
@@ -13159,7 +13303,7 @@ var useImageUpload = (options) => {
13159
13303
  allowedTypes = ["image/jpeg", "image/png", "image/gif", "image/webp"],
13160
13304
  uploadConfig
13161
13305
  } = options;
13162
- const validateFile = useCallback8(
13306
+ const validateFile = useCallback9(
13163
13307
  (file) => {
13164
13308
  if (!allowedTypes.includes(file.type)) {
13165
13309
  const errorMsg = "Tipo de arquivo n\xE3o suportado";
@@ -13177,7 +13321,7 @@ var useImageUpload = (options) => {
13177
13321
  },
13178
13322
  [allowedTypes, maxFileSize, onError]
13179
13323
  );
13180
- const uploadFile = useCallback8(
13324
+ const uploadFile = useCallback9(
13181
13325
  (file) => __async(null, null, function* () {
13182
13326
  if (!validateFile(file)) {
13183
13327
  return null;
@@ -13230,7 +13374,7 @@ var useImageUpload = (options) => {
13230
13374
  }),
13231
13375
  [validateFile, onSuccess, onError, onProgress]
13232
13376
  );
13233
- const reset = useCallback8(() => {
13377
+ const reset = useCallback9(() => {
13234
13378
  setIsUploading(false);
13235
13379
  setProgress(null);
13236
13380
  setError(null);
@@ -13277,6 +13421,7 @@ export {
13277
13421
  Container,
13278
13422
  ContainerStyled,
13279
13423
  CountryFormField,
13424
+ DateAndTimeFormField,
13280
13425
  Divider,
13281
13426
  DoubleCalendar,
13282
13427
  DoubleCalendarFormField,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lets-events/react",
3
- "version": "12.7.3",
3
+ "version": "12.8.1",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -126,7 +126,8 @@ export const DayPickerWrapperStyled = styled("div", {
126
126
  },
127
127
  ".rdp-nav": {
128
128
  position: "absolute",
129
- width: "98%",
129
+ width: "100%",
130
+ left: "0",
130
131
  display: "flex",
131
132
  justifyContent: "space-between",
132
133
  },
@@ -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
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useRef, useState } from "react";
1
+ import React, { useCallback, useEffect, useRef, useState } from "react";
2
2
  import { Box } from "./Box";
3
3
  import { Button } from "./Button";
4
4
  import { TextField, TextFieldSlot } from "./TextField";
@@ -134,6 +134,24 @@ export type TimePickerProps = {
134
134
  };
135
135
  const pad = (num: number) => String(num).padStart(2, "0");
136
136
 
137
+ const parseTime = (value?: string) => {
138
+ if (!value) {
139
+ return {
140
+ parsedHours: "00",
141
+ parsedMinutes: "00",
142
+ };
143
+ }
144
+
145
+ const [hours, minutes] = value.split(":");
146
+ const nextHours = Math.min(Math.max(parseInt(hours || "0", 10), 0), 23);
147
+ const nextMinutes = Math.min(Math.max(parseInt(minutes || "0", 10), 0), 59);
148
+
149
+ return {
150
+ parsedHours: Number.isNaN(nextHours) ? "00" : pad(nextHours),
151
+ parsedMinutes: Number.isNaN(nextMinutes) ? "00" : pad(nextMinutes),
152
+ };
153
+ };
154
+
137
155
  export function TimePicker({
138
156
  selected,
139
157
  setSelected,
@@ -150,6 +168,14 @@ export function TimePicker({
150
168
 
151
169
  useOnClickOutside(dropdownRef, () => setIsOpen(false));
152
170
 
171
+ useEffect(() => {
172
+ const { parsedHours, parsedMinutes } = parseTime(selected);
173
+ setHours(parsedHours);
174
+ setMinutes(parsedMinutes);
175
+ setRawHours(parsedHours);
176
+ setRawMinutes(parsedMinutes);
177
+ }, [selected]);
178
+
153
179
  const handleIncrement = useCallback(
154
180
  (type: "hours" | "minutes") => {
155
181
  if (type === "hours") {
package/src/index.tsx CHANGED
@@ -60,6 +60,7 @@ export * from "./components/FormFields/RichEditorFormField";
60
60
  export * from "./components/FormFields/CalendarFormField";
61
61
  export * from "./components/FormFields/DoubleCalendarFormField";
62
62
  export * from "./components/FormFields/TimePickerFormField";
63
+ export * from "./components/FormFields/DateAndTimeFormField";
63
64
 
64
65
  // Rich Editor
65
66
  export * from "./components/RichEditor";