import React, { useId, useMemo } from 'react' import { Time } from '@internationalized/date' import { useTimeField } from '@react-aria/datepicker' import { I18nProvider } from '@react-aria/i18n' import { useTimeFieldState, type TimeFieldStateOptions } from '@react-stately/datepicker' import classnames from 'classnames' import { FieldMessage } from '~components/FieldMessage' import { Label } from '~components/Label' import { type OverrideClassName } from '~components/types/OverrideClassName' import { TimeSegment } from './subcomponents/TimeSegment' import { type StatusType, type TimeValue, type ValueType } from './types' import styles from './TimeField.module.css' type OmittedTimeFieldProps = 'errorMessage' | 'value' | 'onChange' | 'label' | 'hideTimeZone' export type TimeFieldProps = { id?: string /** * Field label. */ label: string /** * Accepts any valid locale code (https://npm.io/package/locale-codes). */ locale: string onChange: (value: ValueType | null) => void value: ValueType | null status?: StatusType validationMessage?: React.ReactNode } & OverrideClassName> // This needed to be placed directly below the props because // the prop descriptions wouldn't show in Storybook otherwise. export const TimeField = (props: TimeFieldProps): JSX.Element => ( ) TimeField.displayName = 'TimeField' const TimeFieldComponent = ({ id: propsId, label, locale, onChange, value, status = 'default', validationMessage, isDisabled, classNameOverride, ...restProps }: TimeFieldProps): JSX.Element => { const reactId = useId() const id = propsId ?? reactId const handleOnChange = (timeValue: TimeValue | null): void => { if (timeValue === null) { return onChange(null) } onChange({ hour: timeValue.hour, minutes: timeValue.minute }) } const timeValue = useMemo( () => (value ? new Time(value.hour, value.minutes) : null), // eslint-disable-next-line react-hooks/exhaustive-deps [value?.hour, value?.minutes], ) const state = useTimeFieldState({ ...restProps, value: timeValue, onChange: handleOnChange, isDisabled, hideTimeZone: true, locale, }) const hasError = !!validationMessage && status === 'error' const descriptionId = hasError ? `${id}-field-message` : undefined const inputRef = React.useRef(null) const { fieldProps, labelProps } = useTimeField( { ...restProps, label, isDisabled, 'aria-describedby': descriptionId, }, state, inputRef, ) return (
{}
{state.segments.map((segment, i) => { return ( ) })}
{hasError && }
) } TimeFieldComponent.displayName = 'TimeFieldComponent'