import React, { PropsWithChildren, useMemo, useRef, useState } from "react"; import { CalendarDate, DateValue, parseAbsoluteToLocal, toCalendarDate, } from "@internationalized/date"; import { DatePickerStateOptions, useDatePickerState, } from "@react-stately/datepicker"; import { useDatePicker } from "@react-aria/datepicker"; import classNames from "classnames"; import { Button } from ":/components/Button"; import { Field, FieldProps } from ":/components/Forms/Field"; import { LabelledBox } from ":/components/Forms/LabelledBox"; import { DateField } from ":/components/Forms/DatePicker/DateField"; import { Calendar } from ":/components/Forms/DatePicker/Calendar"; import { Popover } from ":/components/Popover"; import { useCunningham } from ":/components/Provider"; type DatePickerProps = PropsWithChildren & FieldProps & { label: string; name?: string; value?: null | Date | string; defaultValue?: Date | string; minValue?: Date | string; maxValue?: Date | string; onChange?: (value: string) => void | undefined; disabled?: boolean; }; export const DatePicker = ({ label, name, disabled = false, ...props }: DatePickerProps) => { if (props.defaultValue && props.value) { throw new Error( "You cannot use both defaultValue and value props on DatePicker component" ); } const parseCalendarDate = ( rawDate: Date | string | undefined ): undefined | CalendarDate => { if (!rawDate) { return undefined; } try { const ISODateString = new Date(rawDate).toISOString(); return toCalendarDate(parseAbsoluteToLocal(ISODateString)); } catch (e) { throw new Error( "Invalid date format when initializing props on DatePicker component" ); } }; const datePickerOptions: DatePickerStateOptions = { value: // Force clear the component's value when passing null or an empty string. props.value === "" || props.value === null ? null : parseCalendarDate(props.value), defaultValue: parseCalendarDate(props.defaultValue), minValue: parseCalendarDate(props.minValue), maxValue: parseCalendarDate(props.maxValue), onChange: (value: DateValue | null) => { props.onChange?.(value?.toString() || ""); }, shouldCloseOnSelect: true, granularity: "day", isDisabled: disabled, label, }; const state = useDatePickerState(datePickerOptions); const pickerRef = useRef(null); const wrapperRef = useRef(null); const { t } = useCunningham(); const { fieldProps, buttonProps, groupProps, calendarProps } = useDatePicker( datePickerOptions, state, wrapperRef ); const [isFocused, setIsFocused] = useState(false); const labelAsPlaceholder = useMemo( () => !state.isOpen && !state.value, [state.value, state.isOpen] ); const isDateInvalid = useMemo( () => state.validationState === "invalid" || props.state === "error", [state.validationState, props.state] ); // onPress props don't exist on the