UNPKG

@yamada-ui/react

Version:

React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion

575 lines (571 loc) • 21.4 kB
"use client"; const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs'); const require_dom = require('../../utils/dom.cjs'); const require_effect = require('../../utils/effect.cjs'); const require_ref = require('../../utils/ref.cjs'); const require_utils_index = require('../../utils/index.cjs'); const require_hooks_use_controllable_state_index = require('../../hooks/use-controllable-state/index.cjs'); const require_i18n_provider = require('../../providers/i18n-provider/i18n-provider.cjs'); const require_use_field_props = require('../field/use-field-props.cjs'); const require_hooks_use_combobox_index = require('../../hooks/use-combobox/index.cjs'); const require_use_format_date_time = require('../format/use-format-date-time.cjs'); const require_use_calendar = require('../calendar/use-calendar.cjs'); let react = require("react"); react = require_rolldown_runtime.__toESM(react); let react_jsx_runtime = require("react/jsx-runtime"); react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime); let dayjs = require("dayjs"); dayjs = require_rolldown_runtime.__toESM(dayjs); //#region src/components/date-picker/use-date-picker.tsx const defaultRender = ({ count, focused, index, max, separator, value }) => { const last = count - 1 === index; return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { style: { marginInlineEnd: "var(--gap)" }, children: [value, (!(0, require_utils_index.utils_exports.isNumber)(max) || count < max) && focused || !last ? separator : null] }); }; const useDatePicker = ({ maxDate = require_use_calendar.DEFAULT_MAX_DATE, minDate = require_use_calendar.DEFAULT_MIN_DATE,...props } = {}) => { if ((0, dayjs.default)(minDate).isAfter((0, dayjs.default)(maxDate))) maxDate = minDate; const { locale: defaultLocale, t } = require_i18n_provider.useI18n("datePicker"); const { props: { id, ref, name, allowInput = true, allowInputBeyond = false, closeOnChange = false, multiple = false, closeOnSelect = !multiple, defaultInputValue, defaultMonth = /* @__PURE__ */ new Date(), range = false, defaultValue = range ? { end: void 0, start: void 0 } : multiple ? [] : void 0, disabled, focusOnClear = true, format, inputValue: inputValueProp, locale = defaultLocale, max, month: monthProp, openOnChange = true, openOnClick = true, openOnFocus = true, parseDate, pattern, placeholder: placeholderProp, readOnly, render = defaultRender, required, separator = range ? "-" : ",", value: valueProp, onChange: onChangeProp, onChangeMonth: onChangeMonthProp, onInputChange: onInputChangeProp,...computedProps }, ariaProps, dataProps, eventProps } = require_use_field_props.useFieldProps(props); const dateTimeFormat = require_use_format_date_time.useDateTimeFormat({ locale }); const { calendarFormat, inputFormat } = (0, react.useMemo)(() => { const { input: inputFormat$1,...calendarFormat$1 } = format ?? {}; return { calendarFormat: calendarFormat$1, inputFormat: inputFormat$1 !== null ? inputFormat$1 ?? { day: "numeric", month: "long", year: "numeric" } : void 0 }; }, [format]); const [calendarProps, rest] = require_use_calendar.useCalendarProps(computedProps); const { excludeDate } = calendarProps; const fieldRef = (0, react.useRef)(null); const contentRef = (0, react.useRef)(null); const startInputRef = (0, react.useRef)(null); const endInputRef = (0, react.useRef)(null); const focusByClickRef = (0, react.useRef)(false); const [focused, setFocused] = (0, react.useState)(false); const [value, setValue] = require_hooks_use_controllable_state_index.useControllableState({ defaultValue, value: valueProp, onChange: onChangeProp }); const [month, setMonth] = require_hooks_use_controllable_state_index.useControllableState({ defaultValue: () => { let value$1 = defaultMonth; if ((0, dayjs.default)(minDate).isAfter((0, dayjs.default)(defaultMonth))) value$1 = (0, dayjs.default)(minDate).set("date", 1).toDate(); if (valueProp) value$1 = require_use_calendar.getAdjustedMonth(valueProp, value$1); else if (defaultValue) value$1 = require_use_calendar.getAdjustedMonth(defaultValue, value$1); return value$1; }, value: monthProp, onChange: onChangeMonthProp }); const stringToDate = (0, react.useCallback)((value$1, start = minDate, end = maxDate) => { let date = parseDate?.(value$1); if (!date && (0, dayjs.default)(value$1).isValid()) date = (0, dayjs.default)(value$1, locale).toDate(); if (date == null) return void 0; if (excludeDate?.(date)) return void 0; if (!allowInputBeyond) { if (require_use_calendar.isBeforeDate(date, start)) date = start; if (require_use_calendar.isAfterDate(date, end)) date = end; } return date; }, [ allowInputBeyond, excludeDate, locale, maxDate, minDate, parseDate ]); const dateToString = (0, react.useCallback)((date) => { if (date == null) return ""; return dateTimeFormat(date, inputFormat); }, [dateTimeFormat, inputFormat]); const [inputValue, setInputValue] = require_hooks_use_controllable_state_index.useControllableState({ defaultValue: () => { if (defaultInputValue) if ((0, require_utils_index.utils_exports.isObject)(defaultInputValue)) { if ((0, dayjs.default)(defaultInputValue.start).isValid()) defaultInputValue.start = dateTimeFormat((0, dayjs.default)(defaultInputValue.start).toDate(), inputFormat); if ((0, dayjs.default)(defaultInputValue.end).isValid()) defaultInputValue.end = dateTimeFormat((0, dayjs.default)(defaultInputValue.end).toDate(), inputFormat); return defaultInputValue; } else if ((0, dayjs.default)(defaultInputValue).isValid()) return dateTimeFormat((0, dayjs.default)(defaultInputValue).toDate(), inputFormat); else return defaultInputValue; else if ((0, require_utils_index.utils_exports.isDate)(value)) return dateToString(value); else if ((0, require_utils_index.utils_exports.isObject)(value) && !(0, require_utils_index.utils_exports.isArray)(value)) return { end: dateToString(value.end), start: dateToString(value.start) }; else return ""; }, value: inputValueProp, onChange: onInputChangeProp }); const { interactive, open, getContentProps: getComboboxContentProps, getTriggerProps, popoverProps, onClose, onOpen } = require_hooks_use_combobox_index.useCombobox({ disabled, matchWidth: false, openOnClick: false, openOnEnter: !allowInput, openOnSpace: !allowInput, placement: "end-start", readOnly, transferFocus: false, ...ariaProps, ...dataProps, ...eventProps, ...rest }); const children = (0, react.useMemo)(() => { if (!(0, require_utils_index.utils_exports.isArray)(value)) return null; const count = value.length; return value.map((date, index) => { const value$1 = dateToString(date); const onClear$1 = (ev) => { ev?.preventDefault(); ev?.stopPropagation(); setValue((prev) => require_use_calendar.updateMaybeDateValue(date, max)(prev)); }; const component = render({ count, date, focused, index, max, separator, value: value$1, onClear: onClear$1 }); if ((0, react.isValidElement)(component)) return (0, react.cloneElement)(component, { ...component.props, key: index }); else return component; }); }, [ dateToString, focused, max, render, separator, setValue, value ]); const { endPlaceholder, startPlaceholder } = (0, react.useMemo)(() => { if (range) { const startPlaceholder$1 = placeholderProp ?? dateTimeFormat(/* @__PURE__ */ new Date(), inputFormat); return { endPlaceholder: placeholderProp ?? dateTimeFormat((0, dayjs.default)().add(1, "day").toDate(), inputFormat), startPlaceholder: startPlaceholder$1 }; } else { const placeholder = placeholderProp ?? dateTimeFormat(/* @__PURE__ */ new Date(), inputFormat); return { endPlaceholder: placeholder, startPlaceholder: placeholder }; } }, [ dateTimeFormat, inputFormat, placeholderProp, range ]); const onChange = (0, react.useCallback)((value$1) => { setValue(value$1); if ((0, require_utils_index.utils_exports.isArray)(value$1)) setInputValue(""); else if ((0, require_utils_index.utils_exports.isObject)(value$1) && !(0, require_utils_index.utils_exports.isDate)(value$1)) setInputValue({ end: dateToString(value$1.end), start: dateToString(value$1.start) }); else setInputValue(dateToString(value$1)); if (!closeOnSelect) return; if ((0, require_utils_index.utils_exports.isObject)(value$1) && !(0, require_utils_index.utils_exports.isArray)(value$1) && !(0, require_utils_index.utils_exports.isDate)(value$1)) { if (value$1.end && value$1.start) onClose(); } else onClose(); }, [ setValue, closeOnSelect, setInputValue, dateToString, onClose ]); const onInputChange = (0, react.useCallback)((ev) => { if (!allowInput) return; if ((0, require_utils_index.utils_exports.isArray)(value) && value.length === max) return; if ((0, require_utils_index.utils_exports.runIfFn)(closeOnChange, ev)) onClose(); else if ((0, require_utils_index.utils_exports.runIfFn)(openOnChange, ev)) onOpen(); let inputValue$1 = ev.target.value; if (pattern) inputValue$1 = inputValue$1.replace(pattern, ""); if ((0, require_utils_index.utils_exports.isArray)(value)) { const date = stringToDate(inputValue$1); setInputValue(inputValue$1); if (date) setMonth((0, dayjs.default)(date).set("date", 1).toDate()); } else if ((0, require_utils_index.utils_exports.isObject)(value) && !(0, require_utils_index.utils_exports.isDate)(value)) { const align = (0, require_utils_index.utils_exports.contains)(endInputRef.current, ev.target) ? "end" : "start"; const minDate$1 = value.start && align === "end" ? (0, dayjs.default)(value.start).add(1, "day").toDate() : void 0; const maxDate$1 = value.end && align === "start" ? (0, dayjs.default)(value.end).subtract(1, "day").toDate() : void 0; const date = stringToDate(inputValue$1, minDate$1, maxDate$1); setInputValue((prev) => (0, require_utils_index.utils_exports.isObject)(prev) ? { ...prev, [align]: inputValue$1 } : prev); setValue((prev) => (0, require_utils_index.utils_exports.isObject)(prev) && !(0, require_utils_index.utils_exports.isDate)(prev) ? { ...prev, [align]: date } : prev); } else { const date = stringToDate(inputValue$1); setInputValue(inputValue$1); setValue(date); } }, [ allowInput, closeOnChange, max, onClose, onOpen, openOnChange, pattern, setInputValue, setMonth, setValue, stringToDate, value ]); const onKeyDown = (0, react.useCallback)((ev) => { if (disabled || require_dom.isComposing(ev)) return; const inputValue$1 = (0, require_utils_index.utils_exports.cast)(ev.target).value; require_dom.runKeyAction(ev, { Backspace: (ev$1) => { if (!value || (0, require_utils_index.utils_exports.isDate)(value)) return; if (!!inputValue$1.length) return; if ((0, require_utils_index.utils_exports.isArray)(value)) { ev$1.preventDefault(); setValue((prev) => (0, require_utils_index.utils_exports.isArray)(prev) ? prev.slice(0, -1) : prev); } else if ((0, require_utils_index.utils_exports.contains)(endInputRef.current, ev$1.target)) { ev$1.preventDefault(); setInputValue({ end: "", start: "" }); setValue({ end: void 0, start: void 0 }); startInputRef.current?.focus(); } }, Enter: (ev$1) => { if (!open || !inputValue$1.length) return; if ((0, require_utils_index.utils_exports.isDate)(value) || (0, require_utils_index.utils_exports.isArray)(value)) { const date = stringToDate(inputValue$1); if (!date) return; ev$1.preventDefault(); if ((0, require_utils_index.utils_exports.isArray)(value)) setInputValue(""); else setInputValue(dateToString(date)); setValue((prev) => require_use_calendar.updateMaybeDateValue(date, max)(prev)); } else if ((0, require_utils_index.utils_exports.isObject)(value)) { const align = (0, require_utils_index.utils_exports.contains)(endInputRef.current, ev$1.target) ? "end" : "start"; const date = stringToDate(inputValue$1, value.start && align === "end" ? (0, dayjs.default)(value.start).add(1, "day").toDate() : void 0, value.end && align === "start" ? (0, dayjs.default)(value.end).subtract(1, "day").toDate() : void 0); if (!date) return; ev$1.preventDefault(); setInputValue((prev) => (0, require_utils_index.utils_exports.isObject)(prev) ? { ...prev, [align]: dateToString(date) } : prev); setValue((prev) => (0, require_utils_index.utils_exports.isObject)(prev) && !(0, require_utils_index.utils_exports.isDate)(prev) ? { ...prev, [align]: date } : prev); if (align === "start") endInputRef.current?.focus(); } } }, { preventDefault: false }); }, [ dateToString, disabled, max, open, setInputValue, setValue, stringToDate, value ]); const onClick = (0, react.useCallback)((ev) => { if (!interactive) return; focusByClickRef.current = true; if (allowInput) if ((0, require_utils_index.utils_exports.isObject)(value) && !(0, require_utils_index.utils_exports.isArray)(value) && !(0, require_utils_index.utils_exports.isDate)(value)) { if ((0, require_utils_index.utils_exports.contains)(startInputRef.current, ev.target)) return; if ((0, require_utils_index.utils_exports.contains)(endInputRef.current, ev.target)) return; const { end, start } = value; if (!start && !end || !!end) startInputRef.current?.focus(); else endInputRef.current?.focus(); } else startInputRef.current?.focus(); if (openOnClick) onOpen(); }, [ allowInput, interactive, onOpen, openOnClick, value ]); const onMouseDown = (0, react.useCallback)((ev) => { if (!openOnFocus) return; ev.preventDefault(); ev.stopPropagation(); }, [openOnFocus]); const onFieldFocus = (0, react.useCallback)(() => { if (allowInput) return; if (openOnFocus) onOpen(); focusByClickRef.current = false; }, [ allowInput, onOpen, openOnFocus ]); const onInputFocus = (0, react.useCallback)((ev) => { ev.preventDefault(); ev.stopPropagation(); setFocused(true); if (openOnFocus && !focusByClickRef.current) onOpen(); focusByClickRef.current = false; }, [onOpen, openOnFocus]); const onBlur = (0, react.useCallback)((ev) => { setFocused(false); if ((0, require_utils_index.utils_exports.contains)(fieldRef.current, ev.relatedTarget) || (0, require_utils_index.utils_exports.contains)(contentRef.current, ev.relatedTarget)) ev.preventDefault(); else if ((0, require_utils_index.utils_exports.isArray)(value)) setInputValue(""); else if ((0, require_utils_index.utils_exports.isObject)(value) && !(0, require_utils_index.utils_exports.isDate)(value)) setInputValue((prev) => (0, require_utils_index.utils_exports.isObject)(prev) ? { end: dateToString(value.end), start: dateToString(value.start) } : prev); else setInputValue(dateToString(value)); }, [ dateToString, setInputValue, value ]); const onClear = (0, react.useCallback)(() => { if (!interactive) return; setValue((prev) => { if ((0, require_utils_index.utils_exports.isDate)(prev)) return; else if ((0, require_utils_index.utils_exports.isArray)(prev)) return []; else if ((0, require_utils_index.utils_exports.isObject)(prev)) return { end: void 0, start: void 0 }; else return prev; }); setInputValue(range ? { end: "", start: "" } : ""); if (focusOnClear) if (allowInput) startInputRef.current?.focus(); else fieldRef.current?.focus(); }, [ allowInput, focusOnClear, interactive, range, setInputValue, setValue ]); (0, react.useEffect)(() => { if (!open) return; return (0, require_utils_index.utils_exports.focusTransfer)(contentRef.current, allowInput ? startInputRef.current : fieldRef.current); }, [allowInput, open]); require_effect.useUpdateEffect(() => { setMonth((prev) => require_use_calendar.getAdjustedMonth(value, prev)); }, [value, range]); require_effect.useUpdateEffect(() => { if ((0, require_utils_index.utils_exports.isArray)(valueProp)) return; if ((0, require_utils_index.utils_exports.isObject)(valueProp) && !(0, require_utils_index.utils_exports.isDate)(valueProp)) setInputValue({ end: dateToString(valueProp.end), start: dateToString(valueProp.start) }); else setInputValue(dateToString(valueProp)); }, [valueProp]); const getRootProps = (0, react.useCallback)((props$1) => ({ "data-range": (0, require_utils_index.utils_exports.dataAttr)(range), ...dataProps, ...props$1 }), [dataProps, range]); const getFieldProps = (0, react.useCallback)(({ ref: ref$1,...props$1 } = {}) => getTriggerProps({ ref: require_ref.mergeRefs(ref$1, fieldRef), "aria-haspopup": "dialog", tabIndex: !allowInput ? 0 : -1, ...props$1, onClick: (0, require_utils_index.utils_exports.handlerAll)(props$1.onClick, onClick), onFocus: (0, require_utils_index.utils_exports.handlerAll)(props$1.onFocus, onFieldFocus), onMouseDown: (0, require_utils_index.utils_exports.handlerAll)(props$1.onMouseDown, onMouseDown) }), [ allowInput, getTriggerProps, onClick, onFieldFocus, onMouseDown ]); const getInputProps = (0, react.useCallback)(({ align = "start",...props$1 } = {}) => { const inputProps = { style: { ...!allowInput ? { pointerEvents: "none" } : {}, ...props$1.style }, autoComplete: "off", disabled, readOnly, required, tabIndex: allowInput ? 0 : -1, ...dataProps, ...props$1, onBlur: (0, require_utils_index.utils_exports.handlerAll)(props$1.onBlur, onBlur), onChange: (0, require_utils_index.utils_exports.handlerAll)(props$1.onChange, onInputChange), onFocus: (0, require_utils_index.utils_exports.handlerAll)(props$1.onFocus, onInputFocus), onKeyDown: (0, require_utils_index.utils_exports.handlerAll)(props$1.onKeyDown, onKeyDown), onMouseDown: (0, require_utils_index.utils_exports.handlerAll)(props$1.onMouseDown, onMouseDown) }; if ((0, require_utils_index.utils_exports.isObject)(inputValue)) { if (align === "start") { inputProps.ref = require_ref.mergeRefs(props$1.ref, ref, startInputRef); inputProps.value = inputValue.start; inputProps.placeholder = startPlaceholder; } else { inputProps.ref = require_ref.mergeRefs(props$1.ref, ref, endInputRef); inputProps.value = inputValue.end; inputProps.placeholder = endPlaceholder; } if (!inputValue.start && align === "start") { inputProps.id = id; inputProps.name = name; } if (!!inputValue.start && align === "end") { inputProps.id = id; inputProps.name = name; } } else { inputProps.ref = require_ref.mergeRefs(props$1.ref, ref, startInputRef); inputProps.value = inputValue; inputProps.id = id; inputProps.name = name; if ((0, require_utils_index.utils_exports.isArray)(value)) { inputProps.style = { ...!focused && !!value.length ? require_dom.visuallyHiddenAttributes.style : {}, ...inputProps.style }; inputProps.placeholder = !value.length ? startPlaceholder : void 0; inputProps["data-max"] = (0, require_utils_index.utils_exports.dataAttr)((0, require_utils_index.utils_exports.isNumber)(max) && value.length >= max); } else inputProps.placeholder = startPlaceholder; } return inputProps; }, [ allowInput, dataProps, disabled, endPlaceholder, focused, id, inputValue, max, name, onBlur, onInputFocus, onInputChange, onKeyDown, onMouseDown, readOnly, ref, required, startPlaceholder, value ]); const getContentProps = (0, react.useCallback)(({ ref: ref$1,...props$1 } = {}) => getComboboxContentProps({ ref: require_ref.mergeRefs(ref$1, contentRef), role: "dialog", ...props$1 }), [getComboboxContentProps]); const getCalendarProps = (0, react.useCallback)((props$1) => ({ disabled: !interactive, format: calendarFormat, locale, max, maxDate, minDate, month, multiple, range, value, onChange, onChangeMonth: setMonth, ...calendarProps, ...props$1 }), [ interactive, calendarFormat, locale, max, maxDate, minDate, month, multiple, range, value, onChange, setMonth, calendarProps ]); const getIconProps = (0, react.useCallback)((props$1) => ({ ...dataProps, ...props$1 }), [dataProps]); return { children, dateToString, inputValue, interactive, month, open, range, separator, setInputValue, setMonth, setValue, stringToDate, value, getCalendarProps, getClearIconProps: (0, react.useCallback)((props$1 = {}) => getIconProps({ "aria-disabled": (0, require_utils_index.utils_exports.ariaAttr)(!interactive), "aria-label": t("Clear value"), role: "button", tabIndex: interactive ? 0 : -1, ...props$1, onClick: (0, require_utils_index.utils_exports.handlerAll)(props$1.onClick, onClear), onKeyDown: (0, require_utils_index.utils_exports.handlerAll)(props$1.onKeyDown, (ev) => require_dom.runKeyAction(ev, { Enter: onClear, Space: onClear })) }), [ getIconProps, interactive, onClear, t ]), getContentProps, getFieldProps, getIconProps, getInputProps, getRootProps, popoverProps, onChange, onClose, onInputChange, onOpen }; }; //#endregion exports.useDatePicker = useDatePicker; //# sourceMappingURL=use-date-picker.cjs.map