react-big-calendar
Version:
Calendar! with events
1,411 lines (1,373 loc) • 235 kB
JavaScript
import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
import _typeof from '@babel/runtime/helpers/esm/typeof';
import _classCallCheck from '@babel/runtime/helpers/esm/classCallCheck';
import _createClass from '@babel/runtime/helpers/esm/createClass';
import _callSuper from '@babel/runtime/helpers/esm/callSuper';
import _inherits from '@babel/runtime/helpers/esm/inherits';
import _slicedToArray from '@babel/runtime/helpers/esm/slicedToArray';
import clsx from 'clsx';
import React, { useEffect, useLayoutEffect, useRef, createRef, Component, useMemo, useState, useCallback } from 'react';
import { uncontrollable } from 'uncontrollable';
import PropTypes from 'prop-types';
import invariant from 'invariant';
import * as dates from 'date-arithmetic';
import { inRange as inRange$1, lt, lte, gt, gte, eq, neq, startOf, endOf, add, min, max, minutes } from 'date-arithmetic';
import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
import _toConsumableArray from '@babel/runtime/helpers/esm/toConsumableArray';
import chunk from 'lodash/chunk';
import getPosition$1 from 'dom-helpers/position';
import * as animationFrame from 'dom-helpers/animationFrame';
import { Overlay } from 'react-overlays';
import getOffset from 'dom-helpers/offset';
import isEqual$1 from 'lodash/isEqual';
import getHeight from 'dom-helpers/height';
import qsa from 'dom-helpers/querySelectorAll';
import contains from 'dom-helpers/contains';
import closest from 'dom-helpers/closest';
import listen from 'dom-helpers/listen';
import findIndex from 'lodash/findIndex';
import range$1 from 'lodash/range';
import memoize from 'memoize-one';
import getWidth from 'dom-helpers/width';
import sortBy from 'lodash/sortBy';
import scrollbarSize from 'dom-helpers/scrollbarSize';
import _toArray from '@babel/runtime/helpers/esm/toArray';
import addClass from 'dom-helpers/addClass';
import removeClass from 'dom-helpers/removeClass';
import defaults from 'lodash/defaults';
import mapValues from 'lodash/mapValues';
import omit from 'lodash/omit';
import transform from 'lodash/transform';
import isBetween from 'dayjs/plugin/isBetween';
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
import localeData from 'dayjs/plugin/localeData';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import minMax from 'dayjs/plugin/minMax';
import utc from 'dayjs/plugin/utc';
import isLeapYear from 'dayjs/plugin/isLeapYear';
function NoopWrapper(props) {
return props.children;
}
var navigate = {
PREVIOUS: 'PREV',
NEXT: 'NEXT',
TODAY: 'TODAY',
DATE: 'DATE'
};
var views = {
MONTH: 'month',
WEEK: 'week',
WORK_WEEK: 'work_week',
DAY: 'day',
AGENDA: 'agenda'
};
var viewNames$1 = Object.keys(views).map(function (k) {
return views[k];
});
PropTypes.oneOfType([PropTypes.string, PropTypes.func]);
PropTypes.any;
PropTypes.func;
/**
* accepts either an array of builtin view names:
*
* ```
* views={['month', 'day', 'agenda']}
* ```
*
* or an object hash of the view name and the component (or boolean for builtin)
*
* ```
* views={{
* month: true,
* week: false,
* workweek: WorkWeekViewComponent,
* }}
* ```
*/
PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOf(viewNames$1)), PropTypes.objectOf(function (prop, key) {
var isBuiltinView = viewNames$1.indexOf(key) !== -1 && typeof prop[key] === 'boolean';
if (isBuiltinView) {
return null;
} else {
for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
args[_key - 2] = arguments[_key];
}
return PropTypes.elementType.apply(PropTypes, [prop, key].concat(args));
}
})]);
PropTypes.oneOfType([PropTypes.oneOf(['overlap', 'no-overlap']), PropTypes.func]);
/* eslint no-fallthrough: off */
var MILLI = {
seconds: 1000,
minutes: 1000 * 60,
hours: 1000 * 60 * 60,
day: 1000 * 60 * 60 * 24
};
function firstVisibleDay(date, localizer) {
var firstOfMonth = dates.startOf(date, 'month');
return dates.startOf(firstOfMonth, 'week', localizer.startOfWeek());
}
function lastVisibleDay(date, localizer) {
var endOfMonth = dates.endOf(date, 'month');
return dates.endOf(endOfMonth, 'week', localizer.startOfWeek());
}
function visibleDays(date, localizer) {
var current = firstVisibleDay(date, localizer),
last = lastVisibleDay(date, localizer),
days = [];
while (dates.lte(current, last, 'day')) {
days.push(current);
current = dates.add(current, 1, 'day');
}
return days;
}
function ceil(date, unit) {
var floor = dates.startOf(date, unit);
return dates.eq(floor, date) ? floor : dates.add(floor, 1, unit);
}
function range(start, end) {
var unit = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'day';
var current = start,
days = [];
while (dates.lte(current, end, unit)) {
days.push(current);
current = dates.add(current, 1, unit);
}
return days;
}
function merge(date, time) {
if (time == null && date == null) return null;
if (time == null) time = new Date();
if (date == null) date = new Date();
date = dates.startOf(date, 'day');
date = dates.hours(date, dates.hours(time));
date = dates.minutes(date, dates.minutes(time));
date = dates.seconds(date, dates.seconds(time));
return dates.milliseconds(date, dates.milliseconds(time));
}
function isJustDate(date) {
return dates.hours(date) === 0 && dates.minutes(date) === 0 && dates.seconds(date) === 0 && dates.milliseconds(date) === 0;
}
function duration(start, end, unit, firstOfWeek) {
if (unit === 'day') unit = 'date';
return Math.abs(
// eslint-disable-next-line import/namespace
dates[unit](start, undefined, firstOfWeek) -
// eslint-disable-next-line import/namespace
dates[unit](end, undefined, firstOfWeek));
}
function diff(dateA, dateB, unit) {
if (!unit || unit === 'milliseconds') return Math.abs(+dateA - +dateB);
// the .round() handles an edge case
// with DST where the total won't be exact
// since one day in the range may be shorter/longer by an hour
return Math.round(Math.abs(+dates.startOf(dateA, unit) / MILLI[unit] - +dates.startOf(dateB, unit) / MILLI[unit]));
}
var localePropType = PropTypes.oneOfType([PropTypes.string, PropTypes.func]);
function _format(localizer, formatter, value, format, culture) {
var result = typeof format === 'function' ? format(value, culture, localizer) : formatter.call(localizer, value, format, culture);
invariant(result == null || typeof result === 'string', '`localizer format(..)` must return a string, null, or undefined');
return result;
}
/**
* This date conversion was moved out of TimeSlots.js, to
* allow for localizer override
* @param {Date} dt - The date to start from
* @param {Number} minutesFromMidnight
* @param {Number} offset
* @returns {Date}
*/
function getSlotDate(dt, minutesFromMidnight, offset) {
return new Date(dt.getFullYear(), dt.getMonth(), dt.getDate(), 0, minutesFromMidnight + offset, 0, 0);
}
function getDstOffset(start, end) {
return start.getTimezoneOffset() - end.getTimezoneOffset();
}
// if the start is on a DST-changing day but *after* the moment of DST
// transition we need to add those extra minutes to our minutesFromMidnight
function getTotalMin(start, end) {
return diff(start, end, 'minutes') + getDstOffset(start, end);
}
function getMinutesFromMidnight(start) {
var daystart = startOf(start, 'day');
return diff(daystart, start, 'minutes') + getDstOffset(daystart, start);
}
// These two are used by DateSlotMetrics
function continuesPrior(start, first) {
return lt(start, first, 'day');
}
function continuesAfter(start, end, last) {
var singleDayDuration = eq(start, end, 'minutes');
return singleDayDuration ? gte(end, last, 'minutes') : gt(end, last, 'minutes');
}
function daySpan(start, end) {
return duration(start, end, 'day');
}
// These two are used by eventLevels
function sortEvents$1(_ref) {
var _ref$evtA = _ref.evtA,
aStart = _ref$evtA.start,
aEnd = _ref$evtA.end,
aAllDay = _ref$evtA.allDay,
_ref$evtB = _ref.evtB,
bStart = _ref$evtB.start,
bEnd = _ref$evtB.end,
bAllDay = _ref$evtB.allDay;
var startSort = +startOf(aStart, 'day') - +startOf(bStart, 'day');
var durA = daySpan(aStart, aEnd);
var durB = daySpan(bStart, bEnd);
return startSort ||
// sort by start Day first
durB - durA ||
// events spanning multiple days go first
!!bAllDay - !!aAllDay ||
// then allDay single day events
+aStart - +bStart ||
// then sort by start time
+aEnd - +bEnd // then sort by end time
;
}
function inEventRange(_ref2) {
var _ref2$event = _ref2.event,
start = _ref2$event.start,
end = _ref2$event.end,
_ref2$range = _ref2.range,
rangeStart = _ref2$range.start,
rangeEnd = _ref2$range.end;
var eStart = startOf(start, 'day');
var startsBeforeEnd = lte(eStart, rangeEnd, 'day');
// when the event is zero duration we need to handle a bit differently
var sameMin = neq(eStart, end, 'minutes');
var endsAfterStart = sameMin ? gt(end, rangeStart, 'minutes') : gte(end, rangeStart, 'minutes');
return startsBeforeEnd && endsAfterStart;
}
// other localizers treats 'day' and 'date' equality very differently, so we
// abstract the change the 'localizer.eq(date1, date2, 'day') into this
// new method, where they can be treated correctly by the localizer overrides
function isSameDate(date1, date2) {
return eq(date1, date2, 'day');
}
function startAndEndAreDateOnly(start, end) {
return isJustDate(start) && isJustDate(end);
}
var DateLocalizer = /*#__PURE__*/_createClass(function DateLocalizer(spec) {
var _this = this;
_classCallCheck(this, DateLocalizer);
invariant(typeof spec.format === 'function', 'date localizer `format(..)` must be a function');
invariant(typeof spec.firstOfWeek === 'function', 'date localizer `firstOfWeek(..)` must be a function');
this.propType = spec.propType || localePropType;
this.formats = spec.formats;
this.format = function () {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _format.apply(void 0, [_this, spec.format].concat(args));
};
// These date arithmetic methods can be overriden by the localizer
this.startOfWeek = spec.firstOfWeek;
this.merge = spec.merge || merge;
this.inRange = spec.inRange || inRange$1;
this.lt = spec.lt || lt;
this.lte = spec.lte || lte;
this.gt = spec.gt || gt;
this.gte = spec.gte || gte;
this.eq = spec.eq || eq;
this.neq = spec.neq || neq;
this.startOf = spec.startOf || startOf;
this.endOf = spec.endOf || endOf;
this.add = spec.add || add;
this.range = spec.range || range;
this.diff = spec.diff || diff;
this.ceil = spec.ceil || ceil;
this.min = spec.min || min;
this.max = spec.max || max;
this.minutes = spec.minutes || minutes;
this.daySpan = spec.daySpan || daySpan;
this.firstVisibleDay = spec.firstVisibleDay || firstVisibleDay;
this.lastVisibleDay = spec.lastVisibleDay || lastVisibleDay;
this.visibleDays = spec.visibleDays || visibleDays;
this.getSlotDate = spec.getSlotDate || getSlotDate;
this.getTimezoneOffset = spec.getTimezoneOffset || function (value) {
return value.getTimezoneOffset();
};
this.getDstOffset = spec.getDstOffset || getDstOffset;
this.getTotalMin = spec.getTotalMin || getTotalMin;
this.getMinutesFromMidnight = spec.getMinutesFromMidnight || getMinutesFromMidnight;
this.continuesPrior = spec.continuesPrior || continuesPrior;
this.continuesAfter = spec.continuesAfter || continuesAfter;
this.sortEvents = spec.sortEvents || sortEvents$1;
this.inEventRange = spec.inEventRange || inEventRange;
this.isSameDate = spec.isSameDate || isSameDate;
this.startAndEndAreDateOnly = spec.startAndEndAreDateOnly || startAndEndAreDateOnly;
this.segmentOffset = spec.browserTZOffset ? spec.browserTZOffset() : 0;
});
function mergeWithDefaults(localizer, culture, formatOverrides, messages) {
var formats = _objectSpread(_objectSpread({}, localizer.formats), formatOverrides);
return _objectSpread(_objectSpread({}, localizer), {}, {
messages: messages,
startOfWeek: function startOfWeek() {
return localizer.startOfWeek(culture);
},
format: function format(value, _format2) {
return localizer.format(value, formats[_format2] || _format2, culture);
}
});
}
var Toolbar = /*#__PURE__*/function (_React$Component) {
function Toolbar() {
var _this;
_classCallCheck(this, Toolbar);
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _callSuper(this, Toolbar, [].concat(args));
_this.navigate = function (action) {
_this.props.onNavigate(action);
};
_this.view = function (view) {
_this.props.onView(view);
};
return _this;
}
_inherits(Toolbar, _React$Component);
return _createClass(Toolbar, [{
key: "render",
value: function render() {
var _this$props = this.props,
messages = _this$props.localizer.messages,
label = _this$props.label;
return /*#__PURE__*/React.createElement("div", {
className: "rbc-toolbar"
}, /*#__PURE__*/React.createElement("span", {
className: "rbc-btn-group"
}, /*#__PURE__*/React.createElement("button", {
type: "button",
onClick: this.navigate.bind(null, navigate.TODAY)
}, messages.today), /*#__PURE__*/React.createElement("button", {
type: "button",
onClick: this.navigate.bind(null, navigate.PREVIOUS)
}, messages.previous), /*#__PURE__*/React.createElement("button", {
type: "button",
onClick: this.navigate.bind(null, navigate.NEXT)
}, messages.next)), /*#__PURE__*/React.createElement("span", {
className: "rbc-toolbar-label"
}, label), /*#__PURE__*/React.createElement("span", {
className: "rbc-btn-group"
}, this.viewNamesGroup(messages)));
}
}, {
key: "viewNamesGroup",
value: function viewNamesGroup(messages) {
var _this2 = this;
var viewNames = this.props.views;
var view = this.props.view;
if (viewNames.length > 1) {
return viewNames.map(function (name) {
return /*#__PURE__*/React.createElement("button", {
type: "button",
key: name,
className: clsx({
'rbc-active': view === name
}),
onClick: _this2.view.bind(null, name)
}, messages[name]);
});
}
}
}]);
}(React.Component);
function notify(handler, args) {
handler && handler.apply(null, [].concat(args));
}
var defaultMessages = {
date: 'Date',
time: 'Time',
event: 'Event',
allDay: 'All Day',
week: 'Week',
work_week: 'Work Week',
day: 'Day',
month: 'Month',
previous: 'Back',
next: 'Next',
yesterday: 'Yesterday',
tomorrow: 'Tomorrow',
today: 'Today',
agenda: 'Agenda',
noEventsInRange: 'There are no events in this range.',
showMore: function showMore(total) {
return "+".concat(total, " more");
}
};
function messages(msgs) {
return _objectSpread(_objectSpread({}, defaultMessages), msgs);
}
function useClickOutside(_ref) {
var ref = _ref.ref,
callback = _ref.callback;
useEffect(function () {
var handleClickOutside = function handleClickOutside(e) {
if (ref.current && !ref.current.contains(e.target)) {
callback();
}
};
document.addEventListener('mousedown', handleClickOutside);
return function () {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [ref, callback]);
}
var _excluded$7 = ["style", "className", "event", "selected", "isAllDay", "onSelect", "onDoubleClick", "onKeyPress", "localizer", "continuesPrior", "continuesAfter", "accessors", "getters", "children", "components", "slotStart", "slotEnd"];
var EventCell = /*#__PURE__*/function (_React$Component) {
function EventCell() {
_classCallCheck(this, EventCell);
return _callSuper(this, EventCell, arguments);
}
_inherits(EventCell, _React$Component);
return _createClass(EventCell, [{
key: "render",
value: function render() {
var _this$props = this.props,
style = _this$props.style,
className = _this$props.className,
event = _this$props.event,
selected = _this$props.selected,
isAllDay = _this$props.isAllDay,
onSelect = _this$props.onSelect,
_onDoubleClick = _this$props.onDoubleClick,
onKeyPress = _this$props.onKeyPress,
localizer = _this$props.localizer,
continuesPrior = _this$props.continuesPrior,
continuesAfter = _this$props.continuesAfter,
accessors = _this$props.accessors,
getters = _this$props.getters,
children = _this$props.children,
_this$props$component = _this$props.components,
Event = _this$props$component.event,
EventWrapper = _this$props$component.eventWrapper,
slotStart = _this$props.slotStart,
slotEnd = _this$props.slotEnd,
props = _objectWithoutProperties(_this$props, _excluded$7);
delete props.resizable;
var title = accessors.title(event);
var tooltip = accessors.tooltip(event);
var end = accessors.end(event);
var start = accessors.start(event);
var allDay = accessors.allDay(event);
var showAsAllDay = isAllDay || allDay || localizer.diff(start, localizer.ceil(end, 'day'), 'day') > 1;
var userProps = getters.eventProp(event, start, end, selected);
var content = /*#__PURE__*/React.createElement("div", {
className: "rbc-event-content",
title: tooltip || undefined
}, Event ? /*#__PURE__*/React.createElement(Event, {
event: event,
continuesPrior: continuesPrior,
continuesAfter: continuesAfter,
title: title,
isAllDay: allDay,
localizer: localizer,
slotStart: slotStart,
slotEnd: slotEnd
}) : title);
return /*#__PURE__*/React.createElement(EventWrapper, Object.assign({}, this.props, {
type: "date"
}), /*#__PURE__*/React.createElement("div", Object.assign({}, props, {
style: _objectSpread(_objectSpread({}, userProps.style), style),
className: clsx('rbc-event', className, userProps.className, {
'rbc-selected': selected,
'rbc-event-allday': showAsAllDay,
'rbc-event-continues-prior': continuesPrior,
'rbc-event-continues-after': continuesAfter
}),
onClick: function onClick(e) {
return onSelect && onSelect(event, e);
},
onDoubleClick: function onDoubleClick(e) {
return _onDoubleClick && _onDoubleClick(event, e);
},
onKeyDown: function onKeyDown(e) {
return onKeyPress && onKeyPress(event, e);
}
}), typeof children === 'function' ? children(content) : content));
}
}]);
}(React.Component);
function isSelected(event, selected) {
if (!event || selected == null) return false;
return isEqual$1(event, selected);
}
function slotWidth(rowBox, slots) {
var rowWidth = rowBox.right - rowBox.left;
var cellWidth = rowWidth / slots;
return cellWidth;
}
function getSlotAtX(rowBox, x, rtl, slots) {
var cellWidth = slotWidth(rowBox, slots);
return rtl ? slots - 1 - Math.floor((x - rowBox.left) / cellWidth) : Math.floor((x - rowBox.left) / cellWidth);
}
function pointInBox(box, _ref) {
var x = _ref.x,
y = _ref.y;
return y >= box.top && y <= box.bottom && x >= box.left && x <= box.right;
}
function dateCellSelection(start, rowBox, box, slots, rtl) {
var startIdx = -1;
var endIdx = -1;
var lastSlotIdx = slots - 1;
var cellWidth = slotWidth(rowBox, slots);
// cell under the mouse
var currentSlot = getSlotAtX(rowBox, box.x, rtl, slots);
// Identify row as either the initial row
// or the row under the current mouse point
var isCurrentRow = rowBox.top < box.y && rowBox.bottom > box.y;
var isStartRow = rowBox.top < start.y && rowBox.bottom > start.y;
// this row's position relative to the start point
var isAboveStart = start.y > rowBox.bottom;
var isBelowStart = rowBox.top > start.y;
var isBetween = box.top < rowBox.top && box.bottom > rowBox.bottom;
// this row is between the current and start rows, so entirely selected
if (isBetween) {
startIdx = 0;
endIdx = lastSlotIdx;
}
if (isCurrentRow) {
if (isBelowStart) {
startIdx = 0;
endIdx = currentSlot;
} else if (isAboveStart) {
startIdx = currentSlot;
endIdx = lastSlotIdx;
}
}
if (isStartRow) {
// select the cell under the initial point
startIdx = endIdx = rtl ? lastSlotIdx - Math.floor((start.x - rowBox.left) / cellWidth) : Math.floor((start.x - rowBox.left) / cellWidth);
if (isCurrentRow) {
if (currentSlot < startIdx) startIdx = currentSlot;else endIdx = currentSlot; //select current range
} else if (start.y < box.y) {
// the current row is below start row
// select cells to the right of the start cell
endIdx = lastSlotIdx;
} else {
// select cells to the left of the start cell
startIdx = 0;
}
}
return {
startIdx: startIdx,
endIdx: endIdx
};
}
/**
* Changes to react-overlays cause issue with auto positioning,
* so we need to manually calculate the position of the popper,
* and constrain it to the Month container.
*/
function getPosition(_ref) {
var target = _ref.target,
offset = _ref.offset,
container = _ref.container,
box = _ref.box;
var _getOffset = getOffset(target),
top = _getOffset.top,
left = _getOffset.left,
width = _getOffset.width,
height = _getOffset.height;
var _getOffset2 = getOffset(container),
cTop = _getOffset2.top,
cLeft = _getOffset2.left,
cWidth = _getOffset2.width,
cHeight = _getOffset2.height;
var _getOffset3 = getOffset(box),
bWidth = _getOffset3.width,
bHeight = _getOffset3.height;
var viewBottom = cTop + cHeight;
var viewRight = cLeft + cWidth;
var bottom = top + bHeight;
var right = left + bWidth;
var x = offset.x,
y = offset.y;
var topOffset = bottom > viewBottom ? top - bHeight - y : top + y + height;
var leftOffset = right > viewRight ? left + x - bWidth + width : left + x;
return {
topOffset: topOffset,
leftOffset: leftOffset
};
}
function Pop(_ref2) {
var containerRef = _ref2.containerRef,
accessors = _ref2.accessors,
getters = _ref2.getters,
selected = _ref2.selected,
components = _ref2.components,
localizer = _ref2.localizer,
position = _ref2.position,
show = _ref2.show,
events = _ref2.events,
slotStart = _ref2.slotStart,
slotEnd = _ref2.slotEnd,
onSelect = _ref2.onSelect,
onDoubleClick = _ref2.onDoubleClick,
onKeyPress = _ref2.onKeyPress,
handleDragStart = _ref2.handleDragStart,
popperRef = _ref2.popperRef,
target = _ref2.target,
offset = _ref2.offset;
useClickOutside({
ref: popperRef,
callback: show
});
useLayoutEffect(function () {
var _getPosition = getPosition({
target: target,
offset: offset,
container: containerRef.current,
box: popperRef.current
}),
topOffset = _getPosition.topOffset,
leftOffset = _getPosition.leftOffset;
popperRef.current.style.top = "".concat(topOffset, "px");
popperRef.current.style.left = "".concat(leftOffset, "px");
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [offset.x, offset.y, target]);
var width = position.width;
var style = {
minWidth: width + width / 2
};
return /*#__PURE__*/React.createElement("div", {
style: style,
className: "rbc-overlay",
ref: popperRef
}, /*#__PURE__*/React.createElement("div", {
className: "rbc-overlay-header"
}, localizer.format(slotStart, 'dayHeaderFormat')), events.map(function (event, idx) {
return /*#__PURE__*/React.createElement(EventCell, {
key: idx,
type: "popup",
localizer: localizer,
event: event,
getters: getters,
onSelect: onSelect,
accessors: accessors,
components: components,
onDoubleClick: onDoubleClick,
onKeyPress: onKeyPress,
continuesPrior: localizer.lt(accessors.end(event), slotStart, 'day'),
continuesAfter: localizer.gte(accessors.start(event), slotEnd, 'day'),
slotStart: slotStart,
slotEnd: slotEnd,
selected: isSelected(event, selected),
draggable: true,
onDragStart: function onDragStart() {
return handleDragStart(event);
},
onDragEnd: function onDragEnd() {
return show();
}
});
}));
}
var Popup = /*#__PURE__*/React.forwardRef(function (props, ref) {
return /*#__PURE__*/React.createElement(Pop, Object.assign({}, props, {
popperRef: ref
}));
});
Popup.propTypes = {
accessors: PropTypes.object.isRequired,
getters: PropTypes.object.isRequired,
selected: PropTypes.object,
components: PropTypes.object.isRequired,
localizer: PropTypes.object.isRequired,
position: PropTypes.object.isRequired,
show: PropTypes.func.isRequired,
events: PropTypes.array.isRequired,
slotStart: PropTypes.instanceOf(Date).isRequired,
slotEnd: PropTypes.instanceOf(Date),
onSelect: PropTypes.func,
onDoubleClick: PropTypes.func,
onKeyPress: PropTypes.func,
handleDragStart: PropTypes.func,
style: PropTypes.object,
offset: PropTypes.shape({
x: PropTypes.number,
y: PropTypes.number
})
};
function CalOverlay(_ref) {
var containerRef = _ref.containerRef,
_ref$popupOffset = _ref.popupOffset,
popupOffset = _ref$popupOffset === void 0 ? 5 : _ref$popupOffset,
overlay = _ref.overlay,
accessors = _ref.accessors,
localizer = _ref.localizer,
components = _ref.components,
getters = _ref.getters,
selected = _ref.selected,
handleSelectEvent = _ref.handleSelectEvent,
handleDoubleClickEvent = _ref.handleDoubleClickEvent,
handleKeyPressEvent = _ref.handleKeyPressEvent,
handleDragStart = _ref.handleDragStart,
onHide = _ref.onHide,
overlayDisplay = _ref.overlayDisplay;
var popperRef = useRef(null);
if (!overlay.position) return null;
var offset = popupOffset;
if (!isNaN(popupOffset)) {
offset = {
x: popupOffset,
y: popupOffset
};
}
var position = overlay.position,
events = overlay.events,
date = overlay.date,
end = overlay.end;
return /*#__PURE__*/React.createElement(Overlay, {
rootClose: true,
flip: true,
show: true,
placement: "bottom",
onHide: onHide,
target: overlay.target
}, function (_ref2) {
var props = _ref2.props;
return /*#__PURE__*/React.createElement(Popup, Object.assign({}, props, {
containerRef: containerRef,
ref: popperRef,
target: overlay.target,
offset: offset,
accessors: accessors,
getters: getters,
selected: selected,
components: components,
localizer: localizer,
position: position,
show: overlayDisplay,
events: events,
slotStart: date,
slotEnd: end,
onSelect: handleSelectEvent,
onDoubleClick: handleDoubleClickEvent,
onKeyPress: handleKeyPressEvent,
handleDragStart: handleDragStart
}));
});
}
var PopOverlay = /*#__PURE__*/React.forwardRef(function (props, ref) {
return /*#__PURE__*/React.createElement(CalOverlay, Object.assign({}, props, {
containerRef: ref
}));
});
PopOverlay.propTypes = {
popupOffset: PropTypes.oneOfType([PropTypes.number, PropTypes.shape({
x: PropTypes.number,
y: PropTypes.number
})]),
overlay: PropTypes.shape({
position: PropTypes.object,
events: PropTypes.array,
date: PropTypes.instanceOf(Date),
end: PropTypes.instanceOf(Date)
}),
accessors: PropTypes.object.isRequired,
localizer: PropTypes.object.isRequired,
components: PropTypes.object.isRequired,
getters: PropTypes.object.isRequired,
selected: PropTypes.object,
handleSelectEvent: PropTypes.func,
handleDoubleClickEvent: PropTypes.func,
handleKeyPressEvent: PropTypes.func,
handleDragStart: PropTypes.func,
onHide: PropTypes.func,
overlayDisplay: PropTypes.func
};
function addEventListener(type, handler) {
var target = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : document;
return listen(target, type, handler, {
passive: false
});
}
function isOverContainer(container, x, y) {
return !container || contains(container, document.elementFromPoint(x, y));
}
function getEventNodeFromPoint(node, _ref) {
var clientX = _ref.clientX,
clientY = _ref.clientY;
var target = document.elementFromPoint(clientX, clientY);
return closest(target, '.rbc-event', node);
}
function getShowMoreNodeFromPoint(node, _ref2) {
var clientX = _ref2.clientX,
clientY = _ref2.clientY;
var target = document.elementFromPoint(clientX, clientY);
return closest(target, '.rbc-show-more', node);
}
function isEvent(node, bounds) {
return !!getEventNodeFromPoint(node, bounds);
}
function isShowMore(node, bounds) {
return !!getShowMoreNodeFromPoint(node, bounds);
}
function getEventCoordinates(e) {
var target = e;
if (e.touches && e.touches.length) {
target = e.touches[0];
}
return {
clientX: target.clientX,
clientY: target.clientY,
pageX: target.pageX,
pageY: target.pageY
};
}
var clickTolerance = 5;
var clickInterval = 250;
var Selection = /*#__PURE__*/function () {
function Selection(node) {
var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref3$global = _ref3.global,
global = _ref3$global === void 0 ? false : _ref3$global,
_ref3$longPressThresh = _ref3.longPressThreshold,
longPressThreshold = _ref3$longPressThresh === void 0 ? 250 : _ref3$longPressThresh,
_ref3$validContainers = _ref3.validContainers,
validContainers = _ref3$validContainers === void 0 ? [] : _ref3$validContainers;
_classCallCheck(this, Selection);
this._initialEvent = null;
this.selecting = false;
this.isDetached = false;
this.container = node;
this.globalMouse = !node || global;
this.longPressThreshold = longPressThreshold;
this.validContainers = validContainers;
this._listeners = Object.create(null);
this._handleInitialEvent = this._handleInitialEvent.bind(this);
this._handleMoveEvent = this._handleMoveEvent.bind(this);
this._handleTerminatingEvent = this._handleTerminatingEvent.bind(this);
this._keyListener = this._keyListener.bind(this);
this._dropFromOutsideListener = this._dropFromOutsideListener.bind(this);
this._dragOverFromOutsideListener = this._dragOverFromOutsideListener.bind(this);
// Fixes an iOS 10 bug where scrolling could not be prevented on the window.
// https://github.com/metafizzy/flickity/issues/457#issuecomment-254501356
this._removeTouchMoveWindowListener = addEventListener('touchmove', function () {}, window);
this._removeKeyDownListener = addEventListener('keydown', this._keyListener);
this._removeKeyUpListener = addEventListener('keyup', this._keyListener);
this._removeDropFromOutsideListener = addEventListener('drop', this._dropFromOutsideListener);
this._removeDragOverFromOutsideListener = addEventListener('dragover', this._dragOverFromOutsideListener);
this._addInitialEventListener();
}
return _createClass(Selection, [{
key: "on",
value: function on(type, handler) {
var handlers = this._listeners[type] || (this._listeners[type] = []);
handlers.push(handler);
return {
remove: function remove() {
var idx = handlers.indexOf(handler);
if (idx !== -1) handlers.splice(idx, 1);
}
};
}
}, {
key: "emit",
value: function emit(type) {
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
var result;
var handlers = this._listeners[type] || [];
handlers.forEach(function (fn) {
if (result === undefined) result = fn.apply(void 0, args);
});
return result;
}
}, {
key: "teardown",
value: function teardown() {
this._initialEvent = null;
this._initialEventData = null;
this._selectRect = null;
this.selecting = false;
this._lastClickData = null;
this.isDetached = true;
this._listeners = Object.create(null);
this._removeTouchMoveWindowListener && this._removeTouchMoveWindowListener();
this._removeInitialEventListener && this._removeInitialEventListener();
this._removeEndListener && this._removeEndListener();
this._onEscListener && this._onEscListener();
this._removeMoveListener && this._removeMoveListener();
this._removeKeyUpListener && this._removeKeyUpListener();
this._removeKeyDownListener && this._removeKeyDownListener();
this._removeDropFromOutsideListener && this._removeDropFromOutsideListener();
this._removeDragOverFromOutsideListener && this._removeDragOverFromOutsideListener();
}
}, {
key: "isSelected",
value: function isSelected(node) {
var box = this._selectRect;
if (!box || !this.selecting) return false;
return objectsCollide(box, getBoundsForNode(node));
}
}, {
key: "filter",
value: function filter(items) {
var box = this._selectRect;
//not selecting
if (!box || !this.selecting) return [];
return items.filter(this.isSelected, this);
}
// Adds a listener that will call the handler only after the user has pressed on the screen
// without moving their finger for 250ms.
}, {
key: "_addLongPressListener",
value: function _addLongPressListener(handler, initialEvent) {
var _this = this;
var timer = null;
var removeTouchMoveListener = null;
var removeTouchEndListener = null;
var handleTouchStart = function handleTouchStart(initialEvent) {
timer = setTimeout(function () {
cleanup();
handler(initialEvent);
}, _this.longPressThreshold);
removeTouchMoveListener = addEventListener('touchmove', function () {
return cleanup();
});
removeTouchEndListener = addEventListener('touchend', function () {
return cleanup();
});
};
var removeTouchStartListener = addEventListener('touchstart', handleTouchStart);
var cleanup = function cleanup() {
if (timer) {
clearTimeout(timer);
}
if (removeTouchMoveListener) {
removeTouchMoveListener();
}
if (removeTouchEndListener) {
removeTouchEndListener();
}
timer = null;
removeTouchMoveListener = null;
removeTouchEndListener = null;
};
if (initialEvent) {
handleTouchStart(initialEvent);
}
return function () {
cleanup();
removeTouchStartListener();
};
}
// Listen for mousedown and touchstart events. When one is received, disable the other and setup
// future event handling based on the type of event.
}, {
key: "_addInitialEventListener",
value: function _addInitialEventListener() {
var _this2 = this;
var removeMouseDownListener = addEventListener('mousedown', function (e) {
_this2._removeInitialEventListener();
_this2._handleInitialEvent(e);
_this2._removeInitialEventListener = addEventListener('mousedown', _this2._handleInitialEvent);
});
var removeTouchStartListener = addEventListener('touchstart', function (e) {
_this2._removeInitialEventListener();
_this2._removeInitialEventListener = _this2._addLongPressListener(_this2._handleInitialEvent, e);
});
this._removeInitialEventListener = function () {
removeMouseDownListener();
removeTouchStartListener();
};
}
}, {
key: "_dropFromOutsideListener",
value: function _dropFromOutsideListener(e) {
var _getEventCoordinates = getEventCoordinates(e),
pageX = _getEventCoordinates.pageX,
pageY = _getEventCoordinates.pageY,
clientX = _getEventCoordinates.clientX,
clientY = _getEventCoordinates.clientY;
this.emit('dropFromOutside', {
x: pageX,
y: pageY,
clientX: clientX,
clientY: clientY
});
e.preventDefault();
}
}, {
key: "_dragOverFromOutsideListener",
value: function _dragOverFromOutsideListener(e) {
var _getEventCoordinates2 = getEventCoordinates(e),
pageX = _getEventCoordinates2.pageX,
pageY = _getEventCoordinates2.pageY,
clientX = _getEventCoordinates2.clientX,
clientY = _getEventCoordinates2.clientY;
this.emit('dragOverFromOutside', {
x: pageX,
y: pageY,
clientX: clientX,
clientY: clientY
});
e.preventDefault();
}
}, {
key: "_handleInitialEvent",
value: function _handleInitialEvent(e) {
this._initialEvent = e;
if (this.isDetached) {
return;
}
var _getEventCoordinates3 = getEventCoordinates(e),
clientX = _getEventCoordinates3.clientX,
clientY = _getEventCoordinates3.clientY,
pageX = _getEventCoordinates3.pageX,
pageY = _getEventCoordinates3.pageY;
var node = this.container(),
collides,
offsetData;
// Right clicks
if (e.which === 3 || e.button === 2 || !isOverContainer(node, clientX, clientY)) return;
if (!this.globalMouse && node && !contains(node, e.target)) {
var _normalizeDistance = normalizeDistance(0),
top = _normalizeDistance.top,
left = _normalizeDistance.left,
bottom = _normalizeDistance.bottom,
right = _normalizeDistance.right;
offsetData = getBoundsForNode(node);
collides = objectsCollide({
top: offsetData.top - top,
left: offsetData.left - left,
bottom: offsetData.bottom + bottom,
right: offsetData.right + right
}, {
top: pageY,
left: pageX
});
if (!collides) return;
}
var result = this.emit('beforeSelect', this._initialEventData = {
isTouch: /^touch/.test(e.type),
x: pageX,
y: pageY,
clientX: clientX,
clientY: clientY
});
if (result === false) return;
switch (e.type) {
case 'mousedown':
this._removeEndListener = addEventListener('mouseup', this._handleTerminatingEvent);
this._onEscListener = addEventListener('keydown', this._handleTerminatingEvent);
this._removeMoveListener = addEventListener('mousemove', this._handleMoveEvent);
break;
case 'touchstart':
this._handleMoveEvent(e);
this._removeEndListener = addEventListener('touchend', this._handleTerminatingEvent);
this._removeMoveListener = addEventListener('touchmove', this._handleMoveEvent);
break;
}
}
// Check whether provided event target element
// - is contained within a valid container
}, {
key: "_isWithinValidContainer",
value: function _isWithinValidContainer(e) {
var eventTarget = e.target;
var containers = this.validContainers;
if (!containers || !containers.length || !eventTarget) {
return true;
}
return containers.some(function (target) {
return !!eventTarget.closest(target);
});
}
}, {
key: "_handleTerminatingEvent",
value: function _handleTerminatingEvent(e) {
var selecting = this.selecting;
var bounds = this._selectRect;
// If it's not in selecting state, it's a click event
if (!selecting && e.type.includes('key')) {
e = this._initialEvent;
}
this.selecting = false;
this._removeEndListener && this._removeEndListener();
this._removeMoveListener && this._removeMoveListener();
this._selectRect = null;
this._initialEvent = null;
this._initialEventData = null;
if (!e) return;
var inRoot = !this.container || contains(this.container(), e.target);
var isWithinValidContainer = this._isWithinValidContainer(e);
if (e.key === 'Escape' || !isWithinValidContainer) {
return this.emit('reset');
}
if (!selecting && inRoot) {
return this._handleClickEvent(e);
}
// User drag-clicked in the Selectable area
if (selecting) return this.emit('select', bounds);
return this.emit('reset');
}
}, {
key: "_handleClickEvent",
value: function _handleClickEvent(e) {
var _getEventCoordinates4 = getEventCoordinates(e),
pageX = _getEventCoordinates4.pageX,
pageY = _getEventCoordinates4.pageY,
clientX = _getEventCoordinates4.clientX,
clientY = _getEventCoordinates4.clientY;
var now = new Date().getTime();
if (this._lastClickData && now - this._lastClickData.timestamp < clickInterval) {
// Double click event
this._lastClickData = null;
return this.emit('doubleClick', {
x: pageX,
y: pageY,
clientX: clientX,
clientY: clientY
});
}
// Click event
this._lastClickData = {
timestamp: now
};
return this.emit('click', {
x: pageX,
y: pageY,
clientX: clientX,
clientY: clientY
});
}
}, {
key: "_handleMoveEvent",
value: function _handleMoveEvent(e) {
if (this._initialEventData === null || this.isDetached) {
return;
}
var _this$_initialEventDa = this._initialEventData,
x = _this$_initialEventDa.x,
y = _this$_initialEventDa.y;
var _getEventCoordinates5 = getEventCoordinates(e),
pageX = _getEventCoordinates5.pageX,
pageY = _getEventCoordinates5.pageY;
var w = Math.abs(x - pageX);
var h = Math.abs(y - pageY);
var left = Math.min(pageX, x),
top = Math.min(pageY, y),
old = this.selecting;
var click = this.isClick(pageX, pageY);
// Prevent emitting selectStart event until mouse is moved.
// in Chrome on Windows, mouseMove event may be fired just after mouseDown event.
if (click && !old && !(w || h)) {
return;
}
if (!old && !click) {
this.emit('selectStart', this._initialEventData);
}
if (!click) {
this.selecting = true;
this._selectRect = {
top: top,
left: left,
x: pageX,
y: pageY,
right: left + w,
bottom: top + h
};
this.emit('selecting', this._selectRect);
}
e.preventDefault();
}
}, {
key: "_keyListener",
value: function _keyListener(e) {
this.ctrl = e.metaKey || e.ctrlKey;
}
}, {
key: "isClick",
value: function isClick(pageX, pageY) {
var _this$_initialEventDa2 = this._initialEventData,
x = _this$_initialEventDa2.x,
y = _this$_initialEventDa2.y,
isTouch = _this$_initialEventDa2.isTouch;
return !isTouch && Math.abs(pageX - x) <= clickTolerance && Math.abs(pageY - y) <= clickTolerance;
}
}]);
}();
/**
* Resolve the disance prop from either an Int or an Object
* @return {Object}
*/
function normalizeDistance() {
var distance = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
if (_typeof(distance) !== 'object') distance = {
top: distance,
left: distance,
right: distance,
bottom: distance
};
return distance;
}
/**
* Given two objects containing "top", "left", "offsetWidth" and "offsetHeight"
* properties, determine if they collide.
* @param {Object|HTMLElement} a
* @param {Object|HTMLElement} b
* @return {bool}
*/
function objectsCollide(nodeA, nodeB) {
var tolerance = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var _getBoundsForNode = getBoundsForNode(nodeA),
aTop = _getBoundsForNode.top,
aLeft = _getBoundsForNode.left,
_getBoundsForNode$rig = _getBoundsForNode.right,
aRight = _getBoundsForNode$rig === void 0 ? aLeft : _getBoundsForNode$rig,
_getBoundsForNode$bot = _getBoundsForNode.bottom,
aBottom = _getBoundsForNode$bot === void 0 ? aTop : _getBoundsForNode$bot;
var _getBoundsForNode2 = getBoundsForNode(nodeB),
bTop = _getBoundsForNode2.top,
bLeft = _getBoundsForNode2.left,
_getBoundsForNode2$ri = _getBoundsForNode2.right,
bRight = _getBoundsForNode2$ri === void 0 ? bLeft : _getBoundsForNode2$ri,
_getBoundsForNode2$bo = _getBoundsForNode2.bottom,
bBottom = _getBoundsForNode2$bo === void 0 ? bTop : _getBoundsForNode2$bo;
return !(
// 'a' bottom doesn't touch 'b' top
aBottom - tolerance < bTop ||
// 'a' top doesn't touch 'b' bottom
aTop + tolerance > bBottom ||
// 'a' right doesn't touch 'b' left
aRight - tolerance < bLeft ||
// 'a' left doesn't touch 'b' right
aLeft + tolerance > bRight);
}
/**
* Given a node, get everything needed to calculate its boundaries
* @param {HTMLElement} node
* @return {Object}
*/
function getBoundsForNode(node) {
if (!node.getBoundingClientRect) return node;
var rect = node.getBoundingClientRect(),
left = rect.left + pageOffset('left'),
top = rect.top + pageOffset('top');
return {
top: top,
left: left,
right: (node.offsetWidth || 0) + left,
bottom: (node.offsetHeight || 0) + top
};
}
function pageOffset(dir) {
if (dir === 'left') return window.pageXOffset || document.body.scrollLeft || 0;
if (dir === 'top') return window.pageYOffset || document.body.scrollTop || 0;
}
var BackgroundCells = /*#__PURE__*/function (_React$Component) {
function BackgroundCells(props, context) {
var _this;
_classCallCheck(this, BackgroundCells);
_this = _callSuper(this, BackgroundCells, [props, context]);
_this.state = {
selecting: false
};
_this.containerRef = /*#__PURE__*/createRef();
return _this;
}
_inherits(BackgroundCells, _React$Component);
return _createClass(BackgroundCells, [{
key: "componentDidMount",
value: function componentDidMount() {
this.props.selectable && this._selectable();
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
this._teardownSelectable();
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate(prevProps) {
if (!prevProps.selectable && this.props.selectable) this._selectable();
if (prevProps.selectable && !this.props.selectable) this._teardownSelectable();
}
}, {
key: "render",
value: function render() {
var _this$props = this.props,
range = _this$props.range,
getNow = _this$props.getNow,
getters = _this$props.getters,
currentDate = _this$props.date,
Wrapper = _this$props.components.dateCellWrapper,
localizer = _this$props.localizer;
var _this$state = this.state,
selecting = _this$state.selecting,
startIdx = _this$state.startIdx,
endIdx = _this$state.endIdx;
var current = getNow();
return /*#__PURE__*/React.createElement("div", {
className: "rbc-row-bg",
ref: this.containerRef
}, range.map(function (date, index) {
var selected = selecting && index >= startIdx && index <= endIdx;
var _getters$dayProp = getters.dayProp(date),
className = _getters$dayProp.className,
style = _getters$dayProp.style;
return /*#__PURE__*/React.createElement(Wrapper, {
key: index,
value: date,
range: range
}, /*#__PURE__*/React.createElement("div", {
style: style,
className: clsx('rbc-day-bg', className, selected && 'rbc-selected-cell', localizer.isSameDate(date, current) && 'rbc-today', currentDate && localizer.neq(currentDate, date, 'month') && 'rbc-off-range-bg')
}));
}));
}
}, {
key: "_selectable",
value: function _selectable() {
var _this2 = this;
var node = this.containerRef.current;
var selector = this._selector = new Selection(this.props.container, {
longPressThreshold: this.props.longPressThreshold
});
var selectorClicksHandler = function selectorClicksHandler(point, actionType) {
if (!isEvent(node, point) && !isShowMore(node, point)) {
var rowBox = getBoundsForNode(node);
var _this2$props = _this2.props,
range = _this2$props.range,
rtl = _this2$props.rtl;
if (pointInBox(rowBox, point)) {
var currentCell = getSlotAtX(rowBox, point.x, rtl, range.length);
_this2._selectSlot({
startIdx: currentCell,
endIdx: currentCell,
action: actionType,
box: point
});
}
}
_this2._initial = {};
_this2.setState({
selecting: false
});
};
selector.on('selecting', function (box) {
var _this2$props2 = _this2.props,
range = _this2$props2.range,
rtl = _this2$props2.rtl;
var startIdx = -1;
var endIdx = -1;
if (!_this2.state.selecting) {
notify(_this2.props.onSelectStart, [box]);
_this2._initial = {
x: box.x,
y: box.y
};
}
if (selector.isSelected(node)) {
var nodeBox = getBoundsForNode(node);
var _dateCellSelection = dateCellSelection(_this2._