@navikt/ds-react
Version:
React components from the Norwegian Labour and Welfare Administration.
175 lines • 7.94 kB
JavaScript
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