@drivy/cobalt
Version:
Opinionated design system for Drivy's projects.
202 lines (201 loc) • 11 kB
JavaScript
import { jsx, jsxs } from "react/jsx-runtime";
import classnames from "classnames";
import { differenceInCalendarDays, format, isSameDay } from "date-fns";
import { useCallback, useMemo } from "react";
import { getMonthDaysByWeeks, getWeekDays } from "../utils.js";
import { CalendarRangePickerDay } from "./CalendarRangePickerDay.js";
function isDisabled(day, firstAvailableDate, lastAvailableDate) {
return day.getTime() < firstAvailableDate.getTime() || null != lastAvailableDate && day.getTime() > lastAvailableDate.getTime();
}
function isInvalidOppositeBound({ isEditingStartDate, isEditingEndDate, isStartDay, isEndDay, startDate, endDate }) {
return null != startDate && null != endDate && startDate > endDate && (isEditingStartDate && isEndDay || isEditingEndDate && isStartDay);
}
function isDayOutOfRange({ day, rangeConstraints, startDate }) {
return null != rangeConstraints && null != rangeConstraints.max && null != startDate && differenceInCalendarDays(day, startDate) >= rangeConstraints.max.value;
}
function isDayInvalid({ day, isDaySelected, rangeConstraints, rangeTooShort, rangeExceeded, isEditingStartDate, isEditingEndDate, isStartDay, isEndDay, isDayInvalidForSelectionFn, startDate, endDate }) {
if (!isDaySelected) return false;
let isInvalid = false;
isInvalid = isEditingStartDate || isEditingEndDate ? rangeTooShort && (!isStartDay || isEndDay) ? true : isInvalidOppositeBound({
isEditingStartDate,
isEditingEndDate,
isStartDay,
isEndDay,
startDate,
endDate
}) ? true : isDayOutOfRange({
day,
rangeConstraints,
startDate
}) : rangeTooShort || rangeExceeded;
if (!isInvalid && isDayInvalidForSelectionFn && (isEditingStartDate && isStartDay || isEditingEndDate && isEndDay)) isInvalid = isDayInvalidForSelectionFn(day);
return isInvalid;
}
function isSelected({ day, startDate, endDate, isStartDay, isEndDay, isOutOfRangeStartDate, rangeTooShort, isEditingStartDate, isEditingEndDate }) {
return !!(isStartDay || isEndDay || (!rangeTooShort || !isEditingStartDate && !isEditingEndDate) && !isOutOfRangeStartDate && endDate && day.getTime() <= endDate.getTime() && startDate && day.getTime() > startDate.getTime());
}
function isRangeExceeded(rangeInDays, rangeLimit) {
return null != rangeLimit && rangeInDays > rangeLimit;
}
function isRangeTooShort(rangeInDays, rangeLimit) {
return rangeInDays <= 0 ? false : null != rangeLimit && rangeInDays < rangeLimit;
}
function buildTooltipMessage({ rangeInDays, isEditingStartDate, isStartDay, isEditingEndDate, isEndDay, rangeConstraints }) {
let tooltipMessage;
if (rangeConstraints && rangeInDays >= 0 && (isEditingStartDate && isStartDay || isEditingEndDate && isEndDay)) {
if (isRangeTooShort(rangeInDays, rangeConstraints.min?.value)) tooltipMessage = rangeConstraints?.min?.message;
else if (isRangeExceeded(rangeInDays, rangeConstraints.max?.value)) tooltipMessage = rangeConstraints?.max?.message;
}
return tooltipMessage;
}
function getRangeInDays(range) {
return range.startDate && range.endDate ? differenceInCalendarDays(range.endDate, range.startDate) + 1 : 0;
}
function CalendarRangePickerMonth({ date, onSelectDate, onChangeDate, onLeaveDate, startDate, endDate, isEditingStartDate = false, isEditingEndDate = false, firstAvailableDate, lastAvailableDate, isDayDisabledFn, isDayInvalidForSelectionFn, hasDayNotificationFn, dayHoverTooltipFn, rangeConstraints, isSundayFirstDayOfWeek, locale }) {
const byWeeks = useMemo(()=>getMonthDaysByWeeks(date, isSundayFirstDayOfWeek), [
date,
isSundayFirstDayOfWeek
]);
const today = new Date().setHours(0, 0, 0, 0);
const weekdays = useMemo(()=>getWeekDays(isSundayFirstDayOfWeek), [
isSundayFirstDayOfWeek
]);
const rangeInDays = getRangeInDays({
startDate,
endDate
});
const rangeExceeded = isRangeExceeded(rangeInDays, rangeConstraints?.max?.value);
const rangeTooShort = isRangeTooShort(rangeInDays, rangeConstraints?.min?.value);
const isOutOfRangeStartDate = isEditingStartDate && rangeExceeded;
const onMouseEnter = (day, disabled)=>{
const status = {};
if (disabled) status.isDisabled = true;
if (!disabled && endDate && startDate) {
const currentRange = isEditingStartDate ? {
startDate: day,
endDate: endDate
} : {
startDate: startDate,
endDate: day
};
const currentRangeInDays = getRangeInDays({
startDate: currentRange.startDate,
endDate: currentRange.endDate
});
const currentRangeExceeded = isRangeExceeded(currentRangeInDays, rangeConstraints?.max?.value);
if (currentRangeExceeded) status.isRangeExceeded = true;
else {
const currentRangeTooShort = isRangeTooShort(currentRangeInDays, rangeConstraints?.min?.value);
if (currentRangeTooShort) status.isRangeTooShort = true;
else status.isCustomInvalid = isDayInvalidForSelectionFn?.(day);
}
}
onChangeDate(day, status);
};
const onSelectDateCallback = useCallback((date)=>{
isEditingStartDate ? onSelectDate(date, isRangeExceeded(getRangeInDays({
startDate: date,
endDate
}), rangeConstraints?.max?.value)) : onSelectDate(date, isRangeExceeded(getRangeInDays({
startDate,
endDate: date
}), rangeConstraints?.max?.value));
}, [
isEditingStartDate,
onSelectDate,
rangeConstraints?.max?.value,
startDate,
endDate
]);
return /*#__PURE__*/ jsxs("div", {
className: classnames("cobalt-CalendarRangePicker__month", {
"cobalt-CalendarRangePicker__month--invalid": rangeExceeded && !isEditingStartDate
}),
"data-month": format(date, "yyyy-MM"),
children: [
/*#__PURE__*/ jsx("div", {
className: "cobalt-CalendarRangePicker__month-header",
children: format(date, "MMMM yyyy", {
locale
})
}),
/*#__PURE__*/ jsxs("div", {
className: "cobalt-CalendarRangePicker__month__weeks-container",
children: [
/*#__PURE__*/ jsx("div", {
className: "cobalt-CalendarRangePicker__month__week-header",
children: weekdays.map((weekday)=>/*#__PURE__*/ jsx("div", {
className: "cobalt-CalendarRangePicker__month__day-header",
children: format(weekday, "iiiiii", {
locale
})
}, weekday.getTime()))
}),
byWeeks.map((week, index)=>/*#__PURE__*/ jsx("div", {
className: "cobalt-CalendarRangePicker__month__week",
children: week.map((day)=>{
const isStartDay = null != startDate && isSameDay(day, startDate);
const isEndDay = null != endDate && isSameDay(day, endDate);
const disabled = isDisabled(day, firstAvailableDate, lastAvailableDate) || isDayDisabledFn?.(day);
const hasNotification = !disabled && null != hasDayNotificationFn && hasDayNotificationFn(day);
const isRange = 0 !== rangeInDays && (isStartDay || isEndDay) && (!rangeTooShort || !isEditingStartDate && !isEditingEndDate);
const isDaySelected = isSelected({
day,
startDate,
endDate,
isStartDay,
isEndDay,
isOutOfRangeStartDate,
rangeTooShort,
isEditingStartDate,
isEditingEndDate
});
const tooltip = buildTooltipMessage({
rangeInDays,
isEditingStartDate: !!isEditingStartDate,
isEditingEndDate: !!isEditingEndDate,
isStartDay,
isEndDay,
rangeConstraints
});
return /*#__PURE__*/ jsx(CalendarRangePickerDay, {
date: day,
onMouseEnter: onMouseEnter,
onMouseLeave: onLeaveDate,
onSelect: onSelectDateCallback,
isToday: isSameDay(day, today),
isActive: isEditingStartDate && isStartDay || isEditingEndDate && isEndDay,
isStartDay: isStartDay,
isEndDay: isEndDay,
isRange: isRange,
isEditingStartDate: isEditingStartDate,
isEditingEndDate: isEditingEndDate,
isInvalid: isDayInvalid({
day,
isDayInvalidForSelectionFn,
isDaySelected,
startDate,
rangeConstraints,
rangeTooShort,
rangeExceeded,
isEditingStartDate,
isEditingEndDate,
isStartDay,
isEndDay,
endDate
}),
hasNotification: hasNotification,
isDisabled: disabled,
tooltipMessage: tooltip,
hoverTooltipMessage: dayHoverTooltipFn ? dayHoverTooltipFn(day) : void 0,
isSelected: isDaySelected
}, day.getTime());
})
}, `week-${index}-${week.map((day)=>day.getTime()).join("-")}`))
]
})
]
});
}
export { CalendarRangePickerMonth };
//# sourceMappingURL=CalendarRangePickerMonth.js.map