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