UNPKG

@navikt/ds-react

Version:

React components from the Norwegian Labour and Welfare Administration.

175 lines 7.94 kB
import { useCallback, useMemo, useState } from "react"; import { dateMatchModifiers } from "react-day-picker"; import { useDateLocale } from "../../../util/i18n/i18n.hooks.js"; import { getLocaleFromString } from "../../Date.locale.js"; import { formatDateForInput, isValidDate, parseDate } from "../../date-utils/index.js"; const getValidationMessage = (val = {}) => (Object.assign({ isDisabled: false, isEmpty: false, isInvalid: false, isBefore: false, isAfter: false, isValidMonth: true }, val)); const getIsBefore = (opt) => opt.fromDate && opt.date && (opt.fromDate.getFullYear() > opt.date.getFullYear() || (opt.fromDate.getFullYear() === opt.date.getFullYear() && opt.fromDate.getMonth() > opt.date.getMonth())); const getIsAfter = (opt) => opt.toDate && opt.date && (opt.toDate.getFullYear() < opt.date.getFullYear() || (opt.toDate.getFullYear() === opt.date.getFullYear() && opt.toDate.getMonth() < opt.date.getMonth())); /** * * @see 🏷️ {@link UseMonthPickerOptions} * @see 🏷️ {@link UseMonthPickerValue} * @see 🏷️ {@link MonthValidationT} * @example * const { monthpickerProps, inputProps } = useMonthpicker({ * fromDate: new Date("Aug 23 2019"), * toDate: new Date("Feb 23 2024"), * onMonthChange: console.log, * onValidate: console.log, * }); */ export const useMonthpicker = (opt = {}) => { var _a; const { locale: _locale, defaultSelected: _defaultSelected, fromDate, toDate, disabled, required, onMonthChange, inputFormat, onValidate, defaultYear, allowTwoDigitYear = true, } = opt; const [anchorRef, setAnchorRef] = useState(null); const [defaultSelected, setDefaultSelected] = useState(_defaultSelected); const today = useMemo(() => new Date(), []); const localeFromProvider = useDateLocale(); const locale = _locale ? getLocaleFromString(_locale) : localeFromProvider; // Initialize states const [year, setYear] = useState((_a = defaultSelected !== null && defaultSelected !== void 0 ? defaultSelected : defaultYear) !== null && _a !== void 0 ? _a : today); const [selectedMonth, setSelectedMonth] = useState(defaultSelected); const [open, setOpen] = useState(false); const defaultInputValue = defaultSelected ? formatDateForInput(defaultSelected, locale, "month", inputFormat) : ""; const [inputValue, setInputValue] = useState(defaultInputValue); const handleOpen = useCallback((newOpen) => { var _a, _b; setOpen(newOpen); newOpen && setYear((_b = (_a = selectedMonth !== null && selectedMonth !== void 0 ? selectedMonth : defaultSelected) !== null && _a !== void 0 ? _a : defaultYear) !== null && _b !== void 0 ? _b : today); }, [defaultSelected, defaultYear, selectedMonth, today]); const updateMonth = (date) => { onMonthChange === null || onMonthChange === void 0 ? void 0 : onMonthChange(date); setSelectedMonth(date); }; const updateValidation = (val = {}) => onValidate === null || onValidate === void 0 ? void 0 : onValidate(getValidationMessage(val)); const reset = () => { var _a; updateMonth(defaultSelected); setYear((_a = defaultSelected !== null && defaultSelected !== void 0 ? defaultSelected : defaultYear) !== null && _a !== void 0 ? _a : today); setInputValue(defaultInputValue !== null && defaultInputValue !== void 0 ? defaultInputValue : ""); setDefaultSelected(_defaultSelected); }; const setSelected = (date) => { var _a; updateMonth(date); setYear((_a = date !== null && date !== void 0 ? date : defaultYear) !== null && _a !== void 0 ? _a : today); setInputValue(date ? formatDateForInput(date, locale, "month", inputFormat) : ""); }; const handleFocus = (e) => { var _a; if (e.target.readOnly) { return; } const day = parseDate(e.target.value, today, locale, "month", allowTwoDigitYear); const isBefore = getIsBefore({ fromDate, date: day }); const isAfter = getIsAfter({ toDate, date: day }); if (isValidDate(day)) { !isBefore && !isAfter && setYear(day); setInputValue(formatDateForInput(day, locale, "month", inputFormat)); } else { setYear((_a = defaultSelected !== null && defaultSelected !== void 0 ? defaultSelected : defaultYear) !== null && _a !== void 0 ? _a : today); } }; const handleBlur = (e) => { const day = parseDate(e.target.value, today, locale, "month", allowTwoDigitYear); isValidDate(day) && setInputValue(formatDateForInput(day, locale, "month", inputFormat)); }; /* Only allow de-selecting if not required */ const handleMonthClick = (month) => { if (!month && required) { return; } if (month) { handleOpen(false); setYear(month); anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.focus(); } if (!month) { updateMonth(undefined); updateValidation({ isValidMonth: false, isEmpty: true }); setInputValue(""); setYear(defaultYear !== null && defaultYear !== void 0 ? defaultYear : today); return; } updateMonth(month); updateValidation(); setInputValue(month ? formatDateForInput(month, locale, "month", inputFormat) : ""); }; // When changing the input field, save its value in state and check if the // string is a valid date. If it is a valid day, set it as selected and update // the calendar’s month. const handleChange = (e) => { setInputValue(e.target.value); const month = parseDate(e.target.value, today, locale, "month", allowTwoDigitYear); const isBefore = getIsBefore({ fromDate, date: month }); const isAfter = getIsAfter({ toDate, date: month }); if (!isValidDate(month) || (disabled && dateMatchModifiers(month, disabled))) { updateMonth(undefined); updateValidation({ isInvalid: isValidDate(month), isDisabled: disabled && dateMatchModifiers(month, disabled), isValidMonth: false, isEmpty: !e.target.value, isBefore: isBefore !== null && isBefore !== void 0 ? isBefore : false, isAfter: isAfter !== null && isAfter !== void 0 ? isAfter : false, }); return; } if (isAfter || isBefore || (fromDate && toDate && !dateMatchModifiers(month, [{ from: fromDate, to: toDate }]))) { updateMonth(undefined); updateValidation({ isValidMonth: false, isBefore: isBefore !== null && isBefore !== void 0 ? isBefore : false, isAfter: isAfter !== null && isAfter !== void 0 ? isAfter : false, }); return; } updateMonth(month); updateValidation(); setYear(month); }; const monthpickerProps = { year, onYearChange: (y) => setYear(y !== null && y !== void 0 ? y : today), onMonthSelect: handleMonthClick, selected: selectedMonth, locale: _locale, fromDate, toDate, open, onOpenToggle: () => handleOpen(!open), onClose: () => { handleOpen(false); anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.focus(); }, disabled, }; const inputProps = { onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, value: inputValue, setAnchorRef, }; return { monthpickerProps, inputProps, reset, selectedMonth, setSelected }; }; //# sourceMappingURL=useMonthPicker.js.map