diff --git a/packages/sanity/src/core/components/inputs/DateInputs/DatePicker.tsx b/packages/sanity/src/core/components/inputs/DateInputs/DatePicker.tsx index e9b59cef274..0367c39baec 100644 --- a/packages/sanity/src/core/components/inputs/DateInputs/DatePicker.tsx +++ b/packages/sanity/src/core/components/inputs/DateInputs/DatePicker.tsx @@ -1,4 +1,11 @@ -import {type ComponentProps, type ForwardedRef, forwardRef, useCallback, useState} from 'react' +import { + type ComponentProps, + type ForwardedRef, + forwardRef, + useCallback, + useMemo, + useState, +} from 'react' import {type TimeZoneScope, useTimeZone} from '../../../hooks/useTimeZone' import {Calendar, type CalendarProps} from './calendar/Calendar' @@ -28,7 +35,15 @@ export const DatePicker = forwardRef(function DatePicker( timeZoneScope, ...rest } = props - const value = _value ?? new Date() + + const value = useMemo(() => { + if (_value) return _value + const now = new Date() + // If no value is provided initialize the date with seconds and milliseconds set to 0 + now.setSeconds(0, 0) + return now + }, [_value]) + const {utcToCurrentZoneDate} = useTimeZone(timeZoneScope) const [focusedDate, setFocusedDay] = useState() diff --git a/packages/sanity/src/core/components/inputs/DateInputs/TimeInput.tsx b/packages/sanity/src/core/components/inputs/DateInputs/TimeInput.tsx index ee30ce6aa7a..d054feb9c4d 100644 --- a/packages/sanity/src/core/components/inputs/DateInputs/TimeInput.tsx +++ b/packages/sanity/src/core/components/inputs/DateInputs/TimeInput.tsx @@ -1,8 +1,7 @@ +import {TextInput} from '@sanity/ui' import {styled} from 'styled-components' -import {LazyTextInput} from './LazyTextInput' - -export const TimeInput = styled(LazyTextInput).attrs(() => ({ +export const TimeInput = styled(TextInput).attrs(() => ({ type: 'time', }))` line-height: 1; diff --git a/packages/sanity/src/core/components/inputs/DateInputs/calendar/Calendar.tsx b/packages/sanity/src/core/components/inputs/DateInputs/calendar/Calendar.tsx index db23b8c457d..e91b40af571 100644 --- a/packages/sanity/src/core/components/inputs/DateInputs/calendar/Calendar.tsx +++ b/packages/sanity/src/core/components/inputs/DateInputs/calendar/Calendar.tsx @@ -36,7 +36,7 @@ export const MONTH_PICKER_VARIANT = { export type CalendarProps = Omit, 'onSelect'> & { selectTime?: boolean - selectedDate?: Date + selectedDate: Date timeStep?: number onSelect: (date: Date) => void focusedDate: Date @@ -76,7 +76,7 @@ export const Calendar = forwardRef(function Calendar( const { selectTime, onFocusedDateChange, - selectedDate: _selectedDate, + selectedDate, focusedDate: _focusedDate, timeStep = 1, onSelect, @@ -88,7 +88,7 @@ export const Calendar = forwardRef(function Calendar( timeZoneScope, ...restProps } = props - const selectedDate = useMemo(() => _selectedDate ?? new Date(), [_selectedDate]) + const focusedDate = _focusedDate ?? selectedDate const {timeZone} = useTimeZone(timeZoneScope) @@ -170,10 +170,27 @@ export const Calendar = forwardRef(function Calendar( [onSelect, savedSelectedDate, timeZone], ) + const timeFromDate = useMemo(() => format(savedSelectedDate, 'HH:mm'), [savedSelectedDate]) + const [timeValue, setTimeValue] = useState(timeFromDate) + + useEffect(() => { + // The change is coming from another source, so we need to update the timeValue to the new value. + // eslint-disable-next-line react-hooks/no-deriving-state-in-effects + setTimeValue(timeFromDate) + }, [timeFromDate]) + const handleTimeChangeInputChange = useCallback( (event: FormEvent) => { - const date = parse(event.currentTarget.value, 'HH:mm', new Date()) - handleTimeChange(date.getHours(), date.getMinutes()) + const value = event.currentTarget.value + if (value) { + const date = parse(value, 'HH:mm', new Date()) + handleTimeChange(date.getHours(), date.getMinutes()) + } else { + // Setting the timeValue to undefined will let the input behave correctly as a time input while the user types. + // This means, that until it has a valid value the time input input won't emit a new onChange event. + // but we cannot send the undefined value to the handleTimeChange, because it expects a valid date. + setTimeValue(undefined) + } }, [handleTimeChange], ) @@ -368,8 +385,15 @@ export const Calendar = forwardRef(function Calendar(