UNPKG

@navikt/ds-react

Version:

React components from the Norwegian Labour and Welfare Administration.

320 lines 16.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useRangeDatepicker = void 0; const date_fns_1 = require("date-fns"); const react_1 = require("react"); const react_day_picker_1 = require("react-day-picker"); const i18n_hooks_1 = require("../../../util/i18n/i18n.hooks"); const Date_locale_1 = require("../../Date.locale"); const date_utils_1 = require("../../date-utils"); const getValidationMessage = (from = {}, to = {}) => ({ from: Object.assign({ isDisabled: false, isWeekend: false, isEmpty: false, isInvalid: false, isBefore: false, isAfter: false, isValidDate: true }, from), to: Object.assign({ isDisabled: false, isWeekend: false, isEmpty: false, isInvalid: false, isBefore: false, isAfter: false, isBeforeFrom: false, isValidDate: true }, to), }); const RANGE = { FROM: "FROM", TO: "TO", }; const fromValidation = (day, opt) => { const isBefore = (opt === null || opt === void 0 ? void 0 : opt.fromDate) && day && (0, date_fns_1.differenceInCalendarDays)(opt === null || opt === void 0 ? void 0 : opt.fromDate, day) > 0; const isAfter = (opt === null || opt === void 0 ? void 0 : opt.toDate) && day && (0, date_fns_1.differenceInCalendarDays)(day, opt === null || opt === void 0 ? void 0 : opt.toDate) > 0; if ((0, date_utils_1.isValidDate)(day) && !((opt === null || opt === void 0 ? void 0 : opt.disableWeekends) && (0, date_fns_1.isWeekend)(day)) && !((opt === null || opt === void 0 ? void 0 : opt.disabled) && (0, react_day_picker_1.dateMatchModifiers)(day, opt.disabled))) { return { isValidDate: false, isInvalid: !(0, date_utils_1.isValidDate)(day), isWeekend: (opt === null || opt === void 0 ? void 0 : opt.disableWeekends) && (0, date_fns_1.isWeekend)(day), isDisabled: (opt === null || opt === void 0 ? void 0 : opt.disabled) && (0, react_day_picker_1.dateMatchModifiers)(day, opt.disabled), isBefore, isAfter, }; } if (isBefore || isAfter) { return { isValidDate: false, isBefore, isAfter, }; } }; const toValidation = (day, from, opt) => { var _a; const isBefore = (opt === null || opt === void 0 ? void 0 : opt.fromDate) && day && (0, date_fns_1.differenceInCalendarDays)(opt === null || opt === void 0 ? void 0 : opt.fromDate, day) > 0; const isAfter = (opt === null || opt === void 0 ? void 0 : opt.toDate) && day && (0, date_fns_1.differenceInCalendarDays)(day, opt === null || opt === void 0 ? void 0 : opt.toDate) > 0; const isBeforeFrom = (_a = (from && (0, date_fns_1.differenceInCalendarDays)(from, day) > 0)) !== null && _a !== void 0 ? _a : false; if ((0, date_utils_1.isValidDate)(day) && !((opt === null || opt === void 0 ? void 0 : opt.disableWeekends) && (0, date_fns_1.isWeekend)(day)) && !((opt === null || opt === void 0 ? void 0 : opt.disabled) && (0, react_day_picker_1.dateMatchModifiers)(day, opt.disabled))) { return { isValidDate: false, isInvalid: !(0, date_utils_1.isValidDate)(day), isWeekend: (opt === null || opt === void 0 ? void 0 : opt.disableWeekends) && (0, date_fns_1.isWeekend)(day), isDisabled: (opt === null || opt === void 0 ? void 0 : opt.disabled) && (0, react_day_picker_1.dateMatchModifiers)(day, opt.disabled), isBefore, isAfter, isBeforeFrom, }; } if (isBefore || isAfter || isBeforeFrom) { return { isValidDate: false, isBefore, isAfter, isBeforeFrom, }; } }; const initialValidation = (range, opt) => { if (!range || !(range === null || range === void 0 ? void 0 : range.from)) { return getValidationMessage({ isEmpty: true, isValidDate: false }, { isEmpty: true, isValidDate: false }); } const fromVal = fromValidation(range.from, opt); const toVal = range.to ? toValidation(range.to, range.from, opt) : { isEmpty: true, isValidDate: false }; return getValidationMessage(Object.assign({}, fromVal), Object.assign({}, toVal)); }; /** * * @see 🏷️ {@link UseRangeDatepickerOptions} * @see 🏷️ {@link UseRangeDatepickerValue} * @see 🏷️ {@link RangeValidationT} * @example * const { datepickerProps, fromInputProps, toInputProps } = useRangeDatepicker({ * fromDate: new Date("Aug 23 2019"), * onRangeChange: console.log, * onValidate: console.log, * }); */ const useRangeDatepicker = (opt = {}) => { const { locale: _locale, defaultSelected: _defaultSelected, today = new Date(), fromDate, toDate, disabled, disableWeekends, onRangeChange, inputFormat, onValidate, defaultMonth, allowTwoDigitYear = true, } = opt; const [anchorRef, setAnchorRef] = (0, react_1.useState)(null); const localeFromProvider = (0, i18n_hooks_1.useDateLocale)(); const locale = _locale ? (0, Date_locale_1.getLocaleFromString)(_locale) : localeFromProvider; const [defaultSelected, setDefaultSelected] = (0, react_1.useState)(_defaultSelected); // Initialize states const [month, setMonth] = (0, react_1.useState)((defaultSelected === null || defaultSelected === void 0 ? void 0 : defaultSelected.from) || (defaultSelected === null || defaultSelected === void 0 ? void 0 : defaultSelected.to) || defaultMonth || today); const [selectedRange, setSelectedRange] = (0, react_1.useState)(defaultSelected !== null && defaultSelected !== void 0 ? defaultSelected : { from: undefined, to: undefined }); const [fromInputValue, setFromInputValue] = (0, react_1.useState)((defaultSelected === null || defaultSelected === void 0 ? void 0 : defaultSelected.from) ? (0, date_utils_1.formatDateForInput)(defaultSelected.from, locale, "date", inputFormat) : ""); const [toInputValue, setToInputValue] = (0, react_1.useState)((defaultSelected === null || defaultSelected === void 0 ? void 0 : defaultSelected.to) ? (0, date_utils_1.formatDateForInput)(defaultSelected.to, locale, "date", inputFormat) : ""); const [validation, setValidation] = (0, react_1.useState)(initialValidation(selectedRange, opt)); const [open, setOpen] = (0, react_1.useState)(false); const updateRange = (range) => { onRangeChange === null || onRangeChange === void 0 ? void 0 : onRangeChange(range); setSelectedRange(range); }; const updateValidation = (from = {}, to = {}) => { const msg = getValidationMessage(from, to); setValidation(msg); onValidate === null || onValidate === void 0 ? void 0 : onValidate(msg); }; const reset = () => { updateRange(defaultSelected !== null && defaultSelected !== void 0 ? defaultSelected : { from: undefined, to: undefined }); setMonth((defaultSelected === null || defaultSelected === void 0 ? void 0 : defaultSelected.from) || (defaultSelected === null || defaultSelected === void 0 ? void 0 : defaultSelected.to) || defaultMonth || today); setValidation(initialValidation(defaultSelected !== null && defaultSelected !== void 0 ? defaultSelected : { from: undefined, to: undefined }, opt)); setFromInputValue((defaultSelected === null || defaultSelected === void 0 ? void 0 : defaultSelected.from) ? (0, date_utils_1.formatDateForInput)(defaultSelected.from, locale, "date", inputFormat) : ""); setToInputValue((defaultSelected === null || defaultSelected === void 0 ? void 0 : defaultSelected.to) ? (0, date_utils_1.formatDateForInput)(defaultSelected.to, locale, "date", inputFormat) : ""); setDefaultSelected(_defaultSelected); }; const setSelected = (range) => { updateRange(range); setFromInputValue((range === null || range === void 0 ? void 0 : range.from) ? (0, date_utils_1.formatDateForInput)(range.from, locale, "date", inputFormat) : ""); setToInputValue((range === null || range === void 0 ? void 0 : range.to) ? (0, date_utils_1.formatDateForInput)(range === null || range === void 0 ? void 0 : range.to, locale, "date", inputFormat) : ""); setValidation(initialValidation(range, opt)); }; const handleFocus = (e, src) => { if (e.target.readOnly) { return; } const day = (0, date_utils_1.parseDate)(e.target.value, today, locale, "date", allowTwoDigitYear); if ((0, date_utils_1.isValidDate)(day)) { src === RANGE.FROM ? setFromInputValue((0, date_utils_1.formatDateForInput)(day, locale, "date", inputFormat)) : setToInputValue((0, date_utils_1.formatDateForInput)(day, locale, "date", inputFormat)); const isBefore = fromDate && day && (0, date_fns_1.differenceInCalendarDays)(fromDate, day) > 0; const isAfter = toDate && day && (0, date_fns_1.differenceInCalendarDays)(day, toDate) > 0; !isBefore && !isAfter && setMonth(day); } }; const handleBlur = (e, src) => { const day = (0, date_utils_1.parseDate)(e.target.value, today, locale, "date", allowTwoDigitYear); if (!(0, date_utils_1.isValidDate)(day)) { return; } if (src === RANGE.FROM) { setFromInputValue((0, date_utils_1.formatDateForInput)(day, locale, "date", inputFormat)); } else if (src === RANGE.TO) { setToInputValue((0, date_utils_1.formatDateForInput)(day, locale, "date", inputFormat)); } }; const validateDay = (day) => { return ((0, date_utils_1.isValidDate)(day) && !(disableWeekends && (0, date_fns_1.isWeekend)(day)) && !(disabled && (0, react_day_picker_1.dateMatchModifiers)(day, disabled))); }; const handleSelect = (range) => { if ((range === null || range === void 0 ? void 0 : range.from) && (range === null || range === void 0 ? void 0 : range.to)) { if (!(0, date_fns_1.isSameDay)(range.from, range.to)) { setOpen(false); anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.focus(); } } setFromInputValue((range === null || range === void 0 ? void 0 : range.from) ? (0, date_utils_1.formatDateForInput)(range.from, locale, "date", inputFormat) : ""); setToInputValue((range === null || range === void 0 ? void 0 : range.to) ? (0, date_utils_1.formatDateForInput)(range.to, locale, "date", inputFormat) : ""); updateRange({ from: range === null || range === void 0 ? void 0 : range.from, to: range === null || range === void 0 ? void 0 : range.to }); updateValidation({ isValidDate: !!(range === null || range === void 0 ? void 0 : range.from), isEmpty: !(range === null || range === void 0 ? void 0 : range.from) }, { isValidDate: !!(range === null || range === void 0 ? void 0 : range.to), isEmpty: !(range === null || range === void 0 ? void 0 : range.to) }); }; const fromChange = (val = "", day, isBefore = false, isAfter = false) => { setFromInputValue(val); if (!validateDay(day)) { updateRange(Object.assign(Object.assign({}, selectedRange), { from: undefined })); updateValidation({ isEmpty: !val, isValidDate: false, isInvalid: !(0, date_utils_1.isValidDate)(day), isWeekend: disableWeekends && (0, date_fns_1.isWeekend)(day), isDisabled: disabled && (0, react_day_picker_1.dateMatchModifiers)(day, disabled), isBefore, isAfter, }, validation.to); return; } if (isBefore || isAfter) { updateRange(Object.assign(Object.assign({}, selectedRange), { from: undefined })); updateValidation({ isValidDate: false, isBefore, isAfter, }, validation.to); return; } if ((selectedRange === null || selectedRange === void 0 ? void 0 : selectedRange.to) && (0, date_fns_1.differenceInCalendarDays)(day, selectedRange === null || selectedRange === void 0 ? void 0 : selectedRange.to) > 0) { updateRange({ to: day, from: day }); setToInputValue((0, date_utils_1.formatDateForInput)(day, locale, "date", inputFormat)); setMonth(day); updateValidation(); return; } if (toInputValue && !(selectedRange === null || selectedRange === void 0 ? void 0 : selectedRange.to)) { const toDay = (0, date_utils_1.parseDate)(toInputValue, today, locale, "date", allowTwoDigitYear); if (validateDay(toDay)) { updateRange({ from: day, to: toDay }); setMonth(day); updateValidation(); return; } } updateRange(Object.assign(Object.assign({}, selectedRange), { from: day })); updateValidation({}, validation.to); setMonth(day); }; const toChange = (val = "", day, isBefore = false, isAfter = false) => { setToInputValue(val); if (!validateDay(day)) { updateRange({ from: selectedRange === null || selectedRange === void 0 ? void 0 : selectedRange.from, to: undefined }); updateValidation(validation.from, { isEmpty: !val, isValidDate: false, isInvalid: !(0, date_utils_1.isValidDate)(day), isWeekend: disableWeekends && (0, date_fns_1.isWeekend)(day), isDisabled: disabled && (0, react_day_picker_1.dateMatchModifiers)(day, disabled), isBefore, isAfter, }); return; } if (isBefore || isAfter) { updateRange({ from: selectedRange === null || selectedRange === void 0 ? void 0 : selectedRange.from, to: undefined }); updateValidation(validation.from, { isValidDate: false, isBefore, isAfter, }); return; } /* If to-value < from-value */ if ((selectedRange === null || selectedRange === void 0 ? void 0 : selectedRange.from) && (0, date_fns_1.differenceInCalendarDays)(selectedRange === null || selectedRange === void 0 ? void 0 : selectedRange.from, day) > 0) { updateRange({ from: selectedRange === null || selectedRange === void 0 ? void 0 : selectedRange.from, to: undefined }); updateValidation(validation.from, { isValidDate: false, isBeforeFrom: true, }); return; } updateRange({ from: selectedRange === null || selectedRange === void 0 ? void 0 : selectedRange.from, to: day }); updateValidation(validation.from, {}); setMonth(day); }; /* live-update datepicker based on changes in inputfields */ const handleChange = (e, src) => { const day = (0, date_utils_1.parseDate)(e.target.value, today, locale, "date", allowTwoDigitYear); const isBefore = fromDate && (0, date_fns_1.differenceInCalendarDays)(fromDate, day) > 0; const isAfter = toDate && (0, date_fns_1.differenceInCalendarDays)(day, toDate) > 0; return src === RANGE.FROM ? fromChange(e.target.value, day, isBefore, isAfter) : toChange(e.target.value, day, isBefore, isAfter); }; const datepickerProps = { month, onMonthChange: setMonth, onSelect: handleSelect, selected: selectedRange, locale: _locale, fromDate, toDate, today, mode: "range", open, onOpenToggle: () => setOpen((x) => !x), onClose: () => { setOpen(false); anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.focus(); }, disabled, disableWeekends, }; const fromInputProps = { onChange: (e) => handleChange(e, RANGE.FROM), onFocus: (e) => handleFocus(e, RANGE.FROM), onBlur: (e) => handleBlur(e, RANGE.FROM), value: fromInputValue, setAnchorRef, }; const toInputProps = { onChange: (e) => handleChange(e, RANGE.TO), onFocus: (e) => handleFocus(e, RANGE.TO), onBlur: (e) => handleBlur(e, RANGE.TO), value: toInputValue, setAnchorRef, }; return { datepickerProps, fromInputProps, toInputProps, reset, selectedRange, setSelected, }; }; exports.useRangeDatepicker = useRangeDatepicker; //# sourceMappingURL=useRangeDatepicker.js.map