@hitachivantara/uikit-react-core
Version:
UI Kit Core React components.
171 lines (170 loc) • 6.28 kB
JavaScript
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 };