UNPKG

@hitachivantara/uikit-react-core

Version:
171 lines (170 loc) 6.28 kB
import { setId } from "../utils/setId.js"; import { useUniqueId } from "../hooks/useUniqueId.js"; import { HvFormElement } from "../FormElement/FormElement.js"; import { HvIcon } from "../icons.js"; import { HvWarningText } from "../FormElement/WarningText/WarningText.js"; import { useControlled } from "../hooks/useControlled.js"; import { HvBaseDropdown } from "../BaseDropdown/BaseDropdown.js"; import { HvLabelContainer } from "../FormElement/LabelContainer.js"; import { Placeholder } from "./Placeholder.js"; import { useClasses } from "./TimePicker.styles.js"; import { Unit } from "./Unit/Unit.js"; import { useDefaultProps } from "@hitachivantara/uikit-react-utils"; import { forwardRef, useMemo, useRef, useState } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; import useForkRef from "@mui/utils/useForkRef"; import { useTimeField } from "react-aria/useTimeField"; import { useTimeFieldState } from "react-stately/useTimeFieldState"; import { Time } from "@internationalized/date"; //#region src/TimePicker/TimePicker.tsx var toTime = (value) => { if (!value) return value; const { hours, minutes, seconds } = value; return new Time(hours, minutes, seconds); }; /** * A Time Picker allows the user to choose a specific time or a time range. */ var HvTimePicker = forwardRef(function HvTimePicker(props, ref) { const { classes: classesProp, className, id: idProp, name, required, disabled, readOnly, label, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, description, "aria-describedby": ariaDescribedBy, status, statusMessage, "aria-errormessage": ariaErrorMessage, placeholder, hoursPlaceholder = "hh", minutesPlaceholder = "mm", secondsPlaceholder = "ss", value: valueProp, defaultValue: defaultValueProp, timeFormat, showSeconds, disableExpand, locale = "en", onToggle, onChange, disablePortal = true, escapeWithReference = true, dropdownProps = {}, ...others } = useDefaultProps("HvTimePicker", props); const id = useUniqueId(idProp); const { classes, cx } = useClasses(classesProp); const timeFieldRef = useRef(null); const { ref: refProp, ...otherDropdownProps } = dropdownProps; const dropdownForkedRef = useForkRef(ref, refProp); const stateProps = { value: useMemo(() => toTime(valueProp), [valueProp]), defaultValue: toTime(defaultValueProp), label, locale, isRequired: required, isReadOnly: readOnly, isDisabled: disabled, granularity: showSeconds === false ? "minute" : "second", hourCycle: timeFormat === "12" ? 12 : 24, onChange: (value) => { if (!value) return; const { hour: hours, minute: minutes, second: seconds } = value; onChange?.({ hours, minutes, seconds }); } }; const state = useTimeFieldState(stateProps); const { labelProps, fieldProps, descriptionProps } = useTimeField({ ...stateProps, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy }, state, timeFieldRef); const popperProps = useMemo(() => { return { modifiers: [{ name: "preventOverflow", enabled: escapeWithReference }] }; }, [escapeWithReference]); const [open, setOpen] = useState(false); const [validationMessage] = useControlled(statusMessage, "Required"); const [validationState] = useControlled(status, "standBy"); const placeholders = useMemo(() => ({ hour: hoursPlaceholder, minute: minutesPlaceholder, second: secondsPlaceholder }), [ hoursPlaceholder, minutesPlaceholder, secondsPlaceholder ]); const canShowError = ariaErrorMessage == null && (status !== void 0 && statusMessage !== void 0 || status === void 0 && required); const isStateInvalid = validationState === "invalid"; const errorMessageId = isStateInvalid ? canShowError ? setId(id, "error") : ariaErrorMessage : void 0; return /* @__PURE__ */ jsxs(HvFormElement, { name, required, disabled, status: validationState, className: cx(classes.root, className), ...others, children: [ /* @__PURE__ */ jsx(HvLabelContainer, { label, description, classes: { root: classes.labelContainer, label: classes.label, description: classes.description }, labelProps, descriptionProps }), /* @__PURE__ */ jsx(HvBaseDropdown, { ref: dropdownForkedRef, role: "combobox", variableWidth: true, disabled, readOnly, placeholder: placeholder && !state.value ? placeholder : /* @__PURE__ */ jsx(Placeholder, { ref: timeFieldRef, name, state, placeholders, className: cx(classes.placeholder, { [classes.placeholderDisabled]: disabled }), ...fieldProps }), classes: { header: cx(classes.dropdownHeader, { [classes.dropdownHeaderInvalid]: isStateInvalid }), panel: classes.dropdownPanel, headerOpen: classes.dropdownHeaderOpen }, placement: "right", adornment: /* @__PURE__ */ jsx(HvIcon, { name: "Time", className: classes.icon }), expanded: open, onToggle: (evt, newOpen) => { if (disableExpand) return; setOpen(newOpen); onToggle?.(evt, newOpen); }, onContainerCreation: (containerRef) => { containerRef?.getElementsByTagName("input")[0]?.focus(); }, "aria-haspopup": "dialog", "aria-label": ariaLabel, "aria-labelledby": fieldProps["aria-labelledby"], "aria-describedby": fieldProps["aria-describedby"], "aria-invalid": isStateInvalid ? true : void 0, "aria-errormessage": errorMessageId, disablePortal, popperProps, ...otherDropdownProps, children: /* @__PURE__ */ jsx("div", { ref: timeFieldRef, className: classes.timePopperContainer, children: state.segments.map((segment, i) => /* @__PURE__ */ jsx(Unit, { state, segment, placeholder: placeholders[segment.type], onAdd: () => state.increment(segment.type), onSub: () => state.decrement(segment.type), onChange: (evt, val) => { state.setSegment(segment.type, Number(val)); } }, segment.type === "literal" ? `literal-${i}` : segment.type)) }) }), canShowError && /* @__PURE__ */ jsx(HvWarningText, { id: setId(id, "error"), disableBorder: true, className: classes.error, children: validationMessage }) ] }); }); //#endregion export { HvTimePicker };