懒羊羊
2023-08-30 1ac2bc1590406d9babec036e154d8d08f34a6aa1
提交 | 用户 | 时间
1ac2bc 1 /*!
2 FullCalendar Interaction Plugin v4.3.0
3 Docs & License: https://fullcalendar.io/
4 (c) 2019 Adam Shaw
5 */
6
7 (function (global, factory) {
8     typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) :
9     typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) :
10     (global = global || self, factory(global.FullCalendarInteraction = {}, global.FullCalendar));
11 }(this, function (exports, core) { 'use strict';
12
13     /*! *****************************************************************************
14     Copyright (c) Microsoft Corporation. All rights reserved.
15     Licensed under the Apache License, Version 2.0 (the "License"); you may not use
16     this file except in compliance with the License. You may obtain a copy of the
17     License at http://www.apache.org/licenses/LICENSE-2.0
18
19     THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20     KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
21     WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
22     MERCHANTABLITY OR NON-INFRINGEMENT.
23
24     See the Apache Version 2.0 License for specific language governing permissions
25     and limitations under the License.
26     ***************************************************************************** */
27     /* global Reflect, Promise */
28
29     var extendStatics = function(d, b) {
30         extendStatics = Object.setPrototypeOf ||
31             ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
32             function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
33         return extendStatics(d, b);
34     };
35
36     function __extends(d, b) {
37         extendStatics(d, b);
38         function __() { this.constructor = d; }
39         d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
40     }
41
42     var __assign = function() {
43         __assign = Object.assign || function __assign(t) {
44             for (var s, i = 1, n = arguments.length; i < n; i++) {
45                 s = arguments[i];
46                 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
47             }
48             return t;
49         };
50         return __assign.apply(this, arguments);
51     };
52
53     core.config.touchMouseIgnoreWait = 500;
54     var ignoreMouseDepth = 0;
55     var listenerCnt = 0;
56     var isWindowTouchMoveCancelled = false;
57     /*
58     Uses a "pointer" abstraction, which monitors UI events for both mouse and touch.
59     Tracks when the pointer "drags" on a certain element, meaning down+move+up.
60
61     Also, tracks if there was touch-scrolling.
62     Also, can prevent touch-scrolling from happening.
63     Also, can fire pointermove events when scrolling happens underneath, even when no real pointer movement.
64
65     emits:
66     - pointerdown
67     - pointermove
68     - pointerup
69     */
70     var PointerDragging = /** @class */ (function () {
71         function PointerDragging(containerEl) {
72             var _this = this;
73             this.subjectEl = null;
74             this.downEl = null;
75             // options that can be directly assigned by caller
76             this.selector = ''; // will cause subjectEl in all emitted events to be this element
77             this.handleSelector = '';
78             this.shouldIgnoreMove = false;
79             this.shouldWatchScroll = true; // for simulating pointermove on scroll
80             // internal states
81             this.isDragging = false;
82             this.isTouchDragging = false;
83             this.wasTouchScroll = false;
84             // Mouse
85             // ----------------------------------------------------------------------------------------------------
86             this.handleMouseDown = function (ev) {
87                 if (!_this.shouldIgnoreMouse() &&
88                     isPrimaryMouseButton(ev) &&
89                     _this.tryStart(ev)) {
90                     var pev = _this.createEventFromMouse(ev, true);
91                     _this.emitter.trigger('pointerdown', pev);
92                     _this.initScrollWatch(pev);
93                     if (!_this.shouldIgnoreMove) {
94                         document.addEventListener('mousemove', _this.handleMouseMove);
95                     }
96                     document.addEventListener('mouseup', _this.handleMouseUp);
97                 }
98             };
99             this.handleMouseMove = function (ev) {
100                 var pev = _this.createEventFromMouse(ev);
101                 _this.recordCoords(pev);
102                 _this.emitter.trigger('pointermove', pev);
103             };
104             this.handleMouseUp = function (ev) {
105                 document.removeEventListener('mousemove', _this.handleMouseMove);
106                 document.removeEventListener('mouseup', _this.handleMouseUp);
107                 _this.emitter.trigger('pointerup', _this.createEventFromMouse(ev));
108                 _this.cleanup(); // call last so that pointerup has access to props
109             };
110             // Touch
111             // ----------------------------------------------------------------------------------------------------
112             this.handleTouchStart = function (ev) {
113                 if (_this.tryStart(ev)) {
114                     _this.isTouchDragging = true;
115                     var pev = _this.createEventFromTouch(ev, true);
116                     _this.emitter.trigger('pointerdown', pev);
117                     _this.initScrollWatch(pev);
118                     // unlike mouse, need to attach to target, not document
119                     // https://stackoverflow.com/a/45760014
120                     var target = ev.target;
121                     if (!_this.shouldIgnoreMove) {
122                         target.addEventListener('touchmove', _this.handleTouchMove);
123                     }
124                     target.addEventListener('touchend', _this.handleTouchEnd);
125                     target.addEventListener('touchcancel', _this.handleTouchEnd); // treat it as a touch end
126                     // attach a handler to get called when ANY scroll action happens on the page.
127                     // this was impossible to do with normal on/off because 'scroll' doesn't bubble.
128                     // http://stackoverflow.com/a/32954565/96342
129                     window.addEventListener('scroll', _this.handleTouchScroll, true // useCapture
130                     );
131                 }
132             };
133             this.handleTouchMove = function (ev) {
134                 var pev = _this.createEventFromTouch(ev);
135                 _this.recordCoords(pev);
136                 _this.emitter.trigger('pointermove', pev);
137             };
138             this.handleTouchEnd = function (ev) {
139                 if (_this.isDragging) { // done to guard against touchend followed by touchcancel
140                     var target = ev.target;
141                     target.removeEventListener('touchmove', _this.handleTouchMove);
142                     target.removeEventListener('touchend', _this.handleTouchEnd);
143                     target.removeEventListener('touchcancel', _this.handleTouchEnd);
144                     window.removeEventListener('scroll', _this.handleTouchScroll, true); // useCaptured=true
145                     _this.emitter.trigger('pointerup', _this.createEventFromTouch(ev));
146                     _this.cleanup(); // call last so that pointerup has access to props
147                     _this.isTouchDragging = false;
148                     startIgnoringMouse();
149                 }
150             };
151             this.handleTouchScroll = function () {
152                 _this.wasTouchScroll = true;
153             };
154             this.handleScroll = function (ev) {
155                 if (!_this.shouldIgnoreMove) {
156                     var pageX = (window.pageXOffset - _this.prevScrollX) + _this.prevPageX;
157                     var pageY = (window.pageYOffset - _this.prevScrollY) + _this.prevPageY;
158                     _this.emitter.trigger('pointermove', {
159                         origEvent: ev,
160                         isTouch: _this.isTouchDragging,
161                         subjectEl: _this.subjectEl,
162                         pageX: pageX,
163                         pageY: pageY,
164                         deltaX: pageX - _this.origPageX,
165                         deltaY: pageY - _this.origPageY
166                     });
167                 }
168             };
169             this.containerEl = containerEl;
170             this.emitter = new core.EmitterMixin();
171             containerEl.addEventListener('mousedown', this.handleMouseDown);
172             containerEl.addEventListener('touchstart', this.handleTouchStart, { passive: true });
173             listenerCreated();
174         }
175         PointerDragging.prototype.destroy = function () {
176             this.containerEl.removeEventListener('mousedown', this.handleMouseDown);
177             this.containerEl.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
178             listenerDestroyed();
179         };
180         PointerDragging.prototype.tryStart = function (ev) {
181             var subjectEl = this.querySubjectEl(ev);
182             var downEl = ev.target;
183             if (subjectEl &&
184                 (!this.handleSelector || core.elementClosest(downEl, this.handleSelector))) {
185                 this.subjectEl = subjectEl;
186                 this.downEl = downEl;
187                 this.isDragging = true; // do this first so cancelTouchScroll will work
188                 this.wasTouchScroll = false;
189                 return true;
190             }
191             return false;
192         };
193         PointerDragging.prototype.cleanup = function () {
194             isWindowTouchMoveCancelled = false;
195             this.isDragging = false;
196             this.subjectEl = null;
197             this.downEl = null;
198             // keep wasTouchScroll around for later access
199             this.destroyScrollWatch();
200         };
201         PointerDragging.prototype.querySubjectEl = function (ev) {
202             if (this.selector) {
203                 return core.elementClosest(ev.target, this.selector);
204             }
205             else {
206                 return this.containerEl;
207             }
208         };
209         PointerDragging.prototype.shouldIgnoreMouse = function () {
210             return ignoreMouseDepth || this.isTouchDragging;
211         };
212         // can be called by user of this class, to cancel touch-based scrolling for the current drag
213         PointerDragging.prototype.cancelTouchScroll = function () {
214             if (this.isDragging) {
215                 isWindowTouchMoveCancelled = true;
216             }
217         };
218         // Scrolling that simulates pointermoves
219         // ----------------------------------------------------------------------------------------------------
220         PointerDragging.prototype.initScrollWatch = function (ev) {
221             if (this.shouldWatchScroll) {
222                 this.recordCoords(ev);
223                 window.addEventListener('scroll', this.handleScroll, true); // useCapture=true
224             }
225         };
226         PointerDragging.prototype.recordCoords = function (ev) {
227             if (this.shouldWatchScroll) {
228                 this.prevPageX = ev.pageX;
229                 this.prevPageY = ev.pageY;
230                 this.prevScrollX = window.pageXOffset;
231                 this.prevScrollY = window.pageYOffset;
232             }
233         };
234         PointerDragging.prototype.destroyScrollWatch = function () {
235             if (this.shouldWatchScroll) {
236                 window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true
237             }
238         };
239         // Event Normalization
240         // ----------------------------------------------------------------------------------------------------
241         PointerDragging.prototype.createEventFromMouse = function (ev, isFirst) {
242             var deltaX = 0;
243             var deltaY = 0;
244             // TODO: repeat code
245             if (isFirst) {
246                 this.origPageX = ev.pageX;
247                 this.origPageY = ev.pageY;
248             }
249             else {
250                 deltaX = ev.pageX - this.origPageX;
251                 deltaY = ev.pageY - this.origPageY;
252             }
253             return {
254                 origEvent: ev,
255                 isTouch: false,
256                 subjectEl: this.subjectEl,
257                 pageX: ev.pageX,
258                 pageY: ev.pageY,
259                 deltaX: deltaX,
260                 deltaY: deltaY
261             };
262         };
263         PointerDragging.prototype.createEventFromTouch = function (ev, isFirst) {
264             var touches = ev.touches;
265             var pageX;
266             var pageY;
267             var deltaX = 0;
268             var deltaY = 0;
269             // if touch coords available, prefer,
270             // because FF would give bad ev.pageX ev.pageY
271             if (touches && touches.length) {
272                 pageX = touches[0].pageX;
273                 pageY = touches[0].pageY;
274             }
275             else {
276                 pageX = ev.pageX;
277                 pageY = ev.pageY;
278             }
279             // TODO: repeat code
280             if (isFirst) {
281                 this.origPageX = pageX;
282                 this.origPageY = pageY;
283             }
284             else {
285                 deltaX = pageX - this.origPageX;
286                 deltaY = pageY - this.origPageY;
287             }
288             return {
289                 origEvent: ev,
290                 isTouch: true,
291                 subjectEl: this.subjectEl,
292                 pageX: pageX,
293                 pageY: pageY,
294                 deltaX: deltaX,
295                 deltaY: deltaY
296             };
297         };
298         return PointerDragging;
299     }());
300     // Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)
301     function isPrimaryMouseButton(ev) {
302         return ev.button === 0 && !ev.ctrlKey;
303     }
304     // Ignoring fake mouse events generated by touch
305     // ----------------------------------------------------------------------------------------------------
306     function startIgnoringMouse() {
307         ignoreMouseDepth++;
308         setTimeout(function () {
309             ignoreMouseDepth--;
310         }, core.config.touchMouseIgnoreWait);
311     }
312     // We want to attach touchmove as early as possible for Safari
313     // ----------------------------------------------------------------------------------------------------
314     function listenerCreated() {
315         if (!(listenerCnt++)) {
316             window.addEventListener('touchmove', onWindowTouchMove, { passive: false });
317         }
318     }
319     function listenerDestroyed() {
320         if (!(--listenerCnt)) {
321             window.removeEventListener('touchmove', onWindowTouchMove, { passive: false });
322         }
323     }
324     function onWindowTouchMove(ev) {
325         if (isWindowTouchMoveCancelled) {
326             ev.preventDefault();
327         }
328     }
329
330     /*
331     An effect in which an element follows the movement of a pointer across the screen.
332     The moving element is a clone of some other element.
333     Must call start + handleMove + stop.
334     */
335     var ElementMirror = /** @class */ (function () {
336         function ElementMirror() {
337             this.isVisible = false; // must be explicitly enabled
338             this.sourceEl = null;
339             this.mirrorEl = null;
340             this.sourceElRect = null; // screen coords relative to viewport
341             // options that can be set directly by caller
342             this.parentNode = document.body;
343             this.zIndex = 9999;
344             this.revertDuration = 0;
345         }
346         ElementMirror.prototype.start = function (sourceEl, pageX, pageY) {
347             this.sourceEl = sourceEl;
348             this.sourceElRect = this.sourceEl.getBoundingClientRect();
349             this.origScreenX = pageX - window.pageXOffset;
350             this.origScreenY = pageY - window.pageYOffset;
351             this.deltaX = 0;
352             this.deltaY = 0;
353             this.updateElPosition();
354         };
355         ElementMirror.prototype.handleMove = function (pageX, pageY) {
356             this.deltaX = (pageX - window.pageXOffset) - this.origScreenX;
357             this.deltaY = (pageY - window.pageYOffset) - this.origScreenY;
358             this.updateElPosition();
359         };
360         // can be called before start
361         ElementMirror.prototype.setIsVisible = function (bool) {
362             if (bool) {
363                 if (!this.isVisible) {
364                     if (this.mirrorEl) {
365                         this.mirrorEl.style.display = '';
366                     }
367                     this.isVisible = bool; // needs to happen before updateElPosition
368                     this.updateElPosition(); // because was not updating the position while invisible
369                 }
370             }
371             else {
372                 if (this.isVisible) {
373                     if (this.mirrorEl) {
374                         this.mirrorEl.style.display = 'none';
375                     }
376                     this.isVisible = bool;
377                 }
378             }
379         };
380         // always async
381         ElementMirror.prototype.stop = function (needsRevertAnimation, callback) {
382             var _this = this;
383             var done = function () {
384                 _this.cleanup();
385                 callback();
386             };
387             if (needsRevertAnimation &&
388                 this.mirrorEl &&
389                 this.isVisible &&
390                 this.revertDuration && // if 0, transition won't work
391                 (this.deltaX || this.deltaY) // if same coords, transition won't work
392             ) {
393                 this.doRevertAnimation(done, this.revertDuration);
394             }
395             else {
396                 setTimeout(done, 0);
397             }
398         };
399         ElementMirror.prototype.doRevertAnimation = function (callback, revertDuration) {
400             var mirrorEl = this.mirrorEl;
401             var finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened
402             mirrorEl.style.transition =
403                 'top ' + revertDuration + 'ms,' +
404                     'left ' + revertDuration + 'ms';
405             core.applyStyle(mirrorEl, {
406                 left: finalSourceElRect.left,
407                 top: finalSourceElRect.top
408             });
409             core.whenTransitionDone(mirrorEl, function () {
410                 mirrorEl.style.transition = '';
411                 callback();
412             });
413         };
414         ElementMirror.prototype.cleanup = function () {
415             if (this.mirrorEl) {
416                 core.removeElement(this.mirrorEl);
417                 this.mirrorEl = null;
418             }
419             this.sourceEl = null;
420         };
421         ElementMirror.prototype.updateElPosition = function () {
422             if (this.sourceEl && this.isVisible) {
423                 core.applyStyle(this.getMirrorEl(), {
424                     left: this.sourceElRect.left + this.deltaX,
425                     top: this.sourceElRect.top + this.deltaY
426                 });
427             }
428         };
429         ElementMirror.prototype.getMirrorEl = function () {
430             var sourceElRect = this.sourceElRect;
431             var mirrorEl = this.mirrorEl;
432             if (!mirrorEl) {
433                 mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true
434                 // we don't want long taps or any mouse interaction causing selection/menus.
435                 // would use preventSelection(), but that prevents selectstart, causing problems.
436                 mirrorEl.classList.add('fc-unselectable');
437                 mirrorEl.classList.add('fc-dragging');
438                 core.applyStyle(mirrorEl, {
439                     position: 'fixed',
440                     zIndex: this.zIndex,
441                     visibility: '',
442                     boxSizing: 'border-box',
443                     width: sourceElRect.right - sourceElRect.left,
444                     height: sourceElRect.bottom - sourceElRect.top,
445                     right: 'auto',
446                     bottom: 'auto',
447                     margin: 0
448                 });
449                 this.parentNode.appendChild(mirrorEl);
450             }
451             return mirrorEl;
452         };
453         return ElementMirror;
454     }());
455
456     /*
457     Is a cache for a given element's scroll information (all the info that ScrollController stores)
458     in addition the "client rectangle" of the element.. the area within the scrollbars.
459
460     The cache can be in one of two modes:
461     - doesListening:false - ignores when the container is scrolled by someone else
462     - doesListening:true - watch for scrolling and update the cache
463     */
464     var ScrollGeomCache = /** @class */ (function (_super) {
465         __extends(ScrollGeomCache, _super);
466         function ScrollGeomCache(scrollController, doesListening) {
467             var _this = _super.call(this) || this;
468             _this.handleScroll = function () {
469                 _this.scrollTop = _this.scrollController.getScrollTop();
470                 _this.scrollLeft = _this.scrollController.getScrollLeft();
471                 _this.handleScrollChange();
472             };
473             _this.scrollController = scrollController;
474             _this.doesListening = doesListening;
475             _this.scrollTop = _this.origScrollTop = scrollController.getScrollTop();
476             _this.scrollLeft = _this.origScrollLeft = scrollController.getScrollLeft();
477             _this.scrollWidth = scrollController.getScrollWidth();
478             _this.scrollHeight = scrollController.getScrollHeight();
479             _this.clientWidth = scrollController.getClientWidth();
480             _this.clientHeight = scrollController.getClientHeight();
481             _this.clientRect = _this.computeClientRect(); // do last in case it needs cached values
482             if (_this.doesListening) {
483                 _this.getEventTarget().addEventListener('scroll', _this.handleScroll);
484             }
485             return _this;
486         }
487         ScrollGeomCache.prototype.destroy = function () {
488             if (this.doesListening) {
489                 this.getEventTarget().removeEventListener('scroll', this.handleScroll);
490             }
491         };
492         ScrollGeomCache.prototype.getScrollTop = function () {
493             return this.scrollTop;
494         };
495         ScrollGeomCache.prototype.getScrollLeft = function () {
496             return this.scrollLeft;
497         };
498         ScrollGeomCache.prototype.setScrollTop = function (top) {
499             this.scrollController.setScrollTop(top);
500             if (!this.doesListening) {
501                 // we are not relying on the element to normalize out-of-bounds scroll values
502                 // so we need to sanitize ourselves
503                 this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0);
504                 this.handleScrollChange();
505             }
506         };
507         ScrollGeomCache.prototype.setScrollLeft = function (top) {
508             this.scrollController.setScrollLeft(top);
509             if (!this.doesListening) {
510                 // we are not relying on the element to normalize out-of-bounds scroll values
511                 // so we need to sanitize ourselves
512                 this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0);
513                 this.handleScrollChange();
514             }
515         };
516         ScrollGeomCache.prototype.getClientWidth = function () {
517             return this.clientWidth;
518         };
519         ScrollGeomCache.prototype.getClientHeight = function () {
520             return this.clientHeight;
521         };
522         ScrollGeomCache.prototype.getScrollWidth = function () {
523             return this.scrollWidth;
524         };
525         ScrollGeomCache.prototype.getScrollHeight = function () {
526             return this.scrollHeight;
527         };
528         ScrollGeomCache.prototype.handleScrollChange = function () {
529         };
530         return ScrollGeomCache;
531     }(core.ScrollController));
532     var ElementScrollGeomCache = /** @class */ (function (_super) {
533         __extends(ElementScrollGeomCache, _super);
534         function ElementScrollGeomCache(el, doesListening) {
535             return _super.call(this, new core.ElementScrollController(el), doesListening) || this;
536         }
537         ElementScrollGeomCache.prototype.getEventTarget = function () {
538             return this.scrollController.el;
539         };
540         ElementScrollGeomCache.prototype.computeClientRect = function () {
541             return core.computeInnerRect(this.scrollController.el);
542         };
543         return ElementScrollGeomCache;
544     }(ScrollGeomCache));
545     var WindowScrollGeomCache = /** @class */ (function (_super) {
546         __extends(WindowScrollGeomCache, _super);
547         function WindowScrollGeomCache(doesListening) {
548             return _super.call(this, new core.WindowScrollController(), doesListening) || this;
549         }
550         WindowScrollGeomCache.prototype.getEventTarget = function () {
551             return window;
552         };
553         WindowScrollGeomCache.prototype.computeClientRect = function () {
554             return {
555                 left: this.scrollLeft,
556                 right: this.scrollLeft + this.clientWidth,
557                 top: this.scrollTop,
558                 bottom: this.scrollTop + this.clientHeight
559             };
560         };
561         // the window is the only scroll object that changes it's rectangle relative
562         // to the document's topleft as it scrolls
563         WindowScrollGeomCache.prototype.handleScrollChange = function () {
564             this.clientRect = this.computeClientRect();
565         };
566         return WindowScrollGeomCache;
567     }(ScrollGeomCache));
568
569     // If available we are using native "performance" API instead of "Date"
570     // Read more about it on MDN:
571     // https://developer.mozilla.org/en-US/docs/Web/API/Performance
572     var getTime = typeof performance === 'function' ? performance.now : Date.now;
573     /*
574     For a pointer interaction, automatically scrolls certain scroll containers when the pointer
575     approaches the edge.
576
577     The caller must call start + handleMove + stop.
578     */
579     var AutoScroller = /** @class */ (function () {
580         function AutoScroller() {
581             var _this = this;
582             // options that can be set by caller
583             this.isEnabled = true;
584             this.scrollQuery = [window, '.fc-scroller'];
585             this.edgeThreshold = 50; // pixels
586             this.maxVelocity = 300; // pixels per second
587             // internal state
588             this.pointerScreenX = null;
589             this.pointerScreenY = null;
590             this.isAnimating = false;
591             this.scrollCaches = null;
592             // protect against the initial pointerdown being too close to an edge and starting the scroll
593             this.everMovedUp = false;
594             this.everMovedDown = false;
595             this.everMovedLeft = false;
596             this.everMovedRight = false;
597             this.animate = function () {
598                 if (_this.isAnimating) { // wasn't cancelled between animation calls
599                     var edge = _this.computeBestEdge(_this.pointerScreenX + window.pageXOffset, _this.pointerScreenY + window.pageYOffset);
600                     if (edge) {
601                         var now = getTime();
602                         _this.handleSide(edge, (now - _this.msSinceRequest) / 1000);
603                         _this.requestAnimation(now);
604                     }
605                     else {
606                         _this.isAnimating = false; // will stop animation
607                     }
608                 }
609             };
610         }
611         AutoScroller.prototype.start = function (pageX, pageY) {
612             if (this.isEnabled) {
613                 this.scrollCaches = this.buildCaches();
614                 this.pointerScreenX = null;
615                 this.pointerScreenY = null;
616                 this.everMovedUp = false;
617                 this.everMovedDown = false;
618                 this.everMovedLeft = false;
619                 this.everMovedRight = false;
620                 this.handleMove(pageX, pageY);
621             }
622         };
623         AutoScroller.prototype.handleMove = function (pageX, pageY) {
624             if (this.isEnabled) {
625                 var pointerScreenX = pageX - window.pageXOffset;
626                 var pointerScreenY = pageY - window.pageYOffset;
627                 var yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY;
628                 var xDelta = this.pointerScreenX === null ? 0 : pointerScreenX - this.pointerScreenX;
629                 if (yDelta < 0) {
630                     this.everMovedUp = true;
631                 }
632                 else if (yDelta > 0) {
633                     this.everMovedDown = true;
634                 }
635                 if (xDelta < 0) {
636                     this.everMovedLeft = true;
637                 }
638                 else if (xDelta > 0) {
639                     this.everMovedRight = true;
640                 }
641                 this.pointerScreenX = pointerScreenX;
642                 this.pointerScreenY = pointerScreenY;
643                 if (!this.isAnimating) {
644                     this.isAnimating = true;
645                     this.requestAnimation(getTime());
646                 }
647             }
648         };
649         AutoScroller.prototype.stop = function () {
650             if (this.isEnabled) {
651                 this.isAnimating = false; // will stop animation
652                 for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
653                     var scrollCache = _a[_i];
654                     scrollCache.destroy();
655                 }
656                 this.scrollCaches = null;
657             }
658         };
659         AutoScroller.prototype.requestAnimation = function (now) {
660             this.msSinceRequest = now;
661             requestAnimationFrame(this.animate);
662         };
663         AutoScroller.prototype.handleSide = function (edge, seconds) {
664             var scrollCache = edge.scrollCache;
665             var edgeThreshold = this.edgeThreshold;
666             var invDistance = edgeThreshold - edge.distance;
667             var velocity = // the closer to the edge, the faster we scroll
668              (invDistance * invDistance) / (edgeThreshold * edgeThreshold) * // quadratic
669                 this.maxVelocity * seconds;
670             var sign = 1;
671             switch (edge.name) {
672                 case 'left':
673                     sign = -1;
674                 // falls through
675                 case 'right':
676                     scrollCache.setScrollLeft(scrollCache.getScrollLeft() + velocity * sign);
677                     break;
678                 case 'top':
679                     sign = -1;
680                 // falls through
681                 case 'bottom':
682                     scrollCache.setScrollTop(scrollCache.getScrollTop() + velocity * sign);
683                     break;
684             }
685         };
686         // left/top are relative to document topleft
687         AutoScroller.prototype.computeBestEdge = function (left, top) {
688             var edgeThreshold = this.edgeThreshold;
689             var bestSide = null;
690             for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
691                 var scrollCache = _a[_i];
692                 var rect = scrollCache.clientRect;
693                 var leftDist = left - rect.left;
694                 var rightDist = rect.right - left;
695                 var topDist = top - rect.top;
696                 var bottomDist = rect.bottom - top;
697                 // completely within the rect?
698                 if (leftDist >= 0 && rightDist >= 0 && topDist >= 0 && bottomDist >= 0) {
699                     if (topDist <= edgeThreshold && this.everMovedUp && scrollCache.canScrollUp() &&
700                         (!bestSide || bestSide.distance > topDist)) {
701                         bestSide = { scrollCache: scrollCache, name: 'top', distance: topDist };
702                     }
703                     if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() &&
704                         (!bestSide || bestSide.distance > bottomDist)) {
705                         bestSide = { scrollCache: scrollCache, name: 'bottom', distance: bottomDist };
706                     }
707                     if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() &&
708                         (!bestSide || bestSide.distance > leftDist)) {
709                         bestSide = { scrollCache: scrollCache, name: 'left', distance: leftDist };
710                     }
711                     if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() &&
712                         (!bestSide || bestSide.distance > rightDist)) {
713                         bestSide = { scrollCache: scrollCache, name: 'right', distance: rightDist };
714                     }
715                 }
716             }
717             return bestSide;
718         };
719         AutoScroller.prototype.buildCaches = function () {
720             return this.queryScrollEls().map(function (el) {
721                 if (el === window) {
722                     return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls
723                 }
724                 else {
725                     return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls
726                 }
727             });
728         };
729         AutoScroller.prototype.queryScrollEls = function () {
730             var els = [];
731             for (var _i = 0, _a = this.scrollQuery; _i < _a.length; _i++) {
732                 var query = _a[_i];
733                 if (typeof query === 'object') {
734                     els.push(query);
735                 }
736                 else {
737                     els.push.apply(els, Array.prototype.slice.call(document.querySelectorAll(query)));
738                 }
739             }
740             return els;
741         };
742         return AutoScroller;
743     }());
744
745     /*
746     Monitors dragging on an element. Has a number of high-level features:
747     - minimum distance required before dragging
748     - minimum wait time ("delay") before dragging
749     - a mirror element that follows the pointer
750     */
751     var FeaturefulElementDragging = /** @class */ (function (_super) {
752         __extends(FeaturefulElementDragging, _super);
753         function FeaturefulElementDragging(containerEl) {
754             var _this = _super.call(this, containerEl) || this;
755             // options that can be directly set by caller
756             // the caller can also set the PointerDragging's options as well
757             _this.delay = null;
758             _this.minDistance = 0;
759             _this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag
760             _this.mirrorNeedsRevert = false;
761             _this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup
762             _this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation
763             _this.isDelayEnded = false;
764             _this.isDistanceSurpassed = false;
765             _this.delayTimeoutId = null;
766             _this.onPointerDown = function (ev) {
767                 if (!_this.isDragging) { // so new drag doesn't happen while revert animation is going
768                     _this.isInteracting = true;
769                     _this.isDelayEnded = false;
770                     _this.isDistanceSurpassed = false;
771                     core.preventSelection(document.body);
772                     core.preventContextMenu(document.body);
773                     // prevent links from being visited if there's an eventual drag.
774                     // also prevents selection in older browsers (maybe?).
775                     // not necessary for touch, besides, browser would complain about passiveness.
776                     if (!ev.isTouch) {
777                         ev.origEvent.preventDefault();
778                     }
779                     _this.emitter.trigger('pointerdown', ev);
780                     if (!_this.pointer.shouldIgnoreMove) {
781                         // actions related to initiating dragstart+dragmove+dragend...
782                         _this.mirror.setIsVisible(false); // reset. caller must set-visible
783                         _this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down
784                         _this.startDelay(ev);
785                         if (!_this.minDistance) {
786                             _this.handleDistanceSurpassed(ev);
787                         }
788                     }
789                 }
790             };
791             _this.onPointerMove = function (ev) {
792                 if (_this.isInteracting) { // if false, still waiting for previous drag's revert
793                     _this.emitter.trigger('pointermove', ev);
794                     if (!_this.isDistanceSurpassed) {
795                         var minDistance = _this.minDistance;
796                         var distanceSq = void 0; // current distance from the origin, squared
797                         var deltaX = ev.deltaX, deltaY = ev.deltaY;
798                         distanceSq = deltaX * deltaX + deltaY * deltaY;
799                         if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem
800                             _this.handleDistanceSurpassed(ev);
801                         }
802                     }
803                     if (_this.isDragging) {
804                         // a real pointer move? (not one simulated by scrolling)
805                         if (ev.origEvent.type !== 'scroll') {
806                             _this.mirror.handleMove(ev.pageX, ev.pageY);
807                             _this.autoScroller.handleMove(ev.pageX, ev.pageY);
808                         }
809                         _this.emitter.trigger('dragmove', ev);
810                     }
811                 }
812             };
813             _this.onPointerUp = function (ev) {
814                 if (_this.isInteracting) { // if false, still waiting for previous drag's revert
815                     _this.isInteracting = false;
816                     core.allowSelection(document.body);
817                     core.allowContextMenu(document.body);
818                     _this.emitter.trigger('pointerup', ev); // can potentially set mirrorNeedsRevert
819                     if (_this.isDragging) {
820                         _this.autoScroller.stop();
821                         _this.tryStopDrag(ev); // which will stop the mirror
822                     }
823                     if (_this.delayTimeoutId) {
824                         clearTimeout(_this.delayTimeoutId);
825                         _this.delayTimeoutId = null;
826                     }
827                 }
828             };
829             var pointer = _this.pointer = new PointerDragging(containerEl);
830             pointer.emitter.on('pointerdown', _this.onPointerDown);
831             pointer.emitter.on('pointermove', _this.onPointerMove);
832             pointer.emitter.on('pointerup', _this.onPointerUp);
833             _this.mirror = new ElementMirror();
834             _this.autoScroller = new AutoScroller();
835             return _this;
836         }
837         FeaturefulElementDragging.prototype.destroy = function () {
838             this.pointer.destroy();
839         };
840         FeaturefulElementDragging.prototype.startDelay = function (ev) {
841             var _this = this;
842             if (typeof this.delay === 'number') {
843                 this.delayTimeoutId = setTimeout(function () {
844                     _this.delayTimeoutId = null;
845                     _this.handleDelayEnd(ev);
846                 }, this.delay); // not assignable to number!
847             }
848             else {
849                 this.handleDelayEnd(ev);
850             }
851         };
852         FeaturefulElementDragging.prototype.handleDelayEnd = function (ev) {
853             this.isDelayEnded = true;
854             this.tryStartDrag(ev);
855         };
856         FeaturefulElementDragging.prototype.handleDistanceSurpassed = function (ev) {
857             this.isDistanceSurpassed = true;
858             this.tryStartDrag(ev);
859         };
860         FeaturefulElementDragging.prototype.tryStartDrag = function (ev) {
861             if (this.isDelayEnded && this.isDistanceSurpassed) {
862                 if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) {
863                     this.isDragging = true;
864                     this.mirrorNeedsRevert = false;
865                     this.autoScroller.start(ev.pageX, ev.pageY);
866                     this.emitter.trigger('dragstart', ev);
867                     if (this.touchScrollAllowed === false) {
868                         this.pointer.cancelTouchScroll();
869                     }
870                 }
871             }
872         };
873         FeaturefulElementDragging.prototype.tryStopDrag = function (ev) {
874             // .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events
875             // that come from the document to fire beforehand. much more convenient this way.
876             this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev) // bound with args
877             );
878         };
879         FeaturefulElementDragging.prototype.stopDrag = function (ev) {
880             this.isDragging = false;
881             this.emitter.trigger('dragend', ev);
882         };
883         // fill in the implementations...
884         FeaturefulElementDragging.prototype.setIgnoreMove = function (bool) {
885             this.pointer.shouldIgnoreMove = bool;
886         };
887         FeaturefulElementDragging.prototype.setMirrorIsVisible = function (bool) {
888             this.mirror.setIsVisible(bool);
889         };
890         FeaturefulElementDragging.prototype.setMirrorNeedsRevert = function (bool) {
891             this.mirrorNeedsRevert = bool;
892         };
893         FeaturefulElementDragging.prototype.setAutoScrollEnabled = function (bool) {
894             this.autoScroller.isEnabled = bool;
895         };
896         return FeaturefulElementDragging;
897     }(core.ElementDragging));
898
899     /*
900     When this class is instantiated, it records the offset of an element (relative to the document topleft),
901     and continues to monitor scrolling, updating the cached coordinates if it needs to.
902     Does not access the DOM after instantiation, so highly performant.
903
904     Also keeps track of all scrolling/overflow:hidden containers that are parents of the given element
905     and an determine if a given point is inside the combined clipping rectangle.
906     */
907     var OffsetTracker = /** @class */ (function () {
908         function OffsetTracker(el) {
909             this.origRect = core.computeRect(el);
910             // will work fine for divs that have overflow:hidden
911             this.scrollCaches = core.getClippingParents(el).map(function (el) {
912                 return new ElementScrollGeomCache(el, true); // listen=true
913             });
914         }
915         OffsetTracker.prototype.destroy = function () {
916             for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
917                 var scrollCache = _a[_i];
918                 scrollCache.destroy();
919             }
920         };
921         OffsetTracker.prototype.computeLeft = function () {
922             var left = this.origRect.left;
923             for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
924                 var scrollCache = _a[_i];
925                 left += scrollCache.origScrollLeft - scrollCache.getScrollLeft();
926             }
927             return left;
928         };
929         OffsetTracker.prototype.computeTop = function () {
930             var top = this.origRect.top;
931             for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
932                 var scrollCache = _a[_i];
933                 top += scrollCache.origScrollTop - scrollCache.getScrollTop();
934             }
935             return top;
936         };
937         OffsetTracker.prototype.isWithinClipping = function (pageX, pageY) {
938             var point = { left: pageX, top: pageY };
939             for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
940                 var scrollCache = _a[_i];
941                 if (!isIgnoredClipping(scrollCache.getEventTarget()) &&
942                     !core.pointInsideRect(point, scrollCache.clientRect)) {
943                     return false;
944                 }
945             }
946             return true;
947         };
948         return OffsetTracker;
949     }());
950     // certain clipping containers should never constrain interactions, like <html> and <body>
951     // https://github.com/fullcalendar/fullcalendar/issues/3615
952     function isIgnoredClipping(node) {
953         var tagName = node.tagName;
954         return tagName === 'HTML' || tagName === 'BODY';
955     }
956
957     /*
958     Tracks movement over multiple droppable areas (aka "hits")
959     that exist in one or more DateComponents.
960     Relies on an existing draggable.
961
962     emits:
963     - pointerdown
964     - dragstart
965     - hitchange - fires initially, even if not over a hit
966     - pointerup
967     - (hitchange - again, to null, if ended over a hit)
968     - dragend
969     */
970     var HitDragging = /** @class */ (function () {
971         function HitDragging(dragging, droppableStore) {
972             var _this = this;
973             // options that can be set by caller
974             this.useSubjectCenter = false;
975             this.requireInitial = true; // if doesn't start out on a hit, won't emit any events
976             this.initialHit = null;
977             this.movingHit = null;
978             this.finalHit = null; // won't ever be populated if shouldIgnoreMove
979             this.handlePointerDown = function (ev) {
980                 var dragging = _this.dragging;
981                 _this.initialHit = null;
982                 _this.movingHit = null;
983                 _this.finalHit = null;
984                 _this.prepareHits();
985                 _this.processFirstCoord(ev);
986                 if (_this.initialHit || !_this.requireInitial) {
987                     dragging.setIgnoreMove(false);
988                     _this.emitter.trigger('pointerdown', ev); // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :(
989                 }
990                 else {
991                     dragging.setIgnoreMove(true);
992                 }
993             };
994             this.handleDragStart = function (ev) {
995                 _this.emitter.trigger('dragstart', ev);
996                 _this.handleMove(ev, true); // force = fire even if initially null
997             };
998             this.handleDragMove = function (ev) {
999                 _this.emitter.trigger('dragmove', ev);
1000                 _this.handleMove(ev);
1001             };
1002             this.handlePointerUp = function (ev) {
1003                 _this.releaseHits();
1004                 _this.emitter.trigger('pointerup', ev);
1005             };
1006             this.handleDragEnd = function (ev) {
1007                 if (_this.movingHit) {
1008                     _this.emitter.trigger('hitupdate', null, true, ev);
1009                 }
1010                 _this.finalHit = _this.movingHit;
1011                 _this.movingHit = null;
1012                 _this.emitter.trigger('dragend', ev);
1013             };
1014             this.droppableStore = droppableStore;
1015             dragging.emitter.on('pointerdown', this.handlePointerDown);
1016             dragging.emitter.on('dragstart', this.handleDragStart);
1017             dragging.emitter.on('dragmove', this.handleDragMove);
1018             dragging.emitter.on('pointerup', this.handlePointerUp);
1019             dragging.emitter.on('dragend', this.handleDragEnd);
1020             this.dragging = dragging;
1021             this.emitter = new core.EmitterMixin();
1022         }
1023         // sets initialHit
1024         // sets coordAdjust
1025         HitDragging.prototype.processFirstCoord = function (ev) {
1026             var origPoint = { left: ev.pageX, top: ev.pageY };
1027             var adjustedPoint = origPoint;
1028             var subjectEl = ev.subjectEl;
1029             var subjectRect;
1030             if (subjectEl !== document) {
1031                 subjectRect = core.computeRect(subjectEl);
1032                 adjustedPoint = core.constrainPoint(adjustedPoint, subjectRect);
1033             }
1034             var initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top);
1035             if (initialHit) {
1036                 if (this.useSubjectCenter && subjectRect) {
1037                     var slicedSubjectRect = core.intersectRects(subjectRect, initialHit.rect);
1038                     if (slicedSubjectRect) {
1039                         adjustedPoint = core.getRectCenter(slicedSubjectRect);
1040                     }
1041                 }
1042                 this.coordAdjust = core.diffPoints(adjustedPoint, origPoint);
1043             }
1044             else {
1045                 this.coordAdjust = { left: 0, top: 0 };
1046             }
1047         };
1048         HitDragging.prototype.handleMove = function (ev, forceHandle) {
1049             var hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top);
1050             if (forceHandle || !isHitsEqual(this.movingHit, hit)) {
1051                 this.movingHit = hit;
1052                 this.emitter.trigger('hitupdate', hit, false, ev);
1053             }
1054         };
1055         HitDragging.prototype.prepareHits = function () {
1056             this.offsetTrackers = core.mapHash(this.droppableStore, function (interactionSettings) {
1057                 interactionSettings.component.buildPositionCaches();
1058                 return new OffsetTracker(interactionSettings.el);
1059             });
1060         };
1061         HitDragging.prototype.releaseHits = function () {
1062             var offsetTrackers = this.offsetTrackers;
1063             for (var id in offsetTrackers) {
1064                 offsetTrackers[id].destroy();
1065             }
1066             this.offsetTrackers = {};
1067         };
1068         HitDragging.prototype.queryHitForOffset = function (offsetLeft, offsetTop) {
1069             var _a = this, droppableStore = _a.droppableStore, offsetTrackers = _a.offsetTrackers;
1070             var bestHit = null;
1071             for (var id in droppableStore) {
1072                 var component = droppableStore[id].component;
1073                 var offsetTracker = offsetTrackers[id];
1074                 if (offsetTracker.isWithinClipping(offsetLeft, offsetTop)) {
1075                     var originLeft = offsetTracker.computeLeft();
1076                     var originTop = offsetTracker.computeTop();
1077                     var positionLeft = offsetLeft - originLeft;
1078                     var positionTop = offsetTop - originTop;
1079                     var origRect = offsetTracker.origRect;
1080                     var width = origRect.right - origRect.left;
1081                     var height = origRect.bottom - origRect.top;
1082                     if (
1083                     // must be within the element's bounds
1084                     positionLeft >= 0 && positionLeft < width &&
1085                         positionTop >= 0 && positionTop < height) {
1086                         var hit = component.queryHit(positionLeft, positionTop, width, height);
1087                         if (hit &&
1088                             (
1089                             // make sure the hit is within activeRange, meaning it's not a deal cell
1090                             !component.props.dateProfile || // hack for DayTile
1091                                 core.rangeContainsRange(component.props.dateProfile.activeRange, hit.dateSpan.range)) &&
1092                             (!bestHit || hit.layer > bestHit.layer)) {
1093                             // TODO: better way to re-orient rectangle
1094                             hit.rect.left += originLeft;
1095                             hit.rect.right += originLeft;
1096                             hit.rect.top += originTop;
1097                             hit.rect.bottom += originTop;
1098                             bestHit = hit;
1099                         }
1100                     }
1101                 }
1102             }
1103             return bestHit;
1104         };
1105         return HitDragging;
1106     }());
1107     function isHitsEqual(hit0, hit1) {
1108         if (!hit0 && !hit1) {
1109             return true;
1110         }
1111         if (Boolean(hit0) !== Boolean(hit1)) {
1112             return false;
1113         }
1114         return core.isDateSpansEqual(hit0.dateSpan, hit1.dateSpan);
1115     }
1116
1117     /*
1118     Monitors when the user clicks on a specific date/time of a component.
1119     A pointerdown+pointerup on the same "hit" constitutes a click.
1120     */
1121     var DateClicking = /** @class */ (function (_super) {
1122         __extends(DateClicking, _super);
1123         function DateClicking(settings) {
1124             var _this = _super.call(this, settings) || this;
1125             _this.handlePointerDown = function (ev) {
1126                 var dragging = _this.dragging;
1127                 // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired
1128                 dragging.setIgnoreMove(!_this.component.isValidDateDownEl(dragging.pointer.downEl));
1129             };
1130             // won't even fire if moving was ignored
1131             _this.handleDragEnd = function (ev) {
1132                 var component = _this.component;
1133                 var pointer = _this.dragging.pointer;
1134                 if (!pointer.wasTouchScroll) {
1135                     var _a = _this.hitDragging, initialHit = _a.initialHit, finalHit = _a.finalHit;
1136                     if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) {
1137                         component.calendar.triggerDateClick(initialHit.dateSpan, initialHit.dayEl, component.view, ev.origEvent);
1138                     }
1139                 }
1140             };
1141             var component = settings.component;
1142             // we DO want to watch pointer moves because otherwise finalHit won't get populated
1143             _this.dragging = new FeaturefulElementDragging(component.el);
1144             _this.dragging.autoScroller.isEnabled = false;
1145             var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, core.interactionSettingsToStore(settings));
1146             hitDragging.emitter.on('pointerdown', _this.handlePointerDown);
1147             hitDragging.emitter.on('dragend', _this.handleDragEnd);
1148             return _this;
1149         }
1150         DateClicking.prototype.destroy = function () {
1151             this.dragging.destroy();
1152         };
1153         return DateClicking;
1154     }(core.Interaction));
1155
1156     /*
1157     Tracks when the user selects a portion of time of a component,
1158     constituted by a drag over date cells, with a possible delay at the beginning of the drag.
1159     */
1160     var DateSelecting = /** @class */ (function (_super) {
1161         __extends(DateSelecting, _super);
1162         function DateSelecting(settings) {
1163             var _this = _super.call(this, settings) || this;
1164             _this.dragSelection = null;
1165             _this.handlePointerDown = function (ev) {
1166                 var _a = _this, component = _a.component, dragging = _a.dragging;
1167                 var canSelect = component.opt('selectable') &&
1168                     component.isValidDateDownEl(ev.origEvent.target);
1169                 // don't bother to watch expensive moves if component won't do selection
1170                 dragging.setIgnoreMove(!canSelect);
1171                 // if touch, require user to hold down
1172                 dragging.delay = ev.isTouch ? getComponentTouchDelay(component) : null;
1173             };
1174             _this.handleDragStart = function (ev) {
1175                 _this.component.calendar.unselect(ev); // unselect previous selections
1176             };
1177             _this.handleHitUpdate = function (hit, isFinal) {
1178                 var calendar = _this.component.calendar;
1179                 var dragSelection = null;
1180                 var isInvalid = false;
1181                 if (hit) {
1182                     dragSelection = joinHitsIntoSelection(_this.hitDragging.initialHit, hit, calendar.pluginSystem.hooks.dateSelectionTransformers);
1183                     if (!dragSelection || !_this.component.isDateSelectionValid(dragSelection)) {
1184                         isInvalid = true;
1185                         dragSelection = null;
1186                     }
1187                 }
1188                 if (dragSelection) {
1189                     calendar.dispatch({ type: 'SELECT_DATES', selection: dragSelection });
1190                 }
1191                 else if (!isFinal) { // only unselect if moved away while dragging
1192                     calendar.dispatch({ type: 'UNSELECT_DATES' });
1193                 }
1194                 if (!isInvalid) {
1195                     core.enableCursor();
1196                 }
1197                 else {
1198                     core.disableCursor();
1199                 }
1200                 if (!isFinal) {
1201                     _this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging
1202                 }
1203             };
1204             _this.handlePointerUp = function (pev) {
1205                 if (_this.dragSelection) {
1206                     // selection is already rendered, so just need to report selection
1207                     _this.component.calendar.triggerDateSelect(_this.dragSelection, pev);
1208                     _this.dragSelection = null;
1209                 }
1210             };
1211             var component = settings.component;
1212             var dragging = _this.dragging = new FeaturefulElementDragging(component.el);
1213             dragging.touchScrollAllowed = false;
1214             dragging.minDistance = component.opt('selectMinDistance') || 0;
1215             dragging.autoScroller.isEnabled = component.opt('dragScroll');
1216             var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, core.interactionSettingsToStore(settings));
1217             hitDragging.emitter.on('pointerdown', _this.handlePointerDown);
1218             hitDragging.emitter.on('dragstart', _this.handleDragStart);
1219             hitDragging.emitter.on('hitupdate', _this.handleHitUpdate);
1220             hitDragging.emitter.on('pointerup', _this.handlePointerUp);
1221             return _this;
1222         }
1223         DateSelecting.prototype.destroy = function () {
1224             this.dragging.destroy();
1225         };
1226         return DateSelecting;
1227     }(core.Interaction));
1228     function getComponentTouchDelay(component) {
1229         var delay = component.opt('selectLongPressDelay');
1230         if (delay == null) {
1231             delay = component.opt('longPressDelay');
1232         }
1233         return delay;
1234     }
1235     function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) {
1236         var dateSpan0 = hit0.dateSpan;
1237         var dateSpan1 = hit1.dateSpan;
1238         var ms = [
1239             dateSpan0.range.start,
1240             dateSpan0.range.end,
1241             dateSpan1.range.start,
1242             dateSpan1.range.end
1243         ];
1244         ms.sort(core.compareNumbers);
1245         var props = {};
1246         for (var _i = 0, dateSelectionTransformers_1 = dateSelectionTransformers; _i < dateSelectionTransformers_1.length; _i++) {
1247             var transformer = dateSelectionTransformers_1[_i];
1248             var res = transformer(hit0, hit1);
1249             if (res === false) {
1250                 return null;
1251             }
1252             else if (res) {
1253                 __assign(props, res);
1254             }
1255         }
1256         props.range = { start: ms[0], end: ms[3] };
1257         props.allDay = dateSpan0.allDay;
1258         return props;
1259     }
1260
1261     var EventDragging = /** @class */ (function (_super) {
1262         __extends(EventDragging, _super);
1263         function EventDragging(settings) {
1264             var _this = _super.call(this, settings) || this;
1265             // internal state
1266             _this.subjectSeg = null; // the seg being selected/dragged
1267             _this.isDragging = false;
1268             _this.eventRange = null;
1269             _this.relevantEvents = null; // the events being dragged
1270             _this.receivingCalendar = null;
1271             _this.validMutation = null;
1272             _this.mutatedRelevantEvents = null;
1273             _this.handlePointerDown = function (ev) {
1274                 var origTarget = ev.origEvent.target;
1275                 var _a = _this, component = _a.component, dragging = _a.dragging;
1276                 var mirror = dragging.mirror;
1277                 var initialCalendar = component.calendar;
1278                 var subjectSeg = _this.subjectSeg = core.getElSeg(ev.subjectEl);
1279                 var eventRange = _this.eventRange = subjectSeg.eventRange;
1280                 var eventInstanceId = eventRange.instance.instanceId;
1281                 _this.relevantEvents = core.getRelevantEvents(initialCalendar.state.eventStore, eventInstanceId);
1282                 dragging.minDistance = ev.isTouch ? 0 : component.opt('eventDragMinDistance');
1283                 dragging.delay =
1284                     // only do a touch delay if touch and this event hasn't been selected yet
1285                     (ev.isTouch && eventInstanceId !== component.props.eventSelection) ?
1286                         getComponentTouchDelay$1(component) :
1287                         null;
1288                 mirror.parentNode = initialCalendar.el;
1289                 mirror.revertDuration = component.opt('dragRevertDuration');
1290                 var isValid = component.isValidSegDownEl(origTarget) &&
1291                     !core.elementClosest(origTarget, '.fc-resizer'); // NOT on a resizer
1292                 dragging.setIgnoreMove(!isValid);
1293                 // disable dragging for elements that are resizable (ie, selectable)
1294                 // but are not draggable
1295                 _this.isDragging = isValid &&
1296                     ev.subjectEl.classList.contains('fc-draggable');
1297             };
1298             _this.handleDragStart = function (ev) {
1299                 var initialCalendar = _this.component.calendar;
1300                 var eventRange = _this.eventRange;
1301                 var eventInstanceId = eventRange.instance.instanceId;
1302                 if (ev.isTouch) {
1303                     // need to select a different event?
1304                     if (eventInstanceId !== _this.component.props.eventSelection) {
1305                         initialCalendar.dispatch({ type: 'SELECT_EVENT', eventInstanceId: eventInstanceId });
1306                     }
1307                 }
1308                 else {
1309                     // if now using mouse, but was previous touch interaction, clear selected event
1310                     initialCalendar.dispatch({ type: 'UNSELECT_EVENT' });
1311                 }
1312                 if (_this.isDragging) {
1313                     initialCalendar.unselect(ev); // unselect *date* selection
1314                     initialCalendar.publiclyTrigger('eventDragStart', [
1315                         {
1316                             el: _this.subjectSeg.el,
1317                             event: new core.EventApi(initialCalendar, eventRange.def, eventRange.instance),
1318                             jsEvent: ev.origEvent,
1319                             view: _this.component.view
1320                         }
1321                     ]);
1322                 }
1323             };
1324             _this.handleHitUpdate = function (hit, isFinal) {
1325                 if (!_this.isDragging) {
1326                     return;
1327                 }
1328                 var relevantEvents = _this.relevantEvents;
1329                 var initialHit = _this.hitDragging.initialHit;
1330                 var initialCalendar = _this.component.calendar;
1331                 // states based on new hit
1332                 var receivingCalendar = null;
1333                 var mutation = null;
1334                 var mutatedRelevantEvents = null;
1335                 var isInvalid = false;
1336                 var interaction = {
1337                     affectedEvents: relevantEvents,
1338                     mutatedEvents: core.createEmptyEventStore(),
1339                     isEvent: true,
1340                     origSeg: _this.subjectSeg
1341                 };
1342                 if (hit) {
1343                     var receivingComponent = hit.component;
1344                     receivingCalendar = receivingComponent.calendar;
1345                     if (initialCalendar === receivingCalendar ||
1346                         receivingComponent.opt('editable') && receivingComponent.opt('droppable')) {
1347                         mutation = computeEventMutation(initialHit, hit, receivingCalendar.pluginSystem.hooks.eventDragMutationMassagers);
1348                         if (mutation) {
1349                             mutatedRelevantEvents = core.applyMutationToEventStore(relevantEvents, receivingCalendar.eventUiBases, mutation, receivingCalendar);
1350                             interaction.mutatedEvents = mutatedRelevantEvents;
1351                             if (!receivingComponent.isInteractionValid(interaction)) {
1352                                 isInvalid = true;
1353                                 mutation = null;
1354                                 mutatedRelevantEvents = null;
1355                                 interaction.mutatedEvents = core.createEmptyEventStore();
1356                             }
1357                         }
1358                     }
1359                     else {
1360                         receivingCalendar = null;
1361                     }
1362                 }
1363                 _this.displayDrag(receivingCalendar, interaction);
1364                 if (!isInvalid) {
1365                     core.enableCursor();
1366                 }
1367                 else {
1368                     core.disableCursor();
1369                 }
1370                 if (!isFinal) {
1371                     if (initialCalendar === receivingCalendar && // TODO: write test for this
1372                         isHitsEqual(initialHit, hit)) {
1373                         mutation = null;
1374                     }
1375                     _this.dragging.setMirrorNeedsRevert(!mutation);
1376                     // render the mirror if no already-rendered mirror
1377                     // TODO: wish we could somehow wait for dispatch to guarantee render
1378                     _this.dragging.setMirrorIsVisible(!hit || !document.querySelector('.fc-mirror'));
1379                     // assign states based on new hit
1380                     _this.receivingCalendar = receivingCalendar;
1381                     _this.validMutation = mutation;
1382                     _this.mutatedRelevantEvents = mutatedRelevantEvents;
1383                 }
1384             };
1385             _this.handlePointerUp = function () {
1386                 if (!_this.isDragging) {
1387                     _this.cleanup(); // because handleDragEnd won't fire
1388                 }
1389             };
1390             _this.handleDragEnd = function (ev) {
1391                 if (_this.isDragging) {
1392                     var initialCalendar_1 = _this.component.calendar;
1393                     var initialView = _this.component.view;
1394                     var _a = _this, receivingCalendar = _a.receivingCalendar, validMutation = _a.validMutation;
1395                     var eventDef = _this.eventRange.def;
1396                     var eventInstance = _this.eventRange.instance;
1397                     var eventApi = new core.EventApi(initialCalendar_1, eventDef, eventInstance);
1398                     var relevantEvents_1 = _this.relevantEvents;
1399                     var mutatedRelevantEvents = _this.mutatedRelevantEvents;
1400                     var finalHit = _this.hitDragging.finalHit;
1401                     _this.clearDrag(); // must happen after revert animation
1402                     initialCalendar_1.publiclyTrigger('eventDragStop', [
1403                         {
1404                             el: _this.subjectSeg.el,
1405                             event: eventApi,
1406                             jsEvent: ev.origEvent,
1407                             view: initialView
1408                         }
1409                     ]);
1410                     if (validMutation) {
1411                         // dropped within same calendar
1412                         if (receivingCalendar === initialCalendar_1) {
1413                             initialCalendar_1.dispatch({
1414                                 type: 'MERGE_EVENTS',
1415                                 eventStore: mutatedRelevantEvents
1416                             });
1417                             var transformed = {};
1418                             for (var _i = 0, _b = initialCalendar_1.pluginSystem.hooks.eventDropTransformers; _i < _b.length; _i++) {
1419                                 var transformer = _b[_i];
1420                                 __assign(transformed, transformer(validMutation, initialCalendar_1));
1421                             }
1422                             var eventDropArg = __assign({}, transformed, { el: ev.subjectEl, delta: validMutation.datesDelta, oldEvent: eventApi, event: new core.EventApi(// the data AFTER the mutation
1423                                 initialCalendar_1, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null), revert: function () {
1424                                     initialCalendar_1.dispatch({
1425                                         type: 'MERGE_EVENTS',
1426                                         eventStore: relevantEvents_1
1427                                     });
1428                                 }, jsEvent: ev.origEvent, view: initialView });
1429                             initialCalendar_1.publiclyTrigger('eventDrop', [eventDropArg]);
1430                             // dropped in different calendar
1431                         }
1432                         else if (receivingCalendar) {
1433                             initialCalendar_1.publiclyTrigger('eventLeave', [
1434                                 {
1435                                     draggedEl: ev.subjectEl,
1436                                     event: eventApi,
1437                                     view: initialView
1438                                 }
1439                             ]);
1440                             initialCalendar_1.dispatch({
1441                                 type: 'REMOVE_EVENT_INSTANCES',
1442                                 instances: _this.mutatedRelevantEvents.instances
1443                             });
1444                             receivingCalendar.dispatch({
1445                                 type: 'MERGE_EVENTS',
1446                                 eventStore: _this.mutatedRelevantEvents
1447                             });
1448                             if (ev.isTouch) {
1449                                 receivingCalendar.dispatch({
1450                                     type: 'SELECT_EVENT',
1451                                     eventInstanceId: eventInstance.instanceId
1452                                 });
1453                             }
1454                             var dropArg = __assign({}, receivingCalendar.buildDatePointApi(finalHit.dateSpan), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.component // should this be finalHit.component.view? See #4644
1455                              });
1456                             receivingCalendar.publiclyTrigger('drop', [dropArg]);
1457                             receivingCalendar.publiclyTrigger('eventReceive', [
1458                                 {
1459                                     draggedEl: ev.subjectEl,
1460                                     event: new core.EventApi(// the data AFTER the mutation
1461                                     receivingCalendar, mutatedRelevantEvents.defs[eventDef.defId], mutatedRelevantEvents.instances[eventInstance.instanceId]),
1462                                     view: finalHit.component // should this be finalHit.component.view? See #4644
1463                                 }
1464                             ]);
1465                         }
1466                     }
1467                     else {
1468                         initialCalendar_1.publiclyTrigger('_noEventDrop');
1469                     }
1470                 }
1471                 _this.cleanup();
1472             };
1473             var component = _this.component;
1474             var dragging = _this.dragging = new FeaturefulElementDragging(component.el);
1475             dragging.pointer.selector = EventDragging.SELECTOR;
1476             dragging.touchScrollAllowed = false;
1477             dragging.autoScroller.isEnabled = component.opt('dragScroll');
1478             var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, core.interactionSettingsStore);
1479             hitDragging.useSubjectCenter = settings.useEventCenter;
1480             hitDragging.emitter.on('pointerdown', _this.handlePointerDown);
1481             hitDragging.emitter.on('dragstart', _this.handleDragStart);
1482             hitDragging.emitter.on('hitupdate', _this.handleHitUpdate);
1483             hitDragging.emitter.on('pointerup', _this.handlePointerUp);
1484             hitDragging.emitter.on('dragend', _this.handleDragEnd);
1485             return _this;
1486         }
1487         EventDragging.prototype.destroy = function () {
1488             this.dragging.destroy();
1489         };
1490         // render a drag state on the next receivingCalendar
1491         EventDragging.prototype.displayDrag = function (nextCalendar, state) {
1492             var initialCalendar = this.component.calendar;
1493             var prevCalendar = this.receivingCalendar;
1494             // does the previous calendar need to be cleared?
1495             if (prevCalendar && prevCalendar !== nextCalendar) {
1496                 // does the initial calendar need to be cleared?
1497                 // if so, don't clear all the way. we still need to to hide the affectedEvents
1498                 if (prevCalendar === initialCalendar) {
1499                     prevCalendar.dispatch({
1500                         type: 'SET_EVENT_DRAG',
1501                         state: {
1502                             affectedEvents: state.affectedEvents,
1503                             mutatedEvents: core.createEmptyEventStore(),
1504                             isEvent: true,
1505                             origSeg: state.origSeg
1506                         }
1507                     });
1508                     // completely clear the old calendar if it wasn't the initial
1509                 }
1510                 else {
1511                     prevCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
1512                 }
1513             }
1514             if (nextCalendar) {
1515                 nextCalendar.dispatch({ type: 'SET_EVENT_DRAG', state: state });
1516             }
1517         };
1518         EventDragging.prototype.clearDrag = function () {
1519             var initialCalendar = this.component.calendar;
1520             var receivingCalendar = this.receivingCalendar;
1521             if (receivingCalendar) {
1522                 receivingCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
1523             }
1524             // the initial calendar might have an dummy drag state from displayDrag
1525             if (initialCalendar !== receivingCalendar) {
1526                 initialCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
1527             }
1528         };
1529         EventDragging.prototype.cleanup = function () {
1530             this.subjectSeg = null;
1531             this.isDragging = false;
1532             this.eventRange = null;
1533             this.relevantEvents = null;
1534             this.receivingCalendar = null;
1535             this.validMutation = null;
1536             this.mutatedRelevantEvents = null;
1537         };
1538         EventDragging.SELECTOR = '.fc-draggable, .fc-resizable'; // TODO: test this in IE11
1539         return EventDragging;
1540     }(core.Interaction));
1541     function computeEventMutation(hit0, hit1, massagers) {
1542         var dateSpan0 = hit0.dateSpan;
1543         var dateSpan1 = hit1.dateSpan;
1544         var date0 = dateSpan0.range.start;
1545         var date1 = dateSpan1.range.start;
1546         var standardProps = {};
1547         if (dateSpan0.allDay !== dateSpan1.allDay) {
1548             standardProps.allDay = dateSpan1.allDay;
1549             standardProps.hasEnd = hit1.component.opt('allDayMaintainDuration');
1550             if (dateSpan1.allDay) {
1551                 // means date1 is already start-of-day,
1552                 // but date0 needs to be converted
1553                 date0 = core.startOfDay(date0);
1554             }
1555         }
1556         var delta = core.diffDates(date0, date1, hit0.component.dateEnv, hit0.component === hit1.component ?
1557             hit0.component.largeUnit :
1558             null);
1559         if (delta.milliseconds) { // has hours/minutes/seconds
1560             standardProps.allDay = false;
1561         }
1562         var mutation = {
1563             datesDelta: delta,
1564             standardProps: standardProps
1565         };
1566         for (var _i = 0, massagers_1 = massagers; _i < massagers_1.length; _i++) {
1567             var massager = massagers_1[_i];
1568             massager(mutation, hit0, hit1);
1569         }
1570         return mutation;
1571     }
1572     function getComponentTouchDelay$1(component) {
1573         var delay = component.opt('eventLongPressDelay');
1574         if (delay == null) {
1575             delay = component.opt('longPressDelay');
1576         }
1577         return delay;
1578     }
1579
1580     var EventDragging$1 = /** @class */ (function (_super) {
1581         __extends(EventDragging, _super);
1582         function EventDragging(settings) {
1583             var _this = _super.call(this, settings) || this;
1584             // internal state
1585             _this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg?
1586             _this.eventRange = null;
1587             _this.relevantEvents = null;
1588             _this.validMutation = null;
1589             _this.mutatedRelevantEvents = null;
1590             _this.handlePointerDown = function (ev) {
1591                 var component = _this.component;
1592                 var seg = _this.querySeg(ev);
1593                 var eventRange = _this.eventRange = seg.eventRange;
1594                 _this.dragging.minDistance = component.opt('eventDragMinDistance');
1595                 // if touch, need to be working with a selected event
1596                 _this.dragging.setIgnoreMove(!_this.component.isValidSegDownEl(ev.origEvent.target) ||
1597                     (ev.isTouch && _this.component.props.eventSelection !== eventRange.instance.instanceId));
1598             };
1599             _this.handleDragStart = function (ev) {
1600                 var calendar = _this.component.calendar;
1601                 var eventRange = _this.eventRange;
1602                 _this.relevantEvents = core.getRelevantEvents(calendar.state.eventStore, _this.eventRange.instance.instanceId);
1603                 _this.draggingSeg = _this.querySeg(ev);
1604                 calendar.unselect();
1605                 calendar.publiclyTrigger('eventResizeStart', [
1606                     {
1607                         el: _this.draggingSeg.el,
1608                         event: new core.EventApi(calendar, eventRange.def, eventRange.instance),
1609                         jsEvent: ev.origEvent,
1610                         view: _this.component.view
1611                     }
1612                 ]);
1613             };
1614             _this.handleHitUpdate = function (hit, isFinal, ev) {
1615                 var calendar = _this.component.calendar;
1616                 var relevantEvents = _this.relevantEvents;
1617                 var initialHit = _this.hitDragging.initialHit;
1618                 var eventInstance = _this.eventRange.instance;
1619                 var mutation = null;
1620                 var mutatedRelevantEvents = null;
1621                 var isInvalid = false;
1622                 var interaction = {
1623                     affectedEvents: relevantEvents,
1624                     mutatedEvents: core.createEmptyEventStore(),
1625                     isEvent: true,
1626                     origSeg: _this.draggingSeg
1627                 };
1628                 if (hit) {
1629                     mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-start-resizer'), eventInstance.range, calendar.pluginSystem.hooks.eventResizeJoinTransforms);
1630                 }
1631                 if (mutation) {
1632                     mutatedRelevantEvents = core.applyMutationToEventStore(relevantEvents, calendar.eventUiBases, mutation, calendar);
1633                     interaction.mutatedEvents = mutatedRelevantEvents;
1634                     if (!_this.component.isInteractionValid(interaction)) {
1635                         isInvalid = true;
1636                         mutation = null;
1637                         mutatedRelevantEvents = null;
1638                         interaction.mutatedEvents = null;
1639                     }
1640                 }
1641                 if (mutatedRelevantEvents) {
1642                     calendar.dispatch({
1643                         type: 'SET_EVENT_RESIZE',
1644                         state: interaction
1645                     });
1646                 }
1647                 else {
1648                     calendar.dispatch({ type: 'UNSET_EVENT_RESIZE' });
1649                 }
1650                 if (!isInvalid) {
1651                     core.enableCursor();
1652                 }
1653                 else {
1654                     core.disableCursor();
1655                 }
1656                 if (!isFinal) {
1657                     if (mutation && isHitsEqual(initialHit, hit)) {
1658                         mutation = null;
1659                     }
1660                     _this.validMutation = mutation;
1661                     _this.mutatedRelevantEvents = mutatedRelevantEvents;
1662                 }
1663             };
1664             _this.handleDragEnd = function (ev) {
1665                 var calendar = _this.component.calendar;
1666                 var view = _this.component.view;
1667                 var eventDef = _this.eventRange.def;
1668                 var eventInstance = _this.eventRange.instance;
1669                 var eventApi = new core.EventApi(calendar, eventDef, eventInstance);
1670                 var relevantEvents = _this.relevantEvents;
1671                 var mutatedRelevantEvents = _this.mutatedRelevantEvents;
1672                 calendar.publiclyTrigger('eventResizeStop', [
1673                     {
1674                         el: _this.draggingSeg.el,
1675                         event: eventApi,
1676                         jsEvent: ev.origEvent,
1677                         view: view
1678                     }
1679                 ]);
1680                 if (_this.validMutation) {
1681                     calendar.dispatch({
1682                         type: 'MERGE_EVENTS',
1683                         eventStore: mutatedRelevantEvents
1684                     });
1685                     calendar.publiclyTrigger('eventResize', [
1686                         {
1687                             el: _this.draggingSeg.el,
1688                             startDelta: _this.validMutation.startDelta || core.createDuration(0),
1689                             endDelta: _this.validMutation.endDelta || core.createDuration(0),
1690                             prevEvent: eventApi,
1691                             event: new core.EventApi(// the data AFTER the mutation
1692                             calendar, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null),
1693                             revert: function () {
1694                                 calendar.dispatch({
1695                                     type: 'MERGE_EVENTS',
1696                                     eventStore: relevantEvents
1697                                 });
1698                             },
1699                             jsEvent: ev.origEvent,
1700                             view: view
1701                         }
1702                     ]);
1703                 }
1704                 else {
1705                     calendar.publiclyTrigger('_noEventResize');
1706                 }
1707                 // reset all internal state
1708                 _this.draggingSeg = null;
1709                 _this.relevantEvents = null;
1710                 _this.validMutation = null;
1711                 // okay to keep eventInstance around. useful to set it in handlePointerDown
1712             };
1713             var component = settings.component;
1714             var dragging = _this.dragging = new FeaturefulElementDragging(component.el);
1715             dragging.pointer.selector = '.fc-resizer';
1716             dragging.touchScrollAllowed = false;
1717             dragging.autoScroller.isEnabled = component.opt('dragScroll');
1718             var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, core.interactionSettingsToStore(settings));
1719             hitDragging.emitter.on('pointerdown', _this.handlePointerDown);
1720             hitDragging.emitter.on('dragstart', _this.handleDragStart);
1721             hitDragging.emitter.on('hitupdate', _this.handleHitUpdate);
1722             hitDragging.emitter.on('dragend', _this.handleDragEnd);
1723             return _this;
1724         }
1725         EventDragging.prototype.destroy = function () {
1726             this.dragging.destroy();
1727         };
1728         EventDragging.prototype.querySeg = function (ev) {
1729             return core.getElSeg(core.elementClosest(ev.subjectEl, this.component.fgSegSelector));
1730         };
1731         return EventDragging;
1732     }(core.Interaction));
1733     function computeMutation(hit0, hit1, isFromStart, instanceRange, transforms) {
1734         var dateEnv = hit0.component.dateEnv;
1735         var date0 = hit0.dateSpan.range.start;
1736         var date1 = hit1.dateSpan.range.start;
1737         var delta = core.diffDates(date0, date1, dateEnv, hit0.component.largeUnit);
1738         var props = {};
1739         for (var _i = 0, transforms_1 = transforms; _i < transforms_1.length; _i++) {
1740             var transform = transforms_1[_i];
1741             var res = transform(hit0, hit1);
1742             if (res === false) {
1743                 return null;
1744             }
1745             else if (res) {
1746                 __assign(props, res);
1747             }
1748         }
1749         if (isFromStart) {
1750             if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) {
1751                 props.startDelta = delta;
1752                 return props;
1753             }
1754         }
1755         else {
1756             if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) {
1757                 props.endDelta = delta;
1758                 return props;
1759             }
1760         }
1761         return null;
1762     }
1763
1764     var UnselectAuto = /** @class */ (function () {
1765         function UnselectAuto(calendar) {
1766             var _this = this;
1767             this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system
1768             this.onSelect = function (selectInfo) {
1769                 if (selectInfo.jsEvent) {
1770                     _this.isRecentPointerDateSelect = true;
1771                 }
1772             };
1773             this.onDocumentPointerUp = function (pev) {
1774                 var _a = _this, calendar = _a.calendar, documentPointer = _a.documentPointer;
1775                 var state = calendar.state;
1776                 // touch-scrolling should never unfocus any type of selection
1777                 if (!documentPointer.wasTouchScroll) {
1778                     if (state.dateSelection && // an existing date selection?
1779                         !_this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp?
1780                     ) {
1781                         var unselectAuto = calendar.viewOpt('unselectAuto');
1782                         var unselectCancel = calendar.viewOpt('unselectCancel');
1783                         if (unselectAuto && (!unselectAuto || !core.elementClosest(documentPointer.downEl, unselectCancel))) {
1784                             calendar.unselect(pev);
1785                         }
1786                     }
1787                     if (state.eventSelection && // an existing event selected?
1788                         !core.elementClosest(documentPointer.downEl, EventDragging.SELECTOR) // interaction DIDN'T start on an event
1789                     ) {
1790                         calendar.dispatch({ type: 'UNSELECT_EVENT' });
1791                     }
1792                 }
1793                 _this.isRecentPointerDateSelect = false;
1794             };
1795             this.calendar = calendar;
1796             var documentPointer = this.documentPointer = new PointerDragging(document);
1797             documentPointer.shouldIgnoreMove = true;
1798             documentPointer.shouldWatchScroll = false;
1799             documentPointer.emitter.on('pointerup', this.onDocumentPointerUp);
1800             /*
1801             TODO: better way to know about whether there was a selection with the pointer
1802             */
1803             calendar.on('select', this.onSelect);
1804         }
1805         UnselectAuto.prototype.destroy = function () {
1806             this.calendar.off('select', this.onSelect);
1807             this.documentPointer.destroy();
1808         };
1809         return UnselectAuto;
1810     }());
1811
1812     /*
1813     Given an already instantiated draggable object for one-or-more elements,
1814     Interprets any dragging as an attempt to drag an events that lives outside
1815     of a calendar onto a calendar.
1816     */
1817     var ExternalElementDragging = /** @class */ (function () {
1818         function ExternalElementDragging(dragging, suppliedDragMeta) {
1819             var _this = this;
1820             this.receivingCalendar = null;
1821             this.droppableEvent = null; // will exist for all drags, even if create:false
1822             this.suppliedDragMeta = null;
1823             this.dragMeta = null;
1824             this.handleDragStart = function (ev) {
1825                 _this.dragMeta = _this.buildDragMeta(ev.subjectEl);
1826             };
1827             this.handleHitUpdate = function (hit, isFinal, ev) {
1828                 var dragging = _this.hitDragging.dragging;
1829                 var receivingCalendar = null;
1830                 var droppableEvent = null;
1831                 var isInvalid = false;
1832                 var interaction = {
1833                     affectedEvents: core.createEmptyEventStore(),
1834                     mutatedEvents: core.createEmptyEventStore(),
1835                     isEvent: _this.dragMeta.create,
1836                     origSeg: null
1837                 };
1838                 if (hit) {
1839                     receivingCalendar = hit.component.calendar;
1840                     if (_this.canDropElOnCalendar(ev.subjectEl, receivingCalendar)) {
1841                         droppableEvent = computeEventForDateSpan(hit.dateSpan, _this.dragMeta, receivingCalendar);
1842                         interaction.mutatedEvents = core.eventTupleToStore(droppableEvent);
1843                         isInvalid = !core.isInteractionValid(interaction, receivingCalendar);
1844                         if (isInvalid) {
1845                             interaction.mutatedEvents = core.createEmptyEventStore();
1846                             droppableEvent = null;
1847                         }
1848                     }
1849                 }
1850                 _this.displayDrag(receivingCalendar, interaction);
1851                 // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?)
1852                 // TODO: wish we could somehow wait for dispatch to guarantee render
1853                 dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-mirror'));
1854                 if (!isInvalid) {
1855                     core.enableCursor();
1856                 }
1857                 else {
1858                     core.disableCursor();
1859                 }
1860                 if (!isFinal) {
1861                     dragging.setMirrorNeedsRevert(!droppableEvent);
1862                     _this.receivingCalendar = receivingCalendar;
1863                     _this.droppableEvent = droppableEvent;
1864                 }
1865             };
1866             this.handleDragEnd = function (pev) {
1867                 var _a = _this, receivingCalendar = _a.receivingCalendar, droppableEvent = _a.droppableEvent;
1868                 _this.clearDrag();
1869                 if (receivingCalendar && droppableEvent) {
1870                     var finalHit = _this.hitDragging.finalHit;
1871                     var finalView = finalHit.component.view;
1872                     var dragMeta = _this.dragMeta;
1873                     var arg = __assign({}, receivingCalendar.buildDatePointApi(finalHit.dateSpan), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView });
1874                     receivingCalendar.publiclyTrigger('drop', [arg]);
1875                     if (dragMeta.create) {
1876                         receivingCalendar.dispatch({
1877                             type: 'MERGE_EVENTS',
1878                             eventStore: core.eventTupleToStore(droppableEvent)
1879                         });
1880                         if (pev.isTouch) {
1881                             receivingCalendar.dispatch({
1882                                 type: 'SELECT_EVENT',
1883                                 eventInstanceId: droppableEvent.instance.instanceId
1884                             });
1885                         }
1886                         // signal that an external event landed
1887                         receivingCalendar.publiclyTrigger('eventReceive', [
1888                             {
1889                                 draggedEl: pev.subjectEl,
1890                                 event: new core.EventApi(receivingCalendar, droppableEvent.def, droppableEvent.instance),
1891                                 view: finalView
1892                             }
1893                         ]);
1894                     }
1895                 }
1896                 _this.receivingCalendar = null;
1897                 _this.droppableEvent = null;
1898             };
1899             var hitDragging = this.hitDragging = new HitDragging(dragging, core.interactionSettingsStore);
1900             hitDragging.requireInitial = false; // will start outside of a component
1901             hitDragging.emitter.on('dragstart', this.handleDragStart);
1902             hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
1903             hitDragging.emitter.on('dragend', this.handleDragEnd);
1904             this.suppliedDragMeta = suppliedDragMeta;
1905         }
1906         ExternalElementDragging.prototype.buildDragMeta = function (subjectEl) {
1907             if (typeof this.suppliedDragMeta === 'object') {
1908                 return core.parseDragMeta(this.suppliedDragMeta);
1909             }
1910             else if (typeof this.suppliedDragMeta === 'function') {
1911                 return core.parseDragMeta(this.suppliedDragMeta(subjectEl));
1912             }
1913             else {
1914                 return getDragMetaFromEl(subjectEl);
1915             }
1916         };
1917         ExternalElementDragging.prototype.displayDrag = function (nextCalendar, state) {
1918             var prevCalendar = this.receivingCalendar;
1919             if (prevCalendar && prevCalendar !== nextCalendar) {
1920                 prevCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
1921             }
1922             if (nextCalendar) {
1923                 nextCalendar.dispatch({ type: 'SET_EVENT_DRAG', state: state });
1924             }
1925         };
1926         ExternalElementDragging.prototype.clearDrag = function () {
1927             if (this.receivingCalendar) {
1928                 this.receivingCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
1929             }
1930         };
1931         ExternalElementDragging.prototype.canDropElOnCalendar = function (el, receivingCalendar) {
1932             var dropAccept = receivingCalendar.opt('dropAccept');
1933             if (typeof dropAccept === 'function') {
1934                 return dropAccept(el);
1935             }
1936             else if (typeof dropAccept === 'string' && dropAccept) {
1937                 return Boolean(core.elementMatches(el, dropAccept));
1938             }
1939             return true;
1940         };
1941         return ExternalElementDragging;
1942     }());
1943     // Utils for computing event store from the DragMeta
1944     // ----------------------------------------------------------------------------------------------------
1945     function computeEventForDateSpan(dateSpan, dragMeta, calendar) {
1946         var defProps = __assign({}, dragMeta.leftoverProps);
1947         for (var _i = 0, _a = calendar.pluginSystem.hooks.externalDefTransforms; _i < _a.length; _i++) {
1948             var transform = _a[_i];
1949             __assign(defProps, transform(dateSpan, dragMeta));
1950         }
1951         var def = core.parseEventDef(defProps, dragMeta.sourceId, dateSpan.allDay, calendar.opt('forceEventDuration') || Boolean(dragMeta.duration), // hasEnd
1952         calendar);
1953         var start = dateSpan.range.start;
1954         // only rely on time info if drop zone is all-day,
1955         // otherwise, we already know the time
1956         if (dateSpan.allDay && dragMeta.startTime) {
1957             start = calendar.dateEnv.add(start, dragMeta.startTime);
1958         }
1959         var end = dragMeta.duration ?
1960             calendar.dateEnv.add(start, dragMeta.duration) :
1961             calendar.getDefaultEventEnd(dateSpan.allDay, start);
1962         var instance = core.createEventInstance(def.defId, { start: start, end: end });
1963         return { def: def, instance: instance };
1964     }
1965     // Utils for extracting data from element
1966     // ----------------------------------------------------------------------------------------------------
1967     function getDragMetaFromEl(el) {
1968         var str = getEmbeddedElData(el, 'event');
1969         var obj = str ?
1970             JSON.parse(str) :
1971             { create: false }; // if no embedded data, assume no event creation
1972         return core.parseDragMeta(obj);
1973     }
1974     core.config.dataAttrPrefix = '';
1975     function getEmbeddedElData(el, name) {
1976         var prefix = core.config.dataAttrPrefix;
1977         var prefixedName = (prefix ? prefix + '-' : '') + name;
1978         return el.getAttribute('data-' + prefixedName) || '';
1979     }
1980
1981     /*
1982     Makes an element (that is *external* to any calendar) draggable.
1983     Can pass in data that determines how an event will be created when dropped onto a calendar.
1984     Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system.
1985     */
1986     var ExternalDraggable = /** @class */ (function () {
1987         function ExternalDraggable(el, settings) {
1988             var _this = this;
1989             if (settings === void 0) { settings = {}; }
1990             this.handlePointerDown = function (ev) {
1991                 var dragging = _this.dragging;
1992                 var _a = _this.settings, minDistance = _a.minDistance, longPressDelay = _a.longPressDelay;
1993                 dragging.minDistance =
1994                     minDistance != null ?
1995                         minDistance :
1996                         (ev.isTouch ? 0 : core.globalDefaults.eventDragMinDistance);
1997                 dragging.delay =
1998                     ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv
1999                         (longPressDelay != null ? longPressDelay : core.globalDefaults.longPressDelay) :
2000                         0;
2001             };
2002             this.handleDragStart = function (ev) {
2003                 if (ev.isTouch &&
2004                     _this.dragging.delay &&
2005                     ev.subjectEl.classList.contains('fc-event')) {
2006                     _this.dragging.mirror.getMirrorEl().classList.add('fc-selected');
2007                 }
2008             };
2009             this.settings = settings;
2010             var dragging = this.dragging = new FeaturefulElementDragging(el);
2011             dragging.touchScrollAllowed = false;
2012             if (settings.itemSelector != null) {
2013                 dragging.pointer.selector = settings.itemSelector;
2014             }
2015             if (settings.appendTo != null) {
2016                 dragging.mirror.parentNode = settings.appendTo; // TODO: write tests
2017             }
2018             dragging.emitter.on('pointerdown', this.handlePointerDown);
2019             dragging.emitter.on('dragstart', this.handleDragStart);
2020             new ExternalElementDragging(dragging, settings.eventData);
2021         }
2022         ExternalDraggable.prototype.destroy = function () {
2023             this.dragging.destroy();
2024         };
2025         return ExternalDraggable;
2026     }());
2027
2028     /*
2029     Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements.
2030     The third-party system is responsible for drawing the visuals effects of the drag.
2031     This class simply monitors for pointer movements and fires events.
2032     It also has the ability to hide the moving element (the "mirror") during the drag.
2033     */
2034     var InferredElementDragging = /** @class */ (function (_super) {
2035         __extends(InferredElementDragging, _super);
2036         function InferredElementDragging(containerEl) {
2037             var _this = _super.call(this, containerEl) || this;
2038             _this.shouldIgnoreMove = false;
2039             _this.mirrorSelector = '';
2040             _this.currentMirrorEl = null;
2041             _this.handlePointerDown = function (ev) {
2042                 _this.emitter.trigger('pointerdown', ev);
2043                 if (!_this.shouldIgnoreMove) {
2044                     // fire dragstart right away. does not support delay or min-distance
2045                     _this.emitter.trigger('dragstart', ev);
2046                 }
2047             };
2048             _this.handlePointerMove = function (ev) {
2049                 if (!_this.shouldIgnoreMove) {
2050                     _this.emitter.trigger('dragmove', ev);
2051                 }
2052             };
2053             _this.handlePointerUp = function (ev) {
2054                 _this.emitter.trigger('pointerup', ev);
2055                 if (!_this.shouldIgnoreMove) {
2056                     // fire dragend right away. does not support a revert animation
2057                     _this.emitter.trigger('dragend', ev);
2058                 }
2059             };
2060             var pointer = _this.pointer = new PointerDragging(containerEl);
2061             pointer.emitter.on('pointerdown', _this.handlePointerDown);
2062             pointer.emitter.on('pointermove', _this.handlePointerMove);
2063             pointer.emitter.on('pointerup', _this.handlePointerUp);
2064             return _this;
2065         }
2066         InferredElementDragging.prototype.destroy = function () {
2067             this.pointer.destroy();
2068         };
2069         InferredElementDragging.prototype.setIgnoreMove = function (bool) {
2070             this.shouldIgnoreMove = bool;
2071         };
2072         InferredElementDragging.prototype.setMirrorIsVisible = function (bool) {
2073             if (bool) {
2074                 // restore a previously hidden element.
2075                 // use the reference in case the selector class has already been removed.
2076                 if (this.currentMirrorEl) {
2077                     this.currentMirrorEl.style.visibility = '';
2078                     this.currentMirrorEl = null;
2079                 }
2080             }
2081             else {
2082                 var mirrorEl = this.mirrorSelector ?
2083                     document.querySelector(this.mirrorSelector) :
2084                     null;
2085                 if (mirrorEl) {
2086                     this.currentMirrorEl = mirrorEl;
2087                     mirrorEl.style.visibility = 'hidden';
2088                 }
2089             }
2090         };
2091         return InferredElementDragging;
2092     }(core.ElementDragging));
2093
2094     /*
2095     Bridges third-party drag-n-drop systems with FullCalendar.
2096     Must be instantiated and destroyed by caller.
2097     */
2098     var ThirdPartyDraggable = /** @class */ (function () {
2099         function ThirdPartyDraggable(containerOrSettings, settings) {
2100             var containerEl = document;
2101             if (
2102             // wish we could just test instanceof EventTarget, but doesn't work in IE11
2103             containerOrSettings === document ||
2104                 containerOrSettings instanceof Element) {
2105                 containerEl = containerOrSettings;
2106                 settings = settings || {};
2107             }
2108             else {
2109                 settings = (containerOrSettings || {});
2110             }
2111             var dragging = this.dragging = new InferredElementDragging(containerEl);
2112             if (typeof settings.itemSelector === 'string') {
2113                 dragging.pointer.selector = settings.itemSelector;
2114             }
2115             else if (containerEl === document) {
2116                 dragging.pointer.selector = '[data-event]';
2117             }
2118             if (typeof settings.mirrorSelector === 'string') {
2119                 dragging.mirrorSelector = settings.mirrorSelector;
2120             }
2121             new ExternalElementDragging(dragging, settings.eventData);
2122         }
2123         ThirdPartyDraggable.prototype.destroy = function () {
2124             this.dragging.destroy();
2125         };
2126         return ThirdPartyDraggable;
2127     }());
2128
2129     var main = core.createPlugin({
2130         componentInteractions: [DateClicking, DateSelecting, EventDragging, EventDragging$1],
2131         calendarInteractions: [UnselectAuto],
2132         elementDraggingImpl: FeaturefulElementDragging
2133     });
2134
2135     exports.Draggable = ExternalDraggable;
2136     exports.FeaturefulElementDragging = FeaturefulElementDragging;
2137     exports.PointerDragging = PointerDragging;
2138     exports.ThirdPartyDraggable = ThirdPartyDraggable;
2139     exports.default = main;
2140
2141     Object.defineProperty(exports, '__esModule', { value: true });
2142
2143 }));