react-next-dates
Version:
Simple and Customizable DatePicker, DateRangePicker and TimePicker for React.
1,633 lines (1,419 loc) • 62.6 kB
JavaScript
import React, { useMemo, useState, useRef, useEffect, Fragment, forwardRef, useLayoutEffect } from 'react';
import { getDate, isToday, differenceInDays, startOfWeek, format, parse, isValid, isBefore, startOfDay, isAfter, set, eachDayOfInterval, endOfWeek, startOfMonth, endOfMonth, subYears, subMonths, addYears, addMonths, isThisYear, getYear, eachYearOfInterval, setYear, isThisMonth, setMonth, startOfYear, setDate, getHours, getMinutes, setHours, setMinutes, isEqual, isSameDay, isSameYear, isSameMonth } from 'date-fns';
import classNames from 'classnames';
import { usePopper } from 'react-popper';
import { createPortal } from 'react-dom';
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
var DEFAULT_MODIFIERS_CLASS_NAMES = {
disabled: '-disabled',
selected: '-selected',
today: '-today',
selectedStart: '-selected-start',
selectedMiddle: '-selected-middle',
selectedEnd: '-selected-end'
};
function mergeModifiers(baseModifiers, extendsModifiers) {
if (baseModifiers === void 0) {
baseModifiers = {};
}
if (extendsModifiers === void 0) {
extendsModifiers = {};
}
var newModifiers = Object.keys(extendsModifiers).reduce(function (modifiers, key) {
var _extends2;
return _extends({}, modifiers, (_extends2 = {}, _extends2[key] = baseModifiers[key] ? function (date) {
return baseModifiers[key](date) || extendsModifiers[key](date);
} : extendsModifiers[key], _extends2));
}, {});
return _extends({}, baseModifiers, newModifiers);
}
function mergeCalendarModifiers(baseModifiers, extendsModifiers) {
if (baseModifiers === void 0) {
baseModifiers = {};
}
if (extendsModifiers === void 0) {
extendsModifiers = {};
}
var newModifiers = Object.keys(extendsModifiers).reduce(function (calendarModifiers, curr) {
var _extends3;
return _extends({}, calendarModifiers, (_extends3 = {}, _extends3[curr] = mergeModifiers(baseModifiers[curr], extendsModifiers[curr]), _extends3));
}, {});
return _extends({}, baseModifiers, newModifiers);
}
function computeModifierClassNames(modifiers, modifiersClassNames) {
if (modifiers === void 0) {
modifiers = {};
}
if (modifiersClassNames === void 0) {
modifiersClassNames = {};
}
var allClassNames = _extends({}, DEFAULT_MODIFIERS_CLASS_NAMES, modifiersClassNames);
return function (date) {
return Object.keys(modifiers).reduce(function (acc, curr) {
var className = allClassNames[curr];
var predicate = modifiers[curr];
if (className && predicate) {
var _extends4;
return _extends({}, acc, (_extends4 = {}, _extends4[className] = predicate(date), _extends4));
}
return acc;
}, {});
};
}
var CalendarDay = function CalendarDay(_ref) {
var locale = _ref.locale,
day = _ref.day,
receivedModifiers = _ref.modifiers,
modifiersClassNames = _ref.modifiersClassNames,
onClick = _ref.onClick,
onHover = _ref.onHover;
var dayNumber = getDate(day);
var handleClick = function handleClick() {
return onClick(day);
};
var handleMouseEnter = function handleMouseEnter() {
return onHover(day);
};
var handleMouseLeave = function handleMouseLeave() {
return onHover(null);
};
var modifiers = mergeModifiers({
today: function today(date) {
return isToday(date);
}
}, receivedModifiers);
var dayClassNames = computeModifierClassNames(modifiers, modifiersClassNames)(day);
var gridColumnStart = useMemo(function () {
if (getDate(day) === 1) {
return differenceInDays(day, startOfWeek(day, {
locale: locale
})) + 1;
}
return undefined;
}, [day, locale]);
return React.createElement("span", {
className: classNames('day', dayClassNames),
onClick: handleClick,
onMouseEnter: handleMouseEnter,
onMouseLeave: handleMouseLeave,
style: {
gridColumnStart: gridColumnStart
}
}, React.createElement("span", {
className: "day-number"
}, dayNumber));
};
function getDefaultDateFormat(locale, formatString) {
var _ref, _locale$formatLong;
return (_ref = formatString != null ? formatString : (_locale$formatLong = locale.formatLong) == null ? void 0 : _locale$formatLong.date({
width: 'short'
})) != null ? _ref : 'MM/dd/yyyy';
}
function parseDate(value, formatString, locale) {
var parsedDate = parse(value, formatString, new Date(), {
locale: locale
});
if (isValid(parsedDate)) {
return parsedDate;
}
return null;
}
function formatDate(date, formatString, locale) {
return format(date, formatString, {
locale: locale
});
}
function isDateInRange(date, minDate, maxDate) {
return !(minDate ? isBefore(date, startOfDay(minDate)) : false) && !(maxDate ? isAfter(date, maxDate) : false);
}
function setTime(date, dateWithTime) {
return set(date, {
hours: dateWithTime.getHours(),
minutes: dateWithTime.getMinutes(),
seconds: dateWithTime.getSeconds(),
milliseconds: dateWithTime.getMilliseconds()
});
}
function setTimeOrRemoveTime(date, dateWithTime) {
return dateWithTime ? setTime(date, dateWithTime) : startOfDay(date);
}
function isRangeLengthValid(startDate, endDate, minLength, maxLength) {
var start = startOfDay(startDate);
var end = startOfDay(endDate);
return differenceInDays(end, start) >= minLength && (!maxLength || differenceInDays(end, start) <= maxLength);
}
var CalendarDayHeader = function CalendarDayHeader(_ref) {
var locale = _ref.locale;
var weekDays = useMemo(function () {
var today = new Date();
return eachDayOfInterval({
start: startOfWeek(today, {
locale: locale
}),
end: endOfWeek(today, {
locale: locale
})
}).map(function (date) {
return formatDate(date, 'eeeee', locale);
});
}, [locale]);
return React.createElement("div", {
className: "day-header"
}, weekDays.map(function (day, i) {
return React.createElement("span", {
key: i
}, day);
}));
};
var CalendarDayGrid = function CalendarDayGrid(_ref) {
var locale = _ref.locale,
month = _ref.month,
modifiers = _ref.modifiers,
modifiersClassNames = _ref.modifiersClassNames,
onSelect = _ref.onSelect,
onHover = _ref.onHover;
var days = useMemo(function () {
return eachDayOfInterval({
start: startOfMonth(month),
end: endOfMonth(month)
});
}, [month]);
return React.createElement("div", {
className: "day-grid"
}, React.createElement(CalendarDayHeader, {
locale: locale
}), React.createElement("div", {
className: "day-grid-content"
}, days.map(function (day) {
return React.createElement(CalendarDay, {
key: day.toISOString(),
locale: locale,
day: day,
modifiers: modifiers,
modifiersClassNames: modifiersClassNames,
onClick: onSelect,
onHover: onHover
});
})));
};
var CalendarNavigation = function CalendarNavigation(_ref) {
var locale = _ref.locale,
month = _ref.month,
mode = _ref.mode,
onChangeMonth = _ref.onChangeMonth,
onChangeMode = _ref.onChangeMode;
var title = useMemo(function () {
switch (mode) {
case 'day':
return formatDate(month, 'LLLL yyyy', locale);
case 'month':
return formatDate(month, 'yyyy', locale);
default:
return null;
}
}, [month, mode, locale]);
var handlePrev = function handlePrev() {
switch (mode) {
case 'day':
onChangeMonth(startOfMonth(subMonths(month, 1)));
break;
case 'month':
onChangeMonth(startOfMonth(subYears(month, 1)));
break;
case 'year':
onChangeMonth(startOfMonth(subYears(month, 24)));
break;
}
};
var handleNext = function handleNext() {
switch (mode) {
case 'day':
onChangeMonth(startOfMonth(addMonths(month, 1)));
break;
case 'month':
onChangeMonth(startOfMonth(addYears(month, 1)));
break;
case 'year':
onChangeMonth(startOfMonth(addYears(month, 24)));
break;
}
};
var handleTitleClick = function handleTitleClick() {
switch (mode) {
case 'day':
onChangeMode('month');
break;
case 'month':
onChangeMode('year');
break;
}
};
return React.createElement("div", {
className: "navigation"
}, React.createElement("div", null, title && React.createElement("p", {
onClick: handleTitleClick
}, title)), React.createElement("button", {
type: "button",
className: "prev",
onClick: handlePrev
}), React.createElement("button", {
type: "button",
className: "next",
onClick: handleNext
}));
};
var CalendarYear = function CalendarYear(_ref) {
var year = _ref.year,
receivedModifiers = _ref.modifiers,
modifiersClassNames = _ref.modifiersClassNames,
onSelect = _ref.onSelect;
var handleClick = function handleClick() {
return onSelect(year);
};
var modifiers = mergeModifiers({
today: function today(date) {
return isThisYear(date);
}
}, receivedModifiers);
var yearClassNames = computeModifierClassNames(modifiers, modifiersClassNames)(year);
return React.createElement("span", {
className: classNames('year', yearClassNames),
onClick: handleClick
}, year.getFullYear());
};
var CalendarYearGrid = function CalendarYearGrid(_ref) {
var month = _ref.month,
modifiers = _ref.modifiers,
modifiersClassNames = _ref.modifiersClassNames,
onYearChange = _ref.onYearChange;
var years = useMemo(function () {
var gridStartYear = Math.floor(getYear(month) / 24) * 24;
return eachYearOfInterval({
start: setYear(month, gridStartYear),
end: setYear(month, gridStartYear + 23)
});
}, [month]);
return React.createElement("div", {
className: "year-grid"
}, years.map(function (year) {
return React.createElement(CalendarYear, {
key: year.getFullYear(),
year: year,
modifiers: modifiers,
modifiersClassNames: modifiersClassNames,
onSelect: onYearChange
});
}));
};
var CalendarMonth = function CalendarMonth(_ref) {
var locale = _ref.locale,
month = _ref.month,
receivedModifiers = _ref.modifiers,
modifiersClassNames = _ref.modifiersClassNames,
onSelect = _ref.onSelect;
var handleClick = function handleClick() {
return onSelect(month);
};
var modifiers = mergeModifiers({
today: function today(date) {
return isThisMonth(date);
}
}, receivedModifiers);
var monthClassNames = computeModifierClassNames(modifiers, modifiersClassNames)(month);
return React.createElement("span", {
className: classNames('month', monthClassNames),
onClick: handleClick
}, formatDate(month, 'LLLL', locale));
};
var CalendarMonthGrid = function CalendarMonthGrid(_ref) {
var locale = _ref.locale,
month = _ref.month,
modifiers = _ref.modifiers,
modifiersClassNames = _ref.modifiersClassNames,
onMonthChange = _ref.onMonthChange;
var months = useMemo(function () {
return Array(12).fill('').map(function (_, i) {
return setMonth(month, i);
}, locale);
}, [locale, month]);
return React.createElement("div", {
className: "month-grid"
}, months.map(function (m) {
return React.createElement(CalendarMonth, {
key: m.toISOString(),
locale: locale,
month: m,
modifiers: modifiers,
modifiersClassNames: modifiersClassNames,
onSelect: onMonthChange
});
}));
};
function useDependentState(factory, inputs) {
var _useState = useState(factory()),
state = _useState[0],
setState = _useState[1];
useMemo(function () {
var newState = factory(state);
if (newState !== state) {
setState(newState);
} // eslint-disable-next-line react-hooks/exhaustive-deps
}, inputs);
return [state, setState];
}
function useControllableState(initialValue, value, onChange) {
var _useState2 = useState(initialValue),
state = _useState2[0],
setState = _useState2[1];
return onChange && value ? [value, onChange] : [state, setState];
}
function useOutsideClickHandler(callback) {
var refA = useRef(null);
var refB = useRef(null);
var refC = useRef(null);
var refD = useRef(null);
var refE = useRef(null);
useEffect(function () {
var handleClickOutside = function handleClickOutside(e) {
var _refA$current, _refB$current, _refC$current, _refD$current, _refE$current;
if (e.target instanceof Element && !((_refA$current = refA.current) != null && _refA$current.contains(e.target)) && !((_refB$current = refB.current) != null && _refB$current.contains(e.target)) && !((_refC$current = refC.current) != null && _refC$current.contains(e.target)) && !((_refD$current = refD.current) != null && _refD$current.contains(e.target)) && !((_refE$current = refE.current) != null && _refE$current.contains(e.target))) {
callback();
}
};
document.addEventListener('mousedown', handleClickOutside, {
passive: true
});
return function () {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [callback]);
return [refA, refB, refC, refD, refE];
}
function usePrevious(value) {
var ref = useRef(value);
useEffect(function () {
ref.current = value;
});
return ref.current;
}
function useDetectTouch() {
var _useState3 = useState(false),
isTouch = _useState3[0],
setIsTouch = _useState3[1];
useEffect(function () {
var handleTouch = function handleTouch() {
setIsTouch(true);
removeListener();
};
var removeListener = function removeListener() {
document.removeEventListener('touchstart', handleTouch);
};
document.addEventListener('touchstart', handleTouch);
return removeListener;
}, []);
return isTouch;
}
function constVoid() {}
var Calendar = function Calendar(_ref) {
var locale = _ref.locale,
_ref$type = _ref.type,
type = _ref$type === void 0 ? 'day' : _ref$type,
receivedMonth = _ref.month,
minDate = _ref.minDate,
maxDate = _ref.maxDate,
receivedModifiers = _ref.modifiers,
modifiersClassNames = _ref.modifiersClassNames,
className = _ref.className,
onMonthChange = _ref.onMonthChange,
_ref$onSelect = _ref.onSelect,
onSelect = _ref$onSelect === void 0 ? constVoid : _ref$onSelect,
_ref$onHover = _ref.onHover,
onHover = _ref$onHover === void 0 ? constVoid : _ref$onHover;
var _useDependentState = useDependentState(function () {
return type;
}, [type]),
mode = _useDependentState[0],
setMode = _useDependentState[1];
var _useControllableState = useControllableState(function () {
return startOfMonth(new Date());
}, receivedMonth != null ? receivedMonth : undefined, onMonthChange),
month = _useControllableState[0],
setMonth = _useControllableState[1];
var modifiers = mergeCalendarModifiers({
day: {
disabled: function disabled(date) {
return !isDateInRange(date, minDate, maxDate);
}
},
month: {
disabled: function disabled(date) {
return (minDate ? isBefore(startOfMonth(date), startOfMonth(minDate)) : false) || (maxDate ? isAfter(startOfMonth(date), startOfMonth(maxDate)) : false);
}
},
year: {
disabled: function disabled(date) {
return (minDate ? isBefore(startOfYear(date), startOfYear(minDate)) : false) || (maxDate ? isAfter(startOfYear(date), startOfYear(maxDate)) : false);
}
}
}, receivedModifiers);
var handleSelectYear = function handleSelectYear(year) {
setMonth(year);
if (type !== 'year') {
setMode('month');
} else {
onSelect(set(year, {
date: 1,
month: 0
}));
}
};
var handleSelectMonth = function handleSelectMonth(month) {
setMonth(month);
if (type !== 'month') {
setMode('day');
} else {
onSelect(setDate(month, 1));
}
};
return React.createElement("div", {
className: classNames('react-next-dates', 'calendar', className)
}, React.createElement(CalendarNavigation, {
locale: locale,
month: month,
mode: mode,
onChangeMonth: setMonth,
onChangeMode: setMode
}), mode === 'day' ? React.createElement(CalendarDayGrid, {
locale: locale,
month: month,
modifiers: modifiers.day,
modifiersClassNames: modifiersClassNames == null ? void 0 : modifiersClassNames.day,
onSelect: onSelect,
onHover: onHover
}) : mode === 'year' ? React.createElement(CalendarYearGrid, {
month: month,
modifiers: modifiers.year,
modifiersClassNames: modifiersClassNames == null ? void 0 : modifiersClassNames.year,
onYearChange: handleSelectYear
}) : React.createElement(CalendarMonthGrid, {
locale: locale,
month: month,
modifiers: modifiers.month,
modifiersClassNames: modifiersClassNames == null ? void 0 : modifiersClassNames.month,
onMonthChange: handleSelectMonth
}));
};
var CLOCK_ITEM_WIDTH = 24;
var HOUR_ANGLE = 30; // 360 / 12
var MINUTE_ANGLE = 6; // 360 / 50
function getClockItemPosition(index, containerRadius, radius) {
return {
top: radius * Math.sin(HOUR_ANGLE * (index - 2) * (Math.PI / 180)) + containerRadius - CLOCK_ITEM_WIDTH / 2,
left: radius * Math.cos(HOUR_ANGLE * (index - 2) * (Math.PI / 180)) + containerRadius - CLOCK_ITEM_WIDTH / 2
};
}
function format2Digits(val) {
return "" + (val < 10 ? '0' : '') + val;
}
var ClockAMHour = function ClockAMHour(_ref) {
var date = _ref.date,
index = _ref.index,
containerRadius = _ref.containerRadius;
var label = index + 1;
return React.createElement("span", {
className: classNames({
selected: date && getHours(date) === label
}),
style: getClockItemPosition(index, containerRadius, containerRadius - 20)
}, label);
};
var ClockPMHour = function ClockPMHour(_ref2) {
var date = _ref2.date,
index = _ref2.index,
containerRadius = _ref2.containerRadius;
var hour = index + 13;
var label = hour === 24 ? '00' : "" + hour;
return React.createElement("span", {
className: classNames({
selected: date && format(date, 'HH') === label
}),
style: getClockItemPosition(index, containerRadius, containerRadius / 2)
}, label);
};
var ClockHours = function ClockHours(_ref3) {
var date = _ref3.date,
containerRadius = _ref3.containerRadius;
return React.createElement(React.Fragment, null, Array(12).fill('').map(function (_, index) {
return React.createElement(Fragment, {
key: index
}, React.createElement(ClockAMHour, {
date: date,
index: index,
containerRadius: containerRadius
}), React.createElement(ClockPMHour, {
date: date,
index: index,
containerRadius: containerRadius
}));
}));
};
var ClockMinute = function ClockMinute(_ref) {
var date = _ref.date,
precision = _ref.precision,
index = _ref.index,
containerRadius = _ref.containerRadius;
var value = index === 11 ? 0 : (index + 1) * 5;
var label = format2Digits(value);
return value % precision === 0 ? React.createElement("span", {
className: classNames({
selected: date && format(date, 'mm') === label
}),
style: getClockItemPosition(index, containerRadius, containerRadius - 20)
}, label) : null;
};
var ClockMinutes = function ClockMinutes(_ref2) {
var date = _ref2.date,
containerRadius = _ref2.containerRadius,
precision = _ref2.precision;
return React.createElement(React.Fragment, null, Array(12).fill('').map(function (_, index) {
return React.createElement(ClockMinute, {
key: index,
date: date,
precision: precision,
index: index,
containerRadius: containerRadius
});
}));
};
var ClockNavigation = function ClockNavigation(_ref) {
var locale = _ref.locale,
date = _ref.date,
showNav = _ref.showNav,
selection = _ref.selection,
onSelectionChange = _ref.onSelectionChange;
var handlePrev = function handlePrev() {
return onSelectionChange('hours');
};
var handleNext = function handleNext() {
return onSelectionChange('minutes');
};
return React.createElement("div", {
className: "navigation"
}, showNav && selection === 'minutes' && React.createElement("button", {
type: "button",
className: "prev",
onClick: handlePrev
}), React.createElement("p", null, date ? formatDate(date, 'HH:mm', locale) : '--:--'), showNav && selection === 'hours' && React.createElement("button", {
type: "button",
className: "next",
onClick: handleNext
}));
};
function getSelectionAngle(date, selection) {
if (selection === 'hours') {
return HOUR_ANGLE * (getHours(date) - 3);
} else {
return MINUTE_ANGLE * (getMinutes(date) - 15);
}
}
var Clock = function Clock(_ref) {
var locale = _ref.locale,
receivedDate = _ref.date,
receivedSelection = _ref.selection,
_ref$precision = _ref.precision,
precision = _ref$precision === void 0 ? 1 : _ref$precision,
_ref$vibrate = _ref.vibrate,
vibrate = _ref$vibrate === void 0 ? true : _ref$vibrate,
className = _ref.className,
_ref$onChange = _ref.onChange,
onChange = _ref$onChange === void 0 ? constVoid : _ref$onChange,
onSelectionChange = _ref.onSelectionChange,
_ref$onSelectionEnd = _ref.onSelectionEnd,
onSelectionEnd = _ref$onSelectionEnd === void 0 ? constVoid : _ref$onSelectionEnd;
var containerRef = useRef(null);
var isDragging = useRef(false);
var _useState = useState(function () {
return receivedDate != null ? receivedDate : null;
}),
date = _useState[0],
setDate = _useState[1];
var _useState2 = useState(function () {
var _containerRef$current, _containerRef$current2;
return (_containerRef$current = (_containerRef$current2 = containerRef.current) == null ? void 0 : _containerRef$current2.clientWidth) != null ? _containerRef$current : null;
}),
containerWidth = _useState2[0],
setContainerWidth = _useState2[1];
var _useControllableState = useControllableState(function () {
return 'hours';
}, receivedSelection, onSelectionChange),
selection = _useControllableState[0],
setSelection = _useControllableState[1];
var isTouch = useDetectTouch();
useEffect(function () {
var getContainerWidth = function getContainerWidth() {
if (containerRef.current) {
setContainerWidth(containerRef.current.clientWidth);
}
};
window.addEventListener('resize', getContainerWidth, {
passive: true
});
getContainerWidth();
return function () {
window.removeEventListener('resize', getContainerWidth);
};
}, []);
useEffect(function () {
setDate(receivedDate != null ? receivedDate : null);
}, [receivedDate]);
var handleDateChange = function handleDateChange(date, fireChange) {
setDate(function (d) {
if (d === null || !isEqual(d, date)) {
if (vibrate && 'vibrate' in navigator) {
navigator.vibrate(10);
}
return date;
}
return d;
});
if (fireChange && (receivedDate == null || !isEqual(receivedDate, date))) {
onChange(date);
}
};
var handleCalcSelected = function handleCalcSelected(currentTarget, clientX, clientY, fireChange) {
if (fireChange === void 0) {
fireChange = false;
}
var rect = currentTarget.getBoundingClientRect();
var containerRadius = rect.width / 2;
var x = clientX - rect.left - containerRadius;
var y = clientY - rect.top - containerRadius;
var angle = Math.atan2(y, x) * 180.0 / Math.PI;
var positiveAngle = angle < 0 ? 360 + angle : angle;
if (selection === 'hours') {
var hour = Math.round(positiveAngle / HOUR_ANGLE + 3);
var pmRadius = containerRadius / 2 + 12;
var amHour = hour > 12 ? hour - 12 : hour;
if (Math.abs(x) < pmRadius && Math.abs(y) < pmRadius) {
handleDateChange(setHours(date != null ? date : startOfDay(new Date()), amHour === 12 ? 0 : amHour + 12), fireChange);
} else {
handleDateChange(setHours(date != null ? date : startOfDay(new Date()), amHour), fireChange);
}
} else {
var minute = Math.round(positiveAngle / MINUTE_ANGLE + 15);
var computedMinute = minute >= 60 ? minute - 60 : minute;
var roundedWithPrecision = Math.round(computedMinute / precision) * precision % 60;
handleDateChange(setMinutes(date != null ? date : startOfDay(new Date()), roundedWithPrecision), fireChange);
}
};
var handleSelectStart = function handleSelectStart(currentTarget, clientX, clientY) {
handleCalcSelected(currentTarget, clientX, clientY);
isDragging.current = true;
};
var handleSelecting = function handleSelecting(currentTarget, clientX, clientY) {
if (isDragging.current) {
handleCalcSelected(currentTarget, clientX, clientY);
}
};
var handleSelectEnd = function handleSelectEnd(currentTarget, clientX, clientY) {
isDragging.current = false;
handleCalcSelected(currentTarget, clientX, clientY, true);
var newSelection = selection === 'hours' && precision !== 60 ? 'minutes' : 'hours';
setSelection(newSelection);
if (newSelection === 'hours') {
onSelectionEnd();
}
};
var handleMouseDown = function handleMouseDown(e) {
return handleSelectStart(e.currentTarget, e.clientX, e.clientY);
};
var handleMouseMove = function handleMouseMove(e) {
return handleSelecting(e.currentTarget, e.clientX, e.clientY);
};
var handleMouseUp = function handleMouseUp(e) {
return handleSelectEnd(e.currentTarget, e.clientX, e.clientY);
};
var handleTouchStart = function handleTouchStart(e) {
if (e.changedTouches[0]) {
handleSelectStart(e.currentTarget, e.changedTouches[0].clientX, e.changedTouches[0].clientY);
}
};
var handleTouchMove = function handleTouchMove(e) {
if (e.changedTouches[0]) {
isDragging.current = true;
handleSelecting(e.currentTarget, e.changedTouches[0].clientX, e.changedTouches[0].clientY);
}
};
var handleTouchEnd = function handleTouchEnd(e) {
if (e.changedTouches[0]) {
handleSelectEnd(e.currentTarget, e.changedTouches[0].clientX, e.changedTouches[0].clientY);
}
};
return React.createElement("div", {
className: classNames('react-next-dates', 'clock', className)
}, React.createElement(ClockNavigation, {
locale: locale,
date: date,
selection: selection,
showNav: precision !== 60,
onSelectionChange: setSelection
}), React.createElement("div", {
className: "clock-wrapper"
}, React.createElement("div", {
ref: containerRef,
className: "clock-content",
onMouseDown: isTouch ? undefined : handleMouseDown,
onMouseMove: isTouch ? undefined : handleMouseMove,
onMouseUp: isTouch ? undefined : handleMouseUp,
onTouchStart: isTouch ? handleTouchStart : undefined,
onTouchMove: isTouch ? handleTouchMove : undefined,
onTouchEnd: isTouch ? handleTouchEnd : undefined
}, containerWidth !== null ? React.createElement(React.Fragment, null, selection === 'hours' ? React.createElement(ClockHours, {
date: date,
containerRadius: containerWidth / 2
}) : React.createElement(ClockMinutes, {
date: date,
containerRadius: containerWidth / 2,
precision: precision
}), date != null ? React.createElement("div", {
className: classNames('clock-selection', {
pm: selection === 'hours' && (date.getHours() === 0 || date.getHours() > 12)
}),
style: {
transform: "rotate(" + getSelectionAngle(date, selection) + "deg)"
}
}) : null) : null)));
};
function isDateValid(date) {
return date != null && isValid(date);
}
function useDateInput(_ref) {
var locale = _ref.locale,
date = _ref.date,
format = _ref.format,
placeholder = _ref.placeholder,
_ref$onChange = _ref.onChange,
onChange = _ref$onChange === void 0 ? constVoid : _ref$onChange;
var defaultFormat = useMemo(function () {
return getDefaultDateFormat(locale, format);
}, [locale, format]);
var _useState = useState(function () {
return date != null && isDateValid(date) ? formatDate(date, defaultFormat, locale) : '';
}),
value = _useState[0],
setValue = _useState[1];
var _useState2 = useState(false),
focused = _useState2[0],
setFocused = _useState2[1];
var handleChange = function handleChange(e) {
var newValue = e.target.value;
setValue(newValue);
var parsedDate = parseDate(newValue, defaultFormat, locale);
if (isDateValid(parsedDate)) {
onChange(parsedDate);
}
};
var handleBlur = function handleBlur() {
if (value) {
var parsedDate = parseDate(value, defaultFormat, locale);
if (isDateValid(parsedDate)) {
setValue(formatDate(parsedDate, defaultFormat, locale));
} else if (isDateValid(date)) {
setValue(formatDate(date, defaultFormat, locale));
} else {
setValue('');
}
} else {
onChange(null);
}
setFocused(false);
};
var handleFocus = function handleFocus() {
return setFocused(true);
};
useEffect(function () {
if (!focused) {
setValue(isDateValid(date) ? formatDate(date, defaultFormat, locale) : '');
}
}, [focused, date, defaultFormat, locale]);
return {
type: 'text',
value: value,
placeholder: placeholder != null ? placeholder : defaultFormat,
onChange: handleChange,
onBlur: handleBlur,
onFocus: handleFocus
};
}
var DatePickerCalendar = function DatePickerCalendar(_ref) {
var locale = _ref.locale,
_ref$type = _ref.type,
type = _ref$type === void 0 ? 'day' : _ref$type,
_ref$date = _ref.date,
date = _ref$date === void 0 ? null : _ref$date,
receivedMonth = _ref.month,
minDate = _ref.minDate,
maxDate = _ref.maxDate,
receivedModifiers = _ref.modifiers,
modifiersClassNames = _ref.modifiersClassNames,
className = _ref.className,
_ref$onDateChange = _ref.onDateChange,
onDateChange = _ref$onDateChange === void 0 ? constVoid : _ref$onDateChange,
onMonthChange = _ref.onMonthChange;
var _useControllableState = useControllableState(function () {
return startOfMonth(date != null ? date : new Date());
}, receivedMonth != null ? receivedMonth : undefined, onMonthChange),
month = _useControllableState[0],
setMonth = _useControllableState[1];
var isSelected = function isSelected(d) {
if (date === null) {
return false;
}
switch (type) {
case 'month':
return isSameMonth(d, date);
case 'year':
return isSameYear(d, date);
default:
return isSameDay(d, date);
}
};
var baseModifier = {
selected: isSelected
};
var modifiers = mergeCalendarModifiers({
day: baseModifier,
month: baseModifier,
year: baseModifier
}, receivedModifiers);
var handleSelectDate = function handleSelectDate(d) {
return onDateChange(setTimeOrRemoveTime(d, date));
};
return React.createElement(Calendar, {
locale: locale,
type: type,
month: month,
minDate: minDate,
maxDate: maxDate,
modifiers: modifiers,
modifiersClassNames: modifiersClassNames,
className: className,
onMonthChange: setMonth,
onSelect: handleSelectDate
});
};
var Popper = /*#__PURE__*/forwardRef(function (_ref, ref) {
var isOpen = _ref.isOpen,
referenceElement = _ref.referenceElement,
popperElement = _ref.popperElement,
portalContainer = _ref.portalContainer,
_ref$offset = _ref.offset,
offset = _ref$offset === void 0 ? [0, 5] : _ref$offset,
className = _ref.className,
children = _ref.children;
var _usePopper = usePopper(referenceElement, popperElement, {
placement: 'bottom-start',
strategy: portalContainer ? 'fixed' : 'absolute',
modifiers: [{
name: 'offset',
options: {
offset: offset
}
}, {
name: 'flip'
}, {
name: 'preventOverflow'
}]
}),
styles = _usePopper.styles,
attributes = _usePopper.attributes,
forceUpdate = _usePopper.forceUpdate;
useLayoutEffect(function () {
if (isOpen && forceUpdate) {
forceUpdate();
}
}, [isOpen, forceUpdate]);
var popperStyle = isOpen ? styles.popper : {
display: 'none'
};
var popper = React.createElement("div", _extends({
ref: ref,
className: classNames('react-next-dates', 'popper', className),
style: popperStyle
}, attributes.popper), isOpen ? children : null);
return portalContainer ? createPortal(popper, portalContainer) : popper;
});
var DatePicker = function DatePicker(_ref) {
var locale = _ref.locale,
_ref$type = _ref.type,
type = _ref$type === void 0 ? 'day' : _ref$type,
date = _ref.date,
format = _ref.format,
minDate = _ref.minDate,
maxDate = _ref.maxDate,
placeholder = _ref.placeholder,
className = _ref.className,
modifiers = _ref.modifiers,
modifiersClassNames = _ref.modifiersClassNames,
portalContainer = _ref.portalContainer,
_ref$readonlyOnTouch = _ref.readonlyOnTouch,
readonlyOnTouch = _ref$readonlyOnTouch === void 0 ? true : _ref$readonlyOnTouch,
_ref$autoOpen = _ref.autoOpen,
autoOpen = _ref$autoOpen === void 0 ? true : _ref$autoOpen,
_ref$onChange = _ref.onChange,
onChange = _ref$onChange === void 0 ? constVoid : _ref$onChange,
children = _ref.children;
var _useState = useState(function () {
return date != null ? date : new Date();
}),
month = _useState[0],
setMonth = _useState[1];
var _useState2 = useState(false),
isOpen = _useState2[0],
setOpen = _useState2[1];
var _useOutsideClickHandl = useOutsideClickHandler(function () {
return setOpen(false);
}),
inputRef = _useOutsideClickHandl[0],
popperRef = _useOutsideClickHandl[1];
var openDatePicker = function openDatePicker() {
var _inputRef$current;
setOpen(true);
(_inputRef$current = inputRef.current) == null ? void 0 : _inputRef$current.focus();
};
var isTouch = useDetectTouch();
var handleDateInputChange = function handleDateInputChange(date) {
onChange(date);
if (date) {
setMonth(date);
}
};
var inputProps = useDateInput({
locale: locale,
date: date,
format: format,
placeholder: placeholder,
onChange: handleDateInputChange
});
var handleChange = function handleChange(date) {
onChange(date);
setOpen(false);
};
var readOnly = readonlyOnTouch && isTouch;
return React.createElement(React.Fragment, null, children({
inputProps: _extends({}, inputProps, {
onFocus: function onFocus(e) {
inputProps.onFocus(e);
if (autoOpen) {
setOpen(true);
}
if (readOnly) {
var _inputRef$current2;
(_inputRef$current2 = inputRef.current) == null ? void 0 : _inputRef$current2.blur();
}
},
ref: inputRef,
readOnly: readOnly
}),
openDatePicker: openDatePicker
}), React.createElement(Popper, {
ref: popperRef,
isOpen: isOpen,
referenceElement: inputRef.current,
popperElement: popperRef.current,
portalContainer: portalContainer,
className: "date"
}, React.createElement(DatePickerCalendar, {
locale: locale,
type: type,
date: date,
month: month,
minDate: minDate,
maxDate: maxDate,
modifiers: modifiers,
modifiersClassNames: modifiersClassNames,
className: className,
onDateChange: handleChange,
onMonthChange: setMonth
})));
};
var DateRangePickerCalendar = function DateRangePickerCalendar(_ref) {
var locale = _ref.locale,
focus = _ref.focus,
_ref$startDate = _ref.startDate,
startDate = _ref$startDate === void 0 ? null : _ref$startDate,
_ref$endDate = _ref.endDate,
endDate = _ref$endDate === void 0 ? null : _ref$endDate,
receivedMonth = _ref.month,
minDate = _ref.minDate,
maxDate = _ref.maxDate,
_ref$minLength = _ref.minLength,
minLength = _ref$minLength === void 0 ? 0 : _ref$minLength,
maxLength = _ref.maxLength,
receivedModifiers = _ref.modifiers,
modifiersClassNames = _ref.modifiersClassNames,
className = _ref.className,
_ref$onStartDateChang = _ref.onStartDateChange,
onStartDateChange = _ref$onStartDateChang === void 0 ? constVoid : _ref$onStartDateChang,
_ref$onEndDateChange = _ref.onEndDateChange,
onEndDateChange = _ref$onEndDateChange === void 0 ? constVoid : _ref$onEndDateChange,
onFocusChange = _ref.onFocusChange,
onMonthChange = _ref.onMonthChange;
var _useControllableState = useControllableState(function () {
var _ref2;
return startOfMonth((_ref2 = startDate != null ? startDate : endDate) != null ? _ref2 : new Date());
}, receivedMonth != null ? receivedMonth : undefined, onMonthChange),
month = _useControllableState[0],
setMonth = _useControllableState[1];
var _useState = useState(null),
hoveredDate = _useState[0],
setHoveredDate = _useState[1];
var displayedStartDate = startDate ? startOfDay(startDate) : null;
var displayedEndDate = endDate ? startOfDay(endDate) : null;
var isStartDate = function isStartDate(date) {
return displayedStartDate !== null && isSameDay(date, displayedStartDate);
};
var isEndDate = function isEndDate(date) {
return displayedEndDate !== null && isSameDay(date, displayedEndDate);
};
var isSelectedMiddleDate = function isSelectedMiddleDate(date) {
return displayedStartDate !== null && displayedEndDate !== null && isAfter(date, displayedStartDate) && isBefore(date, displayedEndDate);
};
var isHoverDate = function isHoverDate(date) {
return hoveredDate !== null && displayedStartDate !== null && displayedEndDate === null && isAfter(date, displayedStartDate) && (isBefore(date, hoveredDate) || isSameDay(date, hoveredDate));
};
var isMiddleDate = function isMiddleDate(date) {
return isSelectedMiddleDate(date) || isHoverDate(date);
};
var modifiers = mergeModifiers({
selectedStart: isStartDate,
selectedMiddle: isMiddleDate,
selectedEnd: isEndDate,
disabled: function disabled(date) {
if (focus === 'endDate' && startDate !== null) {
return isAfter(date, startOfDay(startDate)) && !isRangeLengthValid(startDate, date, minLength, maxLength);
} else if (focus === 'startDate' && endDate !== null) {
return isBefore(date, startOfDay(endDate)) && !isRangeLengthValid(date, endDate, minLength, maxLength);
}
return false;
}
}, receivedModifiers);
var handleSelectDate = function handleSelectDate(d) {
if (focus === 'startDate') {
var date = setTimeOrRemoveTime(d, startDate);
if (endDate !== null && isAfter(date, endDate)) {
onEndDateChange(null);
}
onStartDateChange(date);
onFocusChange('endDate');
} else if (focus === 'endDate') {
var _date = setTimeOrRemoveTime(d, endDate != null ? endDate : startDate);
if (startDate !== null && isBefore(_date, startDate)) {
onStartDateChange(setTimeOrRemoveTime(d, startDate));
onEndDateChange(null);
onFocusChange('endDate');
} else {
onEndDateChange(_date);
onFocusChange(null);
}
}
};
return React.createElement(Calendar, {
type: "day",
locale: locale,
month: month,
minDate: minDate,
maxDate: maxDate,
modifiers: {
day: modifiers
},
modifiersClassNames: {
day: modifiersClassNames
},
className: className,
onMonthChange: setMonth,
onSelect: handleSelectDate,
onHover: setHoveredDate
});
};
var DateRangePicker = function DateRangePicker(_ref) {
var locale = _ref.locale,
format = _ref.format,
startDate = _ref.startDate,
endDate = _ref.endDate,
minDate = _ref.minDate,
maxDate = _ref.maxDate,
_ref$minLength = _ref.minLength,
minLength = _ref$minLength === void 0 ? 0 : _ref$minLength,
maxLength = _ref.maxLength,
modifiers = _ref.modifiers,
modifiersClassNames = _ref.modifiersClassNames,
startDatePlaceholder = _ref.startDatePlaceholder,
endDatePlaceholder = _ref.endDatePlaceholder,
className = _ref.className,
portalContainer = _ref.portalContainer,
_ref$readonlyOnTouch = _ref.readonlyOnTouch,
readonlyOnTouch = _ref$readonlyOnTouch === void 0 ? true : _ref$readonlyOnTouch,
_ref$autoOpen = _ref.autoOpen,
autoOpen = _ref$autoOpen === void 0 ? true : _ref$autoOpen,
_ref$onStartDateChang = _ref.onStartDateChange,
onStartDateChange = _ref$onStartDateChang === void 0 ? constVoid : _ref$onStartDateChang,
_ref$onEndDateChange = _ref.onEndDateChange,
onEndDateChange = _ref$onEndDateChange === void 0 ? constVoid : _ref$onEndDateChange,
children = _ref.children;
var _useState = useState(function () {
var _ref2;
return (_ref2 = startDate != null ? startDate : endDate) != null ? _ref2 : new Date();
}),
month = _useState[0],
setMonth = _useState[1];
var _useState2 = useState(null),
focus = _useState2[0],
setFocus = _useState2[1];
var _useState3 = useState(null),
popperFocus = _useState3[0],
setPopperFocus = _useState3[1];
var _useOutsideClickHandl = useOutsideClickHandler(function () {
return setFocus(null);
}),
startDateInputRef = _useOutsideClickHandl[0],
endDateInputRef = _useOutsideClickHandl[1],
popperRef = _useOutsideClickHandl[2];
var openStartDatePicker = function openStartDatePicker() {
var _startDateInputRef$cu;
setFocus('startDate');
(_startDateInputRef$cu = startDateInputRef.current) == null ? void 0 : _startDateInputRef$cu.focus();
};
var openEndDatePicker = function openEndDatePicker() {
var _endDateInputRef$curr;
setFocus('endDate');
(_endDateInputRef$curr = endDateInputRef.current) == null ? void 0 : _endDateInputRef$curr.focus();
};
var isTouch = useDetectTouch();
var prevFocus = usePrevious(focus);
useEffect(function () {
if (prevFocus === null) {
setPopperFocus(focus);
}
if (prevFocus === 'startDate' && focus === 'endDate') {
var _endDateInputRef$curr2;
(_endDateInputRef$curr2 = endDateInputRef.current) == null ? void 0 : _endDateInputRef$curr2.focus();
}
}, [focus, prevFocus, endDateInputRef]);
var handleStartDateInputChange = function handleStartDateInputChange(date) {
onStartDateChange(date);
if (date) {
setMonth(date);
}
};
var handleEndDateInputChange = function handleEndDateInputChange(date) {
onEndDateChange(date);
if (date) {
setMonth(date);
}
};
var startDateInputProps = useDateInput({
date: startDate,
locale: locale,
format: format,
placeholder: startDatePlaceholder,
onChange: handleStartDateInputChange
});
var endDateInputProps = useDateInput({
date: endDate,
locale: locale,
format: format,
placeholder: endDatePlaceholder,
onChange: handleEndDateInputChange
});
var readOnly = readonlyOnTouch && isTouch;
var getRefFromFocus = function getRefFromFocus(focus) {
return focus === 'endDate' ? endDateInputRef.current : startDateInputRef.current;
};
var handleFocus = function handleFocus(inputProps, focus) {
return function (e) {
inputProps.onFocus(e);
if (focus === 'startDate' && startDate) {
setMonth(startDate);
} else if (focus === 'endDate' && endDate) {
setMonth(endDate);
}
if (autoOpen) {
setFocus(focus);
}
if (readOnly) {
var _getRefFromFocus;
(_getRefFromFocus = getRefFromFocus(focus)) == null ? void 0 : _getRefFromFocus.blur();
}
};
};
return React.createElement(React.Fragment, null, children({
startDateInputProps: _extends({}, startDateInputProps, {
onFocus: handleFocus(startDateInputProps, 'startDate'),
ref: startDateInputRef,
readOnly: readOnly
}),
endDateInputProps: _extends({}, endDateInputProps, {
onFocus: handleFocus(endDateInputProps, 'endDate'),
ref: endDateInputRef,
readOnly: readOnly
}),
openStartDatePicker: openStartDatePicker,
openEndDatePicker: openEndDatePicker
}), React.createElement(Popper, {
ref: popperRef,
isOpen: focus !== null,
referenceElement: getRefFromFocus(popperFocus),
popperElement: popperRef.current,
portalContainer: portalContainer,
className: "date"
}, React.createElement(DateRangePickerCalendar, {
locale: locale,
focus: focus != null ? focus : 'startDate',
startDate: startDate,
endDate: endDate,
month: month,
minDate: minDate,
maxDate: maxDate,
minLength: minLength,
maxLength: maxLength,
modifiers: modifiers,
modifiersClassNames: modifiersClassNames,
className: className,
onStartDateChange: onStartDateChange,
onEndDateChange: onEndDateChange,
onFocusChange: setFocus,
onMonthChange: setMonth
})));
};
var DateTimePicker = function DateTimePicker(_ref) {
var locale = _ref.locale,
date = _ref.date,
dateFormat = _ref.dateFormat,
_ref$timeFormat = _ref.timeFormat,
timeFormat = _ref$timeFormat === void 0 ? 'HH:mm' : _ref$timeFormat,
minDate = _ref.minDate,
maxDate = _ref.maxDate,
datePlaceholder = _ref.datePlaceholder,
timePlaceholder = _ref.timePlaceholder,
_ref$timePrecision = _ref.timePrecision,
timePrecision = _ref$timePrecision === void 0 ? 1 : _ref$timePrecision,
_ref$vibrate = _ref.vibrate,
vibrate = _ref$vibrate === void 0 ? true : _ref$vibrate,
className = _ref.className,
modifiers = _ref.modifiers,
modifiersClassNames = _ref.modifiersClassNames,
portalContainer = _ref.portalContainer,
_ref$readonlyOnTouch = _ref.readonlyOnTouch,
readonlyOnTouch = _ref$readonlyOnTouch === void 0 ? true : _ref$readonlyOnTouch,
_ref$autoOpen = _ref.autoOpen,
autoOpen = _ref$autoOpen === void 0 ? true : _ref$autoOpen,
_ref$onChange = _ref.onChange,
onChange = _ref$onChange === void 0 ? constVoid : _ref$onChange,
children = _ref.children;
var _useState = useState(function () {
return date != null ? date : new Date();
}),
month = _useState[0],
setMonth = _useState[1];
var _useState2 = useState(null),
focus = _useState2[0],
setFocus = _useState2[1];
var _useState3 = useState('hours'),
clockSelection = _useState3[0],
setClockSelection = _useState3[1];
var _useOutsideClickHandl = useOutsideClickHandler(function () {
setFocus(null);
setClockSelection('hours');
}),
dateInputRef = _useOutsideClickHandl[0],
timeInputRef = _useOutsideClickHandl[1],
popperRef = _useOutsideClickHandl[2];
var isTouch = useDetectTouch();
var openDatePicker = function openDatePicker() {
var _dateInputRef$current;
setFocus('date');
(_dateInputRef$current = dateInputRef.current) == null ? void 0 : _dateInputRef$current.focus();
};
var openTimePicker = function openTimePicker() {
var _timeInputRef$current;
setFocus('time');
(_timeInputRef$current = timeInputRef.current) == null ? void 0 : _timeInputRef$current.focus();
};
var handleDateInputChange = function handleDateInputChange(date) {
onChange(date);
if (date) {
setMonth(date);
}
};
var handleTimeInputChange = function handleTimeInputChange(d) {
if (d) {
onChange(setTime(date != null ? date : new Date(), d));
} else if (date) {
onChange(startOfDay(date));
} else {
onChange(d);
}
};
var dateInputProps = useDateInput({
date: date,
locale: locale,
format: dateFormat,
placeholder: datePlaceholder,
onChange: handleDateInputChange
});
var timeInputProps = useDateInput({
date: date,
locale: locale,
format: timeFormat,
placeholder: timePlaceholder,
onChange: handleTimeInputChange
});
var handleDateChange = function handleDateChange(date) {
var _timeInputRef$current2;
onChange(date);
setFocus('time');
(_timeInputRef$current2 = timeInputRef.current) == null ? void 0 : _timeInputRef$current2.focus();
};
var handleSelectionEnd = function handleSelectionEnd() {
return setFocus(null);
};
var readOnly = readonlyOnTouch && isTouch;
var getRefFromFocus = function getRefFromFocus(focus) {
return focus === 'time' ? timeInputRef.current : dateInputRef.current;
};
var handleFocus = function handleFocus(inputProps, focus) {
return function (e) {
inputProps.onFocus(e);
if (autoOpen) {
setFocus(focus);
}
if (readOnly) {
var _getRefFromFocus;
(_getRefFromFocus = getRefFromFocus(focus)) == null ? void 0 : _getRefFromFocus.blur();
}
};
};
return React.createElement(React.Fragment, null, children({
dateInputProps: _extends({}, dateInputProps, {
onFocus: handleFocus(dateInputProps, 'date'),
ref: dateInputRef,
readOnly: readOnly
}),
timeInputProps: _extends({}, timeInputProps, {
onFocus: handleFocus(timeInputProps, 'time'),
ref: timeInputRef,
readOnly: readOnly