UNPKG

@activecollab/components

Version:

ActiveCollab Components

325 lines (324 loc) • 12.2 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import React, { useState, useCallback, useMemo, useEffect } from "react"; import { SwitchTransition } from "react-transition-group"; import { addMonths, isAfter } from "date-fns"; import moment from "moment"; import { customClassNames, modifiersClassNames } from "./ClassNames"; import { CustomNavBarElement } from "./CustomNavBarElement"; import { StyledDatePicker, StyledDatePickerCSSTransition, StyledDayPicker } from "./Styles"; import { YearMonthPicker } from "../Pickers/YearMonthPicker"; const formatWeekdayName = str => moment(str).format("ddd").charAt(0); export const DatePicker = _ref => { let { className, onChange, onDayClick, selectedDays, disabledDays, selectionMode = "daily", month = new Date(), onMonthChange = () => null, dateRequired = false, firstDayOfWeek = 0, fixedWeeks = true, modifiers: defaultModifiers, renderDay, ...rest } = _ref; const [enteredTo, setEnteredTo] = useState(); const [enteredFrom, setEnteredFrom] = useState(); const [stopScroll, setStopScroll] = useState(); const [direction, setDirection] = useState(true); const [isPreselected, setIsPreselected] = useState(() => { return (selectedDays == null ? void 0 : selectedDays.from) instanceof Date && (selectedDays == null ? void 0 : selectedDays.to) instanceof Date; }); const [showMonthPicker, setShowMonthPicker] = useState(selectionMode === "quarterly" || selectionMode === "monthly"); const [modifiers, setModifiers] = useState(defaultModifiers); const week = firstDayOfWeek === 0 ? "week" : "isoWeek"; useEffect(() => { if (enteredFrom instanceof Date && enteredTo instanceof Date) { setModifiers(prev => { return { ...prev, hovered: { from: enteredFrom, to: enteredTo } }; }); } else { setModifiers(defaultModifiers); } }, [enteredTo, enteredFrom, defaultModifiers]); const handleDayClick = useCallback((day, modifiers) => { if (onDayClick) { onDayClick(day, modifiers); } if (!onChange) { return; } if (month.getMonth() !== day.getMonth()) { onMonthChange(day); } if (modifiers["day_disabled"] || selectionMode === "none") { return; } // reset the selectedDays if the user clicks on the same day if (!dateRequired && (selectedDays != null && selectedDays.from && moment(day).isSame(moment(selectedDays.from), "day") || selectedDays != null && selectedDays.to && moment(day).isSame(moment(selectedDays.to), "day"))) { setEnteredTo(undefined); setEnteredFrom(undefined); return onChange(undefined); } if (selectionMode === "daily") { return onChange({ from: day, to: day }); } if (selectionMode === "weekly") { if (!dateRequired && selectedDays != null && selectedDays.from && moment(day).isSame(moment(selectedDays.from), week)) { return onChange(undefined); } return onChange({ from: moment(day).startOf(week).toDate(), to: moment(day).endOf(week).toDate() }); } if (selectionMode === "custom") { if (isPreselected) { setIsPreselected(false); return onChange({ from: day, to: day }); } if (!selectedDays || selectedDays != null && selectedDays.from && selectedDays != null && selectedDays.to && !moment(selectedDays.from).isSame(moment(selectedDays.to))) { if (!dateRequired && selectedDays != null && selectedDays.from && selectedDays != null && selectedDays.to && moment(day).isBetween(moment(selectedDays.from), moment(selectedDays.to))) { setEnteredTo(day); setEnteredFrom(day); return onChange(undefined); } setEnteredFrom(day); return onChange({ from: day, to: day }); } if (selectedDays != null && selectedDays.from && isAfter(day, selectedDays.from)) { setEnteredTo(undefined); setEnteredFrom(undefined); return onChange({ from: selectedDays.from, to: day }); } if (selectedDays != null && selectedDays.to) { setEnteredTo(undefined); setEnteredFrom(undefined); return onChange({ from: day, to: selectedDays.to }); } return onChange({ from: day, to: day }); } }, [onDayClick, onChange, month, selectionMode, dateRequired, selectedDays, onMonthChange, week, isPreselected]); const isSelectedFirstDay = useCallback(() => { if (selectionMode !== "custom") { return false; } if (selectedDays != null && selectedDays.from && selectedDays != null && selectedDays.to) { return moment(selectedDays.from).isSame(selectedDays.to); } }, [selectionMode, selectedDays]); const handleDayMouseEnter = useCallback(day => { if (isPreselected && selectionMode !== "weekly") { setEnteredTo(day); setEnteredFrom(day); return; } if (selectionMode === "daily") { setEnteredTo(day); setEnteredFrom(day); } if (selectionMode === "weekly") { setEnteredFrom(moment(day).startOf(week).toDate()); setEnteredTo(moment(day).endOf(week).toDate()); } if (selectionMode !== "weekly" && (!selectedDays || selectedDays != null && selectedDays.from && selectedDays != null && selectedDays.to && !moment(selectedDays.from).isSame(moment(selectedDays.to)))) { setEnteredTo(day); setEnteredFrom(day); } if (isSelectedFirstDay() && selectedDays != null && selectedDays.from) { setEnteredFrom(selectedDays.from); setEnteredTo(day); } }, [selectionMode, isSelectedFirstDay, selectedDays, week, isPreselected]); const onDayMouseLeave = useCallback(() => { if (selectionMode === "weekly" || selectionMode === "daily" || selectionMode === "custom") { setEnteredFrom(undefined); setEnteredTo(undefined); } }, [setEnteredFrom, setEnteredTo, selectionMode]); const onWheel = useCallback(e => { if (stopScroll && (new Date().getTime() - stopScroll.getTime()) / 1000 < 0.9) { return; } const nextMonth = showMonthPicker ? addMonths(month, 12) : addMonths(month, 1); const previousMonth = showMonthPicker ? addMonths(month, -12) : addMonths(month, -1); if (e.deltaY > 0.9) { setDirection(true); onMonthChange(nextMonth); setStopScroll(new Date()); } if (e.deltaY < -0.9) { setDirection(false); onMonthChange(previousMonth); setStopScroll(new Date()); } }, [stopScroll, showMonthPicker, month, onMonthChange]); const togglePicker = useCallback(() => { if (selectionMode !== "monthly" && selectionMode !== "quarterly") { return setShowMonthPicker(!showMonthPicker); } setShowMonthPicker(true); }, [showMonthPicker, selectionMode]); const handleYearMonthChange = useCallback(m => { if (onChange) { if (selectionMode === "monthly") { if (!dateRequired && selectedDays != null && selectedDays.from && moment(m).isSame(moment(selectedDays.from), "month")) { return onChange(undefined); } onChange({ from: moment(m).startOf("month").toDate(), to: moment(m).endOf("month").toDate() }); } if (selectionMode === "quarterly") { if (!dateRequired && selectedDays != null && selectedDays.from && moment(m).isSame(moment(selectedDays.from).startOf("quarter"), "quarter")) { return onChange(undefined); } onChange({ from: moment(m).startOf("quarter").toDate(), to: moment(m).endOf("quarter").toDate() }); } } onMonthChange(m); }, [onMonthChange, onChange, selectedDays, selectionMode, dateRequired]); const text = useMemo(() => { if (showMonthPicker) { return "" + month.getFullYear(); } return moment(month).format("MMMM") + " " + (moment(month).isSame(moment(), "year") ? "" : month.getFullYear()); }, [showMonthPicker, month]); const customNavBarElement = useCallback(props => { return /*#__PURE__*/React.createElement("div", { className: "c-DayPicker-wrapper" }, /*#__PURE__*/React.createElement(CustomNavBarElement, _extends({}, props, { showMonthPicker: showMonthPicker, month: month, onChangeDirection: setDirection, onMonthChange: onMonthChange, onClick: togglePicker })), /*#__PURE__*/React.createElement(YearMonthPicker, _extends({}, props, { text: text, onClick: togglePicker, month: month, selectedDays: selectedDays, onChange: handleYearMonthChange, isShown: showMonthPicker, selectionMode: selectionMode }))); }, [showMonthPicker, month, onMonthChange, togglePicker, text, selectedDays, handleYearMonthChange, selectionMode]); const onKeyDownCallback = useCallback(e => { // Right Arrow if (e.key === "ArrowRight") { setDirection(true); if (showMonthPicker) { onMonthChange(new Date(month.getFullYear() + 1, month.getMonth())); } else { onMonthChange(new Date(month.getFullYear(), month.getMonth() + 1)); } } // Left Arrow if (e.key === "ArrowLeft") { setDirection(false); if (showMonthPicker) { onMonthChange(new Date(month.getFullYear() - 1, month.getMonth())); } else { onMonthChange(new Date(month.getFullYear(), month.getMonth() - 1)); } } // Up Arrow if (e.key === "ArrowUp") { setDirection(true); onMonthChange(new Date(month.getFullYear() + 1, month.getMonth())); } // Down Arrow if (e.key === "ArrowDown") { setDirection(false); onMonthChange(new Date(month.getFullYear() - 1, month.getMonth())); } }, [showMonthPicker, onMonthChange, month]); useEffect(() => { document.addEventListener("keydown", onKeyDownCallback); return () => { document.removeEventListener("keydown", onKeyDownCallback); }; }, [month, onMonthChange, showMonthPicker, onKeyDownCallback]); const selected = useMemo(() => { const dates = []; if (!(selectedDays != null && selectedDays.from)) return []; // If from and to dates are the same, return an array with one item if (moment(selectedDays == null ? void 0 : selectedDays.from).isSame(selectedDays == null ? void 0 : selectedDays.to, "day")) { dates.push(selectedDays == null ? void 0 : selectedDays.from); return dates; } let currentDate = moment(selectedDays == null ? void 0 : selectedDays.from); while (currentDate.isSameOrBefore(selectedDays == null ? void 0 : selectedDays.to, "day")) { dates.push(currentDate.toDate()); currentDate = currentDate.add(1, "days"); } return dates; }, [selectedDays == null ? void 0 : selectedDays.from, selectedDays == null ? void 0 : selectedDays.to]); return /*#__PURE__*/React.createElement(StyledDatePicker, { className: "c-date-picker-wrapper", onWheel: onWheel }, /*#__PURE__*/React.createElement(SwitchTransition, { mode: "out-in" }, /*#__PURE__*/React.createElement(StyledDatePickerCSSTransition, { key: showMonthPicker ? month.getFullYear() : month.getMonth(), timeout: 300, classNames: "c-date-picker__animation", $direction: direction }, /*#__PURE__*/React.createElement(StyledDayPicker, _extends({}, rest, { mode: "multiple", showOutsideDays: true, disabled: disabledDays, selected: selected, onDayClick: handleDayClick, modifiers: modifiers, onDayMouseEnter: handleDayMouseEnter, onDayMouseLeave: onDayMouseLeave, className: className, $isYearlyView: showMonthPicker, month: month, components: { Caption: customNavBarElement, DayContent: renderDay }, classNames: customClassNames, modifiersClassNames: modifiersClassNames, fixedWeeks: fixedWeeks, weekStartsOn: firstDayOfWeek, formatters: { formatWeekdayName: formatWeekdayName } }))))); }; DatePicker.displayName = "DatePicker"; //# sourceMappingURL=DatePicker.js.map