PageSourceSearch

https://sge.cbat.org.br/template/novo-assets/plugins/custom/fullcalendar/fullcalendar.bundle.js

js cbat.org.br collected 2026-10-01 12:19:50 UTC 647,131 bytes, 14,376 lines download raw bytes

1/*!
2FullCalendar Core Package v4.3.1
3Docs & License: https://fullcalendar.io/
4(c) 2019 Adam Shaw
5*/
6
7(function (global, factory) {
8    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
9    typeof define === 'function' && define.amd ? define(['exports'], factory) :
10    (global = global || self, factory(global.FullCalendar = {}));
11}(this, function (exports) { 'use strict';
12
13    // Creating
14    // ----------------------------------------------------------------------------------------------------------------
15    var elementPropHash = {
16        className: true,
17        colSpan: true,
18        rowSpan: true
19    };
20    var containerTagHash = {
21        '<tr': 'tbody',
22        '<td': 'tr'
23    };
24    function createElement(tagName, attrs, content) {
25        var el = document.createElement(tagName);
26        if (attrs) {
27            for (var attrName in attrs) {
28                if (attrName === 'style') {
29                    applyStyle(el, attrs[attrName]);
30                }
31                else if (elementPropHash[attrName]) {
32                    el[attrName] = attrs[attrName];
33                }
34                else {
35                    el.setAttribute(attrName, attrs[attrName]);
36                }
37            }
38        }
39        if (typeof content === 'string') {
40            el.innerHTML = content; // shortcut. no need to process HTML in any way
41        }
42        else if (content != null) {
43            appendToElement(el, content);
44        }
45        return el;
46    }
47    function htmlToElement(html) {
48        html = html.trim();
49        var container = document.createElement(computeContainerTag(html));
50        container.innerHTML = html;
51        return container.firstChild;
52    }
53    function htmlToElements(html) {
54        return Array.prototype.slice.call(htmlToNodeList(html));
55    }
56    function htmlToNodeList(html) {
57        html = html.trim();
58        var container = document.createElement(computeContainerTag(html));
59        container.innerHTML = html;
60        return container.childNodes;
61    }
62    // assumes html already trimmed and tag names are lowercase
63    function computeContainerTag(html) {
64        return containerTagHash[html.substr(0, 3) // faster than using regex
65        ] || 'div';
66    }
67    function appendToElement(el, content) {
68        var childNodes = normalizeContent(content);
69        for (var i = 0; i < childNodes.length; i++) {
70            el.appendChild(childNodes[i]);
71        }
72    }
73    function prependToElement(parent, content) {
74        var newEls = normalizeContent(content);
75        var afterEl = parent.firstChild || null; // if no firstChild, will append to end, but that's okay, b/c there were no children
76        for (var i = 0; i < newEls.length; i++) {
77            parent.insertBefore(newEls[i], afterEl);
78        }
79    }
80    function insertAfterElement(refEl, content) {
81        var newEls = normalizeContent(content);
82        var afterEl = refEl.nextSibling || null;
83        for (var i = 0; i < newEls.length; i++) {
84            refEl.parentNode.insertBefore(newEls[i], afterEl);
85        }
86    }
87    function normalizeContent(content) {
88        var els;
89        if (typeof content === 'string') {
90            els = htmlToElements(content);
91        }
92        else if (content instanceof Node) {
93            els = [content];
94        }
95        else { // Node[] or NodeList
96            els = Array.prototype.slice.call(content);
97        }
98        return els;
99    }
100    function removeElement(el) {
101        if (el.parentNode) {
102            el.parentNode.removeChild(el);
103        }
104    }
105    // Querying
106    // ----------------------------------------------------------------------------------------------------------------
107    // from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
108    var matchesMethod = Element.prototype.matches ||
109        Element.prototype.matchesSelector ||
110        Element.prototype.msMatchesSelector;
111    var closestMethod = Element.prototype.closest || function (selector) {
112        // polyfill
113        var el = this;
114        if (!document.documentElement.contains(el)) {
115            return null;
116        }
117        do {
118            if (elementMatches(el, selector)) {
119                return el;
120            }
121            el = el.parentElement || el.parentNode;
122        } while (el !== null && el.nodeType === 1);
123        return null;
124    };
125    function elementClosest(el, selector) {
126        return closestMethod.call(el, selector);
127    }
128    function elementMatches(el, selector) {
129        return matchesMethod.call(el, selector);
130    }
131    // accepts multiple subject els
132    // returns a real array. good for methods like forEach
133    function findElements(container, selector) {
134        var containers = container instanceof HTMLElement ? [container] : container;
135        var allMatches = [];
136        for (var i = 0; i < containers.length; i++) {
137            var matches = containers[i].querySelectorAll(selector);
138            for (var j = 0; j < matches.length; j++) {
139                allMatches.push(matches[j]);
140            }
141        }
142        return allMatches;
143    }
144    // accepts multiple subject els
145    // only queries direct child elements
146    function findChildren(parent, selector) {
147        var parents = parent instanceof HTMLElement ? [parent] : parent;
148        var allMatches = [];
149        for (var i = 0; i < parents.length; i++) {
150            var childNodes = parents[i].children; // only ever elements
151            for (var j = 0; j < childNodes.length; j++) {
152                var childNode = childNodes[j];
153                if (!selector || elementMatches(childNode, selector)) {
154                    allMatches.push(childNode);
155                }
156            }
157        }
158        return allMatches;
159    }
160    // Attributes
161    // ----------------------------------------------------------------------------------------------------------------
162    function forceClassName(el, className, bool) {
163        if (bool) {
164            el.classList.add(className);
165        }
166        else {
167            el.classList.remove(className);
168        }
169    }
170    // Style
171    // ----------------------------------------------------------------------------------------------------------------
172    var PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i;
173    function applyStyle(el, props) {
174        for (var propName in props) {
175            applyStyleProp(el, propName, props[propName]);
176        }
177    }
178    function applyStyleProp(el, name, val) {
179        if (val == null) {
180            el.style[name] = '';
181        }
182        else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) {
183            el.style[name] = val + 'px';
184        }
185        else {
186            el.style[name] = val;
187        }
188    }
189
190    function pointInsideRect(point, rect) {
191        return point.left >= rect.left &&
192            point.left < rect.right &&
193            point.top >
193= rect.top &&
194            point.top < rect.bottom;
195    }
196    // Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false
197    function intersectRects(rect1, rect2) {
198        var res = {
199            left: Math.max(rect1.left, rect2.left),
200            right: Math.min(rect1.right, rect2.right),
201            top: Math.max(rect1.top, rect2.top),
202            bottom: Math.min(rect1.bottom, rect2.bottom)
203        };
204        if (res.left < res.right && res.top < res.bottom) {
205            return res;
206        }
207        return false;
208    }
209    function translateRect(rect, deltaX, deltaY) {
210        return {
211            left: rect.left + deltaX,
212            right: rect.right + deltaX,
213            top: rect.top + deltaY,
214            bottom: rect.bottom + deltaY
215        };
216    }
217    // Returns a new point that will have been moved to reside within the given rectangle
218    function constrainPoint(point, rect) {
219        return {
220            left: Math.min(Math.max(point.left, rect.left), rect.right),
221            top: Math.min(Math.max(point.top, rect.top), rect.bottom)
222        };
223    }
224    // Returns a point that is the center of the given rectangle
225    function getRectCenter(rect) {
226        return {
227            left: (rect.left + rect.right) / 2,
228            top: (rect.top + rect.bottom) / 2
229        };
230    }
231    // Subtracts point2's coordinates from point1's coordinates, returning a delta
232    function diffPoints(point1, point2) {
233        return {
234            left: point1.left - point2.left,
235            top: point1.top - point2.top
236        };
237    }
238
239    // Logic for determining if, when the element is right-to-left, the scrollbar appears on the left side
240    var isRtlScrollbarOnLeft = null;
241    function getIsRtlScrollbarOnLeft() {
242        if (isRtlScrollbarOnLeft === null) {
243            isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft();
244        }
245        return isRtlScrollbarOnLeft;
246    }
247    function computeIsRtlScrollbarOnLeft() {
248        var outerEl = createElement('div', {
249            style: {
250                position: 'absolute',
251                top: -1000,
252                left: 0,
253                border: 0,
254                padding: 0,
255                overflow: 'scroll',
256                direction: 'rtl'
257            }
258        }, '<div></div>');
259        document.body.appendChild(outerEl);
260        var innerEl = outerEl.firstChild;
261        var res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left;
262        removeElement(outerEl);
263        return res;
264    }
265    // The scrollbar width computations in computeEdges are sometimes flawed when it comes to
266    // retina displays, rounding, and IE11. Massage them into a usable value.
267    function sanitizeScrollbarWidth(width) {
268        width = Math.max(0, width); // no negatives
269        width = Math.round(width);
270        return width;
271    }
272
273    function computeEdges(el, getPadding) {
274        if (getPadding === void 0) { getPadding = false; }
275        var computedStyle = window.getComputedStyle(el);
276        var borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0;
277        var borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0;
278        var borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0;
279        var borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
280        // must use offset(Width|Height) because compatible with client(Width|Height)
281        var scrollbarLeftRight = sanitizeScrollbarWidth(el.offsetWidth - el.clientWidth - borderLeft - borderRight);
282        var scrollbarBottom = sanitizeScrollbarWidth(el.offsetHeight - el.clientHeight - borderTop - borderBottom);
283        var res = {
284            borderLeft: borderLeft,
285            borderRight: borderRight,
286            borderTop: borderTop,
287            borderBottom: borderBottom,
288            scrollbarBottom: scrollbarBottom,
289            scrollbarLeft: 0,
290            scrollbarRight: 0
291        };
292        if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side?
293            res.scrollbarLeft = scrollbarLeftRight;
294        }
295        else {
296            res.scrollbarRight = scrollbarLeftRight;
297        }
298        if (getPadding) {
299            res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0;
300            res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0;
301            res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0;
302            res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0;
303        }
304        return res;
305    }
306    function computeInnerRect(el, goWithinPadding) {
307        if (goWithinPadding === void 0) { goWithinPadding = false; }
308        var outerRect = computeRect(el);
309        var edges = computeEdges(el, goWithinPadding);
310        var res = {
311            left: outerRect.left + edges.borderLeft + edges.scrollbarLeft,
312            right: outerRect.right - edges.borderRight - edges.scrollbarRight,
313            top: outerRect.top + edges.borderTop,
314            bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom
315        };
316        if (goWithinPadding) {
317            res.left += edges.paddingLeft;
318            res.right -= edges.paddingRight;
319            res.top += edges.paddingTop;
320            res.bottom -= edges.paddingBottom;
321        }
322        return res;
323    }
324    function computeRect(el) {
325        var rect = el.getBoundingClientRect();
326        return {
327            left: rect.left + window.pageXOffset,
328            top: rect.top + window.pageYOffset,
329            right: rect.right + window.pageXOffset,
330            bottom: rect.bottom + window.pageYOffset
331        };
332    }
333    function computeViewportRect() {
334        return {
335            left: window.pageXOffset,
336            right: window.pageXOffset + document.documentElement.clientWidth,
337            top: window.pageYOffset,
338            bottom: window.pageYOffset + document.documentElement.clientHeight
339        };
340    }
341    function computeHeightAndMargins(el) {
342        return el.getBoundingClientRect().height + computeVMargins(el);
343    }
344    function computeVMargins(el) {
345        var computed = window.getComputedStyle(el);
346        return parseInt(computed.marginTop, 10) +
347            parseInt(computed.marginBottom, 10);
348    }
349    // does not return window
350    function getClippingParents(el) {
351        var parents = [];
352        while (el instanceof HTMLElement) { // will stop when gets to document or null
353            var computedStyle = window.getComputedStyle(el);
354            if (computedStyle.position === 'fixed') {
355                break;
356            }
357            if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) {
358                parents.push(el);
359            }
360            el = el.parentNode;
361        }
362        return parents;
363    }
364    function computeClippingRect(el) {
365        return getClippingParents(el)
366            .map(function (el) {
367            return computeInnerRect(el);
368        })
369            .concat(computeViewportRect())
370            .reduce(function (rect0, rect1) {
371            return intersectRects(rect0, rect1) || rect1; // should always intersect
372        });
373    }
374
375    // Stops a mouse/touch event from doing it's native browser action
376    function preventDefault(ev) {
377        ev.preventDefault();
378    }
379    // Event Delegation
380    // ----------------------------------------------------------------------------------------------------------------
381    function listenBySelector(container, eventType, selector, handler) {
382        function realHandler(ev) {
383            var matchedChild = elementClosest(ev.target, selector);
384            if (matchedChild) {
385                handler.call(matchedChild, ev, matchedChild);
386            }
387        }
388        container.addEventListener(eventType, realHandler);
389        return function () {
390            container.removeEventListener(eventType, realHandler);
391        };
392    }
393    function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) {
394        var currentMatchedChild;
395        return listenBySelector(container, 'mouseover', selector, function (ev, matchedChild) {
396            if (matchedChild !== currentMatchedChild) {
397                currentMatchedChild = matchedChild;
398                onMouseEnter(ev, matchedChild);
399                var realOnMouseLeave_1 = function (ev) {
400                    currentMatchedChild = null;
401                    onMouseLeave(ev, matchedChild);
402                    matchedChild.removeEventListener('mouseleave', realOnMouseLeave_1);
403                };
404                // listen to the next mouseleave, and then unattach
405                matchedChild.addEventListener('mouseleave', realOnMouseLeave_1);
406            }
407        });
408    }
409    // Animation
410    // ----------------------------------------------------------------------------------------------------------------
411    var transitionEventNames = [
412        'webkitTransitionEnd',
413        'otransitionend',
414        'oTransitionEnd',
415        'msTransitionEnd',
416        'transitionend'
417    ];
418    // triggered only when the next single subsequent transition finishes
419    function whenTransitionDone(el, callback) {
420        var realCallback = function (ev) {
421            callback(ev);
422            transitionEventNames.forEach(function (eventName) {
423                el.removeEventListener(eventName, realCallback);
424            });
425        };
426        transitionEventNames.forEach(function (eventName) {
427            el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes
428        });
429    }
430
431    var DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
432    // Adding
433    function addWeeks(m, n) {
434        var a = dateToUtcArray(m);
435        a[2] += n * 7;
436        return arrayToUtcDate(a);
437    }
438    function addDays(m, n) {
439        var a = dateToUtcArray(m);
440        a[2] += n;
441        return arrayToUtcDate(a);
442    }
443    function addMs(m, n) {
444        var a = dateToUtcArray(m);
445        a[6] += n;
446        return arrayToUtcDate(a);
447    }
448    // Diffing (all return floats)
449    function diffWeeks(m0, m1) {
450        return diffDays(m0, m1) / 7;
451    }
452    function diffDays(m0, m1) {
453        return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24);
454    }
455    function diffHours(m0, m1) {
456        return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60);
457    }
458    function diffMinutes(m0, m1) {
459        return (m1.valueOf() - m0.valueOf()) / (1000 * 60);
460    }
461    function diffSeconds(m0, m1) {
462        return (m1.valueOf() - m0.valueOf()) / 1000;
463    }
464    function diffDayAndTime(m0, m1) {
465        var m0day = startOfDay(m0);
466        var m1day = startOfDay(m1);
467        return {
468            years: 0,
469            months: 0,
470            days: Math.round(diffDays(m0day, m1day)),
471            milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf())
472        };
473    }
474    // Diffing Whole Units
475    function diffWholeWeeks(m0, m1) {
476        var d = diffWholeDays(m0, m1);
477        if (d !== null && d % 7 === 0) {
478            return d / 7;
479        }
480        return null;
481    }
482    function diffWholeDays(m0, m1) {
483        if (timeAsMs(m0) === timeAsMs(m1)) {
484            return Math.round(diffDays(m0, m1));
485        }
486        return null;
487    }
488    // Start-Of
489    function startOfDay(m) {
490        return arrayToUtcDate([
491            m.getUTCFullYear(),
492            m.getUTCMonth(),
493            m.getUTCDate()
494        ]);
495    }
496    function startOfHour(m) {
497        return arrayToUtcDate([
498            m.getUTCFullYear(),
499            m.getUTCMonth(),
500            m.getUTCDate(),
501            m.getUTCHours()
502        ]);
503    }
504    function startOfMinute(m) {
505        return arrayToUtcDate([
506            m.getUTCFullYear(),
507            m.getUTCMonth(),
508            m.getUTCDate(),
509            m.getUTCHours(),
510            m.getUTCMinutes()
511        ]);
512    }
513    function startOfSecond(m) {
514        return arrayToUtcDate([
515            m.getUTCFullYear(),
516            m.getUTCMonth(),
517            m.getUTCDate(),
518            m.getUTCHours(),
519            m.getUTCMinutes(),
520            m.getUTCSeconds()
521        ]);
522    }
523    // Week Computation
524    function weekOfYear(marker, dow, doy) {
525        var y = marker.getUTCFullYear();
526        var w = weekOfGivenYear(marker, y, dow, doy);
527        if (w < 1) {
528            return weekOfGivenYear(marker, y - 1, dow, doy);
529        }
530        var nextW = weekOfGivenYear(marker, y + 1, dow, doy);
531        if (nextW >= 1) {
532            return Math.min(w, nextW);
533        }
534        return w;
535    }
536    function weekOfGivenYear(marker, year, dow, doy) {
537        var firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]);
538        var dayStart = startOfDay(marker);
539        var days = Math.round(diffDays(firstWeekStart, dayStart));
540        return Math.floor(days / 7) + 1; // zero-indexed
541    }
542    // start-of-first-week - start-of-year
543    function firstWeekOffset(year, dow, doy) {
544        // first-week day -- which january is always in the first week (4 for iso, 1 for other)
545        var fwd = 7 + dow - doy;
546        // first-week day local weekday -- which local weekday is fwd
547        var fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7;
548        return -fwdlw + fwd - 1;
549    }
550    // Array Conversion
551    function dateToLocalArray(date) {
552        return [
553            date.getFullYear(),
554            date.getMonth(),
555            date.getDate(),
556            date.getHours(),
557            date.getMinutes(),
558            date.getSeconds(),
559            date.getMilliseconds()
560        ];
561    }
562    function arrayToLocalDate(a) {
563        return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month
564        a[3] || 0, a[4] || 0, a[5] || 0);
565    }
566    function dateToUtcArray(date) {
567        return [
568            date.getUTCFullYear(),
569            date.getUTCMonth(),
570            date.getUTCDate(),
571            date.getUTCHours(),
572            date.getUTCMinutes(),
573            date.getUTCSeconds(),
574            date.getUTCMilliseconds()
575        ];
576    }
577    function arrayToUtcDate(a) {
578        // according to web standards (and Safari), a month index is required.
579        // massage if only given a year.
580        if (a.length === 1) {
581            a = a.concat([0]);
582        }
583        return new Date(Date.UTC.apply(Date, a));
584    }
585    // Other Utils
586    function isValidDate(m) {
587        return !isNaN(m.valueOf());
588    }
589    function timeAsMs(m) {
590        return m.getUTCHours() * 1000 * 60 * 60 +
591            m.getUTCMinutes() * 1000 * 60 +
592            m.getUTCSeconds() * 1000 +
593            m.getUTCMilliseconds();
594    }
595
596    var INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];
597    var PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/;
598    // Parsing and Creation
599    function createDuration(input, unit) {
600        var _a;
601        if (typeof input === 'string') {
602            return parseString(input);
603        }
604        else if (typeof input === 'object' && input) { // non-null object
605            return normalizeObject(input);
606        }
607        else if (typeof input === 'number') {
608            return normalizeObject((_a = {}, _a[unit || 'milliseconds'] = input, _a));
609        }
610        else {
611            return null;
612        }
613    }
614    function parseString(s) {
615        var m = PARSE_RE.exec(s);
616        if (m) {
617            var sign = m[1] ? -1 : 1;
618            return {
619                years: 0,
620                months: 0,
621                days: sign * (m[2] ? parseInt(m[2], 10) : 0),
622                milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours
623                    (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes
624                    (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds
625                    (m[6] ? parseInt(m[6], 10) : 0) // ms
626                )
627            };
628        }
629        return null;
630    }
631    function normalizeObject(obj) {
632        return {
633            years: obj.years || obj.year || 0,
634            months: obj.months || obj.month || 0,
635            days: (obj.days || obj.day || 0) +
636                getWeeksFromInput(obj) * 7,
637            milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours
638                (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes
639                (obj.seconds || obj.second || 0) * 1000 + // seconds
640                (obj.milliseconds || obj.millisecond || obj.ms || 0) // ms
641        };
642    }
643    function getWeeksFromInput(obj) {
644        return obj.weeks || obj.week || 0;
645    }
646    // Equality
647    function durationsEqual(d0, d1) {
648        return d0.years === d1.years &&
649            d0.months === d1.months &&
650            d0.days === d1.days &&
651            d0.milliseconds === d1.milliseconds;
652    }
653    function isSingleDay(dur) {
654        return dur.years === 0 && dur.months === 0 && dur.days === 1 && dur.milliseconds === 0;
655    }
656    // Simple Math
657    function addDurations(d0, d1) {
658        return {
659            years: d0.years + d1.years,
660            months: d0.months + d1.months,
661            days: d0.days + d1.days,
662            milliseconds: d0.milliseconds + d1.milliseconds
663        };
664    }
665    function subtractDurations(d1, d0) {
666        return {
667            years: d1.years - d0.years,
668            months: d1.months - d0.months,
669            days: d1.days - d0.days,
670            milliseconds: d1.milliseconds - d0.milliseconds
671        };
672    }
673    function multiplyDuration(d, n) {
674        return {
675            years: d.years * n,
676            months: d.months * n,
677            days: d.days * n,
678            milliseconds: d.milliseconds * n
679        };
680    }
681    // Conversions
682    // "Rough" because they are based on average-case Gregorian months/years
683    function asRoughYears(dur) {
684        return asRoughDays(dur) / 365;
685    }
686    function asRoughMonths(dur) {
687        return asRoughDays(dur) / 30;
688    }
689    function asRoughDays(dur) {
690        return asRoughMs(dur) / 864e5;
691    }
692    function asRoughMinutes(dur) {
693        return asRoughMs(dur) / (1000 * 60);
694    }
695    function asRoughSeconds(dur) {
696        return asRoughMs(dur) / 1000;
697    }
698    function asRoughMs(dur) {
699        return dur.years * (365 * 864e5) +
700            dur.months * (30 * 864e5) +
701            dur.days * 864e5 +
702            dur.milliseconds;
703    }
704    // Advanced Math
705    function wholeDivideDurations(numerator, denominator) {
706        var res = null;
707        for (var i = 0; i < INTERNAL_UNITS.length; i++) {
708            var unit = INTERNAL_UNITS[i];
709            if (denominator[unit]) {
710                var localRes = numerator[unit] / denominator[unit];
711                if (!isInt(localRes) || (res !== null && res !== localRes)) {
712                    return null;
713                }
714                res = localRes;
715            }
716            else if (numerator[unit]) {
717                // needs to divide by something but can't!
718                return null;
719            }
720        }
721        return res;
722    }
723    function greatestDurationDenominator(dur, dontReturnWeeks) {
724        var ms = dur.milliseconds;
725        if (ms) {
726            if (ms % 1000 !== 0) {
727                return { unit: 'millisecond', value: ms };
728            }
729            if (ms % (1000 * 60) !== 0) {
730                return { unit: 'second', value: ms / 1000 };
731            }
732            if (ms % (1000 * 60 * 60) !== 0) {
733                return { unit: 'minute', value: ms / (1000 * 60) };
734            }
735            if (ms) {
736                return { unit: 'hour', value: ms / (1000 * 60 * 60) };
737            }
738        }
739        if (dur.days) {
740            if (!dontReturnWeeks && dur.days % 7 === 0) {
741                return { unit: 'week', value: dur.days / 7 };
742            }
743            return { unit: 'day', value: dur.days };
744        }
745        if (dur.months) {
746            return { unit: 'month', value: dur.months };
747        }
748        if (dur.years) {
749            return { unit: 'year', value: dur.years };
750        }
751        return { unit: 'millisecond', value: 0 };
752    }
753
754    /* FullCalendar-specific DOM Utilities
755    ----------------------------------------------------------------------------------------------------------------------*/
756    // Given the scrollbar widths of some other container, create borders/margins on rowEls in order to match the left
757    // and right space that was offset by the scrollbars. A 1-pixel border first, then margin beyond that.
758    function compensateScroll(rowEl, scrollbarWidths) {
759        if (scrollbarWidths.left) {
760            applyStyle(rowEl, {
761                borderLeftWidth: 1,
762                marginLeft: scrollbarWidths.left - 1
763            });
764        }
765        if (scrollbarWidths.right) {
766            applyStyle(rowEl, {
767                borderRightWidth: 1,
768                marginRight: scrollbarWidths.right - 1
769            });
770        }
771    }
772    // Undoes compensateScroll and restores all borders/margins
773    function uncompensateScroll(rowEl) {
774        applyStyle(rowEl, {
775            marginLeft: '',
776            marginRight: '',
777            borderLeftWidth: '',
778            borderRightWidth: ''
779        });
780    }
781    // Make the mouse cursor express that an event is not allowed in the current area
782    function disableCursor() {
783        document.body.classList.add('fc-not-allowed');
784    }
785    // Returns the mouse cursor to its original look
786    function enableCursor() {
787        document.body.classList.remove('fc-not-allowed');
788    }
789    // Given a total available height to fill, have `els` (essentially child rows) expand to accomodate.
790    // By default, all elements that are shorter than the recommended height are expanded uniformly, not considering
791    // any other els that are already too tall. if `shouldRedistribute` is on, it considers these tall rows and
792    // reduces the available height.
793    function distributeHeight(els, availableHeight, shouldRedistribute) {
794        // *FLOORING NOTE*: we floor in certain places because zoom can give inaccurate floating-point dimensions,
795        // and it is better to be shorter than taller, to avoid creating unnecessary scrollbars.
796        var minOffset1 = Math.floor(availableHeight / els.length); // for non-last element
797        var minOffset2 = Math.floor(availableHeight - minOffset1 * (els.length - 1)); // for last element *FLOORING NOTE*
798        var flexEls = []; // elements that are allowed to expand. array of DOM nodes
799        var flexOffsets = []; // amount of vertical space it takes up
800        var flexHeights = []; // actual css height
801        var usedHeight = 0;
802        undistributeHeight(els); // give all elements their natural height
803        // find elements that are below the recommended height (expandable).
804        // important to query for heights in a single first pass (to avoid reflow oscillation).
805        els.forEach(function (el, i) {
806            var minOffset = i === els.length - 1 ? minOffset2 : minOffset1;
807            var naturalHeight = el.getBoundingClientRect().height;
808            var naturalOffset = naturalHeight + computeVMargins(el);
809            if (naturalOffset < minOffset) {
810                flexEls.push(el);
811                flexOffsets.push(naturalOffset);
812                flexHeights.push(naturalHeight);
813            }
814            else {
815                // this element stretches past recommended height (non-expandable). mark the space as occupied.
816                usedHeight += naturalOffset;
817            }
818        });
819        // readjust the recommended height to only consider the height available to non-maxed-out rows.
820        if (shouldRedistribute) {
821            availableHeight -= usedHeight;
822            minOffset1 = Math.floor(availableHeight / flexEls.length);
823            minOffset2 = Math.floor(availableHeight - minOffset1 * (flexEls.length - 1)); // *FLOORING NOTE*
824        }
825        // assign heights to all expandable elements
826        flexEls.forEach(function (el, i) {
827            var minOffset = i === flexEls.length - 1 ? minOffset2 : minOffset1;
828            var naturalOffset = flexOffsets[i];
829            var naturalHeight = flexHeights[i];
830            var newHeight = minOffset - (naturalOffset - naturalHeight); // subtract the margin/padding
831            if (naturalOffset < minOffset) { // we check this again because redistribution might have changed things
832                el.style.height = newHeight + 'px';
833            }
834        });
835    }
836    // Undoes distrubuteHeight, restoring all els to their natural height
837    function undistributeHeight(els) {
838        els.forEach(function (el) {
839            el.style.height = '';
840        });
841    }
842    // Given `els`, a set of <td> cells, find the cell with the largest natural width and set the widths of all the
843    // cells to be that width.
844    // PREREQUISITE: if you want a cell to take up width, it needs to have a single inner element w/ display:inline
845    function matchCellWidths(els) {
846        var maxInnerWidth = 0;
847        els.forEach(function (el) {
848            var innerEl = el.firstChild; // hopefully an element
849            if (innerEl instanceof HTMLElement) {
850                var innerWidth_1 = innerEl.getBoundingClientRect().width;
851                if (innerWidth_1 > maxInnerWidth) {
852                    maxInnerWidth = innerWidth_1;
853                }
854            }
855        });
856        maxInnerWidth++; // sometimes not accurate of width the text needs to stay on one line. insurance
857        els.forEach(function (el) {
858            el.style.width = maxInnerWidth + 'px';
859        });
860        return maxInnerWidth;
861    }
862    // Given one element that resides inside another,
863    // Subtracts the height of the inner element from the outer element.
864    function subtractInnerElHeight(outerEl, innerEl) {
865        // effin' IE8/9/10/11 sometimes returns 0 for dimensions. this weird hack was the only thing that worked
866        var reflowStyleProps = {
867            position: 'relative',
868            left: -1 // ensure reflow in case the el was already relative. negative is less likely to cause new scroll
869        };
870        applyStyle(outerEl, reflowStyleProps);
871        applyStyle(innerEl, reflowStyleProps);
872        var diff = // grab the dimensions
873         outerEl.getBoundingClientRect().height -
874            innerEl.getBoundingClientRect().height;
875        // undo hack
876        var resetStyleProps = { position: '', left: '' };
877        applyStyle(outerEl, resetStyleProps);
878        applyStyle(innerEl, resetStyleProps);
879        return diff;
880    }
881    /* Selection
882    ----------------------------------------------------------------------------------------------------------------------*/
883    function preventSelection(el) {
884        el.classList.add('fc-unselectable');
885        el.addEventListener('selectstart', preventDefault);
886    }
887    function allowSelection(el) {
888        el.classList.remove('fc-unselectable');
889        el.removeEventListener('selectstart', preventDefault);
890    }
891    /* Context Menu
892    ----------------------------------------------------------------------------------------------------------------------*/
893    function preventContextMenu(el) {
894        el.addEventListener('contextmenu', preventDefault);
895    }
896    function allowContextMenu(el) {
897        el.removeEventListener('contextmenu', preventDefault);
898    }
899    /* Object Ordering by Field
900    ----------------------------------------------------------------------------------------------------------------------*/
901    function parseFieldSpecs(input) {
902        var specs = [];
903        var tokens = [];
904        var i;
905        var token;
906        if (typeof input === 'string') {
907            tokens = input.split(/\s*,\s*/);
908        }
909        else if (typeof input === 'function') {
910            tokens = [input];
911        }
912        else if (Array.isArray(input)) {
913            tokens = input;
914        }
915        for (i = 0; i < tokens.length; i++) {
916            token = tokens[i];
917            if (typeof token === 'string') {
918                specs.push(token.charAt(0) === '-' ?
919                    { field: token.substring(1), order: -1 } :
920                    { field: token, order: 1 });
921            }
922            else if (typeof token === 'function') {
923                specs.push({ func: token });
924            }
925        }
926        return specs;
927    }
928    function compareByFieldSpecs(obj0, obj1, fieldSpecs) {
929        var i;
930        var cmp;
931        for (i = 0; i < fieldSpecs.length; i++) {
932            cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]);
933            if (cmp) {
934                return cmp;
935            }
936        }
937        return 0;
938    }
939    function compareByFieldSpec(obj0, obj1, fieldSpec) {
940        if (fieldSpec.func) {
941            return fieldSpec.func(obj0, obj1);
942        }
943        return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field])
944            * (fieldSpec.order || 1);
945    }
946    function flexibleCompare(a, b) {
947        if (!a && !b) {
948            return 0;
949        }
950        if (b == null) {
951            return -1;
952        }
953        if (a == null) {
954            return 1;
955        }
956        if (typeof a === 'string' || typeof b === 'string') {
957            return String(a).localeCompare(String(b));
958        }
959        return a - b;
960    }
961    /* String Utilities
962    ----------------------------------------------------------------------------------------------------------------------*/
963    function capitaliseFirstLetter(str) {
964        return str.charAt(0).toUpperCase() + str.slice(1);
965    }
966    function padStart(val, len) {
967        var s = String(val);
968        return '000'.substr(0, len - s.length) + s;
969    }
970    /* Number Utilities
971    ----------------------------------------------------------------------------------------------------------------------*/
972    function compareNumbers(a, b) {
973        return a - b;
974    }
975    function isInt(n) {
976        return n % 1 === 0;
977    }
978    /* Weird Utilities
979    ----------------------------------------------------------------------------------------------------------------------*/
980    function applyAll(functions, thisObj, args) {
981        if (typeof functions === 'function') { // supplied a single function
982            functions = [functions];
983        }
984        if (functions) {
985            var i = void 0;
986            var ret = void 0;
987            for (i = 0; i < functions.length; i++) {
988                ret = functions[i].apply(thisObj, args) || ret;
989            }
990            return ret;
991        }
992    }
993    function firstDefined() {
994        var args = [];
995        for (var _i = 0; _i < arguments.length; _i++) {
996            args[_i] = arguments[_i];
997        }
998        for (var i = 0; i < args.length; i++) {
999            if (args[i] !== undefined) {
1000                return args[i];
1001            }
1002        }
1003    }
1004    // Returns a function, that, as long as it continues to be invoked, will not
1005    // be triggered. The function will be called after it stops being called for
1006    // N milliseconds. If `immediate` is passed, trigger the function on the
1007    // leading edge, instead of the trailing.
1008    // https://github.com/jashkenas/underscore/blob/1.6.0/underscore.js#L714
1009    function debounce(func, wait) {
1010        var timeout;
1011        var args;
1012        var context;
1013        var timestamp;
1014        var result;
1015        var later = function () {
1016            var last = new Date().valueOf() - timestamp;
1017            if (last < wait) {
1018                timeout = setTimeout(later, wait - last);
1019            }
1020            else {
1021                timeout = null;
1022                result = func.apply(context, args);
1023                context = args = null;
1024            }
1025        };
1026        return function () {
1027            context = this;
1028            args = arguments;
1029            timestamp = new Date().valueOf();
1030            if (!timeout) {
1031                timeout = setTimeout(later, wait);
1032            }
1033            return result;
1034        };
1035    }
1036    // Number and Boolean are only types that defaults or not computed for
1037    // TODO: write more comments
1038    function refineProps(rawProps, processors, defaults, leftoverProps) {
1039        if (defaults === void 0) { defaults = {}; }
1040        var refined = {};
1041        for (var key in processors) {
1042            var processor = processors[key];
1043            if (rawProps[key] !== undefined) {
1044                // found
1045                if (processor === Function) {
1046                    refined[key] = typeof rawProps[key] === 'function' ? rawProps[key] : null;
1047                }
1048                else if (processor) { // a refining function?
1049                    refined[key] = processor(rawProps[key]);
1050                }
1051                else {
1052                    refined[key] = rawProps[key];
1053                }
1054            }
1055            else if (defaults[key] !== undefined) {
1056                // there's an explicit default
1057                refined[key] = defaults[key];
1058            }
1059            else {
1060                // must compute a default
1061                if (processor === String) {
1062                    refined[key] = ''; // empty string is default for String
1063                }
1064                else if (!processor || processor === Number || processor === Boolean || processor === Function) {
1065                    refined[key] = null; // assign null for other non-custom processor funcs
1066                }
1067                else {
1068                    refined[key] = processor(null); // run the custom processor func
1069                }
1070            }
1071        }
1072        if (leftoverProps) {
1073            for (var key in rawProps) {
1074                if (processors[key] === undefined) {
1075                    leftoverProps[key] = rawProps[key];
1076                }
1077            }
1078        }
1079        return refined;
1080    }
1081    /* Date stuff that doesn't belong in datelib core
1082    ----------------------------------------------------------------------------------------------------------------------*/
1083    // given a timed range, computes an all-day range that has the same exact duration,
1084    // but whose start time is aligned with the start of the day.
1085    function computeAlignedDayRange(timedRange) {
1086        var dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1;
1087        var start = startOfDay(timedRange.start);
1088        var end = addDays(start, dayCnt);
1089        return { start: start, end: end };
1090    }
1091    // given a timed range, computes an all-day range based on how for the end date bleeds into the next day
1092    // TODO: give nextDayThreshold a default arg
1093    function computeVisibleDayRange(timedRange, nextDayThreshold) {
1094        if (nextDayThreshold === void 0) { nextDayThreshold = createDuration(0); }
1095        var startDay = null;
1096        var endDay = null;
1097        if (timedRange.end) {
1098            endDay = startOfDay(timedRange.end);
1099            var endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay`
1100            // If the end time is actually inclusively part of the next day and is equal to or
1101            // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.
1102            // Otherwise, leaving it as inclusive will cause it to exclude `endDay`.
1103            if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) {
1104                endDay = addDays(endDay, 1);
1105            }
1106        }
1107        if (timedRange.start) {
1108            startDay = startOfDay(timedRange.start); // the beginning of the day the range starts
1109            // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day.
1110            if (endDay && endDay <= startDay) {
1111                endDay = addDays(startDay, 1);
1112            }
1113        }
1114        return { start: startDay, end: endDay };
1115    }
1116    // spans from one day into another?
1117    function isMultiDayRange(range) {
1118        var visibleRange = computeVisibleDayRange(range);
1119        return diffDays(visibleRange.start, visibleRange.end) > 1;
1120    }
1121    function diffDates(date0, date1, dateEnv, largeUnit) {
1122        if (largeUnit === 'year') {
1123            return createDuration(dateEnv.diffWholeYears(date0, date1), 'year');
1124        }
1125        else if (largeUnit === 'month') {
1126            return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month');
1127        }
1128        else {
1129            return diffDayAndTime(date0, date1); // returns a duration
1130        }
1131    }
1132
1133    /*! *****************************************************************************
1134    Copyright (c) Microsoft Corporation. All rights reserved.
1135    Licensed under the Apache License, Version 2.0 (the "License");
1135 you may not use
1136    this file except in compliance with the License. You may obtain a copy of the
1137    License at http://www.apache.org/licenses/LICENSE-2.0
1138
1139    THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1140    KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
1141    WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
1142    MERCHANTABLITY OR NON-INFRINGEMENT.
1143
1144    See the Apache Version 2.0 License for specific language governing permissions
1145    and limitations under the License.
1146    ***************************************************************************** */
1147    /* global Reflect, Promise */
1148
1149    var extendStatics = function(d, b) {
1150        extendStatics = Object.setPrototypeOf ||
1151            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
1152            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
1153        return extendStatics(d, b);
1154    };
1155
1156    function __extends(d, b) {
1157        extendStatics(d, b);
1158        function __() { this.constructor = d; }
1159        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1160    }
1161
1162    var __assign = function() {
1163        __assign = Object.assign || function __assign(t) {
1164            for (var s, i = 1, n = arguments.length; i < n; i++) {
1165                s = arguments[i];
1166                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
1167            }
1168            return t;
1169        };
1170        return __assign.apply(this, arguments);
1171    };
1172
1173    function parseRecurring(eventInput, allDayDefault, dateEnv, recurringTypes, leftovers) {
1174        for (var i = 0; i < recurringTypes.length; i++) {
1175            var localLeftovers = {};
1176            var parsed = recurringTypes[i].parse(eventInput, localLeftovers, dateEnv);
1177            if (parsed) {
1178                var allDay = localLeftovers.allDay;
1179                delete localLeftovers.allDay; // remove from leftovers
1180                if (allDay == null) {
1181                    allDay = allDayDefault;
1182                    if (allDay == null) {
1183                        allDay = parsed.allDayGuess;
1184                        if (allDay == null) {
1185                            allDay = false;
1186                        }
1187                    }
1188                }
1189                __assign(leftovers, localLeftovers);
1190                return {
1191                    allDay: allDay,
1192                    duration: parsed.duration,
1193                    typeData: parsed.typeData,
1194                    typeId: i
1195                };
1196            }
1197        }
1198        return null;
1199    }
1200    /*
1201    Event MUST have a recurringDef
1202    */
1203    function expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) {
1204        var typeDef = recurringTypes[eventDef.recurringDef.typeId];
1205        var markers = typeDef.expand(eventDef.recurringDef.typeData, {
1206            start: dateEnv.subtract(framingRange.start, duration),
1207            end: framingRange.end
1208        }, dateEnv);
1209        // the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to
1210        if (eventDef.allDay) {
1211            markers = markers.map(startOfDay);
1212        }
1213        return markers;
1214    }
1215
1216    var hasOwnProperty = Object.prototype.hasOwnProperty;
1217    // Merges an array of objects into a single object.
1218    // The second argument allows for an array of property names who's object values will be merged together.
1219    function mergeProps(propObjs, complexProps) {
1220        var dest = {};
1221        var i;
1222        var name;
1223        var complexObjs;
1224        var j;
1225        var val;
1226        var props;
1227        if (complexProps) {
1228            for (i = 0; i < complexProps.length; i++) {
1229                name = complexProps[i];
1230                complexObjs = [];
1231                // collect the trailing object values, stopping when a non-object is discovered
1232                for (j = propObjs.length - 1; j >= 0; j--) {
1233                    val = propObjs[j][name];
1234                    if (typeof val === 'object' && val) { // non-null object
1235                        complexObjs.unshift(val);
1236                    }
1237                    else if (val !== undefined) {
1238                        dest[name] = val; // if there were no objects, this value will be used
1239                        break;
1240                    }
1241                }
1242                // if the trailing values were objects, use the merged value
1243                if (complexObjs.length) {
1244                    dest[name] = mergeProps(complexObjs);
1245                }
1246            }
1247        }
1248        // copy values into the destination, going from last to first
1249        for (i = propObjs.length - 1; i >= 0; i--) {
1250            props = propObjs[i];
1251            for (name in props) {
1252                if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign
1253                    dest[name] = props[name];
1254                }
1255            }
1256        }
1257        return dest;
1258    }
1259    function filterHash(hash, func) {
1260        var filtered = {};
1261        for (var key in hash) {
1262            if (func(hash[key], key)) {
1263                filtered[key] = hash[key];
1264            }
1265        }
1266        return filtered;
1267    }
1268    function mapHash(hash, func) {
1269        var newHash = {};
1270        for (var key in hash) {
1271            newHash[key] = func(hash[key], key);
1272        }
1273        return newHash;
1274    }
1275    function arrayToHash(a) {
1276        var hash = {};
1277        for (var _i = 0, a_1 = a; _i < a_1.length; _i++) {
1278            var item = a_1[_i];
1279            hash[item] = true;
1280        }
1281        return hash;
1282    }
1283    function hashValuesToArray(obj) {
1284        var a = [];
1285        for (var key in obj) {
1286            a.push(obj[key]);
1287        }
1288        return a;
1289    }
1290    function isPropsEqual(obj0, obj1) {
1291        for (var key in obj0) {
1292            if (hasOwnProperty.call(obj0, key)) {
1293                if (!(key in obj1)) {
1294                    return false;
1295                }
1296            }
1297        }
1298        for (var key in obj1) {
1299            if (hasOwnProperty.call(obj1, key)) {
1300                if (obj0[key] !== obj1[key]) {
1301                    return false;
1302                }
1303            }
1304        }
1305        return true;
1306    }
1307
1308    function parseEvents(rawEvents, sourceId, calendar, allowOpenRange) {
1309        var eventStore = createEmptyEventStore();
1310        for (var _i = 0, rawEvents_1 = rawEvents; _i < rawEvents_1.length; _i++) {
1311            var rawEvent = rawEvents_1[_i];
1312            var tuple = parseEvent(rawEvent, sourceId, calendar, allowOpenRange);
1313            if (tuple) {
1314                eventTupleToStore(tuple, eventStore);
1315            }
1316        }
1317        return eventStore;
1318    }
1319    function eventTupleToStore(tuple, eventStore) {
1320        if (eventStore === void 0) { eventStore = createEmptyEventStore(); }
1321        eventStore.defs[tuple.def.defId] = tuple.def;
1322        if (tuple.instance) {
1323            eventStore.instances[tuple.instance.instanceId] = tuple.instance;
1324        }
1325        return eventStore;
1326    }
1327    function expandRecurring(eventStore, framingRange, calendar) {
1328        var dateEnv = calendar.dateEnv;
1329        var defs = eventStore.defs, instances = eventStore.instances;
1330        // remove existing recurring instances
1331        instances = filterHash(instances, function (instance) {
1332            return !defs[instance.defId].recurringDef;
1333        });
1334        for (var defId in defs) {
1335            var def = defs[defId];
1336            if (def.recurringDef) {
1337                var duration = def.recurringDef.duration;
1338                if (!duration) {
1339                    duration = def.allDay ?
1340                        calendar.defaultAllDayEventDuration :
1341                        calendar.defaultTimedEventDuration;
1342                }
1343                var starts = expandRecurringRanges(def, duration, framingRange, calendar.dateEnv, calendar.pluginSystem.hooks.recurringTypes);
1344                for (var _i = 0, starts_1 = starts; _i < starts_1.length; _i++) {
1345                    var start = starts_1[_i];
1346                    var instance = createEventInstance(defId, {
1347                        start: start,
1348                        end: dateEnv.add(start, duration)
1349                    });
1350                    instances[instance.instanceId] = instance;
1351                }
1352            }
1353        }
1354        return { defs: defs, instances: instances };
1355    }
1356    // retrieves events that have the same groupId as the instance specified by `instanceId`
1357    // or they are the same as the instance.
1358    // why might instanceId not be in the store? an event from another calendar?
1359    function getRelevantEvents(eventStore, instanceId) {
1360        var instance = eventStore.instances[instanceId];
1361        if (instance) {
1362            var def_1 = eventStore.defs[instance.defId];
1363            // get events/instances with same group
1364            var newStore = filterEventStoreDefs(eventStore, function (lookDef) {
1365                return isEventDefsGrouped(def_1, lookDef);
1366            });
1367            // add the original
1368            // TODO: wish we could use eventTupleToStore or something like it
1369            newStore.defs[def_1.defId] = def_1;
1370            newStore.instances[instance.instanceId] = instance;
1371            return newStore;
1372        }
1373        return createEmptyEventStore();
1374    }
1375    function isEventDefsGrouped(def0, def1) {
1376        return Boolean(def0.groupId && def0.groupId === def1.groupId);
1377    }
1378    function transformRawEvents(rawEvents, eventSource, calendar) {
1379        var calEachTransform = calendar.opt('eventDataTransform');
1380        var sourceEachTransform = eventSource ? eventSource.eventDataTransform : null;
1381        if (sourceEachTransform) {
1382            rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform);
1383        }
1384        if (calEachTransform) {
1385            rawEvents = transformEachRawEvent(rawEvents, calEachTransform);
1386        }
1387        return rawEvents;
1388    }
1389    function transformEachRawEvent(rawEvents, func) {
1390        var refinedEvents;
1391        if (!func) {
1392            refinedEvents = rawEvents;
1393        }
1394        else {
1395            refinedEvents = [];
1396            for (var _i = 0, rawEvents_2 = rawEvents; _i < rawEvents_2.length; _i++) {
1397                var rawEvent = rawEvents_2[_i];
1398                var refinedEvent = func(rawEvent);
1399                if (refinedEvent) {
1400                    refinedEvents.push(refinedEvent);
1401                }
1402                else if (refinedEvent == null) {
1403                    refinedEvents.push(rawEvent);
1404                } // if a different falsy value, do nothing
1405            }
1406        }
1407        return refinedEvents;
1408    }
1409    function createEmptyEventStore() {
1410        return { defs: {}, instances: {} };
1411    }
1412    function mergeEventStores(store0, store1) {
1413        return {
1414            defs: __assign({}, store0.defs, store1.defs),
1415            instances: __assign({}, store0.instances, store1.instances)
1416        };
1417    }
1418    function filterEventStoreDefs(eventStore, filterFunc) {
1419        var defs = filterHash(eventStore.defs, filterFunc);
1420        var instances = filterHash(eventStore.instances, function (instance) {
1421            return defs[instance.defId]; // still exists?
1422        });
1423        return { defs: defs, instances: instances };
1424    }
1425
1426    function parseRange(input, dateEnv) {
1427        var start = null;
1428        var end = null;
1429        if (input.start) {
1430            start = dateEnv.createMarker(input.start);
1431        }
1432        if (input.end) {
1433            end = dateEnv.createMarker(input.end);
1434        }
1435        if (!start && !end) {
1436            return null;
1437        }
1438        if (start && end && end < start) {
1439            return null;
1440        }
1441        return { start: start, end: end };
1442    }
1443    // SIDE-EFFECT: will mutate ranges.
1444    // Will return a new array result.
1445    function invertRanges(ranges, constraintRange) {
1446        var invertedRanges = [];
1447        var start = constraintRange.start; // the end of the previous range. the start of the new range
1448        var i;
1449        var dateRange;
1450        // ranges need to be in order. required for our date-walking algorithm
1451        ranges.sort(compareRanges);
1452        for (i = 0; i < ranges.length; i++) {
1453            dateRange = ranges[i];
1454            // add the span of time before the event (if there is any)
1455            if (dateRange.start > start) { // compare millisecond time (skip any ambig logic)
1456                invertedRanges.push({ start: start, end: dateRange.start });
1457            }
1458            if (dateRange.end > start) {
1459                start = dateRange.end;
1460            }
1461        }
1462        // add the span of time after the last event (if there is any)
1463        if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic)
1464            invertedRanges.push({ start: start, end: constraintRange.end });
1465        }
1466        return invertedRanges;
1467    }
1468    function compareRanges(range0, range1) {
1469        return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first
1470    }
1471    function intersectRanges(range0, range1) {
1472        var start = range0.start;
1473        var end = range0.end;
1474        var newRange = null;
1475        if (range1.start !== null) {
1476            if (start === null) {
1477                start = range1.start;
1478            }
1479            else {
1480                start = new Date(Math.max(start.valueOf(), range1.start.valueOf()));
1481            }
1482        }
1483        if (range1.end != null) {
1484            if (end === null) {
1485                end = range1.end;
1486            }
1487            else {
1488                end = new Date(Math.min(end.valueOf(), range1.end.valueOf()));
1489            }
1490        }
1491        if (start === null || end === null || start < end) {
1492            newRange = { start: start, end: end };
1493        }
1494        return newRange;
1495    }
1496    function rangesEqual(range0, range1) {
1497        return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) &&
1498            (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf());
1499    }
1500    function rangesIntersect(range0, range1) {
1501        return (range0.end === null || range1.start === null || range0.end > range1.start) &&
1502            (range0.start === null || range1.end === null || range0.start < range1.end);
1503    }
1504    function rangeContainsRange(outerRange, innerRange) {
1505        return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) &&
1506            (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end));
1507    }
1508    function rangeContainsMarker(range, date) {
1509        return (range.start === null || date >= range.start) &&
1510            (range.end === null || date < range.end);
1511    }
1512    // If the given date is not within the given range, move it inside.
1513    // (If it's past the end, make it one millisecond before the end).
1514    function constrainMarkerToRange(date, range) {
1515        if (range.start != null && date < range.start) {
1516            return range.start;
1517        }
1518        if (range.end != null && date >= range.end) {
1519            return new Date(range.end.valueOf() - 1);
1520        }
1521        return date;
1522    }
1523
1524    function removeExact(array, exactVal) {
1525        var removeCnt = 0;
1526        var i = 0;
1527        while (i < array.length) {
1528            if (array[i] === exactVal) {
1529                array.splice(i, 1);
1530                removeCnt++;
1531            }
1532            else {
1533                i++;
1534            }
1535        }
1536        return removeCnt;
1537    }
1538    function isArraysEqual(a0, a1) {
1539        var len = a0.length;
1540        var i;
1541        if (len !== a1.length) { // not array? or not same length?
1542            return false;
1543        }
1544        for (i = 0; i < len; i++) {
1545            if (a0[i] !== a1[i]) {
1546                return false;
1547            }
1548        }
1549        return true;
1550    }
1551
1552    function memoize(workerFunc) {
1553        var args;
1554        var res;
1555        return function () {
1556            if (!args || !isArraysEqual(args, arguments)) {
1557                args = arguments;
1558                res = workerFunc.apply(this, arguments);
1559            }
1560            return res;
1561        };
1562    }
1563    /*
1564    always executes the workerFunc, but if the result is equal to the previous result,
1565    return the previous result instead.
1566    */
1567    function memoizeOutput(workerFunc, equalityFunc) {
1568        var cachedRes = null;
1569        return function () {
1570            var newRes = workerFunc.apply(this, arguments);
1571            if (cachedRes === null || !(cachedRes === newRes || equalityFunc(cachedRes, newRes))) {
1572                cachedRes = newRes;
1573            }
1574            return cachedRes;
1575        };
1576    }
1577
1578    var EXTENDED_SETTINGS_AND_SEVERITIES = {
1579        week: 3,
1580        separator: 0,
1581        omitZeroMinute: 0,
1582        meridiem: 0,
1583        omitCommas: 0
1584    };
1585    var STANDARD_DATE_PROP_SEVERITIES = {
1586        timeZoneName: 7,
1587        era: 6,
1588        year: 5,
1589        month: 4,
1590        day: 2,
1591        weekday: 2,
1592        hour: 1,
1593        minute: 1,
1594        second: 1
1595    };
1596    var MERIDIEM_RE = /\s*([ap])\.?m\.?/i; // eats up leading spaces too
1597    var COMMA_RE = /,/g; // we need re for globalness
1598    var MULTI_SPACE_RE = /\s+/g;
1599    var LTR_RE = /\u200e/g; // control character
1600    var UTC_RE = /UTC|GMT/;
1601    var NativeFormatter = /** @class */ (function () {
1602        function NativeFormatter(formatSettings) {
1603            var standardDateProps = {};
1604            var extendedSettings = {};
1605            var severity = 0;
1606            for (var name_1 in formatSettings) {
1607                if (name_1 in EXTENDED_SETTINGS_AND_SEVERITIES) {
1608                    extendedSettings[name_1] = formatSettings[name_1];
1609                    severity = Math.max(EXTENDED_SETTINGS_AND_SEVERITIES[name_1], severity);
1610                }
1611                else {
1612                    standardDateProps[name_1] = formatSettings[name_1];
1613                    if (name_1 in STANDARD_DATE_PROP_SEVERITIES) {
1614                        severity = Math.max(STANDARD_DATE_PROP_SEVERITIES[name_1], severity);
1615                    }
1616                }
1617            }
1618            this.standardDateProps = standardDateProps;
1619            this.extendedSettings = extendedSettings;
1620            this.severity = severity;
1621            this.buildFormattingFunc = memoize(buildFormattingFunc);
1622        }
1623        NativeFormatter.prototype.format = function (date, context) {
1624            return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date);
1625        };
1626        NativeFormatter.prototype.formatRange = function (start, end, context) {
1627            var _a = this, standardDateProps = _a.standardDateProps, extendedSettings = _a.extendedSettings;
1628            var diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem);
1629            if (!diffSeverity) {
1630                return this.format(start, context);
1631            }
1632            var biggestUnitForPartial = diffSeverity;
1633            if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time
1634                (standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') &&
1635                (standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') &&
1636                (standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) {
1637                biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time
1638            }
1639            var full0 = this.format(start, context);
1640            var full1 = this.format(end, context);
1641            if (full0 === full1) {
1642                return full0;
1643            }
1644            var partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForParti
1644al);
1645            var partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context);
1646            var partial0 = partialFormattingFunc(start);
1647            var partial1 = partialFormattingFunc(end);
1648            var insertion = findCommonInsertion(full0, partial0, full1, partial1);
1649            var separator = extendedSettings.separator || '';
1650            if (insertion) {
1651                return insertion.before + partial0 + separator + partial1 + insertion.after;
1652            }
1653            return full0 + separator + full1;
1654        };
1655        NativeFormatter.prototype.getLargestUnit = function () {
1656            switch (this.severity) {
1657                case 7:
1658                case 6:
1659                case 5:
1660                    return 'year';
1661                case 4:
1662                    return 'month';
1663                case 3:
1664                    return 'week';
1665                default:
1666                    return 'day';
1667            }
1668        };
1669        return NativeFormatter;
1670    }());
1671    function buildFormattingFunc(standardDateProps, extendedSettings, context) {
1672        var standardDatePropCnt = Object.keys(standardDateProps).length;
1673        if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') {
1674            return function (date) {
1675                return formatTimeZoneOffset(date.timeZoneOffset);
1676            };
1677        }
1678        if (standardDatePropCnt === 0 && extendedSettings.week) {
1679            return function (date) {
1680                return formatWeekNumber(context.computeWeekNumber(date.marker), context.weekLabel, context.locale, extendedSettings.week);
1681            };
1682        }
1683        return buildNativeFormattingFunc(standardDateProps, extendedSettings, context);
1684    }
1685    function buildNativeFormattingFunc(standardDateProps, extendedSettings, context) {
1686        standardDateProps = __assign({}, standardDateProps); // copy
1687        extendedSettings = __assign({}, extendedSettings); // copy
1688        sanitizeSettings(standardDateProps, extendedSettings);
1689        standardDateProps.timeZone = 'UTC'; // we leverage the only guaranteed timeZone for our UTC markers
1690        var normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps);
1691        var zeroFormat; // needed?
1692        if (extendedSettings.omitZeroMinute) {
1693            var zeroProps = __assign({}, standardDateProps);
1694            delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings
1695            zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps);
1696        }
1697        return function (date) {
1698            var marker = date.marker;
1699            var format;
1700            if (zeroFormat && !marker.getUTCMinutes()) {
1701                format = zeroFormat;
1702            }
1703            else {
1704                format = normalFormat;
1705            }
1706            var s = format.format(marker);
1707            return postProcess(s, date, standardDateProps, extendedSettings, context);
1708        };
1709    }
1710    function sanitizeSettings(standardDateProps, extendedSettings) {
1711        // deal with a browser inconsistency where formatting the timezone
1712        // requires that the hour/minute be present.
1713        if (standardDateProps.timeZoneName) {
1714            if (!standardDateProps.hour) {
1715                standardDateProps.hour = '2-digit';
1716            }
1717            if (!standardDateProps.minute) {
1718                standardDateProps.minute = '2-digit';
1719            }
1720        }
1721        // only support short timezone names
1722        if (standardDateProps.timeZoneName === 'long') {
1723            standardDateProps.timeZoneName = 'short';
1724        }
1725        // if requesting to display seconds, MUST display minutes
1726        if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) {
1727            delete extendedSettings.omitZeroMinute;
1728        }
1729    }
1730    function postProcess(s, date, standardDateProps, extendedSettings, context) {
1731        s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes
1732        if (standardDateProps.timeZoneName === 'short') {
1733            s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ?
1734                'UTC' : // important to normalize for IE, which does "GMT"
1735                formatTimeZoneOffset(date.timeZoneOffset));
1736        }
1737        if (extendedSettings.omitCommas) {
1738            s = s.replace(COMMA_RE, '').trim();
1739        }
1740        if (extendedSettings.omitZeroMinute) {
1741            s = s.replace(':00', ''); // zeroFormat doesn't always achieve this
1742        }
1743        // ^ do anything that might create adjacent spaces before this point,
1744        // because MERIDIEM_RE likes to eat up loading spaces
1745        if (extendedSettings.meridiem === false) {
1746            s = s.replace(MERIDIEM_RE, '').trim();
1747        }
1748        else if (extendedSettings.meridiem === 'narrow') { // a/p
1749            s = s.replace(MERIDIEM_RE, function (m0, m1) {
1750                return m1.toLocaleLowerCase();
1751            });
1752        }
1753        else if (extendedSettings.meridiem === 'short') { // am/pm
1754            s = s.replace(MERIDIEM_RE, function (m0, m1) {
1755                return m1.toLocaleLowerCase() + 'm';
1756            });
1757        }
1758        else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase
1759            s = s.replace(MERIDIEM_RE, function (m0) {
1760                return m0.toLocaleLowerCase();
1761            });
1762        }
1763        s = s.replace(MULTI_SPACE_RE, ' ');
1764        s = s.trim();
1765        return s;
1766    }
1767    function injectTzoStr(s, tzoStr) {
1768        var replaced = false;
1769        s = s.replace(UTC_RE, function () {
1770            replaced = true;
1771            return tzoStr;
1772        });
1773        // IE11 doesn't include UTC/GMT in the original string, so append to end
1774        if (!replaced) {
1775            s += ' ' + tzoStr;
1776        }
1777        return s;
1778    }
1779    function formatWeekNumber(num, weekLabel, locale, display) {
1780        var parts = [];
1781        if (display === 'narrow') {
1782            parts.push(weekLabel);
1783        }
1784        else if (display === 'short') {
1785            parts.push(weekLabel, ' ');
1786        }
1787        // otherwise, considered 'numeric'
1788        parts.push(locale.simpleNumberFormat.format(num));
1789        if (locale.options.isRtl) { // TODO: use control characters instead?
1790            parts.reverse();
1791        }
1792        return parts.join('');
1793    }
1794    // Range Formatting Utils
1795    // 0 = exactly the same
1796    // 1 = different by time
1797    // and bigger
1798    function computeMarkerDiffSeverity(d0, d1, ca) {
1799        if (ca.getMarkerYear(d0) !== ca.getMarkerYear(d1)) {
1800            return 5;
1801        }
1802        if (ca.getMarkerMonth(d0) !== ca.getMarkerMonth(d1)) {
1803            return 4;
1804        }
1805        if (ca.getMarkerDay(d0) !== ca.getMarkerDay(d1)) {
1806            return 2;
1807        }
1808        if (timeAsMs(d0) !== timeAsMs(d1)) {
1809            return 1;
1810        }
1811        return 0;
1812    }
1813    function computePartialFormattingOptions(options, biggestUnit) {
1814        var partialOptions = {};
1815        for (var name_2 in options) {
1816            if (!(name_2 in STANDARD_DATE_PROP_SEVERITIES) || // not a date part prop (like timeZone)
1817                STANDARD_DATE_PROP_SEVERITIES[name_2] <= biggestUnit) {
1818                partialOptions[name_2] = options[name_2];
1819            }
1820        }
1821        return partialOptions;
1822    }
1823    function findCommonInsertion(full0, partial0, full1, partial1) {
1824        var i0 = 0;
1825        while (i0 < full0.length) {
1826            var found0 = full0.indexOf(partial0, i0);
1827            if (found0 === -1) {
1828                break;
1829            }
1830            var before0 = full0.substr(0, found0);
1831            i0 = found0 + partial0.length;
1832            var after0 = full0.substr(i0);
1833            var i1 = 0;
1834            while (i1 < full1.length) {
1835                var found1 = full1.indexOf(partial1, i1);
1836                if (found1 === -1) {
1837                    break;
1838                }
1839                var before1 = full1.substr(0, found1);
1840                i1 = found1 + partial1.length;
1841                var after1 = full1.substr(i1);
1842                if (before0 === before1 && after0 === after1) {
1843                    return {
1844                        before: before0,
1845                        after: after0
1846                    };
1847                }
1848            }
1849        }
1850        return null;
1851    }
1852
1853    /*
1854    TODO: fix the terminology of "formatter" vs "formatting func"
1855    */
1856    /*
1857    At the time of instantiation, this object does not know which cmd-formatting system it will use.
1858    It receives this at the time of formatting, as a setting.
1859    */
1860    var CmdFormatter = /** @class */ (function () {
1861        function CmdFormatter(cmdStr, separator) {
1862            this.cmdStr = cmdStr;
1863            this.separator = separator;
1864        }
1865        CmdFormatter.prototype.format = function (date, context) {
1866            return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, this.separator));
1867        };
1868        CmdFormatter.prototype.formatRange = function (start, end, context) {
1869            return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, this.separator));
1870        };
1871        return CmdFormatter;
1872    }());
1873
1874    var FuncFormatter = /** @class */ (function () {
1875        function FuncFormatter(func) {
1876            this.func = func;
1877        }
1878        FuncFormatter.prototype.format = function (date, context) {
1879            return this.func(createVerboseFormattingArg(date, null, context));
1880        };
1881        FuncFormatter.prototype.formatRange = function (start, end, context) {
1882            return this.func(createVerboseFormattingArg(start, end, context));
1883        };
1884        return FuncFormatter;
1885    }());
1886
1887    // Formatter Object Creation
1888    function createFormatter(input, defaultSeparator) {
1889        if (typeof input === 'object' && input) { // non-null object
1890            if (typeof defaultSeparator === 'string') {
1891                input = __assign({ separator: defaultSeparator }, input);
1892            }
1893            return new NativeFormatter(input);
1894        }
1895        else if (typeof input === 'string') {
1896            return new CmdFormatter(input, defaultSeparator);
1897        }
1898        else if (typeof input === 'function') {
1899            return new FuncFormatter(input);
1900        }
1901    }
1902    // String Utils
1903    // timeZoneOffset is in minutes
1904    function buildIsoString(marker, timeZoneOffset, stripZeroTime) {
1905        if (stripZeroTime === void 0) { stripZeroTime = false; }
1906        var s = marker.toISOString();
1907        s = s.replace('.000', '');
1908        if (stripZeroTime) {
1909            s = s.replace('T00:00:00Z', '');
1910        }
1911        if (s.length > 10) { // time part wasn't stripped, can add timezone info
1912            if (timeZoneOffset == null) {
1913                s = s.replace('Z', '');
1914            }
1915            else if (timeZoneOffset !== 0) {
1916                s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true));
1917            }
1918            // otherwise, its UTC-0 and we want to keep the Z
1919        }
1920        return s;
1921    }
1922    function formatIsoTimeString(marker) {
1923        return padStart(marker.getUTCHours(), 2) + ':' +
1924            padStart(marker.getUTCMinutes(), 2) + ':' +
1925            padStart(marker.getUTCSeconds(), 2);
1926    }
1927    function formatTimeZoneOffset(minutes, doIso) {
1928        if (doIso === void 0) { doIso = false; }
1929        var sign = minutes < 0 ? '-' : '+';
1930        var abs = Math.abs(minutes);
1931        var hours = Math.floor(abs / 60);
1932        var mins = Math.round(abs % 60);
1933        if (doIso) {
1934            return sign + padStart(hours, 2) + ':' + padStart(mins, 2);
1935        }
1936        else {
1937            return 'GMT' + sign + hours + (mins ? ':' + padStart(mins, 2) : '');
1938        }
1939    }
1940    // Arg Utils
1941    function createVerboseFormattingArg(start, end, context, separator) {
1942        var startInfo = expandZonedMarker(start, context.calendarSystem);
1943        var endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null;
1944        return {
1945            date: startInfo,
1946            start: startInfo,
1947            end: endInfo,
1948            timeZone: context.timeZone,
1949            localeCodes: context.locale.codes,
1950            separator: separator
1951        };
1952    }
1953    function expandZonedMarker(dateInfo, calendarSystem) {
1954        var a = calendarSystem.markerToArray(dateInfo.marker);
1955        return {
1956            marker: dateInfo.marker,
1957            timeZoneOffset: dateInfo.timeZoneOffset,
1958            array: a,
1959            year: a[0],
1960            month: a[1],
1961            day: a[2],
1962            hour: a[3],
1963            minute: a[4],
1964            second: a[5],
1965            millisecond: a[6]
1966        };
1967    }
1968
1969    var EventSourceApi = /** @class */ (function () {
1970        function EventSourceApi(calendar, internalEventSource) {
1971            this.calendar = calendar;
1972            this.internalEventSource = internalEventSource;
1973        }
1974        EventSourceApi.prototype.remove = function () {
1975            this.calendar.dispatch({
1976                type: 'REMOVE_EVENT_SOURCE',
1977                sourceId: this.internalEventSource.sourceId
1978            });
1979        };
1980        EventSourceApi.prototype.refetch = function () {
1981            this.calendar.dispatch({
1982                type: 'FETCH_EVENT_SOURCES',
1983                sourceIds: [this.internalEventSource.sourceId]
1984            });
1985        };
1986        Object.defineProperty(EventSourceApi.prototype, "id", {
1987            get: function () {
1988                return this.internalEventSource.publicId;
1989            },
1990            enumerable: true,
1991            configurable: true
1992        });
1993        Object.defineProperty(EventSourceApi.prototype, "url", {
1994            // only relevant to json-feed event sources
1995            get: function () {
1996                return this.internalEventSource.meta.url;
1997            },
1998            enumerable: true,
1999            configurable: true
2000        });
2001        return EventSourceApi;
2002    }());
2003
2004    var EventApi = /** @class */ (function () {
2005        function EventApi(calendar, def, instance) {
2006            this._calendar = calendar;
2007            this._def = def;
2008            this._instance = instance || null;
2009        }
2010        /*
2011        TODO: make event struct more responsible for this
2012        */
2013        EventApi.prototype.setProp = function (name, val) {
2014            var _a, _b;
2015            if (name in DATE_PROPS) ;
2016            else if (name in NON_DATE_PROPS) {
2017                if (typeof NON_DATE_PROPS[name] === 'function') {
2018                    val = NON_DATE_PROPS[name](val);
2019                }
2020                this.mutate({
2021                    standardProps: (_a = {}, _a[name] = val, _a)
2022                });
2023            }
2024            else if (name in UNSCOPED_EVENT_UI_PROPS) {
2025                var ui = void 0;
2026                if (typeof UNSCOPED_EVENT_UI_PROPS[name] === 'function') {
2027                    val = UNSCOPED_EVENT_UI_PROPS[name](val);
2028                }
2029                if (name === 'color') {
2030                    ui = { backgroundColor: val, borderColor: val };
2031                }
2032                else if (name === 'editable') {
2033                    ui = { startEditable: val, durationEditable: val };
2034                }
2035                else {
2036                    ui = (_b = {}, _b[name] = val, _b);
2037                }
2038                this.mutate({
2039                    standardProps: { ui: ui }
2040                });
2041            }
2042        };
2043        EventApi.prototype.setExtendedProp = function (name, val) {
2044            var _a;
2045            this.mutate({
2046                extendedProps: (_a = {}, _a[name] = val, _a)
2047            });
2048        };
2049        EventApi.prototype.setStart = function (startInput, options) {
2050            if (options === void 0) { options = {}; }
2051            var dateEnv = this._calendar.dateEnv;
2052            var start = dateEnv.createMarker(startInput);
2053            if (start && this._instance) { // TODO: warning if parsed bad
2054                var instanceRange = this._instance.range;
2055                var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!?
2056                if (options.maintainDuration) {
2057                    this.mutate({ datesDelta: startDelta });
2058                }
2059                else {
2060                    this.mutate({ startDelta: startDelta });
2061                }
2062            }
2063        };
2064        EventApi.prototype.setEnd = function (endInput, options) {
2065            if (options === void 0) { options = {}; }
2066            var dateEnv = this._calendar.dateEnv;
2067            var end;
2068            if (endInput != null) {
2069                end = dateEnv.createMarker(endInput);
2070                if (!end) {
2071                    return; // TODO: warning if parsed bad
2072                }
2073            }
2074            if (this._instance) {
2075                if (end) {
2076                    var endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity);
2077                    this.mutate({ endDelta: endDelta });
2078                }
2079                else {
2080                    this.mutate({ standardProps: { hasEnd: false } });
2081                }
2082            }
2083        };
2084        EventApi.prototype.setDates = function (startInput, endInput, options) {
2085            if (options === void 0) { options = {}; }
2086            var dateEnv = this._calendar.dateEnv;
2087            var standardProps = { allDay: options.allDay };
2088            var start = dateEnv.createMarker(startInput);
2089            var end;
2090            if (!start) {
2091                return; // TODO: warning if parsed bad
2092            }
2093            if (endInput != null) {
2094                end = dateEnv.createMarker(endInput);
2095                if (!end) { // TODO: warning if parsed bad
2096                    return;
2097                }
2098            }
2099            if (this._instance) {
2100                var instanceRange = this._instance.range;
2101                // when computing the diff for an event being converted to all-day,
2102                // compute diff off of the all-day values the way event-mutation does.
2103                if (options.allDay === true) {
2104                    instanceRange = computeAlignedDayRange(instanceRange);
2105                }
2106                var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity);
2107                if (end) {
2108                    var endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity);
2109                    if (durationsEqual(startDelta, endDelta)) {
2110                        this.mutate({ datesDelta: startDelta, standardProps: standardProps });
2111                    }
2112                    else {
2113                        this.mutate({ startDelta: startDelta, endDelta: endDelta, standardProps: standardProps });
2114                    }
2115                }
2116                else { // means "clear the end"
2117                    standardProps.hasEnd = false;
2118                    this.mutate({ datesDelta: startDelta, standardProps: standardProps });
2119                }
2120            }
2121        };
2122        EventApi.prototype.moveStart = function (deltaInput) {
2123            var delta = createDuration(deltaInput);
2124            if (delta) { // TODO: warning if parsed bad
2125                this.mutate({ startDelta: delta });
2126            }
2127        };
2128        EventApi.prototype.moveEnd = function (deltaInput) {
2129            var delta = createDuration(deltaInput);
2130            if (delta) { // TODO: warning if parsed bad
2131                this.mutate({ endDelta: delta });
2132            }
2133        };
2134        EventApi.prototype.moveDates = function (deltaInput) {
2135            var delta = createDuration(deltaInput);
2136            if (delta) { // TODO: warning if parsed bad
2137                this.mutate({ datesDelta: delta });
2138            }
2139        };
2140        EventApi.prototype.setAllDay = function (allDay, options) {
2141            if (options === void 0) { options = {}; }
2142            var standardProps = { allDay: allDay };
2143            var maintainDuration = options.maintainDuration;
2144            if (maintainDuration == null) {
2145                maintainDuration = this._calendar.opt('allDayMaintainDuration');
2146            }
2147            if (this._def.allDay !== allDay) {
2148                standardProps.hasEnd = maintainDuration;
2149            }
2150            this.mutate({ standardProps: standardProps });
2151        };
2152        EventApi.prototype.formatRange = function (formatInput) {
2153            var dateEnv = this._calendar.dateEnv;
2154            var instance = this._instance;
2155            var formatter = createFormatter(formatInput, this._calendar.opt('defaultRangeSeparator'));
2156            if (this._def.hasEnd) {
2157                return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, {
2158                    forcedStartTzo: instance.forcedStartTzo,
2159                    forcedEndTzo: instance.forcedEndTzo
2160                });
2161            }
2162            else {
2163                return dateEnv.format(instance.range.start, formatter, {
2164                    forcedTzo: instance.forcedStartTzo
2165                });
2166            }
2167        };
2168        EventApi.prototype.mutate = function (mutation) {
2169            var def = this._def;
2170            var instance = this._instance;
2171            if (instance) {
2172                this._calendar.dispatch({
2173                    type: 'MUTATE_EVENTS',
2174                    instanceId: instance.instanceId,
2175                    mutation: mutation,
2176                    fromApi: true
2177                });
2178                var eventStore = this._calendar.state.eventStore;
2179                this._def = eventStore.defs[def.defId];
2180                this._instance = eventStore.instances[instance.instanceId];
2181            }
2182        };
2183        EventApi.prototype.remove = function () {
2184            this._calendar.dispatch({
2185                type: 'REMOVE_EVENT_DEF',
2186                defId: this._def.defId
2187            });
2188        };
2189        Object.defineProperty(EventApi.prototype, "source", {
2190            get: function () {
2191                var sourceId = this._def.sourceId;
2192                if (sourceId) {
2193                    return new EventSourceApi(this._calendar, this._calendar.state.eventSources[sourceId]);
2194                }
2195                return null;
2196            },
2197            enumerable: true,
2198            configurable: true
2199        });
2200        Object.defineProperty(EventApi.prototype, "start", {
2201            get: function () {
2202                return this._instance ?
2203                    this._calendar.dateEnv.toDate(this._instance.range.start) :
2204                    null;
2205            },
2206            enumerable: true,
2207            configurable: true
2208        });
2209        Object.defineProperty(EventApi.prototype, "end", {
2210            get: function () {
2211                return (this._instance && this._def.hasEnd) ?
2212                    this._calendar.dateEnv.toDate(this._instance.range.end) :
2213                    null;
2214            },
2215            enumerable: true,
2216            configurable: true
2217        });
2218        Object.defineProperty(EventApi.prototype, "id", {
2219            // computable props that all access the def
2220            // TODO: find a TypeScript-compatible way to do this at scale
2221            get: function () { return this._def.publicId; },
2222            enumerable: true,
2223            configurable: true
2224        });
2225        Object.defineProperty(EventApi.prototype, "groupId", {
2226            get: function () { return this._def.groupId; },
2227            enumerable: true,
2228            configurable: true
2229        });
2230        Object.defineProperty(EventApi.prototype, "allDay", {
2231            get: function () { return this._def.allDay; },
2232            enumerable: true,
2233            configurable: true
2234        });
2235        Object.defineProperty(EventApi.prototype, "title", {
2236            get: function () { return this._def.title; },
2237            enumerable: true,
2238            configurable: true
2239        });
2240        Object.defineProperty(EventApi.prototype, "url", {
2241            get: function () { return this._def.url; },
2242            enumerable: true,
2243            configurable: true
2244        });
2245        Object.defineProperty(EventApi.prototype, "rendering", {
2246            get: function () { return this._def.rendering; },
2247            enumerable: true,
2248            configurable: true
2249        });
2250        Object.defineProperty(EventApi.prototype, "startEditable", {
2251            get: function () { return this._def.ui.startEditable; },
2252            enumerable: true,
2253            configurable: true
2254        });
2255        Object.defineProperty(EventApi.prototype, "durationEditable", {
2256            get: function () { return this._def.ui.durationEditable; },
2257            enumerable: true,
2258            configurable: true
2259        });
2260        Object.defineProperty(EventApi.prototype, "constraint", {
2261            get: function () { return this._def.ui.constraints[0] || null; },
2262            enumerable: true,
2263            configurable: true
2264        });
2265        Object.defineProperty(EventApi.prototype, "overlap", {
2266            get: function () { return this._def.ui.overlap; },
2267            enumerable: true,
2268            configurable: true
2269        });
2270        Object.defineProperty(EventApi.prototype, "allow", {
2271            get: function () { return this._def.ui.allows[0] || null; },
2272            enumerable: true,
2273            configurable: true
2274        });
2275        Object.defineProperty(EventApi.prototype, "backgroundColor", {
2276            get: function () { return this._def.ui.backgroundColor; },
2277            enumerable: true,
2278            configurable: true
2279        });
2280        Object.defineProperty(EventApi.prototype, "borderColor", {
2281            get: function () { return this._def.ui.borderColor; },
2282            enumerable: true,
2283            configurable: true
2284        });
2285        Object.defineProperty(EventApi.prototype, "textColor", {
2286            get: function () { return this._def.ui.textColor; },
2287            enumerable: true,
2288            configurable: true
2289        });
2290        Object.defineProperty(EventApi.prototype, "classNames", {
2291            // NOTE: user can't modify these because Object.freeze was called in event-def parsing
2292            get: function () { return this._def.ui.classNames; },
2293            enumerable: true,
2294            configurable: true
2295        });
2296        Object.defineProperty(EventApi.prototype, "extendedProps", {
2297            get: function () { return this._def.extendedProps; },
2298            enumerable: true,
2299            configurable: true
2300        });
2301        return EventApi;
2302    }());
2303
2304    /*
2305    Specifying nextDayThreshold signals that all-day ranges should be sliced.
2306    */
2307    function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) {
2308        var inverseBgByGroupId = {};
2309        var inverseBgByDefId = {};
2310        var defByGroupId = {};
2311        var bgRanges = [];
2312        var fgRanges = [];
2313        var eventUis = compileEventUis(eventStore.defs, eventUiBases);
2314        for (var defId in eventStore.defs) {
2315            var def = eventStore.defs[defId];
2316            if (def.rendering === 'inverse-background') {
2317                if (def.groupId) {
2318                    inverseBgByGroupId[def.groupId] = [];
2319                    if (!defByGroupId[def.groupId]) {
2320                        defByGroupId[def.groupId] = def;
2321                    }
2322                }
2323                else {
2324                    inverseBgByDefId[defId] = [];
2325                }
2326            }
2327        }
2328        for (var instanceId in eventStore.instances) {
2329            var instance = eventStore.instances[instanceId];
2330            var def = eventStore.defs[instance.defId];
2331            var ui = eventUis[def.defId];
2332            var origRange = instance.range;
2333            var normalRange = (!def.allDay && nextDayThreshold) ?
2334                computeVisibleDayRange(origRange, nextDayThreshold) :
2335                origRange;
2336            var slicedRange = intersectRanges(normalRange, framingRange);
2337            if (slicedRange) {
2338                if (def.rendering === 'inverse-background') {
2339                    if (def.groupId) {
2340                        inverseBgByGroupId[def.groupId].push(slicedRange);
2341                    }
2342                    else {
2343                        inverseBgByDefId[instance.defId].push(slicedRange);
2344                    }
2345                }
2346                else {
2347                    (def.rendering === 'background' ? bgRanges : fgRanges).push({
2348                        def: def,
2349                        ui: ui,
2350                        instance: instance,
2351                        range: slicedRange,
2352                        isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(),
2353                        isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf()
2354                    });
2355                }
2356            }
2357        }
2358        for (var groupId in inverseBgByGroupId) { // BY GROUP
2359            var ranges = inverseBgByGroupId[groupId];
2360            var invertedRanges = invertRanges(ranges, framingRange);
2361            for (var _i = 0, invertedRanges_1 = invertedRanges; _i < invertedRanges_1.length; _i++) {
2362                var invertedRange = invertedRanges_1[_i];
2363                var def = defByGroupId[groupId];
2364                var ui = eventUis[def.defId];
2365                bgRanges.push({
2366                    def: def,
2367                    ui: ui,
2368                    instance: null,
2369                    range: invertedRange,
2370                    isStart: false,
2371                    isEnd: false
2372                });
2373            }
2374        }
2375        for (var defId in inverseBgByDefId) {
2376            var ranges = inverseBgByDefId[defId];
2377            var invertedRanges = invertRanges(ranges, framingRange);
2378            for (var _a = 0, invertedRanges_2 = invertedRanges; _a < invertedRanges_2.length; _a++) {
2379                var invertedRange = invertedRanges_2[_a];
2380                bgRanges.push({
2381                    def: eventStore.defs[defId],
2382                    ui: eventUis[defId],
2383                    instance: null,
2384                    range: invertedRange,
2385                    isStart: false,
2386                    isEnd: false
2387                });
2388            }
2389        }
2390        return { bg: bgRanges, fg: fgRanges };
2391    }
2392    function hasBgRendering(def) {
2393        return def.rendering === 'background' || def.rendering === 'inverse-background';
2394    }
2395    function filterSegsViaEls(view, segs, isMirror) {
2396        if (view.hasPublicHandlers('eventRender')) {
2397            segs = segs.filter(function (seg) {
2398                var custom = view.publiclyTrigger('eventRender', [
2399                    {
2400                        event: new EventApi(view.calendar, seg.eventRange.def, seg.eventRange.instance),
2401                        isMirror: isMirror,
2402                        isStart: seg.isStart,
2403                        isEnd: seg.isEnd,
2404                        // TODO: include seg.range once all components consistently generate it
2405                        el: seg.el,
2406                        view: view
2407                    }
2408                ]);
2409                if (custom === false) { // means don't render at all
2410                    return false;
2411                }
2412                else if (custom && custom !== true) {
2413                    seg.el = custom;
2414                }
2415                return true;
2416            });
2417        }
2418        for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
2419            var seg = segs_1[_i];
2420            setElSeg(seg.el, seg);
2421        }
2422        return segs;
2423    }
2424    function setElSeg(el, seg) {
2425        el.fcSeg = seg;
2426    }
2427    function getElSeg(el) {
2428        return el.fcSeg || null;
2429    }
2430    // event ui computation
2431    function compileEventUis(eventDefs, eventUiBases) {
2432        return mapHash(eventDefs, function (eventDef) {
2433            return compileEventUi(eventDef, eventUiBases);
2434        });
2435    }
2436    function compileEventUi(eventDef, eventUiBases) {
2437        var uis = [];
2438        if (eventUiBases['']) {
2439            uis.push(eventUiBases['']);
2440        }
2441        if (eventUiBases[eventDef.defId]) {
2442            uis.push(eventUiBases[eventDef.defId]);
2443        }
2444        uis.push(eventDef.ui);
2445        return combineEventUis(uis);
2446    }
2447
2448    // applies the mutation to ALL defs/instances within the event store
2449    function applyMutationToEventStore(eventStore, eventConfigBase, mutation, calendar) {
2450        var eventConfigs = compileEventUis(eventStore.defs, eventConfigBase);
2451        var dest = createEmptyEventStore();
2452        for (var defId in eventStore.defs) {
2453            var def = eventStore.defs[defId];
2454            dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, calendar.pluginSystem.hooks.eventDefMutationAppliers, calendar);
2455        }
2456        for (var instanceId in eventStore.instances) {
2457            var instance = eventStore.instances[instanceId];
2458            var def = dest.defs[instance.defId]; // important to grab the newly modified def
2459            dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, calendar);
2460        }
2461        return dest;
2462    }
2463    function applyMutationToEventDef(eventDef, eventConfig, mutation, appliers, calendar) {
2464        var standardProps = mutation.standardProps || {};
2465        // if hasEnd has not been specified, guess a good value based on deltas.
2466        // if duration will change, there's no way the default duration will persist,
2467        // and thus, we need to mark the event as having a real end
2468        if (standardProps.hasEnd == null &&
2469            eventConfig.durationEditable &&
2470            (mutation.startDelta || mutation.endDelta)) {
2471            standardProps.hasEnd = true; // TODO: is this mutation okay?
2472        }
2473        var copy = __assign({}, eventDef, standardProps, { ui: __assign({}, eventDef.ui, standardProps.ui) });
2474        if (mutation.extendedProps) {
2475            copy.extendedProps = __assign({}, copy.extendedProps, mutation.extendedProps);
2476        }
2477        for (var _i = 0, appliers_1 = appliers; _i < appliers_1.length; _i++) {
2478            var applier = appliers_1[_i];
2479            applier(copy, mutation, calendar);
2480        }
2481        if (!copy.hasEnd && calendar.opt('forceEventDuration')) {
2482            copy.hasEnd = true;
2483        }
2484        return copy;
2485    }
2486    function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef
2487    eventConfig, mutation, calendar) {
2488        var dateEnv = calendar.dateEnv;
2489        var forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true;
2490        var clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false;
2491        var copy = __assign({}, eventInstance);
2492        if (forceAllDay) {
2493            copy.range = computeAlignedDayRange(copy.range);
2494        }
2495        if (mutation.datesDelta && eventConfig.startEditable) {
2496            copy.range = {
2497                start: dateEnv.add(copy.range.start, mutation.datesDelta),
2498                end: dateEnv.add(copy.range.end, mutation.datesDelta)
2499            };
2500        }
2501        if (mutation.startDelta && eventConfig.durationEditable) {
2502            copy.range = {
2503                start: dateEnv.add(copy.range.start, mutation.startDelta),
2504                end: copy.range.end
2505            };
2506        }
2507        if (mutation.endDelta && eventConfig.durationEditable) {
2508            copy.range = {
2509                start: copy.range.start,
2510                end: dateEnv.add(copy.range.end, mutation.endDelta)
2511            };
2512        }
2513        if (clearEnd) {
2514            copy.range = {
2515                start: copy.range.start,
2516                end: calendar.getDefaultEventEnd(eventDef.allDay, copy.range.start)
2517            };
2518        }
2519        // in case event was all-day but the supplied deltas were not
2520        // better util for this?
2521        if (eventDef.allDay) {
2522            copy.range = {
2523                start: startOfDay(copy.range.start),
2524                end: startOfDay(copy.range.end)
2525            };
2526        }
2527        // handle invalid durations
2528        if (copy.range.end < copy.range.start) {
2529            copy.range.end = calendar.getDefaultEventEnd(eventDef.allDay, copy.range.start);
2530        }
2531        return copy;
2532    }
2533
2534    function reduceEventStore (eventStore, action, eventSources, dateProfile, calendar) {
2535        switch (action.type) {
2536            case 'RECEIVE_EVENTS': // raw
2537                return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, calendar);
2538            case 'ADD_EVENTS': // already parsed, but not expanded
2539                return addEvent(eventStore, action.eventStore, // new ones
2540                dateProfile ? dateProfile.activeRange : null, calendar);
2541            case 'MERGE_EVENTS': // already parsed and expanded
2542                return mergeEventStores(eventStore, action.eventStore);
2543            case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
2544            case 'NEXT':
2545            case 'SET_DATE':
2546            case 'SET_VIEW_TYPE':
2547                if (dateProfile) {
2548                    return expandRecurring(eventStore, dateProfile.activeRange, calendar);
2549                }
2550                else {
2551                    return eventStore;
2552                }
2553            case 'CHANGE_TIMEZONE':
2554                return rezoneDates(eventStore, action.oldDateEnv, calendar.dateEnv);
2555            case 'MUTATE_EVENTS':
2556                return applyMutationToRelated(eventStore, action.instanceId, action.mutation, action.fromApi, calendar);
2557            case 'REMOVE_EVENT_INSTANCES':
2558                return excludeInstances(eventStore, action.instances);
2559            case 'REMOVE_EVENT_DEF':
2560                return filterEventStoreDefs(eventStore, function (eventDef) {
2561                    return eventDef.defId !== action.defId;
2562                });
2563            case 'REMOVE_EVENT_SOURCE':
2564                return excludeEventsBySourceId(eventStore, action.sourceId);
2565            case 'REMOVE_ALL_EVENT_SOURCES':
2566                return filterEventStoreDefs(eventStore, function (eventDef) {
2567                    return !eventDef.sourceId; // only keep events with no source id
2568                });
2569            case 'REMOVE_ALL_EVENTS':
2570                return createEmptyEventStore();
2571            case 'RESET_EVENTS':
2572                return {
2573                    defs: eventStore.defs,
2574                    instances: eventStore.instances
2575                };
2576            default:
2577                return eventStore;
2578        }
2579    }
2580    function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, calendar) {
2581        if (eventSource && // not already removed
2582            fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources
2583        ) {
2584            var subset = parseEvents(transformRawEvents(rawEvents, eventSource, calendar), eventSource.sourceId, calendar);
2585            if (fetchRange) {
2586                subset = expandRecurring(subset, fetchRange, calendar);
2587            }
2588            return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset);
2589        }
2590        return eventStore;
2591    }
2592    function addEvent(eventStore, subset, expandRange, calendar) {
2593        if (expandRange) {
2594            subset = expandRecurring(subset, expandRange, calendar);
2595        }
2596        return mergeEventStores(eventStore, subset);
2597    }
2598    function rezoneDates(eventStore, oldDateEnv, newDateEnv) {
2599        var defs = eventStore.defs;
2600        var instances = mapHash(eventStore.instances, function (instance) {
2601            var def = defs[instance.defId];
2602            if (def.allDay || def.recurringDef) {
2603                return instance; // isn't dependent on timezone
2604            }
2605            else {
2606                return __assign({}, instance, { range: {
2607                        start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)),
2608                        end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo))
2609                    }, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo });
2610            }
2611        });
2612        return { defs: defs, instances: instances };
2613    }
2614    function applyMutationToRelated(eventStore, instanceId, mutation, fromApi, calendar) {
2615        var relevant = getRelevantEvents(eventStore, instanceId);
2616        var eventConfigBase = fromApi ?
2617            { '': {
2618                    startEditable: true,
2619                    durationEditable: true,
2620                    constraints: [],
2621                    overlap: null,
2622                    allows: [],
2623                    backgroundColor: '',
2624                    borderColor: '',
2625                    textColor: '',
2626                    classNames: []
2627                } } :
2628            calendar.eventUiBases;
2629        relevant = applyMutationToEventStore(relevant, eventConfigBase, mutation, calendar);
2630        return mergeEventStores(eventStore, relevant);
2631    }
2632    function excludeEventsBySourceId(eventStore, sourceId) {
2633        return filterEventStoreDefs(eventStore, function (eventDef) {
2634            return eventDef.sourceId !== sourceId;
2635        });
2636    }
2637    // QUESTION: why not just return instances? do a general object-property-exclusion util
2638    function excludeInstances(eventStore, removals) {
2639        return {
2640            defs: eventStore.defs,
2641            instances: filterHash(eventStore.instances, function (instance) {
2642                return !removals[instance.instanceId];
2643            })
2644        };
2645    }
2646
2647    // high-level segmenting-aware tester functions
2648    // ------------------------------------------------------------------------------------------------------------------------
2649    function isInteractionValid(interaction, calendar) {
2650        return isNewPropsValid({ eventDrag: interaction }, calendar); // HACK: the eventDrag props is used for ALL interactions
2651    }
2652    function isDateSelectionValid(dateSelection, calendar) {
2653        return isNewPropsValid({ dateSelection: dateSelection }, calendar);
2654    }
2655    function isNewPropsValid(newProps, calendar) {
2656        var view = calendar.view;
2657        var props = __assign({ businessHours: view ? view.props.businessHours : createEmptyEventStore(), dateSelection: '', eventStore: calendar.state.eventStore, eventUiBases: calendar.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps);
2658        return (calendar.pluginSystem.hooks.isPropsValid || isPropsValid)(props, calendar);
2659    }
2660    function isPropsValid(state, calendar, dateSpanMeta, filterConfig) {
2661        if (dateSpanMeta === void 0) { dateSpanMeta = {}; }
2662        if (state.eventDrag && !isInteractionPropsValid(state, calendar, dateSpanMeta, filterConfig)) {
2663            return false;
2664        }
2665        if (state.dateSelection && !isDateSelectionPropsValid(state, calendar, dateSpanMeta, filterConfig)) {
2666            return false;
2667        }
2668        return true;
2669    }
2670    // Moving Event Validation
2671    // ------------------------------------------------------------------------------------------------------------------------
2672    function isInteractionPropsValid(state, calendar, dateSpanMeta, filterConfig) {
2673        var interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions
2674        var subjectEventStore = interaction.mutatedEvents;
2675        var subjectDefs = subjectEventStore.defs;
2676        var subjectInstances = subjectEventStore.instances;
2677        var subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ?
2678            state.eventUiBases :
2679            { '': calendar.selectionConfig } // if not a real event, validate as a selection
2680        );
2681        if (filterConfig) {
2682            subjectConfigs = mapHash(subjectConfigs, filterConfig);
2683        }
2684        var otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances); // exclude the subject events. TODO: exclude defs too?
2685        var otherDefs = otherEventStore.defs;
2686        var otherInstances = otherEventStore.instances;
2687        var otherConfigs = compileEventUis(otherDefs, state.eventUiBases);
2688        for (var subjectInstanceId in subjectInstances) {
2689            var subjectInstance = subjectInstances[subjectInstanceId];
2690            var subjectRange = subjectInstance.range;
2691            var subjectConfig = subjectConfigs[subjectInstance.defId];
2692            var subjectDef = subjectDefs[subjectInstance.defId];
2693            // constraint
2694            if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, calendar)) {
2695                return false;
2696            }
2697            // overlap
2698            var overlapFunc = calendar.opt('eventOverlap');
2699            if (typeof overlapFunc !== 'function') {
2700                overlapFunc = null;
2701            }
2702            for (var otherInstanceId in otherInstances) {
2703                var otherInstance = otherInstances[otherInstanceId];
2704                // intersect! evaluate
2705                if (rangesIntersect(subjectRange, otherInstance.range)) {
2706                    var otherOverlap = otherConfigs[otherInstance.defId].overlap;
2707                    // consider the other event's overlap. only do this if the subject event is a "real" event
2708                    if (otherOverlap === false && interaction.isEvent) {
2709                        return false;
2710                    }
2711                    if (subjectConfig.overlap === false) {
2712                        return false;
2713                    }
2714                    if (overlapFunc && !overlapFunc(new EventApi(calendar, otherDefs[otherInstance.defId], otherInstance), // still event
2715                    new EventApi(calendar, subjectDef, subjectInstance) // moving event
2716                    )) {
2717                        return false;
2718                    }
2719                }
2720            }
2721            // allow (a function)
2722            var calendarEventStore = calendar.state.eventStore; // need global-to-calendar, not local to component (splittable)state
2723            for (var _i = 0, _a = subjectConfig.allows; _i < _a.length; _i++) {
2724                var subjectAllow = _a[_i];
2725                var subjectDateSpan = __assign({}, dateSpanMeta, { range: subjectInstance.range, allDay: subjectDef.allDay });
2726                var origDef = calendarEventStore.defs[subjectDef.defId];
2727                var origInstance = calendarEventStore.instances[subjectInstanceId];
2728                var eventApi = void 0;
2729                if (origDef) { // was previously in the calendar
2730                    eventApi = new EventApi(calendar, origDef, origInstance);
2731                }
2732                else { // was an external event
2733                    eventApi = new EventApi(calendar, subjectDef); // no instance, because had no dates
2734                }
2735                if (!subjectAllow(calendar.buildDateSpanApi(subjectDateSpan), eventApi)) {
2736                    return false;
2737                }
2738            }
2739        }
2740        return true;
2741    }
2742    // Date Selection Validation
2743    // ------------------------------------------------------------------------------------------------------------------------
2744    function isDateSelectionPropsValid(state, calendar, dateSpanMeta, filterConfig) {
2745        var relevantEventStore = state.eventStore;
2746        var relevantDefs = relevantEventStore.defs;
2747        var relevantInstances = relevantEventStore.instances;
2748        var selection = state.dateSelection;
2749        var selectionRange = selection.range;
2750        var selectionConfig = calendar.selectionConfig;
2751        if (filterConfig) {
2752            selectionConfig = filterConfig(selectionConfig);
2753        }
2754        // constraint
2755        if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, calendar)) {
2756            return false;
2757        }
2758        // overlap
2759        var overlapFunc = calendar.opt('selectOverlap');
2760        if (typeof overlapFunc !== 'function') {
2761            overlapFunc = null;
2762        }
2763        for (var relevantInstanceId in relevantInstances) {
2764            var relevantInstance = relevantInstances[relevantInstanceId];
2765            // intersect! evaluate
2766            if (rangesIntersect(selectionRange, relevantInstance.range)) {
2767                if (selectionConfig.overlap === false) {
2768                    return false;
2769                }
2770                if (overlapFunc && !overlapFunc(new EventApi(calendar, relevantDefs[relevantInstance.defId], relevantInstance))) {
2771                    return false;
2772                }
2773            }
2774        }
2775        // allow (a function)
2776        for (var _i = 0, _a = selectionConfig.allows; _i < _a.length; _i++) {
2777            var selectionAllow = _a[_i];
2778            var fullDateSpan = __assign({}, dateSpanMeta, selection);
2779            if (!selectionAllow(calendar.buildDateSpanApi(fullDateSpan), null)) {
2780                return false;
2781            }
2782        }
2783        return true;
2784    }
2785    // Constraint Utils
2786    // ------------------------------------------------------------------------------------------------------------------------
2787    function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, calendar) {
2788        for (var _i = 0, constraints_1 = constraints; _i < constraints_1.length; _i++) {
2789            var constraint = constraints_1[_i];
2790            if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, calendar), subjectRange)) {
2791                return false;
2792            }
2793        }
2794        return true;
2795    }
2796    function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours
2797    otherEventStore, // for if constraint is an even group ID
2798    businessHoursUnexpanded, // for if constraint is 'businessHours'
2799    calendar // for expanding businesshours
2800    ) {
2801        if (constraint === 'businessHours') {
2802            return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, calendar));
2803        }
2804        else if (typeof constraint === 'string') { // an group ID
2805            return eventStoreToRanges(filterEventStoreDefs(otherEventStore, function (eventDef) {
2806                return eventDef.groupId === constraint;
2807            }));
2808        }
2809        else if (typeof constraint === 'object' && constraint) { // non-null object
2810            return eventStoreToRanges(expandRecurring(constraint, subjectRange, calendar));
2811        }
2812        return []; // if it's false
2813    }
2814    // TODO: move to event-store file?
2815    function eventStoreToRanges(eventStore) {
2816        var instances = eventStore.instances;
2817        var ranges = [];
2818        for (var instanceId in instances) {
2819            ranges.push(instances[instanceId].range);
2820        }
2821        return ranges;
2822    }
2823    // TODO: move to geom file?
2824    function anyRangesContainRange(outerRanges, innerRange) {
2825        for (var _i = 0, outerRanges_1 = outerRanges; _i < outerRanges_1.length; _i++) {
2826            var outerRange = outerRanges_1[_i];
2827            if (rangeContainsRange(outerRange, innerRange)) {
2828                return true;
2829            }
2830        }
2831        return false;
2832    }
2833    // Parsing
2834    // ------------------------------------------------------------------------------------------------------------------------
2835    function normalizeConstraint(input, calendar) {
2836        if (Array.isArray(input)) {
2837            return parseEvents(input, '', calendar, true); // allowOpenRange=true
2838        }
2839        else if (typeof input === 'object' && input) { // non-null object
2840            return parseEvents([input], '', calendar, true); // allowOpenRange=true
2841        }
2842        else if (input != null) {
2843            return String(input);
2844        }
2845        else {
2846            return null;
2847        }
2848    }
2849
2850    function htmlEscape(s) {
2851        return (s + '').replace(/&/g, '&amp;')
2852            .replace(/</g, '&lt;')
2853            .replace(/>/g, '&gt;')
2854            .replace(/'/g, '&#039;')
2855            .replace(/"/g, '&quot;')
2856            .replace(/\n/g, '<br />');
2857    }
2858    // Given a hash of CSS properties, returns a string of CSS.
2859    // Uses property names as-is (no camel-case conversion). Will not make statements for null/undefined values.
2860    function cssToStr(cssProps) {
2861        var statements = [];
2862        for (var name_1 in cssProps) {
2863            var val = cssProps[name_1];
2864            if (val != null && val !== '') {
2865                statements.push(name_1 + ':' + val);
2866            }
2867        }
2868        return statements.join(';');
2869    }
2870    // Given an object hash of HTML attribute names to values,
2871    // generates a string that can be injected between < > in HTML
2872    function attrsToStr(attrs) {
2873        var parts = [];
2874        for (var name_2 in attrs) {
2875            var val = attrs[name_2];
2876            if (val != null) {
2877                parts.push(name_2 + '="' + htmlEscape(val) + '"');
2878            }
2879        }
2880        return parts.join(' ');
2881    }
2882    function parseClassName(raw) {
2883        if (Array.isArray(raw)) {
2884            return raw;
2885        }
2886        else if (typeof raw === 'string') {
2887            return raw.split(/\s+/);
2888        }
2889        else {
2890            return [];
2891        }
2892    }
2893
2894    var UNSCOPED_EVENT_UI_PROPS = {
2895        editable: Boolean,
2896        startEditable: Boolean,
2897        durationEditable: Boolean,
2898        constraint: null,
2899        overlap: null,
2900        allow: null,
2901        className: parseClassName,
2902        classNames: parseClassName,
2903        color: String,
2904        backgroundColor: String,
2905        borderColor: String,
2906        textColor: String
2907    };
2908    function processUnscopedUiProps(rawProps, calendar, leftovers) {
2909        var props = refineProps(rawProps, UNSCOPED_EVENT_UI_PROPS, {}, leftovers);
2910        var constraint = normalizeConstraint(props.constraint, calendar);
2911        return {
2912            startEditable: props.startEditable != null ? props.startEditable : props.editable,
2913            durationEditable: props.durationEditable != null ? props.durationEditable : props.editable,
2914            constraints: constraint != null ? [constraint] : [],
2915            overlap: props.overlap,
2916            allows: props.allow != null ? [props.allow] : [],
2917            backgroundColor: props.backgroundColor || props.color,
2918            borderColor: props.borderColor || props.color,
2919            textColor: props.textColor,
2920            classNames: props.classNames.concat(props.className)
2921        };
2922    }
2923    function processScopedUiProps(prefix, rawScoped, calendar, leftovers) {
2924        var rawUnscoped = {};
2925        var wasFound = {};
2926        for (var key in UNSCOPED_EVENT_UI_PROPS) {
2927            var scopedKey = prefix + capitaliseFirstLetter(key);
2928            rawUnscoped[key] = rawScoped[scopedKey];
2929            wasFound[scopedKey] = true;
2930        }
2931        if (prefix === 'event') {
2932            rawUnscoped.editable = rawScoped.editable; // special case. there is no 'eventEditable', just 'editable'
2933        }
2934        if (leftovers) {
2935            for (var key in rawScoped) {
2936                if (!wasFound[key]) {
2937                    leftovers[key] = rawScoped[key];
2938                }
2939            }
2940        }
2941        return processUnscopedUiProps(rawUnscoped, calendar);
2942    }
2943    var EMPTY_EVENT_UI = {
2944        startEditable: null,
2945        durationEditable: null,
2946        constraints: [],
2947        overlap: null,
2948        allows: [],
2949        backgroundColor: '',
2950        borderColor: '',
2951        textColor: '',
2952        classNames: []
2953    };
2954    // prevent against problems with <2 args!
2955    function combineEventUis(uis) {
2956        return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI);
2957    }
2958    function combineTwoEventUis(item0, item1) {
2959        return {
2960            startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable,
2961            durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable,
2962            constraints: item0.constraints.concat(item1.constraints),
2963            overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap,
2964            allows: item0.allows.concat(item1.allows),
2965            backgroundColor: item1.backgroundColor || item0.backgroundColor,
2966            borderColor: item1.borderColor || item0.borderColor,
2967            textColor: item1.textColor || item0.textColor,
2968            classNames: item0.classNames.concat(item1.classNames)
2969        };
2970    }
2971
2972    var NON_DATE_PROPS = {
2973        id: String,
2974        groupId: String,
2975        title: String,
2976        url: String,
2977        rendering: String,
2978        extendedProps: null
2979    };
2980    var DATE_PROPS = {
2981        start: null,
2982        date: null,
2983        end: null,
2984        allDay: null
2985    };
2986    var uid = 0;
2987    function parseEvent(raw, sourceId, calendar, allowOpenRange) {
2988        var allDayDefault = computeIsAllDayDefault(sourceId, calendar);
2989        var leftovers0 = {};
2990        var recurringRes = parseRecurring(raw, // raw, but with single-event stuff stripped out
2991        allDayDefault, calendar.dateEnv, calendar.pluginSystem.hooks.recurringTypes, leftovers0 // will populate with non-recurring props
2992        );
2993        if (recurringRes) {
2994            var def = parseEventDef(leftovers0, sourceId, recurringRes.allDay, Boolean(recurringRes.duration), calendar);
2995            def.recurringDef = {
2996                typeId: recurringRes.typeId,
2997                typeData: recurringRes.typeData,
2998                duration: recurringRes.duration
2999            };
3000            return { def: def, instance: null };
3001        }
3002        else {
3003            var leftovers1 = {};
3004            var singleRes = parseSingle(raw, allDayDefault, calendar, leftovers1, allowOpenRange);
3005            if (singleRes) {
3006                var def = parseEventDef(leftovers1, sourceId, singleRes.allDay, singleRes.hasEnd, calendar);
3007                var instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo);
3008                return { def: def, instance: instance };
3009            }
3010        }
3011        return null;
3012    }
3013    /*
3014    Will NOT populate extendedProps with the leftover properties.
3015    Will NOT populate date-related props.
3016    The EventNonDateInput has been normalized (id => publicId, etc).
3017    */
3018    function parseEventDef(raw, sourceId, allDay, hasEnd, calendar) {
3019        var leftovers = {};
3020        var def = pluckNonDateProps(raw, calendar, leftovers);
3021        def.defId = String(uid++);
3022        def.sourceId = sourceId;
3023        def.allDay = allDay;
3024        def.hasEnd = hasEnd;
3025        for (var _i = 0, _a = calendar.pluginSystem.hooks.eventDefParsers; _i < _a.length; _i++) {
3026            var eventDefParser = _a[_i];
3027            var newLeftovers = {};
3028            eventDefParser(def, leftovers, newLeftovers);
3029            leftovers = newLeftovers;
3030        }
3031        def.extendedProps = __assign(leftovers, def.extendedProps || {});
3032        // help out EventApi from having user modify props
3033        Object.freeze(def.ui.classNames);
3034        Object.freeze(def.extendedProps);
3035        return def;
3036    }
3037    function createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) {
3038        return {
3039            instanceId: String(uid++),
3040            defId: defId,
3041            range: range,
3042            forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo,
3043            forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo
3044        };
3045    }
3046    function parseSingle(raw, allDayDefault, calendar, leftovers, allowOpenRange) {
3047        var props = pluckDateProps(raw, leftovers);
3048        var allDay = props.allDay;
3049        var startMeta;
3050        var startMarker = null;
3051        var hasEnd = false;
3052        var endMeta;
3053        var endMarker = null;
3054        startMeta = calendar.dateEnv.createMarkerMeta(props.start);
3055        if (startMeta) {
3056            startMarker = startMeta.marker;
3057        }
3058        else if (!allowOpenRange) {
3059            return null;
3060        }
3061        if (props.end != null) {
3062            endMeta = calendar.dateEnv.createMarkerMeta(props.end);
3063        }
3064        if (allDay == null) {
3065            if (allDayDefault != null) {
3066                allDay = allDayDefault;
3067            }
3068            else {
3069                // fall back to the date props LAST
3070                allDay = (!startMeta || startMeta.isTimeUnspecified) &&
3071                    (!endMeta || endMeta.isTimeUnspecified);
3072            }
3073        }
3074        if (allDay && startMarker) {
3075            startMarker = startOfDay(startMarker);
3076        }
3077        if (endMeta) {
3078            endMarker = endMeta.marker;
3079            if (allDay) {
3080                endMarker = startOfDay(endMarker);
3081            }
3082            if (startMarker && endMarker <= startMarker) {
3083                endMarker = null;
3084            }
3085        }
3086        if (endMarker) {
3087            hasEnd = true;
3088        }
3089        else if (!allowOpenRange) {
3090            hasEnd = calendar.opt('forceEventDuration') || false;
3091            endMarker = calendar.dateEnv.add(startMarker, allDay ?
3092                calendar.defaultAllDayEventDuration :
3093                calendar.defaultTimedEventDuration);
3094        }
3095        return {
3096            allDay: allDay,
3097            hasEnd: hasEnd,
3098            range: { start: startMarker, end: endMarker },
3099            forcedStartTzo: startMeta ? startMeta.forcedTzo : null,
3100            forcedEndTzo: endMeta ? endMeta.forcedTzo : null
3101        };
3102    }
3103    function pluckDateProps(raw, leftovers) {
3104        var props = refineProps(raw, DATE_PROPS, {}, leftovers);
3105        props.start = (props.start !== null) ? props.start : props.date;
3106        delete props.date;
3107        return props;
3108    }
3109    function pluckNonDateProps(raw, calendar, leftovers) {
3110        var preLeftovers = {};
3111        var props = refineProps(raw, NON_DATE_PROPS, {}, preLeftovers);
3112        var ui = processUnscopedUiProps(preLeftovers, calendar, leftovers);
3113        props.publicId = props.id;
3114        delete props.id;
3115        props.ui = ui;
3116        return props;
3117    }
3118    function computeIsAllDayDefault(sourceId, calendar) {
3119        var res = null;
3120        if (sourceId) {
3121            var source = calendar.state.eventSources[sourceId];
3122            res = source.allDayDefault;
3123        }
3124        if (res == null) {
3125            res = calendar.opt('allDayDefault');
3126        }
3127        return res;
3128    }
3129
3130    var DEF_DEFAULTS = {
3131        startTime: '09:00',
3132        endTime: '17:00',
3133        daysOfWeek: [1, 2, 3, 4, 5],
3134        rendering: 'inverse-background',
3135        classNames: 'fc-nonbusiness',
3136        groupId: '_businessHours' // so multiple defs get grouped
3137    };
3138    /*
3139    TODO: pass around as EventDefHash!!!
3140    */
3141    function parseBusinessHours(input, calendar) {
3142        return parseEvents(refineInputs(input), '', calendar);
3143    }
3144    function refineInputs(input) {
3145        var rawDefs;
3146        if (input === true) {
3147            rawDefs = [{}]; // will get DEF_DEFAULTS verbatim
3148        }
3149        else if (Array.isArray(input)) {
3150            // if specifying an array, every sub-definition NEEDS a day-of-week
3151            rawDefs = input.filter(function (rawDef) {
3152                return rawDef.daysOfWeek;
3153            });
3154        }
3155        else if (typeof input === 'object' && input) { // non-null object
3156            rawDefs = [input];
3157        }
3158        else { // is probably false
3159            rawDefs = [];
3160        }
3161        rawDefs = rawDefs.map(function (rawDef) {
3162            return __assign({}, DEF_DEFAULTS, rawDef);
3163        });
3164        return rawDefs;
3165    }
3166
3167    function memoizeRendering(renderFunc, unrenderFunc, dependencies) {
3168        if (dependencies === void 0) { dependencies = []; }
3169        var dependents = [];
3170        var thisContext;
3171        var prevArgs;
3172        function unrender() {
3173            if (prevArgs) {
3174                for (var _i = 0, dependents_1 = dependents; _i < dependents_1.length; _i++) {
3175                    var dependent = dependents_1[_i];
3176                    dependent.unrender();
3177                }
3178                if (unrenderFunc) {
3179                    unrenderFunc.apply(thisContext, prevArgs);
3180                }
3181                prevArgs = null;
3182            }
3183        }
3184        function res() {
3185            if (!prevArgs || !isArraysEqual(prevArgs, arguments)) {
3186                unrender();
3187                thisContext = this;
3188                prevArgs = arguments;
3189                renderFunc.apply(this, arguments);
3190            }
3191        }
3192        res.dependents = dependents;
3193        res.unrender = unrender;
3194        for (var _i = 0, dependencies_1 = dependencies; _i < dependencies_1.length; _i++) {
3195            var dependency = dependencies_1[_i];
3196            dependency.dependents.push(res);
3197        }
3198        return res;
3199    }
3200
3201    var EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere
3202    var Splitter = /** @class */ (function () {
3203        function Splitter() {
3204            this.getKeysForEventDefs = memoize(this._getKeysForEventDefs);
3205            this.splitDateSelection = memoize(this._splitDateSpan);
3206            this.splitEventStore = memoize(this._splitEventStore);
3207            this.splitIndividualUi = memoize(this._splitIndividualUi);
3208            this.splitEventDrag = memoize(this._splitInteraction);
3209            this.splitEventResize = memoize(this._splitInteraction);
3210            this.eventUiBuilders = {}; // TODO: typescript protection
3211        }
3212        Splitter.prototype.splitProps = function (props) {
3213            var _this = this;
3214            var keyInfos = this.getKeyInfo(props);
3215            var defKeys = this.getKeysForEventDefs(props.eventStore);
3216            var dateSelections = this.splitDateSelection(props.dateSelection);
3217            var individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases*
3218            var eventStores = this.splitEventStore(props.eventStore, defKeys);
3219            var eventDrags = this.splitEventDrag(props.eventDrag);
3220            var eventResizes = this.splitEventResize(props.eventResize);
3221            var splitProps = {};
3222            this.eventUiBuilders = mapHash(keyInfos, function (info, key) {
3223                return _this.eventUiBuilders[key] || memoize(buildEventUiForKey);
3224            });
3225            for (var key in keyInfos) {
3226                var keyInfo = keyInfos[key];
3227                var eventStore = eventStores[key] || EMPTY_EVENT_STORE;
3228                var buildEventUi = this.eventUiBuilders[key];
3229                splitProps[key] = {
3230                    businessHours: keyInfo.businessHours || props.businessHours,
3231                    dateSelection: dateSelections[key] || null,
3232                    eventStore: eventStore,
3233                    eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]),
3234                    eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '',
3235                    eventDrag: eventDrags[key] || null,
3236                    eventResize: eventResizes[key] || null
3237                };
3238            }
3239            return splitProps;
3240        };
3241        Splitter.prototype._splitDateSpan = function (dateSpan) {
3242            var dateSpans = {};
3243            if (dateSpan) {
3244                var keys = this.getKeysForDateSpan(dateSpan);
3245                for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
3246                    var key = keys_1[_i];
3247                    dateSpans[key] = dateSpan;
3248                }
3249            }
3250            return dateSpans;
3251        };
3252        Splitter.prototype._getKeysForEventDefs = function (eventStore) {
3253            var _this = this;
3254            return mapHash(eventStore.defs, function (eventDef) {
3255                return _this.getKeysForEventDef(eventDef);
3256            });
3257        };
3258        Splitter.prototype._splitEventStore = function (eventStore, defKeys) {
3259            var defs = eventStore.defs, instances = eventStore.instances;
3260            var splitStores = {};
3261            for (var defId in defs) {
3262                for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) {
3263                    var key = _a[_i];
3264                    if (!splitStores[key]) {
3265                        splitStores[key] = createEmptyEventStore();
3266                    }
3267                    splitStores[key].defs[defId] = defs[defId];
3268                }
3269            }
3270            for (var instanceId in instances) {
3271                var instance = instances[instanceId];
3272                for (var _b = 0, _c = defKeys[instance.defId]; _b < _c.length; _b++) {
3273                    var key = _c[_b];
3274                    if (splitStores[key]) { // must have already been created
3275                        splitStores[key].instances[instanceId] = instance;
3276                    }
3277                }
3278            }
3279            return splitStores;
3280        };
3281        Splitter.prototype._splitIndividualUi = function (eventUiBases, defKeys) {
3282            var splitHashes = {};
3283            for (var defId in eventUiBases) {
3284                if (defId) { // not the '' key
3285                    for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) {
3286                        var key = _a[_i];
3287                        if (!splitHashes[key]) {
3288                            splitHashes[key] = {};
3289                        }
3290                        splitHashes[key][defId] = eventUiBases[defId];
3291                    }
3292                }
3293            }
3294            return splitHashes;
3295        };
3296        Splitter.prototype._splitInteraction = function (interaction) {
3297            var splitStates = {};
3298            if (interaction) {
3299                var affectedStores_1 = this._splitEventStore(interaction.affectedEvents, this._getKeysForEventDefs(interaction.affectedEvents) // can't use cached. might be events from other calendar
3300                );
3301                // can't rely on defKeys because event data is mutated
3302                var mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents);
3303                var mutatedStores_1 = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId);
3304                var populate = function (key) {
3305                    if (!splitStates[key]) {
3306                        splitStates[key] = {
3307                            affectedEvents: affectedStores_1[key] || EMPTY_EVENT_STORE,
3308                            mutatedEvents: mutatedStores_1[key] || EMPTY_EVENT_STORE,
3309                            isEvent: interaction.isEvent,
3310                            origSeg: interaction.origSeg
3311                        };
3312                    }
3313                };
3314                for (var key in affectedStores_1) {
3315                    populate(key);
3316                }
3317                for (var key in mutatedStores_1) {
3318                    populate(key);
3319                }
3320            }
3321            return splitStates;
3322        };
3323        return Splitter;
3324    }());
3325    function buildEventUiForKey(allUi, eventUiForKey, individualUi) {
3326        var baseParts = [];
3327        if (allUi) {
3328            baseParts.push(allUi);
3329        }
3330        if (eventUiForKey) {
3331            baseParts.push(eventUiForKey);
3332        }
3333        var stuff = {
3334            '': combineEventUis(baseParts)
3335        };
3336        if (individualUi) {
3337            __assign(stuff, individualUi);
3338        }
3339        return stuff;
3340    }
3341
3342    // Generates HTML for an anchor to another view into the calendar.
3343    // Will either generate an <a> tag or a non-clickable <span> tag, depending on enabled settings.
3344    // `gotoOptions` can either be a DateMarker, or an object with the form:
3345    // { date, type, forceOff }
3346    // `type` is a view-type like "day" or "week". default value is "day".
3347    // `attrs` and `innerHtml` are use to generate the rest of the HTML tag.
3348    function buildGotoAnchorHtml(component, gotoOptions, attrs, innerHtml) {
3349        var dateEnv = component.dateEnv;
3350        var date;
3351        var type;
3352        var forceOff;
3353        var finalOptions;
3354        if (gotoOptions instanceof Date) {
3355            date = gotoOptions; // a single date-like input
3356        }
3357        else {
3358            date = gotoOptions.date;
3359            type = gotoOptions.type;
3360            forceOff = gotoOptions.forceOff;
3361        }
3362        finalOptions = {
3363            date: dateEnv.formatIso(date, { omitTime: true }),
3364            type: type || 'day'
3365        };
3366        if (typeof attrs === 'string') {
3367            innerHtml = attrs;
3368            attrs = null;
3369        }
3370        attrs = attrs ? ' ' + attrsToStr(attrs) : ''; // will have a leading space
3371        innerHtml = innerHtml || '';
3372        if (!forceOff && component.opt('navLinks')) {
3373            return '<a' + attrs +
3374                ' data-goto="' + htmlEscape(JSON.stringify(finalOptions)) + '">' +
3375                innerHtml +
3376                '</a>';
3377        }
3378        else {
3379            return '<span' + attrs + '>' +
3380                innerHtml +
3381                '</span>';
3382        }
3383    }
3384    function getAllDayHtml(component) {
3385        return component.opt('allDayHtml') || htmlEscape(component.opt('allDayText'));
3386    }
3387    // Computes HTML classNames for a single-day element
3388    function getDayClasses(date, dateProfile, context, noThemeHighlight) {
3389        var calendar = context.calendar, view = context.view, theme = context.theme, dateEnv = context.dateEnv;
3390        var classes = [];
3391        var todayStart;
3392        var todayEnd;
3393        if (!rangeContainsMarker(dateProfile.activeRange, date)) {
3394            classes.push('fc-disabled-day');
3395        }
3396        else {
3397            classes.push('fc-' + DAY_IDS[date.getUTCDay()]);
3398            if (view.opt('monthMode') &&
3399                dateEnv.getMonth(date) !== dateEnv.getMonth(dateProfile.currentRange.start)) {
3400                classes.push('fc-other-month');
3401            }
3402            todayStart = startOfDay(calendar.getNow());
3403            todayEnd = addDays(todayStart, 1);
3404            if (date < todayStart) {
3405                classes.push('fc-past');
3406            }
3407            else if (date >= todayEnd) {
3408                classes.push('fc-future');
3409            }
3410            else {
3411                classes.push('fc-today');
3412                if (noThemeHighlight !== true) {
3413                    classes.push(theme.getClass('today'));
3414                }
3415            }
3416        }
3417        return classes;
3418    }
3419
3420    // given a function that resolves a result asynchronously.
3421    // the function can either call passed-in success and failure callbacks,
3422    // or it can return a promise.
3423    // if you need to pass additional params to func, bind them first.
3424    function unpromisify(func, success, failure) {
3425        // guard against success/failure callbacks being called more than once
3426        // and guard against a promise AND callback being used together.
3427        var isResolved = false;
3428        var wrappedSuccess = function () {
3429            if (!isResolved) {
3430                isResolved = true;
3431                success.apply(this, arguments);
3432            }
3433        };
3434        var wrappedFailure = function () {
3435            if (!isResolved) {
3436                isResolved = true;
3437                if (failure) {
3438                    failure.apply(this, arguments);
3439                }
3440            }
3441        };
3442        var res = func(wrappedSuccess, wrappedFailure);
3443        if (res && typeof res.then === 'function') {
3444            res.then(wrappedSuccess, wrappedFailure);
3445        }
3446    }
3447
3448    var Mixin = /** @class */ (function () {
3449        function Mixin() {
3450        }
3451        // mix into a CLASS
3452        Mixin.mixInto = function (destClass) {
3453            this.mixIntoObj(destClass.prototype);
3454        };
3455        // mix into ANY object
3456        Mixin.mixIntoObj = function (destObj) {
3457            var _this = this;
3458            Object.getOwnPropertyNames(this.prototype).forEach(function (name) {
3459                if (!destObj[name]) { // if destination doesn't already define it
3460                    destObj[name] = _this.prototype[name];
3461                }
3462            });
3463        };
3464        /*
3465        will override existing methods
3466        TODO: remove! not used anymore
3467        */
3468        Mixin.mixOver = function (destClass) {
3469            var _this = this;
3470            Object.getOwnPropertyNames(this.prototype).forEach(function (name) {
3471                destClass.prototype[name] = _this.prototype[name];
3472            });
3473        };
3474        return Mixin;
3475    }());
3476
3477    /*
3478    USAGE:
3479      import { default as EmitterMixin, EmitterInterface } from './EmitterMixin'
3480    in class:
3481      on: EmitterInterface['on']
3482      one: EmitterInterface['one']
3483      off: EmitterInterface['off']
3484      trigger: EmitterInterface['trigger']
3485      triggerWith: EmitterInterface['triggerWith']
3486      hasHandlers: EmitterInterface['hasHandlers']
3487    after class:
3488      EmitterMixin.mixInto(TheClass)
3489    */
3490    var EmitterMixin = /** @class */ (function (_super) {
3491        __extends(EmitterMixin, _super);
3492        function EmitterMixin() {
3493            return _super !== null && _super.apply(this, arguments) || this;
3494        }
3495        EmitterMixin.prototype.on = function (type, handler) {
3496            addToHash(this._handlers || (this._handlers = {}), type, handler);
3497            return this; // for chaining
3498        };
3499        // todo: add comments
3500        EmitterMixin.prototype.one = function (type, handler) {
3501            addToHash(this._oneHandlers || (this._oneHandlers = {}), type, handler);
3502            return this; // for chaining
3503        };
3504        EmitterMixin.prototype.off = function (type, handler) {
3505            if (this._handlers) {
3506                removeFromHash(this._handlers, type, handler);
3507            }
3508            if (this._oneHandlers) {
3509                removeFromHash(this._oneHandlers, type, handler);
3510            }
3511            return this; // for chaining
3512        };
3513        EmitterMixin.prototype.trigger = function (type) {
3514            var args = [];
3515            for (var _i = 1; _i < arguments.length; _i++) {
3516                args[_i - 1] = arguments[_i];
3517            }
3518            this.triggerWith(type, this, args);
3519            return this; // for chaining
3520        };
3521        EmitterMixin.prototype.triggerWith = function (type, context, args) {
3522            if (this._handlers) {
3523                applyAll(this._handlers[type], context, args);
3524            }
3525            if (this._oneHandlers) {
3526                applyAll(this._oneHandlers[type], context, args);
3527                delete this._oneHandlers[type]; // will never fire again
3528            }
3529            return this; // for chaining
3530        };
3531        EmitterMixin.prototype.hasHandlers = function (type) {
3532            return (this._handlers && this._handlers[type] && this._handlers[type].length) ||
3533                (this._oneHandlers && this._oneHandlers[type] && this._oneHandlers[type].length);
3534        };
3535        return EmitterMixin;
3536    }(Mixin));
3537    function addToHash(hash, type, handler) {
3538        (hash[type] || (hash[type] = []))
3539            .push(handler);
3540    }
3541    function removeFromHash(hash, type, handler) {
3542        if (handler) {
3543            if (hash[type]) {
3544                hash[type] = hash[type].filter(function (func) {
3545                    return func !== handler;
3546                });
3547            }
3548        }
3549        else {
3550            delete hash[type]; // remove all handler funcs for this type
3551        }
3552    }
3553
3554    /*
3555    Records offset information for a set of elements, relative to an origin element.
3556    Can record the left/right OR the top/bottom OR both.
3557    Provides methods for querying the cache by position.
3558    */
3559    var PositionCache = /** @class */ (function () {
3560        function PositionCache(originEl, els, isHorizontal, isVertical) {
3561            this.originEl = originEl;
3562            this.els = els;
3563            this.isHorizontal = isHorizontal;
3564            this.isVertical = isVertical;
3565        }
3566        // Queries the els for coordinates and stores them.
3567        // Call this method before using and of the get* methods below.
3568        PositionCache.prototype.build = function () {
3569            var originEl = this.originEl;
3570            var originClientRect = this.originClientRect =
3571                originEl.getBoundingClientRect(); // relative to viewport top-left
3572            if (this.isHorizontal) {
3573                this.buildElHorizontals(originClientRect.left);
3574            }
3575            if (this.isVertical) {
3576                this.buildElVerticals(originClientRect.top);
3577            }
3578        };
3579        // Populates the left/right internal coordinate arrays
3580        PositionCache.prototype.buildElHorizontals = function (originClientLeft) {
3581            var lefts = [];
3582            var rights = [];
3583            for (var _i = 0, _a = this.els; _i < _a.length; _i++) {
3584                var el = _a[_i];
3585                var rect = el.getBoundingClientRect();
3586                lefts.push(rect.left - originClientLeft);
3587                rights.push(rect.right - originClientLeft);
3588            }
3589            this.lefts = lefts;
3590            this.rights = rights;
3591        };
3592        // Populates the top/bottom internal coordinate arrays
3593        PositionCache.prototype.buildElVerticals = function (originClientTop) {
3594            var tops = [];
3595            var bottoms = [];
3596            for (var _i = 0, _a = this.els; _i < _a.length; _i++) {
3597                var el = _a[_i];
3598                var rect = el.getBoundingClientRect();
3599                tops.push(rect.top - originClientTop);
3600                bottoms.push(rect.bottom - originClientTop);
3601            }
3602            this.tops = tops;
3603            this.bottoms = bottoms;
3604        };
3605        // Given a left offset (from document left), returns the index of the el that it horizontally intersects.
3606        // If no intersection is made, returns undefined.
3607        PositionCache.prototype.leftToIndex = function (leftPosition) {
3608            var lefts = this.lefts;
3609            var rights = this.rights;
3610            var len = lefts.length;
3611            var i;
3612            for (i = 0; i < len; i++) {
3613                if (leftPosition >= lefts[i] && leftPosition < rights[i]) {
3614                    return i;
3615                }
3616            }
3617        };
3618        // Given a top offset (from document top), returns the index of the el that it vertically intersects.
3619        // If no intersection is made, returns undefined.
3620        PositionCache.prototype.topToIndex = function (topPosition) {
3621            var tops = this.tops;
3622            var bottoms = this.bottoms;
3623            var len = tops.length;
3624            var i;
3625            for (i = 0; i < len; i++) {
3626                if (topPosition >= tops[i] && topPosition < bottoms[i]) {
3627                    return i;
3628                }
3629            }
3630        };
3631        // Gets the width of the element at the given index
3632        PositionCache.prototype.getWidth = function (leftIndex) {
3633            return this.rights[leftIndex] - this.lefts[leftIndex];
3634        };
3635        // Gets the height of the element at the given index
3636        PositionCache.prototype.getHeight = function (topIndex) {
3637            return this.bottoms[topIndex] - this.tops[topIndex];
3638        };
3639        return PositionCache;
3640    }());
3641
3642    /*
3643    An object for getting/setting scroll-related information for an element.
3644    Internally, this is done very differently for window versus DOM element,
3645    so this object serves as a common interface.
3646    */
3647    var ScrollController = /** @class */ (function () {
3648        function ScrollController() {
3649        }
3650        ScrollController.prototype.getMaxScrollTop = function () {
3651            return this.getScrollHeight() - this.getClientHeight();
3652        };
3653        ScrollController.prototype.getMaxScrollLeft = function () {
3654            return this.getScrollWidth() - this.getClientWidth();
3655        };
3656        ScrollController.prototype.canScrollVertically = function () {
3657            return this.getMaxScrollTop() > 0;
3658        };
3659        ScrollController.prototype.canScrollHorizontally = function () {
3660            return this.getMaxScrollLeft() > 0;
3661        };
3662        ScrollController.prototype.canScrollUp = function () {
3663            return this.getScrollTop() > 0;
3664        };
3665        ScrollController.prototype.canScrollDown = function () {
3666            return this.getScrollTop() < this.getMaxScrollTop();
3667        };
3668        ScrollController.prototype.canScrollLeft = function () {
3669            return this.getScrollLeft() > 0;
3670        };
3671        ScrollController.prototype.canScrollRight = function () {
3672            return this.getScrollLeft() < this.getMaxScrollLeft();
3673        };
3674        return ScrollController;
3675    }());
3676    var ElementScrollController = /** @class */ (function (_super) {
3677        __extends(ElementScrollController, _super);
3678        function ElementScrollController(el) {
3679            var _this = _super.call(this) || this;
3680            _this.el = el;
3681            return _this;
3682        }
3683        ElementScrollController.prototype.getScrollTop = function () {
3684            return this.el.scrollTop;
3685        };
3686        ElementScrollController.prototype.getScrollLeft = function () {
3687            return this.el.scrollLeft;
3688        };
3689        ElementScrollController.prototype.setScrollTop = function (top) {
3690            this.el.scrollTop = top;
3691        };
3692        ElementScrollController.prototype.setScrollLeft = function (left) {
3693            this.el.scrollLeft = left;
3694        };
3695        ElementScrollController.prototype.getScrollWidth = function () {
3696            return this.el.scrollWidth;
3697        };
3698        ElementScrollController.prototype.getScrollHeight = function () {
3699            return this.el.scrollHeight;
3700        };
3701        ElementScrollController.prototype.getClientHeight = function () {
3702            return this.el.clientHeight;
3703        };
3704        ElementScrollController.prototype.getClientWidth = function () {
3705            return this.el.clientWidth;
3706        };
3707        return ElementScrollController;
3708    }(ScrollController));
3709    var WindowScrollController = /** @class */ (function (_super) {
3710        __extends(WindowScrollController, _super);
3711        function WindowScrollController() {
3712            return _super !== null && _super.apply(this, arguments) || this;
3713        }
3714        WindowScrollController.prototype.getScrollTop = function () {
3715            return window.pageYOffset;
3716        };
3717        WindowScrollController.prototype.getScrollLeft = function () {
3718            return window.pageXOffset;
3719        };
3720        WindowScrollController.prototype.setScrollTop = function (n) {
3721            window.scroll(window.pageXOffset, n);
3722        };
3723        WindowScrollController.prototype.setScrollLeft = function (n) {
3724            window.scroll(n, window.pageYOffset);
3725        };
3726        WindowScrollController.prototype.getScrollWidth = function () {
3727            return document.documentElement.scrollWidth;
3728        };
3729        WindowScrollController.prototype.getScrollHeight = function () {
3730            return document.documentElement.scrollHeight;
3731        };
3732        WindowScrollController.prototype.getClientHeight = function () {
3733            return document.documentElement.clientHeight;
3734        };
3735        WindowScrollController.prototype.getClientWidth = function () {
3736            return document.documentElement.clientWidth;
3737        };
3738        return WindowScrollController;
3739    }(ScrollController));
3740
3741    /*
3742    Embodies a div that has potential scrollbars
3743    */
3744    var ScrollComponent = /** @class */ (function (_super) {
3745        __extends(ScrollComponent, _super);
3746        function ScrollComponent(overflowX, overflowY) {
3747            var _this = _super.call(this, createElement('div', {
3748                className: 'fc-scroller'
3749            })) || this;
3750            _this.overflowX = overflowX;
3751            _this.overflowY = overflowY;
3752            _this.applyOverflow();
3753            return _this;
3754        }
3755        // sets to natural height, unlocks overflow
3756        ScrollComponent.prototype.clear = function () {
3757            this.setHeight('auto');
3758            this.applyOverflow();
3759        };
3760        ScrollComponent.prototype.destroy = function () {
3761            removeElement(this.el);
3762        };
3763        // Overflow
3764        // -----------------------------------------------------------------------------------------------------------------
3765        ScrollComponent.prototype.applyOverflow = function () {
3766            applyStyle(this.el, {
3767                overflowX: this.overflowX,
3768                overflowY: this.overflowY
3769            });
3770        };
3771        // Causes any 'auto' overflow values to resolves to 'scroll' or 'hidden'.
3772        // Useful for preserving scrollbar widths regardless of future resizes.
3773        // Can pass in scrollbarWidths for optimization.
3774        ScrollComponent.prototype.lockOverflow = function (scrollbarWidths) {
3775            var overflowX = this.overflowX;
3776            var overflowY = this.overflowY;
3777            scrollbarWidths = scrollbarWidths || this.getScrollbarWidths();
3778            if (overflowX === 'auto') {
3779                overflowX = (scrollbarWidths.bottom || // horizontal scrollbars?
3780                    this.canScrollHorizontally() // OR scrolling pane with massless scrollbars?
3781                ) ? 'scroll' : 'hidden';
3782            }
3783            if (overflowY === 'auto') {
3784                overflowY = (scrollbarWidths.left || scrollbarWidths.right || // horizontal scrollbars?
3785                    this.canScrollVertically() // OR scrolling pane with massless scrollbars?
3786                ) ? 'scroll' : 'hidden';
3787            }
3788            applyStyle(this.el, { overflowX: overflowX, overflowY: overflowY });
3789        };
3790        ScrollComponent.prototype.setHeight = function (height) {
3791            applyStyleProp(this.el, 'height', height);
3792        };
3793        ScrollComponent.prototype.getScrollbarWidths = function () {
3794            var edges = computeEdges(this.el);
3795            return {
3796                left: edges.scrollbarLeft,
3797                right: edges.scrollbarRight,
3798                bottom: edges.scrollbarBottom
3799            };
3800        };
3801        return ScrollComponent;
3802    }(ElementScrollController));
3803
3804    var Theme = /** @class */ (function () {
3805        function Theme(calendarOptions) {
3806            this.calendarOptions = calendarOptions;
3807            this.processIconOverride();
3808        }
3809        Theme.prototype.processIconOverride = function () {
3810            if (this.iconOverrideOption) {
3811                this.setIconOverride(this.calendarOptions[this.iconOverrideOption]);
3812            }
3813        };
3814        Theme.prototype.setIconOverride = function (iconOverrideHash) {
3815            var iconClassesCopy;
3816            var buttonName;
3817            if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object
3818                iconClassesCopy = __assign({}, this.iconClasses);
3819                for (buttonName in iconOverrideHash) {
3820                    iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]);
3821                }
3822                this.iconClasses = iconClassesCopy;
3823            }
3824            else if (iconOverrideHash === false) {
3825                this.iconClasses = {};
3826            }
3827        };
3828        Theme.prototype.applyIconOverridePrefix = function (className) {
3829            var prefix = this.iconOverridePrefix;
3830            if (prefix && className.indexOf(prefix) !== 0) { // if not already present
3831                className = prefix + className;
3832            }
3833            return className;
3834        };
3835        Theme.prototype.getClass = function (key) {
3836            return this.classes[key] || '';
3837        };
3838        Theme.prototype.getIconClass = function (buttonName) {
3839            var className = this.iconClasses[buttonName];
3840            if (className) {
3841                return this.baseIconClass + ' ' + className;
3842            }
3843            return '';
3844        };
3845        Theme.prototype.getCustomButtonIconClass = function (customButtonProps) {
3846            var className;
3847            if (this.iconOverrideCustomButtonOption) {
3848                className = customButtonProps[this.iconOverrideCustomButtonOption];
3849                if (className) {
3850                    return this.baseIconClass + ' ' + this.applyIconOverridePrefix(className);
3851                }
3852            }
3853            return '';
3854        };
3855        return Theme;
3856    }());
3857    Theme.prototype.classes = {};
3858    Theme.prototype.iconClasses = {};
3859    Theme.prototype.baseIconClass = '';
3860    Theme.prototype.iconOverridePrefix = '';
3861
3862    var guid = 0;
3863    var Component = /** @class */ (function () {
3864        function Component(context, isView) {
3865            // HACK to populate view at top of component instantiation call chain
3866            if (isView) {
3867                context.view = this;
3868            }
3869            this.uid = String(guid++);
3870            this.context = context;
3871            this.dateEnv = context.dateEnv;
3872            this.theme = context.theme;
3873            this.view = context.view;
3874            this.calendar = context.calendar;
3875            this.isRtl = this.opt('dir') === 'rtl';
3876        }
3877        Component.addEqualityFuncs = function (newFuncs) {
3878            this.prototype.equalityFuncs = __assign({}, this.prototype.equalityFuncs, newFuncs);
3879        };
3880        Component.prototype.opt = function (name) {
3881            return this.context.options[name];
3882        };
3883        Component.prototype.receiveProps = function (props) {
3884            var _a = recycleProps(this.props || {}, props, this.equalityFuncs), anyChanges = _a.anyChanges, comboProps = _a.comboProps;
3885            this.props = comboProps;
3886            if (anyChanges) {
3887                this.render(comboProps);
3888            }
3889        };
3890        Component.prototype.render = function (props) {
3891        };
3892        // after destroy is called, this component won't ever be used again
3893        Component.prototype.destroy = function () {
3894        };
3895        return Component;
3896    }());
3897    Component.prototype.equalityFuncs = {};
3898    /*
3899    Reuses old values when equal. If anything is unequal, returns newProps as-is.
3900    Great for PureComponent, but won't be feasible with React, so just eliminate and use React's DOM diffing.
3901    */
3902    function recycleProps(oldProps, newProps, equalityFuncs) {
3903        var comboProps = {}; // some old, some new
3904        var anyChanges = false;
3905        for (var key in newProps) {
3906            if (key in oldProps && (oldProps[key] === newProps[key] ||
3907                (equalityFuncs[key] && equalityFuncs[key](oldProps[key], newProps[key])))) {
3908                // equal to old? use old prop
3909                comboProps[key] = oldProps[key];
3910            }
3911            else {
3912                comboProps[key] = newProps[key];
3913                anyChanges = true;
3914            }
3915        }
3916        for (var key in oldProps) {
3917            if (!(key in newProps)) {
3918                anyChanges = true;
3919                break;
3920            }
3921        }
3922        return { anyChanges: anyChanges, comboProps: comboProps };
3923    }
3924
3925    /*
3926    PURPOSES:
3927    - hook up to fg, fill, and mirror renderers
3928    - interface for dragging and hits
3929    */
3930    var DateComponent = /** @class */ (function (_super) {
3931        __extends(DateComponent, _super);
3932        function DateComponent(context, el, isView) {
3933            var _this = _super.call(this, context, isView) || this;
3934            _this.el = el;
3935            return _this;
3936        }
3937        DateComponent.prototype.destroy = function () {
3938            _super.prototype.destroy.call(this);
3939            removeElement(this.el);
3940        };
3941        // TODO: WHAT ABOUT (sourceSeg && sourceSeg.component.doesDragMirror)
3942        //
3943        // Event Drag-n-Drop Rendering (for both events and external elements)
3944        // ---------------------------------------------------------------------------------------------------------------
3945        /*
3946        renderEventDragSegs(state: EventSegUiInteractionState) {
3947          if (state) {
3948            let { isEvent, segs, sourceSeg } = state
3949      
3950            if (this.eventRenderer) {
3951              this.eventRenderer.hideByHash(state.affectedInstances)
3952            }
3953      
3954            // if the user is dragging something that is considered an event with real event data,
3955            // and this component likes to do drag mirrors OR the component where the seg came from
3956            // likes to do drag mirrors, then render a drag mirror.
3957            if (isEvent && (this.doesDragMirror || sourceSeg && sourceSeg.component.doesDragMirror)) {
3958              if (this.mirrorRenderer) {
3959                this.mirrorRenderer.renderSegs(segs, { isDragging: true, sourceSeg })
3960              }
3961            }
3962      
3963            // if it would be impossible to render a drag mirror OR this component likes to render
3964            // highlights, then render a highlight.
3965            if (!isEvent || this.doesDragHighlight) {
3966              if (this.fillRenderer) {
3967                this.fillRenderer.renderSegs('highlight', segs)
3968              }
3969            }
3970          }
3971        }
3972        */
3973        // Hit System
3974        // -----------------------------------------------------------------------------------------------------------------
3975        DateComponent.prototype.buildPositionCaches = function () {
3976        };
3977        DateComponent.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) {
3978            return null; // this should be abstract
3979        };
3980        // Validation
3981        // -----------------------------------------------------------------------------------------------------------------
3982        DateComponent.prototype.isInteractionValid = function (interaction) {
3983            var calendar = this.calendar;
3984            var dateProfile = this.props.dateProfile; // HACK
3985            var instances = interaction.mutatedEvents.instances;
3986            if (dateProfile) { // HACK for DayTile
3987                for (var instanceId in instances) {
3988                    if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) {
3989                        return false;
3990                    }
3991                }
3992            }
3993            return isInteractionValid(interaction, calendar);
3994        };
3995        DateComponent.prototype.isDateSelectionValid = function (selection) {
3996            var dateProfile = this.props.dateProfile; // HACK
3997            if (dateProfile && // HACK for DayTile
3998                !rangeContainsRange(dateProfile.validRange, selection.range)) {
3999                return false;
4000            }
4001            return isDateSelectionValid(selection, this.calendar);
4002        };
4003        // Triggering
4004        // -----------------------------------------------------------------------------------------------------------------
4005        // TODO: move to Calendar
4006        DateComponent.prototype.publiclyTrigger = function (name, args) {
4007            var calendar = this.calendar;
4008            return calendar.publiclyTrigger(name, args);
4009        };
4010        DateComponent.prototype.publiclyTriggerAfterSizing = function (name, args) {
4011            var calendar = this.calendar;
4012            return calendar.publiclyTriggerAfterSizing(name, args);
4013        };
4014        DateComponent.prototype.hasPublicHandlers = function (name) {
4015            var calendar = this.calendar;
4016            return calendar.hasPublicHandlers(name);
4017        };
4018        DateComponent.prototype.triggerRenderedSegs = function (segs, isMirrors) {
4019            var calendar = this.calendar;
4020            if (this.hasPublicHandlers('eventPositioned')) {
4021                for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
4022                    var seg = segs_1[_i];
4023                    this.publiclyTriggerAfterSizing('eventPositioned', [
4024                        {
4025                            event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
4026                            isMirror: isMirrors,
4027                            isStart: seg.isStart,
4028                            isEnd: seg.isEnd,
4029                            el: seg.el,
4030                            view: this // safe to cast because this method is only called on context.view
4031                        }
4032                    ]);
4033                }
4034            }
4035            if (!calendar.state.loadingLevel) { // avoid initial empty state while pending
4036                calendar.afterSizingTriggers._eventsPositioned = [null]; // fire once
4037            }
4038        };
4039        DateComponent.prototype.triggerWillRemoveSegs = function (segs, isMirrors) {
4040            var calendar = this.calendar;
4041            for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
4042                var seg = segs_2[_i];
4043                calendar.trigger('eventElRemove', seg.el);
4044            }
4045            if (this.hasPublicHandlers('eventDestroy')) {
4046                for (var _a = 0, segs_3 = segs; _a < segs_3.length; _a++) {
4047                    var seg = segs_3[_a];
4048                    this.publiclyTrigger('eventDestroy', [
4049                        {
4050                            event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
4051                            isMirror: isMirrors,
4052                            el: seg.el,
4053                            view: this // safe to cast because this method is only called on context.view
4054                        }
4055                    ]);
4056                }
4057            }
4058        };
4059        // Pointer Interaction Utils
4060        // -----------------------------------------------------------------------------------------------------------------
4061        DateComponent.prototype.isValidSegDownEl = function (el) {
4062            return !this.props.eventDrag && // HACK
4063                !this.props.eventResize && // HACK
4064                !elementClosest(el, '.fc-mirror') &&
4065                (this.isPopover() || !this.isInPopover(el));
4066            // ^above line ensures we don't detect a seg interaction within a nested component.
4067            // it's a HACK because it only supports a popover as the nested component.
4068        };
4069        DateComponent.prototype.isValidDateDownEl = function (el) {
4070            var segEl = elementClosest(el, this.fgSegSelector);
4071            return (!segEl || segEl.classList.contains('fc-mirror')) &&
4072                !elementClosest(el, '.fc-more') && // a "more.." link
4073                !elementClosest(el, 'a[data-goto]') && // a clickable nav link
4074                !this.isInPopover(el);
4075        };
4076        DateComponent.prototype.isPopover = function () {
4077            return this.el.classList.contains('fc-popover');
4078        };
4079        DateComponent.prototype.isInPopover = function (el) {
4080            return Boolean(elementClosest(el, '.fc-popover'));
4081        };
4082        return DateComponent;
4083    }(Component));
4084    DateComponent.prototype.fgSegSelector = '.fc-event-container > *';
4085    DateComponent.prototype.bgSegSelector = '.fc-bgevent:not(.fc-nonbusiness)';
4086
4087    var uid$1 = 0;
4088    function createPlugin(input) {
4089        return {
4090            id: String(uid$1++),
4091            deps: input.deps || [],
4092            reducers: input.reducers || [],
4093            eventDefParsers: input.eventDefParsers || [],
4094            isDraggableTransformers: input.isDraggableTransformers || [],
4095            eventDragMutationMassagers: input.eventDragMutationMassagers || [],
4096            eventDefMutationAppliers: input.eventDefMutationAppliers || [],
4097            dateSelectionTransformers: input.dateSelectionTransformers || [],
4098            datePointTransforms: input.datePointTransforms || [],
4099            dateSpanTransforms: input.dateSpanTransforms || [],
4100            views: input.views || {},
4101            viewPropsTransformers: input.viewPropsTransformers || [],
4102            isPropsValid: input.isPropsValid || null,
4103            externalDefTransforms: input.externalDefTransforms || [],
4104            eventResizeJoinTransforms: input.eventResizeJoinTransforms || [],
4105            viewContainerModifiers: input.viewContainerModifiers || [],
4106            eventDropTransformers: input.eventDropTransformers || [],
4107            componentInteractions: input.componentInteractions || [],
4108            calendarInteractions: input.calendarInteractions || [],
4109            themeClasses: input.themeClasses || {},
4110            eventSourceDefs: input.eventSourceDefs || [],
4111            cmdFormatter: input.cmdFormatter,
4112            recurringTypes: input.recurringTypes || [],
4113            namedTimeZonedImpl: input.namedTimeZonedImpl,
4114            defaultView: input.defaultView || '',
4115            elementDraggingImpl: input.elementDraggingImpl,
4116            optionChangeHandlers: input.optionChangeHandlers || {}
4117        };
4118    }
4119    var PluginSystem = /** @class */ (function () {
4120        function PluginSystem() {
4121            this.hooks = {
4122                reducers: [],
4123                eventDefParsers: [],
4124                isDraggableTransformers: [],
4125                eventDragMutationMassagers: [],
4126                eventDefMutationAppliers: [],
4127                dateSelectionTransformers: [],
4128                datePointTransforms: [],
4129                dateSpanTransforms: [],
4130                views: {},
4131                viewPropsTransformers: [],
4132                isPropsValid: null,
4133                externalDefTransforms: [],
4134                eventResizeJoinTransforms: [],
4135                viewContainerModifiers: [],
4136                eventDropTransformers: [],
4137                componentInteractions: [],
4138                calendarInteractions: [],
4139                themeClasses: {},
4140                eventSourceDefs: [],
4141                cmdFormatter: null,
4142                recurringTypes: [],
4143                namedTimeZonedImpl: null,
4144                defaultView: '',
4145                elementDraggingImpl: null,
4146                optionChangeHandlers: {}
4147            };
4148            this.addedHash = {};
4149        }
4150        PluginSystem.prototype.add = function (plugin) {
4151            if (!this.addedHash[plugin.id]) {
4152                this.addedHash[plugin.id] = true;
4153                for (var _i = 0, _a = plugin.deps; _i < _a.length; _i++) {
4154                    var dep = _a[_i];
4155                    this.add(dep);
4156                }
4157                this.hooks = combineHooks(this.hooks, plugin);
4158            }
4159        };
4160        return PluginSystem;
4161    }());
4162    function combineHooks(hooks0, hooks1) {
4163        return {
4164            reducers: hooks0.reducers.concat(hooks1.reducers),
4165            eventDefParsers: hooks0.eventDefParsers.concat(hooks1.eventDefParsers),
4166            isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers),
4167            eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers),
4168            eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers),
4169            dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers),
4170            datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms),
4171            dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms),
4172            views: __assign({}, hooks0.views, hooks1.views),
4173            viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers),
4174            isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid,
4175            externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms),
4176            eventResizeJoinTransforms: hooks0.eventResizeJoinTransforms.concat(hooks1.eventResizeJoinTransforms),
4177            viewContainerModifiers: hooks0.viewContainerModifiers.concat(hooks1.viewContainerModifiers),
4178            eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers),
4179            calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions),
4180            componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions),
4181            themeClasses: __assign({}, hooks0.themeClasses, hooks1.themeClasses),
4182            eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs),
4183            cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter,
4184            recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes),
4185            namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl,
4186            defaultView: hooks0.defaultView || hooks1.defaultView,
4187            elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl,
4188            optionChangeHandlers: __assign({}, hooks0.optionChangeHandlers, hooks1.optionChangeHandlers)
4189        };
4190    }
4191
4192    var eventSourceDef = {
4193        ignoreRange: true,
4194        parseMeta: function (raw) {
4195            if (Array.isArray(raw)) { // short form
4196                return raw;
4197            }
4198            else if (Array.isArray(raw.events)) {
4199                return raw.events;
4200            }
4201            return null;
4202        },
4203        fetch: function (arg, success) {
4204            success({
4205                rawEvents: arg.eventSource.meta
4206            });
4207        }
4208    };
4209    var ArrayEventSourcePlugin = createPlugin({
4210        eventSourceDefs: [eventSourceDef]
4211    });
4212
4213    var eventSourceDef$1 = {
4214        parseMeta: function (raw) {
4215            if (typeof raw === 'function') { // short form
4216                return raw;
4217            }
4218            else if (typeof raw.events === 'function') {
4219                return raw.events;
4220            }
4221            return null;
4222        },
4223        fetch: function (arg, success, failure) {
4224            var dateEnv = arg.calendar.dateEnv;
4225            var func = arg.eventSource.meta;
4226            unpromisify(func.bind(null, {
4227                start: dateEnv.toDate(arg.range.start),
4228                end: dateEnv.toDate(arg.range.end),
4229                startStr: dateEnv.formatIso(arg.range.start),
4230                endStr: dateEnv.formatIso(arg.range.end),
4231                timeZone: dateEnv.timeZone
4232            }), function (rawEvents) {
4233                success({ rawEvents: rawEvents }); // needs an object response
4234            }, failure // send errorObj directly to failure callback
4235            );
4236        }
4237    };
4238    var FuncEventSourcePlugin = createPlugin({
4239        eventSourceDefs: [eventSourceDef$1]
4240    });
4241
4242    function requestJson(method, url, params, successCallback, failureCallback) {
4243        method = method.toUpperCase();
4244        var body = null;
4245        if (method === 'GET') {
4246            url = injectQueryStringParams(url, params);
4247        }
4248        else {
4249            body = encodeParams(params);
4250        }
4251        var xhr = new XMLHttpRequest();
4252        xhr.open(method, url, true);
4253        if (method !== 'GET') {
4254            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
4255        }
4256        xhr.onload = function () {
4257            if (xhr.status >= 200 && xhr.status < 400) {
4258                try {
4259                    var res = JSON.parse(xhr.responseText);
4260                    successCallback(res, xhr);
4261                }
4262                catch (err) {
4263                    failureCallback('Failure parsing JSON', xhr);
4264                }
4265            }
4266            else {
4267                failureCallback('Request failed', xhr);
4268            }
4269        };
4270        xhr.onerror = function () {
4271            failureCallback('Request failed', xhr);
4272        };
4273        xhr.send(body);
4274    }
4275    function injectQueryStringParams(url, params) {
4276        return url +
4277            (url.indexOf('?') === -1 ? '?' : '&') +
4278            encodeParams(params);
4279    }
4280    function encodeParams(params) {
4281        var parts = [];
4282        for (var key in params) {
4283            parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key]));
4284        }
4285        return parts.join('&');
4286    }
4287
4288    var eventSourceDef$2 = {
4289        parseMeta: function (raw) {
4290            if (typeof raw === 'string') { // short form
4291                raw = { url: raw };
4292            }
4293            else if (!raw || typeof raw !== 'object' || !raw.url) {
4294                return null;
4295            }
4296            return {
4297                url: raw.url,
4298                method: (raw.method || 'GET').toUpperCase(),
4299                extraParams: raw.extraParams,
4300                startParam: raw.startParam,
4301                endParam: raw.endParam,
4302                timeZoneParam: raw.timeZoneParam
4303            };
4304        },
4305        fetch: function (arg, success, failure) {
4306            var meta = arg.eventSource.meta;
4307            var requestParams = buildRequestParams(meta, arg.range, arg.calendar);
4308            requestJson(meta.method, meta.url, requestParams, function (rawEvents, xhr) {
4309                success({ rawEvents: rawEvents, xhr: xhr });
4310            }, function (errorMessage, xhr) {
4311                failure({ message: errorMessage, xhr: xhr });
4312            });
4313        }
4314    };
4315    var JsonFeedEventSourcePlugin = createPlugin({
4316        eventSourceDefs: [eventSourceDef$2]
4317    });
4318    function buildRequestParams(meta, range, calendar) {
4319        var dateEnv = calendar.dateEnv;
4320        var startParam;
4321        var endParam;
4322        var timeZoneParam;
4323        var customRequestParams;
4324        var params = {};
4325        startParam = meta.startParam;
4326        if (startParam == null) {
4327            startParam = calendar.opt('startParam');
4328        }
4329        endParam = meta.endParam;
4330        if (endParam == null) {
4331            endParam = calendar.opt('endParam');
4332        }
4333        timeZoneParam = meta.timeZoneParam;
4334        if (timeZoneParam == null) {
4335            timeZoneParam = calendar.opt('timeZoneParam');
4336        }
4337        // retrieve any outbound GET/POST data from the options
4338        if (typeof meta.extraParams === 'function') {
4339            // supplied as a function that returns a key/value object
4340            customRequestParams = meta.extraParams();
4341        }
4342        else {
4343            // probably supplied as a straight key/value object
4344            customRequestParams = meta.extraParams || {};
4345        }
4346        __assign(params, customRequestParams);
4347        params[startParam] = dateEnv.formatIso(range.start);
4348        params[endParam] = dateEnv.formatIso(range.end);
4349        if (dateEnv.timeZone !== 'local') {
4350            params[timeZoneParam] = dateEnv.timeZone;
4351        }
4352        return params;
4353    }
4354
4355    var recurring = {
4356        parse: function (rawEvent, leftoverProps, dateEnv) {
4357            var createMarker = dateEnv.createMarker.bind(dateEnv);
4358            var processors = {
4359                daysOfWeek: null,
4360                startTime: createDuration,
4361                endTime: createDuration,
4362                startRecur: createMarker,
4363                endRecur: createMarker
4364            };
4365            var props = refineProps(rawEvent, processors, {}, leftoverProps);
4366            var anyValid = false;
4367            for (var propName in props) {
4368                if (props[propName] != null) {
4369                    anyValid = true;
4370                    break;
4371                }
4372            }
4373            if (anyValid) {
4374                var duration = null;
4375                if ('duration' in leftoverProps) {
4376                    duration = createDuration(leftoverProps.duration);
4377                    delete leftoverProps.duration;
4378                }
4379                if (!duration && props.startTime && props.endTime) {
4380                    duration = subtractDurations(props.endTime, props.startTime);
4381                }
4382                return {
4383                    allDayGuess: Boolean(!props.startTime && !props.endTime),
4384                    duration: duration,
4385                    typeData: props // doesn't need endTime anymore but oh well
4386                };
4387            }
4388            return null;
4389        },
4390        expand: function (typeData, framingRange, dateEnv) {
4391            var clippedFramingRange = intersectRanges(framingRange, { start: typeData.startRecur, end: typeData.endRecur });
4392            if (clippedFramingRange) {
4393                return expandRanges(typeData.daysOfWeek, typeData.startTime, clippedFramingRange, dateEnv);
4394            }
4395            else {
4396                return [];
4397            }
4398        }
4399    };
4400    var SimpleRecurrencePlugin = createPlugin({
4401        recurringTypes: [recurring]
4402    });
4403    function expandRanges(daysOfWeek, startTime, framingRange, dateEnv) {
4404        var dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null;
4405        var dayMarker = startOfDay(framingRange.start);
4406        var endMarker = framingRange.end;
4407        var instanceStarts = [];
4408        while (dayMarker < endMarker) {
4409            var instanceStart 
4410            // if everyday, or this particular day-of-week
4411            = void 0;
4412            // if everyday, or this particular day-of-week
4413            if (!dowHash || dowHash[dayMarker.getUTCDay()]) {
4414                if (startTime) {
4415                    instanceStart = dateEnv.add(dayMarker, startTime);
4416                }
4417                else {
4418                    instanceStart = dayMarker;
4419                }
4420                instanceStarts.push(instanceStart);
4421            }
4422            dayMarker = addDays(dayMarker, 1);
4423        }
4424        return instanceStarts;
4425    }
4426
4427    var DefaultOptionChangeHandlers = createPlugin({
4428        optionChangeHandlers: {
4429            events: function (events, calendar, deepEqual) {
4430                handleEventSources([events], calendar, deepEqual);
4431            },
4432            eventSources: handleEventSources,
4433            plugins: handlePlugins
4434        }
4435    });
4436    function handleEventSources(inputs, calendar, deepEqual) {
4437        var unfoundSources = hashValuesToArray(calendar.state.eventSources);
4438        var newInputs = [];
4439        for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) {
4440            var input = inputs_1[_i];
4441            var inputFound = false;
4442            for (var i = 0; i < unfoundSources.length; i++) {
4443                if (deepEqual(unfoundSources[i]._raw, input)) {
4444                    unfoundSources.splice(i, 1); // delete
4445                    inputFound = true;
4446                    break;
4447                }
4448            }
4449            if (!inputFound) {
4450                newInputs.push(input);
4451            }
4452        }
4453        for (var _a = 0, unfoundSources_1 = unfoundSources; _a < unfoundSources_1.length; _a++) {
4454            var unfoundSource = unfoundSources_1[_a];
4455            calendar.dispatch({
4456                type: 'REMOVE_EVENT_SOURCE',
4457                sourceId: unfoundSource.sourceId
4458            });
4459        }
4460        for (var _b = 0, newInputs_1 = newInputs; _b < newInputs_1.length; _b++) {
4461            var newInput = newInputs_1[_b];
4462            calendar.addEventSource(newInput);
4463        }
4464    }
4465    // shortcoming: won't remove plugins
4466    function handlePlugins(inputs, calendar) {
4467        calendar.addPluginInputs(inputs); // will gracefully handle duplicates
4468    }
4469
4470    var config = {}; // TODO: make these options
4471    var globalDefaults = {
4472        defaultRangeSeparator: ' - ',
4473        titleRangeSeparator: ' \u2013 ',
4474        defaultTimedEventDuration: '01:00:00',
4475        defaultAllDayEventDuration: { day: 1 },
4476        forceEventDuration: false,
4477        nextDayThreshold: '00:00:00',
4478        // display
4479        columnHeader: true,
4480        defaultView: '',
4481        aspectRatio: 1.35,
4482        header: {
4483            left: 'title',
4484            center: '',
4485            right: 'today prev,next'
4486        },
4487        weekends: true,
4488        weekNumbers: false,
4489        weekNumberCalculation: 'local',
4490        editable: false,
4491        // nowIndicator: false,
4492        scrollTime: '06:00:00',
4493        minTime: '00:00:00',
4494        maxTime: '24:00:00',
4495        showNonCurrentDates: true,
4496        // event ajax
4497        lazyFetching: true,
4498        startParam: 'start',
4499        endParam: 'end',
4500        timeZoneParam: 'timeZone',
4501        timeZone: 'local',
4502        // allDayDefault: undefined,
4503        // locale
4504        locales: [],
4505        locale: '',
4506        // dir: will get this from the default locale
4507        // buttonIcons: null,
4508        // allows setting a min-height to the event segment to prevent short events overlapping each other
4509        timeGridEventMinHeight: 0,
4510        themeSystem: 'standard',
4511        // eventResizableFromStart: false,
4512        dragRevertDuration: 500,
4513        dragScroll: true,
4514        allDayMaintainDuration: false,
4515        // selectable: false,
4516        unselectAuto: true,
4517        // selectMinDistance: 0,
4518        dropAccept: '*',
4519        eventOrder: 'start,-duration,allDay,title',
4520        // ^ if start tie, longer events go before shorter. final tie-breaker is title text
4521        // rerenderDelay: null,
4522        eventLimit: false,
4523        eventLimitClick: 'popover',
4524        dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' },
4525        handleWindowResize: true,
4526        windowResizeDelay: 100,
4527        longPressDelay: 1000,
4528        eventDragMinDistance: 5 // only applies to mouse
4529    };
4530    var rtlDefaults = {
4531        header: {
4532            left: 'next,prev today',
4533            center: '',
4534            right: 'title'
4535        },
4536        buttonIcons: {
4537            // TODO: make RTL support the responibility of the theme
4538            prev: 'fc-icon-chevron-right',
4539            next: 'fc-icon-chevron-left',
4540            prevYear: 'fc-icon-chevrons-right',
4541            nextYear: 'fc-icon-chevrons-left'
4542        }
4543    };
4544    var complexOptions = [
4545        'header',
4546        'footer',
4547        'buttonText',
4548        'buttonIcons'
4549    ];
4550    // Merges an array of option objects into a single object
4551    function mergeOptions(optionObjs) {
4552        return mergeProps(optionObjs, complexOptions);
4553    }
4554    // TODO: move this stuff to a "plugin"-related file...
4555    var INTERNAL_PLUGINS = [
4556        ArrayEventSourcePlugin,
4557        FuncEventSourcePlugin,
4558        JsonFeedEventSourcePlugin,
4559        SimpleRecurrencePlugin,
4560        DefaultOptionChangeHandlers
4561    ];
4562    function refinePluginDefs(pluginInputs) {
4563        var plugins = [];
4564        for (var _i = 0, pluginInputs_1 = pluginInputs; _i < pluginInputs_1.length; _i++) {
4565            var pluginInput = pluginInputs_1[_i];
4566            if (typeof pluginInput === 'string') {
4567                var globalName = 'FullCalendar' + capitaliseFirstLetter(pluginInput);
4568                if (!window[globalName]) {
4569                    console.warn('Plugin file not loaded for ' + pluginInput);
4570                }
4571                else {
4572                    plugins.push(window[globalName].default); // is an ES6 module
4573                }
4574            }
4575            else {
4576                plugins.push(pluginInput);
4577            }
4578        }
4579        return INTERNAL_PLUGINS.concat(plugins);
4580    }
4581
4582    var RAW_EN_LOCALE = {
4583        code: 'en',
4584        week: {
4585            dow: 0,
4586            doy: 4 // 4 days need to be within the year to be considered the first week
4587        },
4588        dir: 'ltr',
4589        buttonText: {
4590            prev: 'prev',
4591            next: 'next',
4592            prevYear: 'prev year',
4593            nextYear: 'next year',
4594            year: 'year',
4595            today: 'today',
4596            month: 'month',
4597            week: 'week',
4598            day: 'day',
4599            list: 'list'
4600        },
4601        weekLabel: 'W',
4602        allDayText: 'all-day',
4603        eventLimitText: 'more',
4604        noEventsMessage: 'No events to display'
4605    };
4606    function parseRawLocales(explicitRawLocales) {
4607        var defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en';
4608        var globalArray = window['FullCalendarLocalesAll'] || []; // from locales-all.js
4609        var globalObject = window['FullCalendarLocales'] || {}; // from locales/*.js. keys are meaningless
4610        var allRawLocales = globalArray.concat(// globalArray is low prio
4611        hashValuesToArray(globalObject), // medium prio
4612        explicitRawLocales // highest prio
4613        );
4614        var rawLocaleMap = {
4615            en: RAW_EN_LOCALE // necessary?
4616        };
4617        for (var _i = 0, allRawLocales_1 = allRawLocales; _i < allRawLocales_1.length; _i++) {
4618            var rawLocale = allRawLocales_1[_i];
4619            rawLocaleMap[rawLocale.code] = rawLocale;
4620        }
4621        return {
4622            map: rawLocaleMap,
4623            defaultCode: defaultCode
4624        };
4625    }
4626    function buildLocale(inputSingular, available) {
4627        if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) {
4628            return parseLocale(inputSingular.code, [inputSingular.code], inputSingular);
4629        }
4630        else {
4631            return queryLocale(inputSingular, available);
4632        }
4633    }
4634    function queryLocale(codeArg, available) {
4635        var codes = [].concat(codeArg || []); // will convert to array
4636        var raw = queryRawLocale(codes, available) || RAW_EN_LOCALE;
4637        return parseLocale(codeArg, codes, raw);
4638    }
4639    function queryRawLocale(codes, available) {
4640        for (var i = 0; i < codes.length; i++) {
4641            var parts = codes[i].toLocaleLowerCase().split('-');
4642            for (var j = parts.length; j > 0; j--) {
4643                var simpleId = parts.slice(0, j).join('-');
4644                if (available[simpleId]) {
4645                    return available[simpleId];
4646                }
4647            }
4648        }
4649        return null;
4650    }
4651    function parseLocale(codeArg, codes, raw) {
4652        var merged = mergeProps([RAW_EN_LOCALE, raw], ['buttonText']);
4653        delete merged.code; // don't want this part of the options
4654        var week = merged.week;
4655        delete merged.week;
4656        return {
4657            codeArg: codeArg,
4658            codes: codes,
4659            week: week,
4660            simpleNumberFormat: new Intl.NumberFormat(codeArg),
4661            options: merged
4662        };
4663    }
4664
4665    var OptionsManager = /** @class */ (function () {
4666        function OptionsManager(overrides) {
4667            this.overrides = __assign({}, overrides); // make a copy
4668            this.dynamicOverrides = {};
4669            this.compute();
4670        }
4671        OptionsManager.prototype.mutate = function (updates, removals, isDynamic) {
4672            var overrideHash = isDynamic ? this.dynamicOverrides : this.overrides;
4673            __assign(overrideHash, updates);
4674            for (var _i = 0, removals_1 = removals; _i < removals_1.length; _i++) {
4675                var propName = removals_1[_i];
4676                delete overrideHash[propName];
4677            }
4678            this.compute();
4679        };
4680        // Computes the flattened options hash for the calendar and assigns to `this.options`.
4681        // Assumes this.overrides and this.dynamicOverrides have already been initialized.
4682        OptionsManager.prototype.compute = function () {
4683            // TODO: not a very efficient system
4684            var locales = firstDefined(// explicit locale option given?
4685            this.dynamicOverrides.locales, this.overrides.locales, globalDefaults.locales);
4686            var locale = firstDefined(// explicit locales option given?
4687            this.dynamicOverrides.locale, this.overrides.locale, globalDefaults.locale);
4688            var available = parseRawLocales(locales);
4689            var localeDefaults = buildLocale(locale || available.defaultCode, available.map).options;
4690            var dir = firstDefined(// based on options computed so far, is direction RTL?
4691            this.dynamicOverrides.dir, this.overrides.dir, localeDefaults.dir);
4692            var dirDefaults = dir === 'rtl' ? rtlDefaults : {};
4693            this.dirDefaults = dirDefaults;
4694            this.localeDefaults = localeDefaults;
4695            this.computed = mergeOptions([
4696                globalDefaults,
4697                dirDefaults,
4698                localeDefaults,
4699                this.overrides,
4700                this.dynamicOverrides
4701            ]);
4702        };
4703        return OptionsManager;
4704    }());
4705
4706    var calendarSystemClassMap = {};
4707    function registerCalendarSystem(name, theClass) {
4708        calendarSystemClassMap[name] = theClass;
4709    }
4710    function createCalendarSystem(name) {
4711        return new calendarSystemClassMap[name]();
4712    }
4713    var GregorianCalendarSystem = /** @class */ (function () {
4714        function GregorianCalendarSystem() {
4715        }
4716        GregorianCalendarSystem.prototype.getMarkerYear = function (d) {
4717            return d.getUTCFullYear();
4718        };
4719        GregorianCalendarSystem.prototype.getMarkerMonth = function (d) {
4720            return d.getUTCMonth();
4721        };
4722        GregorianCalendarSystem.prototype.getMarkerDay = function (d) {
4723            return d.getUTCDate();
4724        };
4725        GregorianCalendarSystem.prototype.arrayToMarker = function (arr) {
4726            return arrayToUtcDate(arr);
4727        };
4728        GregorianCalendarSystem.prototype.markerToArray = function (marker) {
4729            return dateToUtcArray(marker);
4730        };
4731        return GregorianCalendarSystem;
4732    }());
4733    registerCalendarSystem('gregory', GregorianCalendarSystem);
4734
4735    var ISO_RE = /^\s*(\d{4})(-(\d{2})(-(\d{2})([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/;
4736    function parse(str) {
4737        var m = ISO_RE.exec(str);
4738        if (m) {
4739            var marker = new Date(Date.UTC(Number(m[1]), m[3] ? Number(m[3]) - 1 : 0, Number(m[5] || 1), Number(m[7] || 0), Number(m[8] || 0), Number(m[10] || 0), m[12] ? Number('0.' + m[12]) * 1000 : 0));
4740            if (isValidDate(marker)) {
4741                var timeZoneOffset = null;
4742                if (m[13]) {
4743                    timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 +
4744                        Number(m[18] || 0));
4745                }
4746                return {
4747                    marker: marker,
4748                    isTimeUnspecified: !m[6],
4749                    timeZoneOffset: timeZoneOffset
4750                };
4751            }
4752        }
4753        return null;
4754    }
4755
4756    var DateEnv = /** @class */ (function () {
4757        function DateEnv(settings) {
4758            var timeZone = this.timeZone = settings.timeZone;
4759            var isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC';
4760            if (settings.namedTimeZoneImpl && isNamedTimeZone) {
4761                this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone);
4762            }
4763            this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl);
4764            this.calendarSystem = createCalendarSystem(settings.calendarSystem);
4765            this.locale = settings.locale;
4766            this.weekDow = settings.locale.week.dow;
4767            this.weekDoy = settings.locale.week.doy;
4768            if (settings.weekNumberCalculation === 'ISO') {
4769                this.weekDow = 1;
4770                this.weekDoy = 4;
4771            }
4772            if (typeof settings.firstDay === 'number') {
4773                this.weekDow = settings.firstDay;
4774            }
4775            if (typeof settings.weekNumberCalculation === 'function') {
4776                this.weekNumberFunc = settings.weekNumberCalculation;
4777            }
4778            this.weekLabel = settings.weekLabel != null ? settings.weekLabel : settings.locale.options.weekLabel;
4779            this.cmdFormatter = settings.cmdFormatter;
4780        }
4781        // Creating / Parsing
4782        DateEnv.prototype.createMarker = function (input) {
4783            var meta = this.createMarkerMeta(input);
4784            if (meta === null) {
4785                return null;
4786            }
4787            return meta.marker;
4788        };
4789        DateEnv.prototype.createNowMarker = function () {
4790            if (this.canComputeOffset) {
4791                return this.timestampToMarker(new Date().valueOf());
4792            }
4793            else {
4794                // if we can't compute the current date val for a timezone,
4795                // better to give the current local date vals than UTC
4796                return arrayToUtcDate(dateToLocalArray(new Date()));
4797            }
4798        };
4799        DateEnv.prototype.createMarkerMeta = function (input) {
4800            if (typeof input === 'string') {
4801                return this.parse(input);
4802            }
4803            var marker = null;
4804            if (typeof input === 'number') {
4805                marker = this.timestampToMarker(input);
4806            }
4807            else if (input instanceof Date) {
4808                input = input.valueOf();
4809                if (!isNaN(input)) {
4810                    marker = this.timestampToMarker(input);
4811                }
4812            }
4813            else if (Array.isArray(input)) {
4814                marker = arrayToUtcDate(input);
4815            }
4816            if (marker === null || !isValidDate(marker)) {
4817                return null;
4818            }
4819            return { marker: marker, isTimeUnspecified: false, forcedTzo: null };
4820        };
4821        DateEnv.prototype.parse = function (s) {
4822            var parts = parse(s);
4823            if (parts === null) {
4824                return null;
4825            }
4826            var marker = parts.marker;
4827            var forcedTzo = null;
4828            if (parts.timeZoneOffset !== null) {
4829                if (this.canComputeOffset) {
4830                    marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000);
4831                }
4832                else {
4833                    forcedTzo = parts.timeZoneOffset;
4834                }
4835            }
4836            return { marker: marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo: forcedTzo };
4837        };
4838        // Accessors
4839        DateEnv.prototype.getYear = function (marker) {
4840            return this.calendarSystem.getMarkerYear(marker);
4841        };
4842        DateEnv.prototype.getMonth = function (marker) {
4843            return this.calendarSystem.getMarkerMonth(marker);
4844        };
4845        // Adding / Subtracting
4846        DateEnv.prototype.add = function (marker, dur) {
4847            var a = this.calendarSystem.markerToArray(marker);
4848            a[0] += dur.years;
4849            a[1] += dur.months;
4850            a[2] += dur.days;
4851            a[6] += dur.milliseconds;
4852            return this.calendarSystem.arrayToMarker(a);
4853        };
4854        DateEnv.prototype.subtract = function (marker, dur) {
4855            var a = this.calendarSystem.markerToArray(marker);
4856            a[0] -= dur.years;
4857            a[1] -= dur.months;
4858            a[2] -= dur.days;
4859            a[6] -= dur.milliseconds;
4860            return this.calendarSystem.arrayToMarker(a);
4861        };
4862        DateEnv.prototype.addYears = function (marker, n) {
4863            var a = this.calendarSystem.markerToArray(marker);
4864            a[0] += n;
4865            return this.calendarSystem.arrayToMarker(a);
4866        };
4867        DateEnv.prototype.addMonths = function (marker, n) {
4868            var a = this.calendarSystem.markerToArray(marker);
4869            a[1] += n;
4870            return this.calendarSystem.arrayToMarker(a);
4871        };
4872        // Diffing Whole Units
4873        DateEnv.prototype.diffWholeYears = function (m0, m1) {
4874            var calendarSystem = this.calendarSystem;
4875            if (timeAsMs(m0) === timeAsMs(m1) &&
4876                calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) &&
4877                calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) {
4878                return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0);
4879            }
4880            return null;
4881        };
4882        DateEnv.prototype.diffWholeMonths = function (m0, m1) {
4883            var calendarSystem = this.calendarSystem;
4884            if (timeAsMs(m0) === timeAsMs(m1) &&
4885                calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) {
4886                return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) +
4887                    (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12;
4888            }
4889            return null;
4890        };
4891        // Range / Duration
4892        DateEnv.prototype.greatestWholeUnit = function (m0, m1) {
4893            var n = this.diffWholeYears(m0, m1);
4894            if (n !== null) {
4895                return { unit: 'year', value: n };
4896            }
4897            n = this.diffWholeMonths(m0, m1);
4898            if (n !== null) {
4899                return { unit: 'month', value: n };
4900            }
4901            n = diffWholeWeeks(m0, m1);
4902            if (n !== null) {
4903                return { unit: 'week', value: n };
4904            }
4905            n = diffWholeDays(m0, m1);
4906            if (n !== null) {
4907                return { unit: 'day', value: n };
4908            }
4909            n = diffHours(m0, m1);
4910            if (isInt(n)) {
4911                return { unit: 'hour', value: n };
4912            }
4913            n = diffMinutes(m0, m1);
4914            if (isInt(n)) {
4915                return { unit: 'minute', value: n };
4916            }
4917            n = diffSeconds(m0, m1);
4918            if (isInt(n)) {
4919                return { unit: 'second', value: n };
4920            }
4921            return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() };
4922        };
4923        DateEnv.prototype.countDurationsBetween = function (m0, m1, d) {
4924            // TODO: can use greatestWholeUnit
4925            var diff;
4926            if (d.years) {
4927                diff = this.diffWholeYears(m0, m1);
4928                if (diff !== null) {
4929                    return diff / asRoughYears(d);
4930                }
4931            }
4932            if (d.months) {
4933                diff = this.diffWholeMonths(m0, m1);
4934                if (diff !== null) {
4935                    return diff / asRoughMonths(d);
4936                }
4937            }
4938            if (d.days) {
4939                diff = diffWholeDays(m0, m1);
4940                if (diff !== null) {
4941                    return diff / asRoughDays(d);
4942                }
4943            }
4944            return (m1.valueOf() - m0.valueOf()) / asRoughMs(d);
4945        };
4946        // Start-Of
4947        DateEnv.prototype.startOf = function (m, unit) {
4948            if (unit === 'year') {
4949                return this.startOfYear(m);
4950            }
4951            else if (unit === 'month') {
4952                return this.startOfMonth(m);
4953            }
4954            else if (unit === 'week') {
4955                return this.startOfWeek(m);
4956            }
4957            else if (unit === 'day') {
4958                return startOfDay(m);
4959            }
4960            else if (unit === 'hour') {
4961                return startOfHour(m);
4962            }
4963            else if (unit === 'minute') {
4964                return startOfMinute(m);
4965            }
4966            else if (unit === 'second') {
4967                return startOfSecond(m);
4968            }
4969        };
4970        DateEnv.prototype.startOfYear = function (m) {
4971            return this.calendarSystem.arrayToMarker([
4972                this.calendarSystem.getMarkerYear(m)
4973            ]);
4974        };
4975        DateEnv.prototype.startOfMonth = function (m) {
4976            return this.calendarSystem.arrayToMarker([
4977                this.calendarSystem.getMarkerYear(m),
4978                this.calendarSystem.getMarkerMonth(m)
4979            ]);
4980        };
4981        DateEnv.prototype.startOfWeek = function (m) {
4982            return this.calendarSystem.arrayToMarker([
4983                this.calendarSystem.getMarkerYear(m),
4984                this.calendarSystem.getMarkerMonth(m),
4985                m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7)
4986            ]);
4987        };
4988        // Week Number
4989        DateEnv.prototype.computeWeekNumber = function (marker) {
4990            if (this.weekNumberFunc) {
4991                return this.weekNumberFunc(this.toDate(marker));
4992            }
4993            else {
4994                return weekOfYear(marker, this.weekDow, this.weekDoy);
4995            }
4996        };
4997        // TODO: choke on timeZoneName: long
4998        DateEnv.prototype.format = function (marker, formatter, dateOptions) {
4999            if (dateOptions === void 0) { dateOptions = {}; }
5000            return formatter.format({
5001                marker: marker,
5002                timeZoneOffset: dateOptions.forcedTzo != null ?
5003                    dateOptions.forcedTzo :
5004                    this.offsetForMarker(marker)
5005            }, this);
5006        };
5007        DateEnv.prototype.formatRange = function (start, end, formatter, dateOptions) {
5008            if (dateOptions === void 0) { dateOptions = {}; }
5009            if (dateOptions.isEndExclusive) {
5010                end = addMs(end, -1);
5011            }
5012            return formatter.formatRange({
5013                marker: start,
5014                timeZoneOffset: dateOptions.forcedStartTzo != null ?
5015                    dateOptions.forcedStartTzo :
5016                    this.offsetForMarker(start)
5017            }, {
5018                marker: end,
5019                timeZoneOffset: dateOptions.forcedEndTzo != null ?
5020                    dateOptions.forcedEndTzo :
5021                    this.offsetForMarker(end)
5022            }, this);
5023        };
5024        DateEnv.prototype.formatIso = function (marker, extraOptions) {
5025            if (extraOptions === void 0) { extraOptions = {}; }
5026            var timeZoneOffset = null;
5027            if (!extraOptions.omitTimeZoneOffset) {
5028                if (extraOptions.forcedTzo != null) {
5029                    timeZoneOffset = extraOptions.forcedTzo;
5030                }
5031                else {
5032                    timeZoneOffset = this.offsetForMarker(marker);
5033                }
5034            }
5035            return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime);
5036        };
5037        // TimeZone
5038        DateEnv.prototype.timestampToMarker = function (ms) {
5039            if (this.timeZone === 'local') {
5040                return arrayToUtcDate(dateToLocalArray(new Date(ms)));
5041            }
5042            else if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) {
5043                return new Date(ms);
5044            }
5045            else {
5046                return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms));
5047            }
5048        };
5049        DateEnv.prototype.offsetForMarker = function (m) {
5050            if (this.timeZone === 'local') {
5051                return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset
5052            }
5053            else if (this.timeZone === 'UTC') {
5054                return 0;
5055            }
5056            else if (this.namedTimeZoneImpl) {
5057                return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m));
5058            }
5059            return null;
5060        };
5061        // Conversion
5062        DateEnv.prototype.toDate = function (m, forcedTzo) {
5063            if (this.timeZone === 'local') {
5064                return arrayToLocalDate(dateToUtcArray(m));
5065            }
5066            else if (this.timeZone === 'UTC') {
5067                return new Date(m.valueOf()); // make sure it's a copy
5068            }
5069            else if (!this.namedTimeZoneImpl) {
5070                return new Date(m.valueOf() - (forcedTzo || 0));
5071            }
5072            else {
5073                return new Date(m.valueOf() -
5074                    this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60 // convert minutes -> ms
5075                );
5076            }
5077        };
5078        return DateEnv;
5079    }());
5080
5081    var SIMPLE_SOURCE_PROPS = {
5082        id: String,
5083        allDayDefault: Boolean,
5084        eventDataTransform: Function,
5085        success: Function,
5086        failure: Function
5087    };
5088    var uid$2 = 0;
5089    function doesSourceNeedRange(eventSource, calendar) {
5090        var defs = calendar.pluginSystem.hooks.eventSourceDefs;
5091        return !defs[eventSource.sourceDefId].ignoreRange;
5092    }
5093    function parseEventSource(raw, calendar) {
5094        var defs = calendar.pluginSystem.hooks.eventSourceDefs;
5095        for (var i = defs.length - 1; i >= 0; i--) { // later-added plugins take precedence
5096            var def = defs[i];
5097            var meta = def.parseMeta(raw);
5098            if (meta) {
5099                var res = parseEventSourceProps(typeof raw === 'object' ? raw : {}, meta, i, calendar);
5100                res._raw = raw;
5101                return res;
5102            }
5103        }
5104        return null;
5105    }
5106    function parseEventSourceProps(raw, meta, sourceDefId, calendar) {
5107        var leftovers0 = {};
5108        var props = refineProps(raw, SIMPLE_SOURCE_PROPS, {}, leftovers0);
5109        var leftovers1 = {};
5110        var ui = processUnscopedUiProps(leftovers0, calendar, leftovers1);
5111        props.isFetching = false;
5112        props.latestFetchId = '';
5113        props.fetchRange = null;
5114        props.publicId = String(raw.id || '');
5115        props.sourceId = String(uid$2++);
5116        props.sourceDefId = sourceDefId;
5117        props.meta = meta;
5118        props.ui = ui;
5119        props.extendedProps = leftovers1;
5120        return props;
5121    }
5122
5123    function reduceEventSources (eventSources, action, dateProfile, calendar) {
5124        switch (action.type) {
5125            case 'ADD_EVENT_SOURCES': // already parsed
5126                return addSources(eventSources, action.sources, dateProfile ? dateProfile.activeRange : null, calendar);
5127            case 'REMOVE_EVENT_SOURCE':
5128                return removeSource(eventSources, action.sourceId);
5129            case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
5130            case 'NEXT':
5131            case 'SET_DATE':
5132            case 'SET_VIEW_TYPE':
5133                if (dateProfile) {
5134                    return fetchDirtySources(eventSources, dateProfile.activeRange, calendar);
5135                }
5136                else {
5137                    return eventSources;
5138                }
5139            case 'FETCH_EVENT_SOURCES':
5140            case 'CHANGE_TIMEZONE':
5141                return fetchSourcesByIds(eventSources, action.sourceIds ?
5142                    arrayToHash(action.sourceIds) :
5143                    excludeStaticSources(eventSources, calendar), dateProfile ? dateProfile.activeRange : null, calendar);
5144            case 'RECEIVE_EVENTS':
5145            case 'RECEIVE_EVENT_ERROR':
5146                return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange);
5147            case 'REMOVE_ALL_EVENT_SOURCES':
5148                return {};
5149            default:
5150                return eventSources;
5151        }
5152    }
5153    var uid$3 = 0;
5154    function addSources(eventSourceHash, sources, fetchRange, calendar) {
5155        var hash = {};
5156        for (var _i = 0, sources_1 = sources; _i < sources_1.length; _i++) {
5157            var source = sources_1[_i];
5158            hash[source.sourceId] = source;
5159        }
5160        if (fetchRange) {
5161            hash = fetchDirtySources(hash, fetchRange, calendar);
5162        }
5163        return __assign({}, eventSourceHash, hash);
5164    }
5165    function removeSource(eventSourceHash, sourceId) {
5166        return filterHash(eventSourceHash, function (eventSource) {
5167            return eventSource.sourceId !== sourceId;
5168        });
5169    }
5170    function fetchDirtySources(sourceHash, fetchRange, calendar) {
5171        return fetchSourcesByIds(sourceHash, filterHash(sourceHash, function (eventSource) {
5172            return isSourceDirty(eventSource, fetchRange, calendar);
5173        }), fetchRange, calendar);
5174    }
5175    function isSourceDirty(eventSource, fetchRange, calendar) {
5176        if (!doesSourceNeedRange(eventSource, calendar)) {
5177            return !eventSource.latestFetchId;
5178        }
5179        else {
5180            return !calendar.opt('lazyFetching') ||
5181                !eventSource.fetchRange ||
5182                fetchRange.start < eventSource.fetchRange.start ||
5183                fetchRange.end > eventSource.fetchRange.end;
5184        }
5185    }
5186    function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, calendar) {
5187        var nextSources = {};
5188        for (var sourceId in prevSources) {
5189            var source = prevSources[sourceId];
5190            if (sourceIdHash[sourceId]) {
5191                nextSources[sourceId] = fetchSource(source, fetchRange, calendar);
5192            }
5193            else {
5194                nextSources[sourceId] = source;
5195            }
5196        }
5197        return nextSources;
5198    }
5199    function fetchSource(eventSource, fetchRange, calendar) {
5200        var sourceDef = calendar.pluginSystem.hooks.eventSourceDefs[eventSource.sourceDefId];
5201        var fetchId = String(uid$3++);
5202        sourceDef.fetch({
5203            eventSource: eventSource,
5204            calendar: calendar,
5205            range: fetchRange
5206        }, function (res) {
5207            var rawEvents = res.rawEvents;
5208            var calSuccess = calendar.opt('eventSourceSuccess');
5209            var calSuccessRes;
5210            var sourceSuccessRes;
5211            if (eventSource.success) {
5212                sourceSuccessRes = eventSource.success(rawEvents, res.xhr);
5213            }
5214            if (calSuccess) {
5215                calSuccessRes = calSuccess(rawEvents, res.xhr);
5216            }
5217            rawEvents = sourceSuccessRes || calSuccessRes || rawEvents;
5218            calendar.dispatch({
5219                type: 'RECEIVE_EVENTS',
5220                sourceId: eventSource.sourceId,
5221                fetchId: fetchId,
5222                fetchRange: fetchRange,
5223                rawEvents: rawEvents
5224            });
5225        }, function (error) {
5226            var callFailure = calendar.opt('eventSourceFailure');
5227            console.warn(error.message, error);
5228            if (eventSource.failure) {
5229                eventSource.failure(error);
5230            }
5231            if (callFailure) {
5232                callFailure(error);
5233            }
5234            calendar.dispatch({
5235                type: 'RECEIVE_EVENT_ERROR',
5236                sourceId: eventSource.sourceId,
5237                fetchId: fetchId,
5238                fetchRange: fetchRange,
5239                error: error
5240            });
5241        });
5242        return __assign({}, eventSource, { isFetching: true, latestFetchId: fetchId });
5243    }
5244    function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) {
5245        var _a;
5246        var eventSource = sourceHash[sourceId];
5247        if (eventSource && // not already removed
5248            fetchId === eventSource.latestFetchId) {
5249            return __assign({}, sourceHash, (_a = {}, _a[sourceId] = __assign({}, eventSource, { isFetching: false, fetchRange: fetchRange }), _a));
5250        }
5251        return sourceHash;
5252    }
5253    function excludeStaticSources(eventSources, calendar) {
5254        return filterHash(eventSources, function (eventSource) {
5255            return doesSourceNeedRange(eventSource, calendar);
5256        });
5257    }
5258
5259    var DateProfileGenerator = /** @class */ (function () {
5260        function DateProfileGenerator(viewSpec, calendar) {
5261            this.viewSpec = viewSpec;
5262            this.options = viewSpec.options;
5263            this.dateEnv = calendar.dateEnv;
5264            this.calendar = calendar;
5265            this.initHiddenDays();
5266        }
5267        /* Date Range Computation
5268        ------------------------------------------------------------------------------------------------------------------*/
5269        // Builds a structure with info about what the dates/ranges will be for the "prev" view.
5270        DateProfileGenerator.prototype.buildPrev = function (currentDateProfile, currentDate) {
5271            var dateEnv = this.dateEnv;
5272            var prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
5273            currentDateProfile.dateIncrement);
5274            return this.build(prevDate, -1);
5275        };
5276        // Builds a structure with info about what the dates/ranges will be for the "next" view.
5277        DateProfileGenerator.prototype.buildNext = function (currentDateProfile, currentDate) {
5278            var dateEnv = this.dateEnv;
5279            var nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
5280            currentDateProfile.dateIncrement);
5281            return this.build(nextDate, 1);
5282        };
5283        // Builds a structure holding dates/ranges for rendering around the given date.
5284        // Optional direction param indicates whether the date is being incremented/decremented
5285        // from its previous value. decremented = -1, incremented = 1 (default).
5286        DateProfileGenerator.prototype.build = function (currentDate, direction, forceToValid) {
5287            if (forceToValid === void 0) { forceToValid = false; }
5288            var validRange;
5289            var minTime = null;
5290            var maxTime = null;
5291            var currentInfo;
5292            var isRangeAllDay;
5293            var renderRange;
5294            var activeRange;
5295            var isValid;
5296            validRange = this.buildValidRange();
5297            validRange = this.trimHiddenDays(validRange);
5298            if (forceToValid) {
5299                currentDate = constrainMarkerToRange(currentDate, validRange);
5300            }
5301            currentInfo = this.buildCurrentRangeInfo(currentDate, direction);
5302            isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit);
5303            renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay);
5304            renderRange = this.trimHiddenDays(renderRange);
5305            activeRange = renderRange;
5306            if (!this.options.showNonCurrentDates) {
5307                activeRange = intersectRanges(activeRange, currentInfo.range);
5308            }
5309            minTime = createDuration(this.options.minTime);
5310            maxTime = createDuration(this.options.maxTime);
5311            activeRange = this.adjustActiveRange(activeRange, minTime, maxTime);
5312            activeRange = intersectRanges(activeRange, validRange); // might return null
5313            // it's invalid if the originally requested date is not contained,
5314            // or if the range is completely outside of the valid range.
5315            isValid = rangesIntersect(currentInfo.range, validRange);
5316            return {
5317                // constraint for where prev/next operations can go and where events can be dragged/resized to.
5318                // an object with optional start and end properties.
5319                validRange: validRange,
5320                // range the view is formally responsible for.
5321                // for example, a month view might have 1st-31st, excluding padded dates
5322                currentRange: currentInfo.range,
5323                // name of largest unit being displayed, like "month" or "week"
5324                currentRangeUnit: currentInfo.unit,
5325                isRangeAllDay: isRangeAllDay,
5326                // dates that display events and accept drag-n-drop
5327                // will be `null` if no dates accept events
5328                activeRange: activeRange,
5329                // date range with a rendered skeleton
5330                // includes not-active days that need some sort of DOM
5331                renderRange: renderRange,
5332                // Duration object that denotes the first visible time of any given day
5333                minTime: minTime,
5334                // Duration object that denotes the exclusive visible end time of any given day
5335                maxTime: maxTime,
5336                isValid: isValid,
5337                // how far the current date will move for a prev/next operation
5338                dateIncrement: this.buildDateIncrement(currentInfo.duration)
5339                // pass a fallback (might be null) ^
5340            };
5341        };
5342        // Builds an object with optional start/end properties.
5343        // Indicates the minimum/maximum dates to display.
5344        // not responsible for trimming hidden days.
5345        DateProfileGenerator.prototype.buildValidRange = function () {
5346            return this.getRangeOption('validRange', this.calendar.getNow()) ||
5347                { start: null, end: null }; // completely open-ended
5348        };
5349        // Builds a structure with info about the "current" range, the range that is
5350        // highlighted as being the current month for example.
5351        // See build() for a description of `direction`.
5352        // Guaranteed to have `range` and `unit` properties. `duration` is optional.
5353        DateProfileGenerator.prototype.buildCurrentRangeInfo = function (date, direction) {
5354            var _a = this, viewSpec = _a.viewSpec, dateEnv = _a.dateEnv;
5355            var duration = null;
5356            var unit = null;
5357            var range = null;
5358            var dayCount;
5359            if (viewSpec.duration) {
5360                duration = viewSpec.duration;
5361                unit = viewSpec.durationUnit;
5362                range = this.buildRangeFromDuration(date, direction, duration, unit);
5363            }
5364            else if ((dayCount = this.options.dayCount)) {
5365                unit = 'day';
5366                range = this.buildRangeFromDayCount(date, direction, dayCount);
5367            }
5368            else if ((range = this.buildCustomVisibleRange(date))) {
5369                unit = dateEnv.greatestWholeUnit(range.start, range.end).unit;
5370            }
5371            else {
5372                duration = this.getFallbackDuration();
5373                unit = greatestDurationDenominator(duration).unit;
5374                range = this.buildRangeFromDuration(date, direction, duration, unit);
5375            }
5376            return { duration: duration, unit: unit, range: range };
5377        };
5378        DateProfileGenerator.prototype.getFallbackDuration = function () {
5379            return createDuration({ day: 1 });
5380        };
5381        // Returns a new activeRange to have time values (un-ambiguate)
5382        // minTime or maxTime causes the range to expand.
5383        DateProfileGenerator.prototype.adjustActiveRange = function (range, minTime, maxTime) {
5384            var dateEnv = this.dateEnv;
5385            var start = range.start;
5386            var end = range.end;
5387            if (this.viewSpec.class.prototype.usesMinMaxTime) {
5388                // expand active range if minTime is negative (why not when positive?)
5389                if (asRoughDays(minTime) < 0) {
5390                    start = startOfDay(start); // necessary?
5391                    start = dateEnv.add(start, minTime);
5392                }
5393                // expand active range if maxTime is beyond one day (why not when positive?)
5394                if (asRoughDays(maxTime) > 1) {
5395                    end = startOfDay(end); // necessary?
5396                    end = addDays(end, -1);
5397                    end = dateEnv.add(end, maxTime);
5398                }
5399            }
5400            return { start: start, end: end };
5401        };
5402        // Builds the "current" range when it is specified as an explicit duration.
5403        // `unit` is the already-computed greatestDurationDenominator unit of duration.
5404        DateProfileGenerator.prototype.buildRangeFromDuration = function (date, direction, duration, unit) {
5405            var dateEnv = this.dateEnv;
5406            var alignment = this.options.dateAlignment;
5407            var dateIncrementInput;
5408            var dateIncrementDuration;
5409            var start;
5410            var end;
5411            var res;
5412            // compute what the alignment should be
5413            if (!alignment) {
5414                dateIncrementInput = this.options.dateIncrement;
5415                if (dateIncrementInput) {
5416                    dateIncrementDuration = createDuration(dateIncrementInput);
5417                    // use the smaller of the two units
5418                    if (asRoughMs(dateIncrementDuration) < asRoughMs(duration)) {
5419                        alignment = greatestDurationDenominator(dateIncrementDuration, !getWeeksFromInput(dateIncrementInput)).unit;
5420                    }
5421                    else {
5422                        alignment = unit;
5423                    }
5424                }
5425                else {
5426                    alignment = unit;
5427                }
5428            }
5429            // if the view displays a single day or smaller
5430            if (asRoughDays(duration) <= 1) {
5431                if (this.isHiddenDay(start)) {
5432                    start = this.skipHiddenDays(start, direction);
5433                    start = startOfDay(start);
5434                }
5435            }
5436            function computeRes() {
5437                start = dateEnv.startOf(date, alignment);
5438                end = dateEnv.add(start, duration);
5439                res = { start: start, end: end };
5440            }
5441            computeRes();
5442            // if range is completely enveloped by hidden days, go past the hidden days
5443            if (!this.trimHiddenDays(res)) {
5444                date = this.skipHiddenDays(date, direction);
5445                computeRes();
5446            }
5447            return res;
5448        };
5449        // Builds the "current" range when a dayCount is specified.
5450        DateProfileGenerator.prototype.buildRangeFromDayCount = function (date, direction, dayCount) {
5451            var dateEnv = this.dateEnv;
5452            var customAlignment = this.options.dateAlignment;
5453            var runningCount = 0;
5454            var start = date;
5455            var end;
5456            if (customAlignment) {
5457                start = dateEnv.startOf(start, customAlignment);
5458            }
5459            start = startOfDay(start);
5460            start = this.skipHiddenDays(start, direction);
5461            end = start;
5462            do {
5463                end = addDays(end, 1);
5464                if (!this.isHiddenDay(end)) {
5465                    runningCount++;
5466                }
5467            } while (runningCount < dayCount);
5468            return { start: start, end: end };
5469        };
5470        // Builds a normalized range object for the "visible" range,
5471        // which is a way to define the currentRange and activeRange at the same time.
5472        DateProfileGenerator.prototype.buildCustomVisibleRange = function (date) {
5473            var dateEnv = this.dateEnv;
5474            var visibleRange = this.getRangeOption('visibleRange', dateEnv.toDate(date));
5475            if (visibleRange && (visibleRange.start == null || visibleRange.end == null)) {
5476                return null;
5477            }
5478            return visibleRange;
5479        };
5480        // Computes the range that will represent the element/cells for *rendering*,
5481        // but which may have voided days/times.
5482        // not responsible for trimming hidden days.
5483        DateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) {
5484            return currentRange;
5485        };
5486        // Compute the duration value that should be added/substracted to the current date
5487        // when a prev/next operation happens.
5488        DateProfileGenerator.prototype.buildDateIncrement = function (fallback) {
5489            var dateIncrementInput = this.options.dateIncrement;
5490            var customAlignment;
5491            if (dateIncrementInput) {
5492                return createDuration(dateIncrementInput);
5493            }
5494            else if ((customAlignment = this.options.dateAlignment)) {
5495                return createDuration(1, customAlignment);
5496            }
5497            else if (fallback) {
5498                return fallback;
5499            }
5500            else {
5501                return createDuration({ days: 1 });
5502            }
5503        };
5504        // Arguments after name will be forwarded to a hypothetical function value
5505        // WARNING: passed-in arguments will be given to generator functions as-is and can cause side-effects.
5506        // Always clone your objects if you fear mutation.
5507        DateProfileGenerator.prototype.getRangeOption = function (name) {
5508            var otherArgs = [];
5509            for (var _i = 1; _i < arguments.length; _i++) {
5510                otherArgs[_i - 1] = arguments[_i];
5511            }
5512            var val = this.options[name];
5513            if (typeof val === 'function') {
5514                val = val.apply(null, otherArgs);
5515            }
5516            if (val) {
5517                val = parseRange(val, this.dateEnv);
5518            }
5519            if (val) {
5520                val = computeVisibleDayRange(val);
5521            }
5522            return val;
5523        };
5524        /* Hidden Days
5525        ------------------------------------------------------------------------------------------------------------------*/
5526        // Initializes internal variables related to calculating hidden days-of-week
5527        DateProfileGenerator.prototype.initHiddenDays = function () {
5528            var hiddenDays = this.options.hiddenDays || []; // array of day-of-week indices that are hidden
5529            var isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool)
5530            var dayCnt = 0;
5531            var i;
5532            if (this.options.weekends === false) {
5533                hiddenDays.push(0, 6); // 0=sunday, 6=saturday
5534            }
5535            for (i = 0; i < 7; i++) {
5536                if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) {
5537                    dayCnt++;
5538                }
5539            }
5540            if (!dayCnt) {
5541                throw new Error('invalid hiddenDays'); // all days were hidden? bad.
5542            }
5543            this.isHiddenDayHash = isHiddenDayHash;
5544        };
5545        // Remove days from the beginning and end of the range that are computed as hidden.
5546        // If the whole range is trimmed off, returns null
5547        DateProfileGenerator.prototype.trimHiddenDays = function (range) {
5548            var start = range.start;
5549            var end = range.end;
5550            if (start) {
5551                start = this.skipHiddenDays(start);
5552            }
5553            if (end) {
5554                end = this.skipHiddenDays(end, -1, true);
5555            }
5556            if (start == null || end == null || start < end) {
5557                return { start: start, end: end };
5558            }
5559            return null;
5560        };
5561        // Is the current day hidden?
5562        // `day` is a day-of-week index (0-6), or a Date (used for UTC)
5563        DateProfileGenerator.prototype.isHiddenDay = function (day) {
5564            if (day instanceof Date) {
5565                day = day.getUTCDay();
5566            }
5567            return this.isHiddenDayHash[day];
5568        };
5569        // Incrementing the current day until it is no longer a hidden day, returning a copy.
5570        // DOES NOT CONSIDER validRange!
5571        // If the initial value of `date` is not a hidden day, don't do anything.
5572        // Pass `isExclusive` as `true` if you are dealing with an end date.
5573        // `inc` defaults to `1` (increment one day forward each time)
5574        DateProfileGenerator.prototype.skipHiddenDays = function (date, inc, isExclusive) {
5575            if (inc === void 0) { inc = 1; }
5576            if (isExclusive === void 0) { isExclusive = false; }
5577            while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) {
5578                date = addDays(date, inc);
5579            }
5580            return date;
5581        };
5582        return DateProfileGenerator;
5583    }());
5584    // TODO: find a way to avoid comparing DateProfiles. it's tedious
5585    function isDateProfilesEqual(p0, p1) {
5586        return rangesEqual(p0.validRange, p1.validRange) &&
5587            rangesEqual(p0.activeRange, p1.activeRange) &&
5588            rangesEqual(p0.renderRange, p1.renderRange) &&
5589            durationsEqual(p0.minTime, p1.minTime) &&
5590            durationsEqual(p0.maxTime, p1.maxTime);
5591        /*
5592        TODO: compare more?
5593          currentRange: DateRange
5594          currentRangeUnit: string
5595          isRangeAllDay: boolean
5596          isValid: boolean
5597          dateIncrement: Duration
5598        */
5599    }
5600
5601    function reduce (state, action, calendar) {
5602        var viewType = reduceViewType(state.viewType, action);
5603        var dateProfile = reduceDateProfile(state.dateProfile, action, state.currentDate, viewType, calendar);
5604        var eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendar);
5605        var nextState = __assign({}, state, { viewType: viewType,
5606            dateProfile: dateProfile, currentDate: reduceCurrentDate(state.currentDate, action, dateProfile), eventSources: eventSources, eventStore: reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendar), dateSelection: reduceDateSelection(state.dateSelection, action, calendar), eventSelection: reduceSelectedEvent(state.eventSelection, action), eventDrag: reduceEventDrag(state.eventDrag, action, eventSources, calendar), eventResize: reduceEventResize(state.eventResize, action, eventSources, calendar), eventSourceLoadingLevel: computeLoadingLevel(eventSources), loadingLevel: computeLoadingLevel(eventSources) });
5607        for (var _i = 0, _a = calendar.pluginSystem.hooks.reducers; _i < _a.length; _i++) {
5608            var reducerFunc = _a[_i];
5609            nextState = reducerFunc(nextState, action, calendar);
5610        }
5611        // console.log(action.type, nextState)
5612        return nextState;
5613    }
5614    function reduceViewType(currentViewType, action) {
5615        switch (action.type) {
5616            case 'SET_VIEW_TYPE':
5617                return action.viewType;
5618            default:
5619                return currentViewType;
5620        }
5621    }
5622    function reduceDateProfile(currentDateProfile, action, currentDate, viewType, calendar) {
5623        var newDateProfile;
5624        switch (action.type) {
5625            case 'PREV':
5626                newDateProfile = calendar.dateProfileGenerators[viewType].buildPrev(currentDateProfile, currentDate);
5627                break;
5628            case 'NEXT':
5629                newDateProfile = calendar.dateProfileGenerators[viewType].buildNext(currentDateProfile, currentDate);
5630                break;
5631            case 'SET_DATE':
5632                if (!currentDateProfile.activeRange ||
5633                    !rangeContainsMarker(currentDateProfile.currentRange, action.dateMarker)) {
5634                    newDateProfile = calendar.dateProfileGenerators[viewType].build(action.dateMarker, undefined, true // forceToValid
5635                    );
5636                }
5637                break;
5638            case 'SET_VIEW_TYPE':
5639                var generator = calendar.dateProfileGenerators[viewType];
5640                if (!generator) {
5641                    throw new Error(viewType ?
5642                        'The FullCalendar view "' + viewType + '" does not exist. Make sure your plugins are loaded correctly.' :
5643                        'No available FullCalendar view plugins.');
5644                }
5645                newDateProfile = generator.build(action.dateMarker || currentDate, undefined, true // forceToValid
5646                );
5647                break;
5648        }
5649        if (newDateProfile &&
5650            newDateProfile.isValid &&
5651            !(currentDateProfile && isDateProfilesEqual(currentDateProfile, newDateProfile))) {
5652            return newDateProfile;
5653        }
5654        else {
5655            return currentDateProfile;
5656        }
5657    }
5658    function reduceCurrentDate(currentDate, action, dateProfile) {
5659        switch (action.type) {
5660            case 'PREV':
5661            case 'NEXT':
5662                if (!rangeContainsMarker(dateProfile.currentRange, currentDate)) {
5663                    return dateProfile.currentRange.start;
5664                }
5665                else {
5666                    return currentDate;
5667                }
5668            case 'SET_DATE':
5669            case 'SET_VIEW_TYPE':
5670                var newDate = action.dateMarker || currentDate;
5671                if (dateProfile.activeRange && !rangeContainsMarker(dateProfile.activeRange, newD
5671ate)) {
5672                    return dateProfile.currentRange.start;
5673                }
5674                else {
5675                    return newDate;
5676                }
5677            default:
5678                return currentDate;
5679        }
5680    }
5681    function reduceDateSelection(currentSelection, action, calendar) {
5682        switch (action.type) {
5683            case 'SELECT_DATES':
5684                return action.selection;
5685            case 'UNSELECT_DATES':
5686                return null;
5687            default:
5688                return currentSelection;
5689        }
5690    }
5691    function reduceSelectedEvent(currentInstanceId, action) {
5692        switch (action.type) {
5693            case 'SELECT_EVENT':
5694                return action.eventInstanceId;
5695            case 'UNSELECT_EVENT':
5696                return '';
5697            default:
5698                return currentInstanceId;
5699        }
5700    }
5701    function reduceEventDrag(currentDrag, action, sources, calendar) {
5702        switch (action.type) {
5703            case 'SET_EVENT_DRAG':
5704                var newDrag = action.state;
5705                return {
5706                    affectedEvents: newDrag.affectedEvents,
5707                    mutatedEvents: newDrag.mutatedEvents,
5708                    isEvent: newDrag.isEvent,
5709                    origSeg: newDrag.origSeg
5710                };
5711            case 'UNSET_EVENT_DRAG':
5712                return null;
5713            default:
5714                return currentDrag;
5715        }
5716    }
5717    function reduceEventResize(currentResize, action, sources, calendar) {
5718        switch (action.type) {
5719            case 'SET_EVENT_RESIZE':
5720                var newResize = action.state;
5721                return {
5722                    affectedEvents: newResize.affectedEvents,
5723                    mutatedEvents: newResize.mutatedEvents,
5724                    isEvent: newResize.isEvent,
5725                    origSeg: newResize.origSeg
5726                };
5727            case 'UNSET_EVENT_RESIZE':
5728                return null;
5729            default:
5730                return currentResize;
5731        }
5732    }
5733    function computeLoadingLevel(eventSources) {
5734        var cnt = 0;
5735        for (var sourceId in eventSources) {
5736            if (eventSources[sourceId].isFetching) {
5737                cnt++;
5738            }
5739        }
5740        return cnt;
5741    }
5742
5743    var STANDARD_PROPS = {
5744        start: null,
5745        end: null,
5746        allDay: Boolean
5747    };
5748    function parseDateSpan(raw, dateEnv, defaultDuration) {
5749        var span = parseOpenDateSpan(raw, dateEnv);
5750        var range = span.range;
5751        if (!range.start) {
5752            return null;
5753        }
5754        if (!range.end) {
5755            if (defaultDuration == null) {
5756                return null;
5757            }
5758            else {
5759                range.end = dateEnv.add(range.start, defaultDuration);
5760            }
5761        }
5762        return span;
5763    }
5764    /*
5765    TODO: somehow combine with parseRange?
5766    Will return null if the start/end props were present but parsed invalidly.
5767    */
5768    function parseOpenDateSpan(raw, dateEnv) {
5769        var leftovers = {};
5770        var standardProps = refineProps(raw, STANDARD_PROPS, {}, leftovers);
5771        var startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null;
5772        var endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null;
5773        var allDay = standardProps.allDay;
5774        if (allDay == null) {
5775            allDay = (startMeta && startMeta.isTimeUnspecified) &&
5776                (!endMeta || endMeta.isTimeUnspecified);
5777        }
5778        // use this leftover object as the selection object
5779        leftovers.range = {
5780            start: startMeta ? startMeta.marker : null,
5781            end: endMeta ? endMeta.marker : null
5782        };
5783        leftovers.allDay = allDay;
5784        return leftovers;
5785    }
5786    function isDateSpansEqual(span0, span1) {
5787        return rangesEqual(span0.range, span1.range) &&
5788            span0.allDay === span1.allDay &&
5789            isSpanPropsEqual(span0, span1);
5790    }
5791    // the NON-DATE-RELATED props
5792    function isSpanPropsEqual(span0, span1) {
5793        for (var propName in span1) {
5794            if (propName !== 'range' && propName !== 'allDay') {
5795                if (span0[propName] !== span1[propName]) {
5796                    return false;
5797                }
5798            }
5799        }
5800        // are there any props that span0 has that span1 DOESN'T have?
5801        // both have range/allDay, so no need to special-case.
5802        for (var propName in span0) {
5803            if (!(propName in span1)) {
5804                return false;
5805            }
5806        }
5807        return true;
5808    }
5809    function buildDateSpanApi(span, dateEnv) {
5810        return {
5811            start: dateEnv.toDate(span.range.start),
5812            end: dateEnv.toDate(span.range.end),
5813            startStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }),
5814            endStr: dateEnv.formatIso(span.range.end, { omitTime: span.allDay }),
5815            allDay: span.allDay
5816        };
5817    }
5818    function buildDatePointApi(span, dateEnv) {
5819        return {
5820            date: dateEnv.toDate(span.range.start),
5821            dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }),
5822            allDay: span.allDay
5823        };
5824    }
5825    function fabricateEventRange(dateSpan, eventUiBases, calendar) {
5826        var def = parseEventDef({ editable: false }, '', // sourceId
5827        dateSpan.allDay, true, // hasEnd
5828        calendar);
5829        return {
5830            def: def,
5831            ui: compileEventUi(def, eventUiBases),
5832            instance: createEventInstance(def.defId, dateSpan.range),
5833            range: dateSpan.range,
5834            isStart: true,
5835            isEnd: true
5836        };
5837    }
5838
5839    function compileViewDefs(defaultConfigs, overrideConfigs) {
5840        var hash = {};
5841        var viewType;
5842        for (viewType in defaultConfigs) {
5843            ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
5844        }
5845        for (viewType in overrideConfigs) {
5846            ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
5847        }
5848        return hash;
5849    }
5850    function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
5851        if (hash[viewType]) {
5852            return hash[viewType];
5853        }
5854        var viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs);
5855        if (viewDef) {
5856            hash[viewType] = viewDef;
5857        }
5858        return viewDef;
5859    }
5860    function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
5861        var defaultConfig = defaultConfigs[viewType];
5862        var overrideConfig = overrideConfigs[viewType];
5863        var queryProp = function (name) {
5864            return (defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] :
5865                ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null);
5866        };
5867        var theClass = queryProp('class');
5868        var superType = queryProp('superType');
5869        if (!superType && theClass) {
5870            superType =
5871                findViewNameBySubclass(theClass, overrideConfigs) ||
5872                    findViewNameBySubclass(theClass, defaultConfigs);
5873        }
5874        var superDef = null;
5875        if (superType) {
5876            if (superType === viewType) {
5877                throw new Error('Can\'t have a custom view type that references itself');
5878            }
5879            superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs);
5880        }
5881        if (!theClass && superDef) {
5882            theClass = superDef.class;
5883        }
5884        if (!theClass) {
5885            return null; // don't throw a warning, might be settings for a single-unit view
5886        }
5887        return {
5888            type: viewType,
5889            class: theClass,
5890            defaults: __assign({}, (superDef ? superDef.defaults : {}), (defaultConfig ? defaultConfig.options : {})),
5891            overrides: __assign({}, (superDef ? superDef.overrides : {}), (overrideConfig ? overrideConfig.options : {}))
5892        };
5893    }
5894    function findViewNameBySubclass(viewSubclass, configs) {
5895        var superProto = Object.getPrototypeOf(viewSubclass.prototype);
5896        for (var viewType in configs) {
5897            var parsed = configs[viewType];
5898            // need DIRECT subclass, so instanceof won't do it
5899            if (parsed.class && parsed.class.prototype === superProto) {
5900                return viewType;
5901            }
5902        }
5903        return '';
5904    }
5905
5906    function parseViewConfigs(inputs) {
5907        return mapHash(inputs, parseViewConfig);
5908    }
5909    var VIEW_DEF_PROPS = {
5910        type: String,
5911        class: null
5912    };
5913    function parseViewConfig(input) {
5914        if (typeof input === 'function') {
5915            input = { class: input };
5916        }
5917        var options = {};
5918        var props = refineProps(input, VIEW_DEF_PROPS, {}, options);
5919        return {
5920            superType: props.type,
5921            class: props.class,
5922            options: options
5923        };
5924    }
5925
5926    function buildViewSpecs(defaultInputs, optionsManager) {
5927        var defaultConfigs = parseViewConfigs(defaultInputs);
5928        var overrideConfigs = parseViewConfigs(optionsManager.overrides.views);
5929        var viewDefs = compileViewDefs(defaultConfigs, overrideConfigs);
5930        return mapHash(viewDefs, function (viewDef) {
5931            return buildViewSpec(viewDef, overrideConfigs, optionsManager);
5932        });
5933    }
5934    function buildViewSpec(viewDef, overrideConfigs, optionsManager) {
5935        var durationInput = viewDef.overrides.duration ||
5936            viewDef.defaults.duration ||
5937            optionsManager.dynamicOverrides.duration ||
5938            optionsManager.overrides.duration;
5939        var duration = null;
5940        var durationUnit = '';
5941        var singleUnit = '';
5942        var singleUnitOverrides = {};
5943        if (durationInput) {
5944            duration = createDuration(durationInput);
5945            if (duration) { // valid?
5946                var denom = greatestDurationDenominator(duration, !getWeeksFromInput(durationInput));
5947                durationUnit = denom.unit;
5948                if (denom.value === 1) {
5949                    singleUnit = durationUnit;
5950                    singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].options : {};
5951                }
5952            }
5953        }
5954        var queryButtonText = function (options) {
5955            var buttonTextMap = options.buttonText || {};
5956            var buttonTextKey = viewDef.defaults.buttonTextKey;
5957            if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) {
5958                return buttonTextMap[buttonTextKey];
5959            }
5960            if (buttonTextMap[viewDef.type] != null) {
5961                return buttonTextMap[viewDef.type];
5962            }
5963            if (buttonTextMap[singleUnit] != null) {
5964                return buttonTextMap[singleUnit];
5965            }
5966        };
5967        return {
5968            type: viewDef.type,
5969            class: viewDef.class,
5970            duration: duration,
5971            durationUnit: durationUnit,
5972            singleUnit: singleUnit,
5973            options: __assign({}, globalDefaults, viewDef.defaults, optionsManager.dirDefaults, optionsManager.localeDefaults, optionsManager.overrides, singleUnitOverrides, viewDef.overrides, optionsManager.dynamicOverrides),
5974            buttonTextOverride: queryButtonText(optionsManager.dynamicOverrides) ||
5975                queryButtonText(optionsManager.overrides) || // constructor-specified buttonText lookup hash takes precedence
5976                viewDef.overrides.buttonText,
5977            buttonTextDefault: queryButtonText(optionsManager.localeDefaults) ||
5978                queryButtonText(optionsManager.dirDefaults) ||
5979                viewDef.defaults.buttonText ||
5980                queryButtonText(globalDefaults) ||
5981                viewDef.type // fall back to given view name
5982        };
5983    }
5984
5985    var Toolbar = /** @class */ (function (_super) {
5986        __extends(Toolbar, _super);
5987        function Toolbar(context, extraClassName) {
5988            var _this = _super.call(this, context) || this;
5989            _this._renderLayout = memoizeRendering(_this.renderLayout, _this.unrenderLayout);
5990            _this._updateTitle = memoizeRendering(_this.updateTitle, null, [_this._renderLayout]);
5991            _this._updateActiveButton = memoizeRendering(_this.updateActiveButton, null, [_this._renderLayout]);
5992            _this._updateToday = memoizeRendering(_this.updateToday, null, [_this._renderLayout]);
5993            _this._updatePrev = memoizeRendering(_this.updatePrev, null, [_this._renderLayout]);
5994            _this._updateNext = memoizeRendering(_this.updateNext, null, [_this._renderLayout]);
5995            _this.el = createElement('div', { className: 'fc-toolbar ' + extraClassName });
5996            return _this;
5997        }
5998        Toolbar.prototype.destroy = function () {
5999            _super.prototype.destroy.call(this);
6000            this._renderLayout.unrender(); // should unrender everything else
6001            removeElement(this.el);
6002        };
6003        Toolbar.prototype.render = function (props) {
6004            this._renderLayout(props.layout);
6005            this._updateTitle(props.title);
6006            this._updateActiveButton(props.activeButton);
6007            this._updateToday(props.isTodayEnabled);
6008            this._updatePrev(props.isPrevEnabled);
6009            this._updateNext(props.isNextEnabled);
6010        };
6011        Toolbar.prototype.renderLayout = function (layout) {
6012            var el = this.el;
6013            this.viewsWithButtons = [];
6014            appendToElement(el, this.renderSection('left', layout.left));
6015            appendToElement(el, this.renderSection('center', layout.center));
6016            appendToElement(el, this.renderSection('right', layout.right));
6017        };
6018        Toolbar.prototype.unrenderLayout = function () {
6019            this.el.innerHTML = '';
6020        };
6021        Toolbar.prototype.renderSection = function (position, buttonStr) {
6022            var _this = this;
6023            var _a = this, theme = _a.theme, calendar = _a.calendar;
6024            var optionsManager = calendar.optionsManager;
6025            var viewSpecs = calendar.viewSpecs;
6026            var sectionEl = createElement('div', { className: 'fc-' + position });
6027            var calendarCustomButtons = optionsManager.computed.customButtons || {};
6028            var calendarButtonTextOverrides = optionsManager.overrides.buttonText || {};
6029            var calendarButtonText = optionsManager.computed.buttonText || {};
6030            if (buttonStr) {
6031                buttonStr.split(' ').forEach(function (buttonGroupStr, i) {
6032                    var groupChildren = [];
6033                    var isOnlyButtons = true;
6034                    var groupEl;
6035                    buttonGroupStr.split(',').forEach(function (buttonName, j) {
6036                        var customButtonProps;
6037                        var viewSpec;
6038                        var buttonClick;
6039                        var buttonIcon; // only one of these will be set
6040                        var buttonText; // "
6041                        var buttonInnerHtml;
6042                        var buttonClasses;
6043                        var buttonEl;
6044                        var buttonAriaAttr;
6045                        if (buttonName === 'title') {
6046                            groupChildren.push(htmlToElement('<h2>&nbsp;</h2>')); // we always want it to take up height
6047                            isOnlyButtons = false;
6048                        }
6049                        else {
6050                            if ((customButtonProps = calendarCustomButtons[buttonName])) {
6051                                buttonClick = function (ev) {
6052                                    if (customButtonProps.click) {
6053                                        customButtonProps.click.call(buttonEl, ev);
6054                                    }
6055                                };
6056                                (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) ||
6057                                    (buttonIcon = theme.getIconClass(buttonName)) ||
6058                                    (buttonText = customButtonProps.text);
6059                            }
6060                            else if ((viewSpec = viewSpecs[buttonName])) {
6061                                _this.viewsWithButtons.push(buttonName);
6062                                buttonClick = function () {
6063                                    calendar.changeView(buttonName);
6064                                };
6065                                (buttonText = viewSpec.buttonTextOverride) ||
6066                                    (buttonIcon = theme.getIconClass(buttonName)) ||
6067                                    (buttonText = viewSpec.buttonTextDefault);
6068                            }
6069                            else if (calendar[buttonName]) { // a calendar method
6070                                buttonClick = function () {
6071                                    calendar[buttonName]();
6072                                };
6073                                (buttonText = calendarButtonTextOverrides[buttonName]) ||
6074                                    (buttonIcon = theme.getIconClass(buttonName)) ||
6075                                    (buttonText = calendarButtonText[buttonName]);
6076                                //            ^ everything else is considered default
6077                            }
6078                            if (buttonClick) {
6079                                buttonClasses = [
6080                                    'fc-' + buttonName + '-button',
6081                                    theme.getClass('button')
6082                                ];
6083                                if (buttonText) {
6084                                    buttonInnerHtml = htmlEscape(buttonText);
6085                                    buttonAriaAttr = '';
6086                                }
6087                                else if (buttonIcon) {
6088                                    buttonInnerHtml = "<span class='" + buttonIcon + "'></span>";
6089                                    buttonAriaAttr = ' aria-label="' + buttonName + '"';
6090                                }
6091                                buttonEl = htmlToElement(// type="button" so that it doesn't submit a form
6092                                '<button type="button" class="' + buttonClasses.join(' ') + '"' +
6093                                    buttonAriaAttr +
6094                                    '>' + buttonInnerHtml + '</button>');
6095                                buttonEl.addEventListener('click', buttonClick);
6096                                groupChildren.push(buttonEl);
6097                            }
6098                        }
6099                    });
6100                    if (groupChildren.length > 1) {
6101                        groupEl = document.createElement('div');
6102                        var buttonGroupClassName = theme.getClass('buttonGroup');
6103                        if (isOnlyButtons && buttonGroupClassName) {
6104                            groupEl.classList.add(buttonGroupClassName);
6105                        }
6106                        appendToElement(groupEl, groupChildren);
6107                        sectionEl.appendChild(groupEl);
6108                    }
6109                    else {
6110                        appendToElement(sectionEl, groupChildren); // 1 or 0 children
6111                    }
6112                });
6113            }
6114            return sectionEl;
6115        };
6116        Toolbar.prototype.updateToday = function (isTodayEnabled) {
6117            this.toggleButtonEnabled('today', isTodayEnabled);
6118        };
6119        Toolbar.prototype.updatePrev = function (isPrevEnabled) {
6120            this.toggleButtonEnabled('prev', isPrevEnabled);
6121        };
6122        Toolbar.prototype.updateNext = function (isNextEnabled) {
6123            this.toggleButtonEnabled('next', isNextEnabled);
6124        };
6125        Toolbar.prototype.updateTitle = function (text) {
6126            findElements(this.el, 'h2').forEach(function (titleEl) {
6127                titleEl.innerText = text;
6128            });
6129        };
6130        Toolbar.prototype.updateActiveButton = function (buttonName) {
6131            var className = this.theme.getClass('buttonActive');
6132            findElements(this.el, 'button').forEach(function (buttonEl) {
6133                if (buttonName && buttonEl.classList.contains('fc-' 
6133+ buttonName + '-button')) {
6134                    buttonEl.classList.add(className);
6135                }
6136                else {
6137                    buttonEl.classList.remove(className);
6138                }
6139            });
6140        };
6141        Toolbar.prototype.toggleButtonEnabled = function (buttonName, bool) {
6142            findElements(this.el, '.fc-' + buttonName + '-button').forEach(function (buttonEl) {
6143                buttonEl.disabled = !bool;
6144            });
6145        };
6146        return Toolbar;
6147    }(Component));
6148
6149    var CalendarComponent = /** @class */ (function (_super) {
6150        __extends(CalendarComponent, _super);
6151        function CalendarComponent(context, el) {
6152            var _this = _super.call(this, context) || this;
6153            _this._renderToolbars = memoizeRendering(_this.renderToolbars);
6154            _this.buildViewPropTransformers = memoize(buildViewPropTransformers);
6155            _this.el = el;
6156            prependToElement(el, _this.contentEl = createElement('div', { className: 'fc-view-container' }));
6157            var calendar = _this.calendar;
6158            for (var _i = 0, _a = calendar.pluginSystem.hooks.viewContainerModifiers; _i < _a.length; _i++) {
6159                var modifyViewContainer = _a[_i];
6160                modifyViewContainer(_this.contentEl, calendar);
6161            }
6162            _this.toggleElClassNames(true);
6163            _this.computeTitle = memoize(computeTitle);
6164            _this.parseBusinessHours = memoize(function (input) {
6165                return parseBusinessHours(input, _this.calendar);
6166            });
6167            return _this;
6168        }
6169        CalendarComponent.prototype.destroy = function () {
6170            if (this.header) {
6171                this.header.destroy();
6172            }
6173            if (this.footer) {
6174                this.footer.destroy();
6175            }
6176            if (this.view) {
6177                this.view.destroy();
6178            }
6179            removeElement(this.contentEl);
6180            this.toggleElClassNames(false);
6181            _super.prototype.destroy.call(this);
6182        };
6183        CalendarComponent.prototype.toggleElClassNames = function (bool) {
6184            var classList = this.el.classList;
6185            var dirClassName = 'fc-' + this.opt('dir');
6186            var themeClassName = this.theme.getClass('widget');
6187            if (bool) {
6188                classList.add('fc');
6189                classList.add(dirClassName);
6190                classList.add(themeClassName);
6191            }
6192            else {
6193                classList.remove('fc');
6194                classList.remove(dirClassName);
6195                classList.remove(themeClassName);
6196            }
6197        };
6198        CalendarComponent.prototype.render = function (props) {
6199            this.freezeHeight();
6200            var title = this.computeTitle(props.dateProfile, props.viewSpec.options);
6201            this._renderToolbars(props.viewSpec, props.dateProfile, props.currentDate, props.dateProfileGenerator, title);
6202            this.renderView(props, title);
6203            this.updateSize();
6204            this.thawHeight();
6205        };
6206        CalendarComponent.prototype.renderToolbars = function (viewSpec, dateProfile, currentDate, dateProfileGenerator, title) {
6207            var headerLayout = this.opt('header');
6208            var footerLayout = this.opt('footer');
6209            var now = this.calendar.getNow();
6210            var todayInfo = dateProfileGenerator.build(now);
6211            var prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate);
6212            var nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate);
6213            var toolbarProps = {
6214                title: title,
6215                activeButton: viewSpec.type,
6216                isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now),
6217                isPrevEnabled: prevInfo.isValid,
6218                isNextEnabled: nextInfo.isValid
6219            };
6220            if (headerLayout) {
6221                if (!this.header) {
6222                    this.header = new Toolbar(this.context, 'fc-header-toolbar');
6223                    prependToElement(this.el, this.header.el);
6224                }
6225                this.header.receiveProps(__assign({ layout: headerLayout }, toolbarProps));
6226            }
6227            else if (this.header) {
6228                this.header.destroy();
6229                this.header = null;
6230            }
6231            if (footerLayout) {
6232                if (!this.footer) {
6233                    this.footer = new Toolbar(this.context, 'fc-footer-toolbar');
6234                    appendToElement(this.el, this.footer.el);
6235                }
6236                this.footer.receiveProps(__assign({ layout: footerLayout }, toolbarProps));
6237            }
6238            else if (this.footer) {
6239                this.footer.destroy();
6240                this.footer = null;
6241            }
6242        };
6243        CalendarComponent.prototype.renderView = function (props, title) {
6244            var view = this.view;
6245            var viewSpec = props.viewSpec, dateProfileGenerator = props.dateProfileGenerator;
6246            if (!view || view.viewSpec !== viewSpec) {
6247                if (view) {
6248                    view.destroy();
6249                }
6250                view = this.view = new viewSpec['class']({
6251                    calendar: this.calendar,
6252                    view: null,
6253                    dateEnv: this.dateEnv,
6254                    theme: this.theme,
6255                    options: viewSpec.options
6256                }, viewSpec, dateProfileGenerator, this.contentEl);
6257            }
6258            else {
6259                view.addScroll(view.queryScroll());
6260            }
6261            view.title = title; // for the API
6262            var viewProps = {
6263                dateProfile: props.dateProfile,
6264                businessHours: this.parseBusinessHours(viewSpec.options.businessHours),
6265                eventStore: props.eventStore,
6266                eventUiBases: props.eventUiBases,
6267                dateSelection: props.dateSelection,
6268                eventSelection: props.eventSelection,
6269                eventDrag: props.eventDrag,
6270                eventResize: props.eventResize
6271            };
6272            var transformers = this.buildViewPropTransformers(this.calendar.pluginSystem.hooks.viewPropsTransformers);
6273            for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) {
6274                var transformer = transformers_1[_i];
6275                __assign(viewProps, transformer.transform(viewProps, viewSpec, props, view));
6276            }
6277            view.receiveProps(viewProps);
6278        };
6279        // Sizing
6280        // -----------------------------------------------------------------------------------------------------------------
6281        CalendarComponent.prototype.updateSize = function (isResize) {
6282            if (isResize === void 0) { isResize = false; }
6283            var view = this.view;
6284            if (isResize) {
6285                view.addScroll(view.queryScroll());
6286            }
6287            if (isResize || this.isHeightAuto == null) {
6288                this.computeHeightVars();
6289            }
6290            view.updateSize(isResize, this.viewHeight, this.isHeightAuto);
6291            view.updateNowIndicator(); // we need to guarantee this will run after updateSize
6292            view.popScroll(isResize);
6293        };
6294        CalendarComponent.prototype.computeHeightVars = function () {
6295            var calendar = this.calendar; // yuck. need to handle dynamic options
6296            var heightInput = calendar.opt('height');
6297            var contentHeightInput = calendar.opt('contentHeight');
6298            this.isHeightAuto = heightInput === 'auto' || contentHeightInput === 'auto';
6299            if (typeof contentHeightInput === 'number') { // exists and not 'auto'
6300                this.viewHeight = contentHeightInput;
6301            }
6302            else if (typeof contentHeightInput === 'function') { // exists and is a function
6303                this.viewHeight = contentHeightInput();
6304            }
6305            else if (typeof heightInput === 'number') { // exists and not 'auto'
6306                this.viewHeight = heightInput - this.queryToolbarsHeight();
6307            }
6308            else if (typeof heightInput === 'function') { // exists and is a function
6309                this.viewHeight = heightInput() - this.queryToolbarsHeight();
6310            }
6311            else if (heightInput === 'parent') { // set to height of parent element
6312                var parentEl = this.el.parentNode;
6313                this.viewHeight = parentEl.getBoundingClientRect().height - this.queryToolbarsHeight();
6314            }
6315            else {
6316                this.viewHeight = Math.round(this.contentEl.getBoundingClientRect().width /
6317                    Math.max(calendar.opt('aspectRatio'), .5));
6318            }
6319        };
6320        CalendarComponent.prototype.queryToolbarsHeight = function () {
6321            var height = 0;
6322            if (this.header) {
6323                height += computeHeightAndMargins(this.header.el);
6324            }
6325            if (this.footer) {
6326                height += computeHeightAndMargins(this.footer.el);
6327            }
6328            return height;
6329        };
6330        // Height "Freezing"
6331        // -----------------------------------------------------------------------------------------------------------------
6332        CalendarComponent.prototype.freezeHeight = function () {
6333            applyStyle(this.el, {
6334                height: this.el.getBoundingClientRect().height,
6335                overflow: 'hidden'
6336            });
6337        };
6338        CalendarComponent.prototype.thawHeight = function () {
6339            applyStyle(this.el, {
6340                height: '',
6341                overflow: ''
6342            });
6343        };
6344        return CalendarComponent;
6345    }(Component));
6346    // Title and Date Formatting
6347    // -----------------------------------------------------------------------------------------------------------------
6348    // Computes what the title at the top of the calendar should be for this view
6349    function computeTitle(dateProfile, viewOptions) {
6350        var range;
6351        // for views that span a large unit of time, show the proper interval, ignoring stray days before and after
6352        if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) {
6353            range = dateProfile.currentRange;
6354        }
6355        else { // for day units or smaller, use the actual day range
6356            range = dateProfile.activeRange;
6357        }
6358        return this.dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || computeTitleFormat(dateProfile), viewOptions.titleRangeSeparator), { isEndExclusive: dateProfile.isRangeAllDay });
6359    }
6360    // Generates the format string that should be used to generate the title for the current date range.
6361    // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
6362    function computeTitleFormat(dateProfile) {
6363        var currentRangeUnit = dateProfile.currentRangeUnit;
6364        if (currentRangeUnit === 'year') {
6365            return { year: 'numeric' };
6366        }
6367        else if (currentRangeUnit === 'month') {
6368            return { year: 'numeric', month: 'long' }; // like "September 2014"
6369        }
6370        else {
6371            var days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end);
6372            if (days !== null && days > 1) {
6373                // multi-day range. shorter, like "Sep 9 - 10 2014"
6374                return { year: 'numeric', month: 'short', day: 'numeric' };
6375            }
6376            else {
6377                // one day. longer, like "September 9 2014"
6378                return { year: 'numeric', month: 'long', day: 'numeric' };
6379            }
6380        }
6381    }
6382    // Plugin
6383    // -----------------------------------------------------------------------------------------------------------------
6384    function buildViewPropTransformers(theClasses) {
6385        return theClasses.map(function (theClass) {
6386            return new theClass();
6387        });
6388    }
6389
6390    var Interaction = /** @class */ (function () {
6391        function Interaction(settings) {
6392            this.component = settings.component;
6393        }
6394        Interaction.prototype.destroy = function () {
6395        };
6396        return Interaction;
6397    }());
6398    function parseInteractionSettings(component, input) {
6399        return {
6400            component: component,
6401            el: input.el,
6402            useEventCenter: input.useEventCenter != null ? input.useEventCenter : true
6403        };
6404    }
6405    function interactionSettingsToStore(settings) {
6406        var _a;
6407        return _a = {},
6408            _a[settings.component.uid] = settings,
6409            _a;
6410    }
6411    // global state
6412    var interactionSettingsStore = {};
6413
6414    /*
6415    Detects when the user clicks on an event within a DateComponent
6416    */
6417    var EventClicking = /** @class */ (function (_super) {
6418        __extends(EventClicking, _super);
6419        function EventClicking(settings) {
6420            var _this = _super.call(this, settings) || this;
6421            _this.handleSegClick = function (ev, segEl) {
6422                var component = _this.component;
6423                var seg = getElSeg(segEl);
6424                if (seg && // might be the <div> surrounding the more link
6425                    component.isValidSegDownEl(ev.target)) {
6426                    // our way to simulate a link click for elements that can't be <a> tags
6427                    // grab before trigger fired in case trigger trashes DOM thru rerendering
6428                    var hasUrlContainer = elementClosest(ev.target, '.fc-has-url');
6429                    var url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : '';
6430                    component.publiclyTrigger('eventClick', [
6431                        {
6432                            el: segEl,
6433                            event: new EventApi(component.calendar, seg.eventRange.def, seg.eventRange.instance),
6434                            jsEvent: ev,
6435                            view: component.view
6436                        }
6437                    ]);
6438                    if (url && !ev.defaultPrevented) {
6439                        window.location.href = url;
6440                    }
6441                }
6442            };
6443            var component = settings.component;
6444            _this.destroy = listenBySelector(component.el, 'click', component.fgSegSelector + ',' + component.bgSegSelector, _this.handleSegClick);
6445            return _this;
6446        }
6447        return EventClicking;
6448    }(Interaction));
6449
6450    /*
6451    Triggers events and adds/removes core classNames when the user's pointer
6452    enters/leaves event-elements of a component.
6453    */
6454    var EventHovering = /** @class */ (function (_super) {
6455        __extends(EventHovering, _super);
6456        function EventHovering(settings) {
6457            var _this = _super.call(this, settings) || this;
6458            // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it
6459            _this.handleEventElRemove = function (el) {
6460                if (el === _this.currentSegEl) {
6461                    _this.handleSegLeave(null, _this.currentSegEl);
6462                }
6463            };
6464            _this.handleSegEnter = function (ev, segEl) {
6465                if (getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper
6466                    segEl.classList.add('fc-allow-mouse-resize');
6467                    _this.currentSegEl = segEl;
6468                    _this.triggerEvent('eventMouseEnter', ev, segEl);
6469                }
6470            };
6471            _this.handleSegLeave = function (ev, segEl) {
6472                if (_this.currentSegEl) {
6473                    segEl.classList.remove('fc-allow-mouse-resize');
6474                    _this.currentSegEl = null;
6475                    _this.triggerEvent('eventMouseLeave', ev, segEl);
6476                }
6477            };
6478            var component = settings.component;
6479            _this.removeHoverListeners = listenToHoverBySelector(component.el, component.fgSegSelector + ',' + component.bgSegSelector, _this.handleSegEnter, _this.handleSegLeave);
6480            component.calendar.on('eventElRemove', _this.handleEventElRemove);
6481            return _this;
6482        }
6483        EventHovering.prototype.destroy = function () {
6484            this.removeHoverListeners();
6485            this.component.calendar.off('eventElRemove', this.handleEventElRemove);
6486        };
6487        EventHovering.prototype.triggerEvent = function (publicEvName, ev, segEl) {
6488            var component = this.component;
6489            var seg = getElSeg(segEl);
6490            if (!ev || component.isValidSegDownEl(ev.target)) {
6491                component.publiclyTrigger(publicEvName, [
6492                    {
6493                        el: segEl,
6494                        event: new EventApi(this.component.calendar, seg.eventRange.def, seg.eventRange.instance),
6495                        jsEvent: ev,
6496                        view: component.view
6497                    }
6498                ]);
6499            }
6500        };
6501        return EventHovering;
6502    }(Interaction));
6503
6504    var StandardTheme = /** @class */ (function (_super) {
6505        __extends(StandardTheme, _super);
6506        function StandardTheme() {
6507            return _super !== null && _super.apply(this, arguments) || this;
6508        }
6509        return StandardTheme;
6510    }(Theme));
6511    StandardTheme.prototype.classes = {
6512        widget: 'fc-unthemed',
6513        widgetHeader: 'fc-widget-header',
6514        widgetContent: 'fc-widget-content',
6515        buttonGroup: 'fc-button-group',
6516        button: 'fc-button fc-button-primary',
6517        buttonActive: 'fc-button-active',
6518        popoverHeader: 'fc-widget-header',
6519        popoverContent: 'fc-widget-content',
6520        // day grid
6521        headerRow: 'fc-widget-header',
6522        dayRow: 'fc-widget-content',
6523        // list view
6524        listView: 'fc-widget-content'
6525    };
6526    StandardTheme.prototype.baseIconClass = 'fc-icon';
6527    StandardTheme.prototype.iconClasses = {
6528        close: 'fc-icon-x',
6529        prev: 'fc-icon-chevron-left',
6530        next: 'fc-icon-chevron-right',
6531        prevYear: 'fc-icon-chevrons-left',
6532        nextYear: 'fc-icon-chevrons-right'
6533    };
6534    StandardTheme.prototype.iconOverrideOption = 'buttonIcons';
6535    StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon';
6536    StandardTheme.prototype.iconOverridePrefix = 'fc-icon-';
6537
6538    var Calendar = /** @class */ (function () {
6539        function Calendar(el, overrides) {
6540            var _this = this;
6541            this.parseRawLocales = memoize(parseRawLocales);
6542            this.buildLocale = memoize(buildLocale);
6543            this.buildDateEnv = memoize(buildDateEnv);
6544            this.buildTheme = memoize(buildTheme);
6545            this.buildEventUiSingleBase = memoize(this._buildEventUiSingleBase);
6546            this.buildSelectionConfig = memoize(this._buildSelectionConfig);
6547            this.buildEventUiBySource = memoizeOutput(buildEventUiBySource, isPropsEqual);
6548            this.buildEventUiBases = memoize(buildEventUiBases);
6549            this.interactionsStore = {};
6550            this.actionQueue = [];
6551            this.isReducing = false;
6552            // isDisplaying: boolean = false // installed in DOM? accepting renders?
6553            this.needsRerender = false; // needs a render?
6554            this.needsFullRerender = false;
6555            this.isRendering = false; // currently in the executeRender function?
6556            this.renderingPauseDepth = 0;
6557            this.buildDelayedRerender = memoize(buildDelayedRerender);
6558            this.afterSizingTriggers = {};
6559            this.isViewUpdated = false;
6560            this.isDatesUpdated = false;
6561            this.isEventsUpdated = false;
6562            this.el = el;
6563            this.optionsManager = new OptionsManager(overrides || {});
6564            this.pluginSystem = new PluginSystem();
6565            // only do once. don't do in handleOptions. because can't remove plugins
6566            this.addPluginInputs(this.optionsManager.computed.plugins || []);
6567            this.handleOptions(this.optionsManager.computed);
6568            this.publiclyTrigger('_init'); // for tests
6569            this.hydrate();
6570            this.calendarInteractions = this.pluginSystem.hooks.calendarInteractions
6571                .map(function (calendarInteractionClass) {
6572                return new calendarInteractionClass(_this);
6573            });
6574        }
6575        Calendar.prototype.addPluginInputs = function (pluginInputs) {
6576            var pluginDefs = refinePluginDefs(pluginInputs);
6577            for (var _i = 0, pluginDefs_1 = pluginDefs; _i < pluginDefs_1.length; _i++) {
6578                var pluginDef = pluginDefs_1[_i];
6579                this.pluginSystem.add(pluginDef);
6580            }
6581        };
6582        Object.defineProperty(Calendar.prototype, "view", {
6583            // public API
6584            get: function () {
6585                return this.component ? this.component.view : null;
6586            },
6587            enumerable: true,
6588            configurable: true
6589        });
6590        // Public API for rendering
6591        // -----------------------------------------------------------------------------------------------------------------
6592        Calendar.prototype.render = function () {
6593            if (!this.component) {
6594                this.renderableEventStore = createEmptyEventStore();
6595                this.bindHandlers();
6596                this.executeRender();
6597            }
6598            else {
6599                this.requestRerender(true);
6600            }
6601        };
6602        Calendar.prototype.destroy = function () {
6603            if (this.component) {
6604                this.unbindHandlers();
6605                this.component.destroy(); // don't null-out. in case API needs access
6606                this.component = null; // umm ???
6607                for (var _i = 0, _a = this.calendarInteractions; _i < _a.length; _i++) {
6608                    var interaction = _a[_i];
6609                    interaction.destroy();
6610                }
6611                this.publiclyTrigger('_destroyed');
6612            }
6613        };
6614        // Handlers
6615        // -----------------------------------------------------------------------------------------------------------------
6616        Calendar.prototype.bindHandlers = function () {
6617            var _this = this;
6618            // event delegation for nav links
6619            this.removeNavLinkListener = listenBySelector(this.el, 'click', 'a[data-goto]', function (ev, anchorEl) {
6620                var gotoOptions = anchorEl.getAttribute('data-goto');
6621                gotoOptions = gotoOptions ? JSON.parse(gotoOptions) : {};
6622                var dateEnv = _this.dateEnv;
6623                var dateMarker = dateEnv.createMarker(gotoOptions.date);
6624                var viewType = gotoOptions.type;
6625                // property like "navLinkDayClick". might be a string or a function
6626                var customAction = _this.viewOpt('navLink' + capitaliseFirstLetter(viewType) + 'Click');
6627                if (typeof customAction === 'function') {
6628                    customAction(dateEnv.toDate(dateMarker), ev);
6629                }
6630                else {
6631                    if (typeof customAction === 'string') {
6632                        viewType = customAction;
6633                    }
6634                    _this.zoomTo(dateMarker, viewType);
6635                }
6636            });
6637            if (this.opt('handleWindowResize')) {
6638                window.addEventListener('resize', this.windowResizeProxy = debounce(// prevents rapid calls
6639                this.windowResize.bind(this), this.opt('windowResizeDelay')));
6640            }
6641        };
6642        Calendar.prototype.unbindHandlers = function () {
6643            this.removeNavLinkListener();
6644            if (this.windowResizeProxy) {
6645                window.removeEventListener('resize', this.windowResizeProxy);
6646                this.windowResizeProxy = null;
6647            }
6648        };
6649        // Dispatcher
6650        // -----------------------------------------------------------------------------------------------------------------
6651        Calendar.prototype.hydrate = function () {
6652            var _this = this;
6653            this.state = this.buildInitialState();
6654            var rawSources = this.opt('eventSources') || [];
6655            var singleRawSource = this.opt('events');
6656            var sources = []; // parsed
6657            if (singleRawSource) {
6658                rawSources.unshift(singleRawSource);
6659            }
6660            for (var _i = 0, rawSources_1 = rawSources; _i < rawSources_1.length; _i++) {
6661                var rawSource = rawSources_1[_i];
6662                var source = parseEventSource(rawSource, this);
6663                if (source) {
6664                    sources.push(source);
6665                }
6666            }
6667            this.batchRendering(function () {
6668                _this.dispatch({ type: 'INIT' }); // pass in sources here?
6669                _this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: sources });
6670                _this.dispatch({
6671                    type: 'SET_VIEW_TYPE',
6672                    viewType: _this.opt('defaultView') || _this.pluginSystem.hooks.defaultView
6673                });
6674            });
6675        };
6676        Calendar.prototype.buildInitialState = function () {
6677            return {
6678                viewType: null,
6679                loadingLevel: 0,
6680                eventSourceLoadingLevel: 0,
6681                currentDate: this.getInitialDate(),
6682                dateProfile: null,
6683                eventSources: {},
6684                eventStore: createEmptyEventStore(),
6685                dateSelection: null,
6686                eventSelection: '',
6687                eventDrag: null,
6688                eventResize: null
6689            };
6690        };
6691        Calendar.prototype.dispatch = function (action) {
6692            this.actionQueue.push(action);
6693            if (!this.isReducing) {
6694                this.isReducing = true;
6695                var oldState = this.state;
6696                while (this.actionQueue.length) {
6697                    this.state = this.reduce(this.state, this.actionQueue.shift(), this);
6698                }
6699                var newState = this.state;
6700                this.isReducing = false;
6701                if (!oldState.loadingLevel && newState.loadingLevel) {
6702                    this.publiclyTrigger('loading', [true]);
6703                }
6704                else if (oldState.loadingLevel && !newState.loadingLevel) {
6705                    this.publiclyTrigger('loading', [false]);
6706                }
6707                var view = this.component && this.component.view;
6708                if (oldState.eventStore !== newState.eventStore || this.needsFullRerender) {
6709                    if (oldState.eventStore) {
6710                        this.isEventsUpdated = true;
6711                    }
6712                }
6713                if (oldState.dateProfile !== newState.dateProfile || this.needsFullRerender) {
6714                    if (oldState.dateProfile && view) { // why would view be null!?
6715                        this.publiclyTrigger('datesDestroy', [
6716                            {
6717                                view: view,
6718                                el: view.el
6719                            }
6720                        ]);
6721                    }
6722                    this.isDatesUpdated = true;
6723                }
6724                if (oldState.viewType !== newState.viewType || this.needsFullRerender) {
6725                    if (oldState.viewType && view) { // why would view be null!?
6726                        this.publiclyTrigger('viewSkeletonDestroy', [
6727                            {
6728                                view: view,
6729                                el: view.el
6730                            }
6731                        ]);
6732                    }
6733                    this.isViewUpdated = true;
6734                }
6735                this.requestRerender();
6736            }
6737        };
6738        Calendar.prototype.reduce = function (state, action, calendar) {
6739            return reduce(state, action, calendar);
6740        };
6741        // Render Queue
6742        // -----------------------------------------------------------------------------------------------------------------
6743        Calendar.prototype.requestRerender = function (needsFull) {
6744            if (needsFull === void 0) { needsFull = false; }
6745            this.needsRerender = true;
6746            this.needsFullRerender = this.needsFullRerender || needsFull;
6747            this.delayedRerender(); // will call a debounced-version of tryRerender
6748        };
6749        Calendar.prototype.tryRerender = function () {
6750            if (this.component && // must be accepting renders
6751                this.needsRerender && // indicates that a rerender was requested
6752                !this.renderingPauseDepth && // not paused
6753                !this.isRendering // not currently in the render loop
6754            ) {
6755                this.executeRender();
6756            }
6757        };
6758        Calendar.prototype.batchRendering = function (func) {
6759            this.renderingPauseDepth++;
6760            func();
6761            this.renderingPauseDepth--;
6762            if (this.needsRerender) {
6763                this.requestRerender();
6764            }
6765        };
6766        // Rendering
6767        // -----------------------------------------------------------------------------------------------------------------
6768        Calendar.prototype.executeRender = function () {
6769            var needsFullRerender = this.needsFullRerender; // save before clearing
6770            // clear these BEFORE the render so that new values will accumulate during render
6771            this.needsRerender = false;
6772            this.needsFullRerender = false;
6773            this.isRendering = true;
6774            this.renderComponent(needsFullRerender);
6775            this.isRendering = false;
6776            // received a rerender request while rendering
6777            if (this.needsRerender) {
6778                this.delayedRerender();
6779            }
6780        };
6781        /*
6782        don't call this directly. use executeRender instead
6783        */
6784        Calendar.prototype.renderComponent = function (needsFull) {
6785            var _a = this, state = _a.state, component = _a.component;
6786            var viewType = state.viewType;
6787            var viewSpec = this.viewSpecs[viewType];
6788            var savedScroll = (needsFull && component) ? component.view.queryScroll() : null;
6789            if (!viewSpec) {
6790                throw new Error("View type \"" + viewType + "\" is not valid");
6791            }
6792            // if event sources are still loading and progressive rendering hasn't been enabled,
6793            // keep rendering the last fully loaded set of events
6794            var renderableEventStore = this.renderableEventStore =
6795                (state.eventSourceLoadingLevel && !this.opt('progressiveEventRendering')) ?
6796                    this.renderableEventStore :
6797                    state.eventStore;
6798            var eventUiSingleBase = this.buildEventUiSingleBase(viewSpec.options);
6799            var eventUiBySource = this.buildEventUiBySource(state.eventSources);
6800            var eventUiBases = this.eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource);
6801            if (needsFull || !component) {
6802                if (component) {
6803                    component.freezeHeight(); // next component will unfreeze it
6804                    component.destroy();
6805                }
6806                component = this.component = new CalendarComponent({
6807                    calendar: this,
6808                    view: null,
6809                    dateEnv: this.dateEnv,
6810                    theme: this.theme,
6811                    options: this.optionsManager.computed
6812                }, this.el);
6813                this.isViewUpdated = true;
6814                this.isDatesUpdated = true;
6815                this.isEventsUpdated = true;
6816            }
6817            component.receiveProps(__assign({}, state, { viewSpec: viewSpec, dateProfile: state.dateProfile, dateProfileGenerator: this.dateProfileGenerators[viewType], eventStore: renderableEventStore, eventUiBases: eventUiBases, dateSelection: state.dateSelection, eventSelection: state.eventSelection, eventDrag: state.eventDrag, eventResize: state.eventResize }));
6818            if (savedScroll) {
6819                component.view.applyScroll(savedScroll, false);
6820            }
6821            if (this.isViewUpdated) {
6822                this.isViewUpdated = false;
6823                this.publiclyTrigger('viewSkeletonRender', [
6824                    {
6825                        view: component.view,
6826                        el: component.view.el
6827                    }
6828                ]);
6829            }
6830            if (this.isDatesUpdated) {
6831                this.isDatesUpdated = false;
6832                this.publiclyTrigger('datesRender', [
6833                    {
6834                        view: component.view,
6835                        el: component.view.el
6836                    }
6837                ]);
6838            }
6839            if (this.isEventsUpdated) {
6840                this.isEventsUpdated = false;
6841            }
6842            this.releaseAfterSizingTriggers();
6843        };
6844        // Options
6845        // -----------------------------------------------------------------------------------------------------------------
6846        Calendar.prototype.setOption = function (name, val) {
6847            var _a;
6848            this.mutateOptions((_a = {}, _a[name] = val, _a), [], true);
6849        };
6850        Calendar.prototype.getOption = function (name) {
6851            return this.optionsManager.computed[name];
6852        };
6853        Calendar.prototype.opt = function (name) {
6854            return this.optionsManager.computed[name];
6855        };
6856        Calendar.prototype.viewOpt = function (name) {
6857            return this.viewOpts()[name];
6858        };
6859        Calendar.prototype.viewOpts = function () {
6860            return this.viewSpecs[this.state.viewType].options;
6861        };
6862        /*
6863        handles option changes (like a diff)
6864        */
6865        Calendar.prototype.mutateOptions = function (updates, removals, isDynamic, deepEqual) {
6866            var _this = this;
6867            var changeHandlers = this.pluginSystem.hooks.optionChangeHandlers;
6868            var normalUpdates = {};
6869            var specialUpdates = {};
6870            var oldDateEnv = this.dateEnv; // do this before handleOptions
6871            var isTimeZoneDirty = false;
6872            var isSizeDirty = false;
6873            var anyDifficultOptions = Boolean(removals.length);
6874            for (var name_1 in updates) {
6875                if (changeHandlers[name_1]) {
6876                    specialUpdates[name_1] = updates[name_1];
6877                }
6878                else {
6879                    normalUpdates[name_1] = updates[name_1];
6880                }
6881            }
6882            for (var name_2 in normalUpdates) {
6883                if (/^(height|contentHeight|aspectRatio)$/.test(name_2)) {
6884                    isSizeDirty = true;
6885                }
6886                else if (/^(defaultDate|defaultView)$/.test(name_2)) ;
6887                else {
6888                    anyDifficultOptions = true;
6889                    if (name_2 === 'timeZone') {
6890                        isTimeZoneDirty = true;
6891                    }
6892                }
6893            }
6894            this.optionsManager.mutate(normalUpdates, removals, isDynamic);
6895            if (anyDifficultOptions) {
6896                this.handleOptions(this.optionsManager.computed);
6897                this.needsFullRerender = true;
6898            }
6899            this.batchRendering(function () {
6900                if (anyDifficultOptions) {
6901                    if (isTimeZoneDirty) {
6902                        _this.dispatch({
6903                            type: 'CHANGE_TIMEZONE',
6904                            oldDateEnv: oldDateEnv
6905                        });
6906                    }
6907                    /* HACK
6908                    has the same effect as calling this.requestRerender(true)
6909                    but recomputes the state's dateProfile
6910                    */
6911                    _this.dispatch({
6912                        type: 'SET_VIEW_TYPE',
6913                        viewType: _this.state.viewType
6914                    });
6915                }
6916                else if (isSizeDirty) {
6917                    _this.updateSize();
6918                }
6919                // special updates
6920                if (deepEqual) {
6921                    for (var name_3 in specialUpdates) {
6922                        changeHandlers[name_3](specialUpdates[name_3], _this, deepEqual);
6923                    }
6924                }
6925            });
6926        };
6927        /*
6928        rebuilds things based off of a complete set of refined options
6929        */
6930        Calendar.prototype.handleOptions = function (options) {
6931            var _this = this;
6932            var pluginHooks = this.pluginSystem.hooks;
6933            this.defaultAllDayEventDuration = createDuration(options.defaultAllDayEventDuration);
6934            this.defaultTimedEventDuration = createDuration(options.defaultTimedEventDuration);
6935            this.delayedRerender = this.buildDelayedRerender(options.rerenderDelay);
6936            this.theme = this.buildTheme(options);
6937            var available = this.parseRawLocales(options.locales);
6938            this.availableRawLocales = available.map;
6939            var locale = this.buildLocale(options.locale || available.defaultCode, available.map);
6940            this.dateEnv = this.buildDateEnv(locale, options.timeZone, pluginHooks.namedTimeZonedImpl, options.firstDay, options.weekNumberCalculation, options.weekLabel, pluginHooks.cmdFormatter);
6941            this.selectionConfig = this.buildSelectionConfig(options); // needs dateEnv. do after :(
6942            // ineffecient to do every time?
6943            this.viewSpecs = buildViewSpecs(pluginHooks.views, this.optionsManager);
6944            // ineffecient to do every time?
6945            this.dateProfileGenerators = mapHash(this.viewSpecs, function (viewSpec) {
6946                return new viewSpec.class.prototype.dateProfileGeneratorClass(viewSpec, _this);
6947            });
6948        };
6949        Calendar.prototype.getAvailableLocaleCodes = function () {
6950            return Object.keys(this.availableRawLocales);
6951        };
6952        Calendar.prototype._buildSelectionConfig = function (rawOpts) {
6953            return processScopedUiProps('select', rawOpts, this);
6954        };
6955        Calendar.prototype._buildEventUiSingleBase = function (rawOpts) {
6956            if (rawOpts.editable) { // so 'editable' affected events
6957                rawOpts = __assign({}, rawOpts, { eventEditable: true });
6958            }
6959            return processScopedUiProps('event', rawOpts, this);
6960        };
6961        // Trigger
6962        // -----------------------------------------------------------------------------------------------------------------
6963        Calendar.prototype.hasPublicHandlers = function (name) {
6964            return this.hasHandlers(name) ||
6965                this.opt(name); // handler specified in options
6966        };
6967        Calendar.prototype.publiclyTrigger = function (name, args) {
6968            var optHandler = this.opt(name);
6969            this.triggerWith(name, this, args);
6970            if (optHandler) {
6971                return optHandler.apply(this, args);
6972            }
6973        };
6974        Calendar.prototype.publiclyTriggerAfterSizing = function (name, args) {
6975            var afterSizingTriggers = this.afterSizingTriggers;
6976            (afterSizingTriggers[name] || (afterSizingTriggers[name] = [])).push(args);
6977        };
6978        Calendar.prototype.releaseAfterSizingTriggers = function () {
6979            var afterSizingTriggers = this.afterSizingTriggers;
6980            for (var name_4 in afterSizingTriggers) {
6981                for (var _i = 0, _a = afterSizingTriggers[name_4]; _i < _a.length; _i++) {
6982                    var args = _a[_i];
6983                    this.publiclyTrigger(name_4, args);
6984                }
6985            }
6986            this.afterSizingTriggers = {};
6987        };
6988        // View
6989        // -----------------------------------------------------------------------------------------------------------------
6990        // Returns a boolean about whether the view is okay to instantiate at some point
6991        Calendar.prototype.isValidViewType = function (viewType) {
6992            return Boolean(this.viewSpecs[viewType]);
6993        };
6994        Calendar.prototype.changeView = function (viewType, dateOrRange) {
6995            var dateMarker = null;
6996            if (dateOrRange) {
6997                if (dateOrRange.start && dateOrRange.end) { // a range
6998                    this.optionsManager.mutate({ visibleRange: dateOrRange }, []); // will not rerender
6999                    this.handleOptions(this.optionsManager.computed); // ...but yuck
7000                }
7001                else { // a date
7002                    dateMarker = this.dateEnv.createMarker(dateOrRange); // just like gotoDate
7003                }
7004            }
7005            this.unselect();
7006            this.dispatch({
7007                type: 'SET_VIEW_TYPE',
7008                viewType: viewType,
7009                dateMarker: dateMarker
7010            });
7011        };
7012        // Forces navigation to a view for the given date.
7013        // `viewType` can be a specific view name or a generic one like "week" or "day".
7014        // needs to change
7015        Calendar.prototype.zoomTo = function (dateMarker, viewType) {
7016            var spec;
7017            viewType = viewType || 'day'; // day is default zoom
7018            spec = this.viewSpecs[viewType] ||
7019                this.getUnitViewSpec(viewType);
7020            this.unselect();
7021            if (spec) {
7022                this.dispatch({
7023                    type: 'SET_VIEW_TYPE',
7024                    viewType: spec.type,
7025                    dateMarker: dateMarker
7026                });
7027            }
7028            else {
7029                this.dispatch({
7030                    type: 'SET_DATE',
7031                    dateMarker: dateMarker
7032                });
7033            }
7034        };
7035        // Given a duration singular unit, like "week" or "day", finds a matching view spec.
7036        // Preference is given to views that have corresponding buttons.
7037        Calendar.prototype.getUnitViewSpec = function (unit) {
7038            var component = this.component;
7039            var viewTypes = [];
7040            var i;
7041            var spec;
7042            // put views that have buttons first. there will be duplicates, but oh
7043            if (component.header) {
7044                viewTypes.push.apply(viewTypes, component.header.viewsWithButtons);
7045            }
7046            if (component.footer) {
7047                viewTypes.push.apply(viewTypes, component.footer.viewsWithButtons);
7048            }
7049            for (var viewType in this.viewSpecs) {
7050                viewTypes.push(viewType);
7051            }
7052            for (i = 0; i < viewTypes.length; i++) {
7053                spec = this.viewSpecs[viewTypes[i]];
7054                if (spec) {
7055                    if (spec.singleUnit === unit) {
7056                        return spec;
7057                    }
7058                }
7059            }
7060        };
7061        // Current Date
7062        // -----------------------------------------------------------------------------------------------------------------
7063        Calendar.prototype.getInitialDate = function () {
7064            var defaultDateInput = this.opt('defaultDate');
7065            // compute the initial ambig-timezone date
7066            if (defaultDateInput != null) {
7067                return this.dateEnv.createMarker(defaultDateInput);
7068            }
7069            else {
7070                return this.getNow(); // getNow already returns unzoned
7071            }
7072        };
7073        Calendar.prototype.prev = function () {
7074            this.unselect();
7075            this.dispatch({ type: 'PREV' });
7076        };
7077        Calendar.prototype.next = function () {
7078            this.unselect();
7079            this.dispatch({ type: 'NEXT' });
7080        };
7081        Calendar.prototype.prevYear = function () {
7082            this.unselect();
7083            this.dispatch({
7084                type: 'SET_DATE',
7085                dateMarker: this.dateEnv.addYears(this.state.currentDate, -1)
7086            });
7087        };
7088        Calendar.prototype.nextYear = function () {
7089            this.unselect();
7090            this.dispatch({
7091                type: 'SET_DATE',
7092                dateMarker: this.dateEnv.addYears(this.state.currentDate, 1)
7093            });
7094        };
7095        Calendar.prototype.today = function () {
7096            this.unselect();
7097            this.dispatch({
7098                type: 'SET_DATE',
7099                dateMarker: this.getNow()
7100            });
7101        };
7102        Calendar.prototype.gotoDate = function (zonedDateInput) {
7103            this.unselect();
7104            this.dispatch({
7105                type: 'SET_DATE',
7106                dateMarker: this.dateEnv.createMarker(zonedDateInput)
7107            });
7108        };
7109        Calendar.prototype.incrementDate = function (deltaInput) {
7110            var delta = createDuration(deltaInput);
7111            if (delta) { // else, warn about invalid input?
7112                this.unselect();
7113                this.dispatch({
7114                    type: 'SET_DATE',
7115                    dateMarker: this.dateEnv.add(this.state.currentDate, delta)
7116                });
7117            }
7118        };
7119        // for external API
7120        Calendar.prototype.getDate = function () {
7121            return this.dateEnv.toDate(this.state.currentDate);
7122        };
7123        // Date Formatting Utils
7124        // -----------------------------------------------------------------------------------------------------------------
7125        Calendar.prototype.formatDate = function (d, formatter) {
7126            var dateEnv = this.dateEnv;
7127            return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter));
7128        };
7129        // `settings` is for formatter AND isEndExclusive
7130        Calendar.prototype.formatRange = function (d0, d1, settings) {
7131            var dateEnv = this.dateEnv;
7132            return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings, this.opt('defaultRangeSeparator')), settings);
7133        };
7134        Calendar.prototype.formatIso = function (d, omitTime) {
7135            var dateEnv = this.dateEnv;
7136            return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime: omitTime });
7137        };
7138        // Sizing
7139        // -----------------------------------------------------------------------------------------------------------------
7140        Calendar.prototype.windowResize = function (ev) {
7141            if (!this.isHandlingWindowResize &&
7142                this.component && // why?
7143                ev.target === window // not a jqui resize event
7144            ) {
7145                this.isHandlingWindowResize = true;
7146                this.updateSize();
7147                this.publiclyTrigger('windowResize', [this.view]);
7148                this.isHandlingWindowResize = false;
7149            }
7150        };
7151        Calendar.prototype.updateSize = function () {
7152            if (this.component) { // when?
7153                this.component.updateSize(true);
7154            }
7155        };
7156        // Component Registration
7157        // -----------------------------------------------------------------------------------------------------------------
7158        Calendar.prototype.registerInteractiveComponent = function (component, settingsInput) {
7159            var settings = parseInteractionSettings(component, settingsInput);
7160            var DEFAULT_INTERACTIONS = [
7161                EventClicking,
7162                EventHovering
7163            ];
7164            var interactionClasses = DEFAULT_INTERACTIONS.concat(this.pluginSystem.hooks.componentInteractions);
7165            var interactions = interactionClasses.map(function (interactionClass) {
7166                return new interactionClass(settings);
7167            });
7168            this.interactionsStore[component.uid] = interactions;
7169            interactionSettingsStore[component.uid] = settings;
7170        };
7171        Calendar.prototype.unregisterInteractiveComponent = function (component) {
7172            for (var _i = 0, _a = this.interactionsStore[component.uid]; _i < _a.length; _i++) {
7173                var listener = _a[_i];
7174                listener.destroy();
7175            }
7176            delete this.interactionsStore[component.uid];
7177            delete interactionSettingsStore[component.uid];
7178        };
7179        // Date Selection / Event Selection / DayClick
7180        // -----------------------------------------------------------------------------------------------------------------
7181        // this public method receives start/end dates in any format, with any timezone
7182        // NOTE: args were changed from v3
7183        Calendar.prototype.select = function (dateOrObj, endDate) {
7184            var selectionInput;
7185            if (endDate == null) {
7186                if (dateOrObj.start != null) {
7187                    selectionInput = dateOrObj;
7188                }
7189                else {
7190                    selectionInput = {
7191                        start: dateOrObj,
7192                        end: null
7193                    };
7194                }
7195            }
7196            else {
7197                selectionInput = {
7198                    start: dateOrObj,
7199                    end: endDate
7200                };
7201            }
7202            var selection = parseDateSpan(selectionInput, this.dateEnv, createDuration({ days: 1 }) // TODO: cache this?
7203            );
7204            if (selection) { // throw parse error otherwise?
7205                this.dispatch({ type: 'SELECT_DATES', selection: selection });
7206                this.triggerDateSelect(selection);
7207            }
7208        };
7209        // public method
7210        Calendar.prototype.unselect = function (pev) {
7211            if (this.state.dateSelection) {
7212                this.dispatch({ type: 'UNSELECT_DATES' });
7213                this.triggerDateUnselect(pev);
7214            }
7215        };
7216        Calendar.prototype.triggerDateSelect = function (selection, pev) {
7217            var arg = __assign({}, this.buildDateSpanApi(selection), { jsEvent: pev ? pev.origEvent : null, view: this.view });
7218            this.publiclyTrigger('select', [arg]);
7219        };
7220        Calendar.prototype.triggerDateUnselect = function (pev) {
7221            this.publiclyTrigger('unselect', [
7222                {
7223                    jsEvent: pev ? pev.origEvent : null,
7224                    view: this.view
7225                }
7226            ]);
7227        };
7228        // TODO: receive pev?
7229        Calendar.prototype.triggerDateClick = function (dateSpan, dayEl, view, ev) {
7230            var arg = __assign({}, this.buildDatePointApi(dateSpan), { dayEl: dayEl, jsEvent: ev, // Is this always a mouse event? See #4655
7231                view: view });
7232            this.publiclyTrigger('dateClick', [arg]);
7233        };
7234        Calendar.prototype.buildDatePointApi = function (dateSpan) {
7235            var props = {};
7236            for (var _i = 0, _a = this.pluginSystem.hooks.datePointTransforms; _i < _a.length; _i++) {
7237                var transform = _a[_i];
7238                __assign(props, transform(dateSpan, this));
7239            }
7240            __assign(props, buildDatePointApi(dateSpan, this.dateEnv));
7241            return props;
7242        };
7243        Calendar.prototype.buildDateSpanApi = function (dateSpan) {
7244            var props = {};
7245            for (var _i = 0, _a = this.pluginSystem.hooks.dateSpanTransforms; _i < _a.length; _i++) {
7246                var transform = _a[_i];
7247                __assign(props, transform(dateSpan, this));
7248            }
7249            __assign(props, buildDateSpanApi(dateSpan, this.dateEnv));
7250            return props;
7251        };
7252        // Date Utils
7253        // -----------------------------------------------------------------------------------------------------------------
7254        // Returns a DateMarker for the current date, as defined by the client's computer or from the `now` option
7255        Calendar.prototype.getNow = function () {
7256            var now = this.opt('now');
7257            if (typeof now === 'function') {
7258                now = now();
7259            }
7260            if (now == null) {
7261                return this.dateEnv.createNowMarker();
7262            }
7263            return this.dateEnv.createMarker(now);
7264        };
7265        // Event-Date Utilities
7266        // -----------------------------------------------------------------------------------------------------------------
7267        // Given an event's allDay status and start date, return what its fallback end date should be.
7268        // TODO: rename to computeDefaultEventEnd
7269        Calendar.prototype.getDefaultEventEnd = function (allDay, marker) {
7270            var end = marker;
7271            if (allDay) {
7272                end = startOfDay(end);
7273                end = this.dateEnv.add(end, this.defaultAllDayEventDuration);
7274            }
7275            else {
7276                end = this.dateEnv.add(end, this.defaultTimedEventDuration);
7277            }
7278            return end;
7279        };
7280        // Public Events API
7281        // -----------------------------------------------------------------------------------------------------------------
7282        Calendar.prototype.addEvent = function (eventInput, sourceIn
7282put) {
7283            if (eventInput instanceof EventApi) {
7284                var def = eventInput._def;
7285                var instance = eventInput._instance;
7286                // not already present? don't want to add an old snapshot
7287                if (!this.state.eventStore.defs[def.defId]) {
7288                    this.dispatch({
7289                        type: 'ADD_EVENTS',
7290                        eventStore: eventTupleToStore({ def: def, instance: instance }) // TODO: better util for two args?
7291                    });
7292                }
7293                return eventInput;
7294            }
7295            var sourceId;
7296            if (sourceInput instanceof EventSourceApi) {
7297                sourceId = sourceInput.internalEventSource.sourceId;
7298            }
7299            else if (sourceInput != null) {
7300                var sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function
7301                if (!sourceApi) {
7302                    console.warn('Could not find an event source with ID "' + sourceInput + '"'); // TODO: test
7303                    return null;
7304                }
7305                else {
7306                    sourceId = sourceApi.internalEventSource.sourceId;
7307                }
7308            }
7309            var tuple = parseEvent(eventInput, sourceId, this);
7310            if (tuple) {
7311                this.dispatch({
7312                    type: 'ADD_EVENTS',
7313                    eventStore: eventTupleToStore(tuple)
7314                });
7315                return new EventApi(this, tuple.def, tuple.def.recurringDef ? null : tuple.instance);
7316            }
7317            return null;
7318        };
7319        // TODO: optimize
7320        Calendar.prototype.getEventById = function (id) {
7321            var _a = this.state.eventStore, defs = _a.defs, instances = _a.instances;
7322            id = String(id);
7323            for (var defId in defs) {
7324                var def = defs[defId];
7325                if (def.publicId === id) {
7326                    if (def.recurringDef) {
7327                        return new EventApi(this, def, null);
7328                    }
7329                    else {
7330                        for (var instanceId in instances) {
7331                            var instance = instances[instanceId];
7332                            if (instance.defId === def.defId) {
7333                                return new EventApi(this, def, instance);
7334                            }
7335                        }
7336                    }
7337                }
7338            }
7339            return null;
7340        };
7341        Calendar.prototype.getEvents = function () {
7342            var _a = this.state.eventStore, defs = _a.defs, instances = _a.instances;
7343            var eventApis = [];
7344            for (var id in instances) {
7345                var instance = instances[id];
7346                var def = defs[instance.defId];
7347                eventApis.push(new EventApi(this, def, instance));
7348            }
7349            return eventApis;
7350        };
7351        Calendar.prototype.removeAllEvents = function () {
7352            this.dispatch({ type: 'REMOVE_ALL_EVENTS' });
7353        };
7354        Calendar.prototype.rerenderEvents = function () {
7355            this.dispatch({ type: 'RESET_EVENTS' });
7356        };
7357        // Public Event Sources API
7358        // -----------------------------------------------------------------------------------------------------------------
7359        Calendar.prototype.getEventSources = function () {
7360            var sourceHash = this.state.eventSources;
7361            var sourceApis = [];
7362            for (var internalId in sourceHash) {
7363                sourceApis.push(new EventSourceApi(this, sourceHash[internalId]));
7364            }
7365            return sourceApis;
7366        };
7367        Calendar.prototype.getEventSourceById = function (id) {
7368            var sourceHash = this.state.eventSources;
7369            id = String(id);
7370            for (var sourceId in sourceHash) {
7371                if (sourceHash[sourceId].publicId === id) {
7372                    return new EventSourceApi(this, sourceHash[sourceId]);
7373                }
7374            }
7375            return null;
7376        };
7377        Calendar.prototype.addEventSource = function (sourceInput) {
7378            if (sourceInput instanceof EventSourceApi) {
7379                // not already present? don't want to add an old snapshot
7380                if (!this.state.eventSources[sourceInput.internalEventSource.sourceId]) {
7381                    this.dispatch({
7382                        type: 'ADD_EVENT_SOURCES',
7383                        sources: [sourceInput.internalEventSource]
7384                    });
7385                }
7386                return sourceInput;
7387            }
7388            var eventSource = parseEventSource(sourceInput, this);
7389            if (eventSource) { // TODO: error otherwise?
7390                this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] });
7391                return new EventSourceApi(this, eventSource);
7392            }
7393            return null;
7394        };
7395        Calendar.prototype.removeAllEventSources = function () {
7396            this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' });
7397        };
7398        Calendar.prototype.refetchEvents = function () {
7399            this.dispatch({ type: 'FETCH_EVENT_SOURCES' });
7400        };
7401        // Scroll
7402        // -----------------------------------------------------------------------------------------------------------------
7403        Calendar.prototype.scrollToTime = function (timeInput) {
7404            var duration = createDuration(timeInput);
7405            if (duration) {
7406                this.component.view.scrollToDuration(duration);
7407            }
7408        };
7409        return Calendar;
7410    }());
7411    EmitterMixin.mixInto(Calendar);
7412    // for memoizers
7413    // -----------------------------------------------------------------------------------------------------------------
7414    function buildDateEnv(locale, timeZone, namedTimeZoneImpl, firstDay, weekNumberCalculation, weekLabel, cmdFormatter) {
7415        return new DateEnv({
7416            calendarSystem: 'gregory',
7417            timeZone: timeZone,
7418            namedTimeZoneImpl: namedTimeZoneImpl,
7419            locale: locale,
7420            weekNumberCalculation: weekNumberCalculation,
7421            firstDay: firstDay,
7422            weekLabel: weekLabel,
7423            cmdFormatter: cmdFormatter
7424        });
7425    }
7426    function buildTheme(calendarOptions) {
7427        var themeClass = this.pluginSystem.hooks.themeClasses[calendarOptions.themeSystem] || StandardTheme;
7428        return new themeClass(calendarOptions);
7429    }
7430    function buildDelayedRerender(wait) {
7431        var func = this.tryRerender.bind(this);
7432        if (wait != null) {
7433            func = debounce(func, wait);
7434        }
7435        return func;
7436    }
7437    function buildEventUiBySource(eventSources) {
7438        return mapHash(eventSources, function (eventSource) {
7439            return eventSource.ui;
7440        });
7441    }
7442    function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) {
7443        var eventUiBases = { '': eventUiSingleBase };
7444        for (var defId in eventDefs) {
7445            var def = eventDefs[defId];
7446            if (def.sourceId && eventUiBySource[def.sourceId]) {
7447                eventUiBases[defId] = eventUiBySource[def.sourceId];
7448            }
7449        }
7450        return eventUiBases;
7451    }
7452
7453    var View = /** @class */ (function (_super) {
7454        __extends(View, _super);
7455        function View(context, viewSpec, dateProfileGenerator, parentEl) {
7456            var _this = _super.call(this, context, createElement('div', { className: 'fc-view fc-' + viewSpec.type + '-view' }), true // isView (HACK)
7457            ) || this;
7458            _this.renderDatesMem = memoizeRendering(_this.renderDatesWrap, _this.unrenderDatesWrap);
7459            _this.renderBusinessHoursMem = memoizeRendering(_this.renderBusinessHours, _this.unrenderBusinessHours, [_this.renderDatesMem]);
7460            _this.renderDateSelectionMem = memoizeRendering(_this.renderDateSelectionWrap, _this.unrenderDateSelectionWrap, [_this.renderDatesMem]);
7461            _this.renderEventsMem = memoizeRendering(_this.renderEvents, _this.unrenderEvents, [_this.renderDatesMem]);
7462            _this.renderEventSelectionMem = memoizeRendering(_this.renderEventSelectionWrap, _this.unrenderEventSelectionWrap, [_this.renderEventsMem]);
7463            _this.renderEventDragMem = memoizeRendering(_this.renderEventDragWrap, _this.unrenderEventDragWrap, [_this.renderDatesMem]);
7464            _this.renderEventResizeMem = memoizeRendering(_this.renderEventResizeWrap, _this.unrenderEventResizeWrap, [_this.renderDatesMem]);
7465            _this.viewSpec = viewSpec;
7466            _this.dateProfileGenerator = dateProfileGenerator;
7467            _this.type = viewSpec.type;
7468            _this.eventOrderSpecs = parseFieldSpecs(_this.opt('eventOrder'));
7469            _this.nextDayThreshold = createDuration(_this.opt('nextDayThreshold'));
7470            parentEl.appendChild(_this.el);
7471            _this.initialize();
7472            return _this;
7473        }
7474        View.prototype.initialize = function () {
7475        };
7476        Object.defineProperty(View.prototype, "activeStart", {
7477            // Date Setting/Unsetting
7478            // -----------------------------------------------------------------------------------------------------------------
7479            get: function () {
7480                return this.dateEnv.toDate(this.props.dateProfile.activeRange.start);
7481            },
7482            enumerable: true,
7483            configurable: true
7484        });
7485        Object.defineProperty(View.prototype, "activeEnd", {
7486            get: function () {
7487                return this.dateEnv.toDate(this.props.dateProfile.activeRange.end);
7488            },
7489            enumerable: true,
7490            configurable: true
7491        });
7492        Object.defineProperty(View.prototype, "currentStart", {
7493            get: function () {
7494                return this.dateEnv.toDate(this.props.dateProfile.currentRange.start);
7495            },
7496            enumerable: true,
7497            configurable: true
7498        });
7499        Object.defineProperty(View.prototype, "currentEnd", {
7500            get: function () {
7501                return this.dateEnv.toDate(this.props.dateProfile.currentRange.end);
7502            },
7503            enumerable: true,
7504            configurable: true
7505        });
7506        // General Rendering
7507        // -----------------------------------------------------------------------------------------------------------------
7508        View.prototype.render = function (props) {
7509            this.renderDatesMem(props.dateProfile);
7510            this.renderBusinessHoursMem(props.businessHours);
7511            this.renderDateSelectionMem(props.dateSelection);
7512            this.renderEventsMem(props.eventStore);
7513            this.renderEventSelectionMem(props.eventSelection);
7514            this.renderEventDragMem(props.eventDrag);
7515            this.renderEventResizeMem(props.eventResize);
7516        };
7517        View.prototype.destroy = function () {
7518            _super.prototype.destroy.call(this);
7519            this.renderDatesMem.unrender(); // should unrender everything else
7520        };
7521        // Sizing
7522        // -----------------------------------------------------------------------------------------------------------------
7523        View.prototype.updateSize = function (isResize, viewHeight, isAuto) {
7524            var calendar = this.calendar;
7525            if (isResize || // HACKS...
7526                calendar.isViewUpdated ||
7527                calendar.isDatesUpdated ||
7528                calendar.isEventsUpdated) {
7529                // sort of the catch-all sizing
7530                // anything that might cause dimension changes
7531                this.updateBaseSize(isResize, viewHeight, isAuto);
7532            }
7533        };
7534        View.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) {
7535        };
7536        // Date Rendering
7537        // -----------------------------------------------------------------------------------------------------------------
7538        View.prototype.renderDatesWrap = function (dateProfile) {
7539            this.renderDates(dateProfile);
7540            this.addScroll({
7541                duration: createDuration(this.opt('scrollTime'))
7542            });
7543            this.startNowIndicator(dateProfile); // shouldn't render yet because updateSize will be called soon
7544        };
7545        View.prototype.unrenderDatesWrap = function () {
7546            this.stopNowIndicator();
7547            this.unrenderDates();
7548        };
7549        View.prototype.renderDates = function (dateProfile) { };
7550        View.prototype.unrenderDates = function () { };
7551        // Business Hours
7552        // -----------------------------------------------------------------------------------------------------------------
7553        View.prototype.renderBusinessHours = function (businessHours) { };
7554        View.prototype.unrenderBusinessHours = function () { };
7555        // Date Selection
7556        // -----------------------------------------------------------------------------------------------------------------
7557        View.prototype.renderDateSelectionWrap = function (selection) {
7558            if (selection) {
7559                this.renderDateSelection(selection);
7560            }
7561        };
7562        View.prototype.unrenderDateSelectionWrap = function (selection) {
7563            if (selection) {
7564                this.unrenderDateSelection(selection);
7565            }
7566        };
7567        View.prototype.renderDateSelection = function (selection) { };
7568        View.prototype.unrenderDateSelection = function (selection) { };
7569        // Event Rendering
7570        // -----------------------------------------------------------------------------------------------------------------
7571        View.prototype.renderEvents = function (eventStore) { };
7572        View.prototype.unrenderEvents = function () { };
7573        // util for subclasses
7574        View.prototype.sliceEvents = function (eventStore, allDay) {
7575            var props = this.props;
7576            return sliceEventStore(eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? this.nextDayThreshold : null).fg;
7577        };
7578        View.prototype.computeEventDraggable = function (eventDef, eventUi) {
7579            var transformers = this.calendar.pluginSystem.hooks.isDraggableTransformers;
7580            var val = eventUi.startEditable;
7581            for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) {
7582                var transformer = transformers_1[_i];
7583                val = transformer(val, eventDef, eventUi, this);
7584            }
7585            return val;
7586        };
7587        View.prototype.computeEventStartResizable = function (eventDef, eventUi) {
7588            return eventUi.durationEditable && this.opt('eventResizableFromStart');
7589        };
7590        View.prototype.computeEventEndResizable = function (eventDef, eventUi) {
7591            return eventUi.durationEditable;
7592        };
7593        // Event Selection
7594        // -----------------------------------------------------------------------------------------------------------------
7595        View.prototype.renderEventSelectionWrap = function (instanceId) {
7596            if (instanceId) {
7597                this.renderEventSelection(instanceId);
7598            }
7599        };
7600        View.prototype.unrenderEventSelectionWrap = function (instanceId) {
7601            if (instanceId) {
7602                this.unrenderEventSelection(instanceId);
7603            }
7604        };
7605        View.prototype.renderEventSelection = function (instanceId) { };
7606        View.prototype.unrenderEventSelection = function (instanceId) { };
7607        // Event Drag
7608        // -----------------------------------------------------------------------------------------------------------------
7609        View.prototype.renderEventDragWrap = function (state) {
7610            if (state) {
7611                this.renderEventDrag(state);
7612            }
7613        };
7614        View.prototype.unrenderEventDragWrap = function (state) {
7615            if (state) {
7616                this.unrenderEventDrag(state);
7617            }
7618        };
7619        View.prototype.renderEventDrag = function (state) { };
7620        View.prototype.unrenderEventDrag = function (state) { };
7621        // Event Resize
7622        // -----------------------------------------------------------------------------------------------------------------
7623        View.prototype.renderEventResizeWrap = function (state) {
7624            if (state) {
7625                this.renderEventResize(state);
7626            }
7627        };
7628        View.prototype.unrenderEventResizeWrap = function (state) {
7629            if (state) {
7630                this.unrenderEventResize(state);
7631            }
7632        };
7633        View.prototype.renderEventResize = function (state) { };
7634        View.prototype.unrenderEventResize = function (state) { };
7635        /* Now Indicator
7636        ------------------------------------------------------------------------------------------------------------------*/
7637        // Immediately render the current time indicator and begins re-rendering it at an interval,
7638        // which is defined by this.getNowIndicatorUnit().
7639        // TODO: somehow do this for the current whole day's background too
7640        View.prototype.startNowIndicator = function (dateProfile) {
7641            var _this = this;
7642            var dateEnv = this.dateEnv;
7643            var unit;
7644            var update;
7645            var delay; // ms wait value
7646            if (this.opt('nowIndicator')) {
7647                unit = this.getNowIndicatorUnit(dateProfile);
7648                if (unit) {
7649                    update = this.updateNowIndicator.bind(this);
7650                    this.initialNowDate = this.calendar.getNow();
7651                    this.initialNowQueriedMs = new Date().valueOf();
7652                    // wait until the beginning of the next interval
7653                    delay = dateEnv.add(dateEnv.startOf(this.initialNowDate, unit), createDuration(1, unit)).valueOf() - this.initialNowDate.valueOf();
7654                    // TODO: maybe always use setTimeout, waiting until start of next unit
7655                    this.nowIndicatorTimeoutID = setTimeout(function () {
7656                        _this.nowIndicatorTimeoutID = null;
7657                        update();
7658                        if (unit === 'second') {
7659                            delay = 1000; // every second
7660                        }
7661                        else {
7662                            delay = 1000 * 60; // otherwise, every minute
7663                        }
7664                        _this.nowIndicatorIntervalID = setInterval(update, delay); // update every interval
7665                    }, delay);
7666                }
7667                // rendering will be initiated in updateSize
7668            }
7669        };
7670        // rerenders the now indicator, computing the new current time from the amount of time that has passed
7671        // since the initial getNow call.
7672        View.prototype.updateNowIndicator = function () {
7673            if (this.props.dateProfile && // a way to determine if dates were rendered yet
7674                this.initialNowDate // activated before?
7675            ) {
7676                this.unrenderNowIndicator(); // won't unrender if unnecessary
7677                this.renderNowIndicator(addMs(this.initialNowDate, new Date().valueOf() - this.initialNowQueriedMs));
7678                this.isNowIndicatorRendered = true;
7679            }
7680        };
7681        // Immediately unrenders the view's current time indicator and stops any re-rendering timers.
7682        // Won't cause side effects if indicator isn't rendered.
7683        View.prototype.stopNowIndicator = function () {
7684            if (this.isNowIndicatorRendered) {
7685                if (this.nowIndicatorTimeoutID) {
7686                    clearTimeout(this.nowIndicatorTimeoutID);
7687                    this.nowIndicatorTimeoutID = null;
7688                }
7689                if (this.nowIndicatorIntervalID) {
7690                    clearInterval(this.nowIndicatorIntervalID);
7691                    this.nowIndicatorIntervalID = null;
7692                }
7693                this.unrenderNowIndicator();
7694                this.isNowIndicatorRendered = false;
7695            }
7696        };
7697        View.prototype.getNowIndicatorUnit = function (dateProfile) {
7698            // subclasses should implement
7699        };
7700        // Renders a current time indicator at the given datetime
7701        View.prototype.renderNowIndicator = function (date) {
7702            // SUBCLASSES MUST PASS TO CHILDREN!
7703        };
7704        // Undoes the rendering actions from renderNowIndicator
7705        View.prototype.unrenderNowIndicator = function () {
7706            // SUBCLASSES MUST PASS TO CHILDREN!
7707        };
7708        /* Scroller
7709        ------------------------------------------------------------------------------------------------------------------*/
7710        View.prototype.addScroll = function (scroll) {
7711            var queuedScroll = this.queuedScroll || (this.queuedScroll = {});
7712            __assign(queuedScroll, scroll);
7713        };
7714        View.prototype.popScroll = function (isResize) {
7715            this.applyQueuedScroll(isResize);
7716            this.queuedScroll = null;
7717        };
7718        View.prototype.applyQueuedScroll = function (isResize) {
7719            this.applyScroll(this.queuedScroll || {}, isResize);
7720        };
7721        View.prototype.queryScroll = function () {
7722            var scroll = {};
7723            if (this.props.dateProfile) { // dates rendered yet?
7724                __assign(scroll, this.queryDateScroll());
7725            }
7726            return scroll;
7727        };
7728        View.prototype.applyScroll = function (scroll, isResize) {
7729            var duration = scroll.duration;
7730            if (duration != null) {
7731                delete scroll.duration;
7732                if (this.props.dateProfile) { // dates rendered yet?
7733                    __assign(scroll, this.computeDateScroll(duration));
7734                }
7735            }
7736            if (this.props.dateProfile) { // dates rendered yet?
7737                this.applyDateScroll(scroll);
7738            }
7739        };
7740        View.prototype.computeDateScroll = function (duration) {
7741            return {}; // subclasses must implement
7742        };
7743        View.prototype.queryDateScroll = function () {
7744            return {}; // subclasses must implement
7745        };
7746        View.prototype.applyDateScroll = function (scroll) {
7747            // subclasses must implement
7748        };
7749        // for API
7750        View.prototype.scrollToDuration = function (duration) {
7751            this.applyScroll({ duration: duration }, false);
7752        };
7753        return View;
7754    }(DateComponent));
7755    EmitterMixin.mixInto(View);
7756    View.prototype.usesMinMaxTime = false;
7757    View.prototype.dateProfileGeneratorClass = DateProfileGenerator;
7758
7759    var FgEventRenderer = /** @class */ (function () {
7760        function FgEventRenderer(context) {
7761            this.segs = [];
7762            this.isSizeDirty = false;
7763            this.context = context;
7764        }
7765        FgEventRenderer.prototype.renderSegs = function (segs, mirrorInfo) {
7766            this.rangeUpdated(); // called too frequently :(
7767            // render an `.el` on each seg
7768            // returns a subset of the segs. segs that were actually rendered
7769            segs = this.renderSegEls(segs, mirrorInfo);
7770            this.segs = segs;
7771            this.attachSegs(segs, mirrorInfo);
7772            this.isSizeDirty = true;
7773            this.context.view.triggerRenderedSegs(this.segs, Boolean(mirrorInfo));
7774        };
7775        FgEventRenderer.prototype.unrender = function (_segs, mirrorInfo) {
7776            this.context.view.triggerWillRemoveSegs(this.segs, Boolean(mirrorInfo));
7777            this.detachSegs(this.segs);
7778            this.segs = [];
7779        };
7780        // Updates values that rely on options and also relate to range
7781        FgEventRenderer.prototype.rangeUpdated = function () {
7782            var options = this.context.options;
7783            var displayEventTime;
7784            var displayEventEnd;
7785            this.eventTimeFormat = createFormatter(options.eventTimeFormat || this.computeEventTimeFormat(), options.defaultRangeSeparator);
7786            displayEventTime = options.displayEventTime;
7787            if (displayEventTime == null) {
7788                displayEventTime = this.computeDisplayEventTime(); // might be based off of range
7789            }
7790            displayEventEnd = options.displayEventEnd;
7791            if (displayEventEnd == null) {
7792                displayEventEnd = this.computeDisplayEventEnd(); // might be based off of range
7793            }
7794            this.displayEventTime = displayEventTime;
7795            this.displayEventEnd = displayEventEnd;
7796        };
7797        // Renders and assigns an `el` property for each foreground event segment.
7798        // Only returns segments that successfully rendered.
7799        FgEventRenderer.prototype.renderSegEls = function (segs, mirrorInfo) {
7800            var html = '';
7801            var i;
7802            if (segs.length) { // don't build an empty html string
7803                // build a large concatenation of event segment HTML
7804                for (i = 0; i < segs.length; i++) {
7805                    html += this.renderSegHtml(segs[i], mirrorInfo);
7806                }
7807                // Grab individual elements from the combined HTML string. Use each as the default rendering.
7808                // Then, compute the 'el' for each segment. An el might be null if the eventRender callback returned false.
7809                htmlToElements(html).forEach(function (el, i) {
7810                    var seg = segs[i];
7811                    if (el) {
7812                        seg.el = el;
7813                    }
7814                });
7815                segs = filterSegsViaEls(this.context.view, segs, Boolean(mirrorInfo));
7816            }
7817            return segs;
7818        };
7819        // Generic utility for generating the HTML classNames for an event segment's element
7820        FgEventRenderer.prototype.getSegClasses = function (seg, isDraggable, isResizable, mirrorInfo) {
7821            var classes = [
7822                'fc-event',
7823                seg.isStart ? 'fc-start' : 'fc-not-start',
7824                seg.isEnd ? 'fc-end' : 'fc-not-end'
7825            ].concat(seg.eventRange.ui.classNames);
7826            if (isDraggable) {
7827                classes.push('fc-draggable');
7828            }
7829            if (isResizable) {
7830                classes.push('fc-resizable');
7831            }
7832            if (mirrorInfo) {
7833                classes.push('fc-mirror');
7834                if (mirrorInfo.isDragging) {
7835                    classes.push('fc-dragging');
7836                }
7837                if (mirrorInfo.isResizing) {
7838                    classes.push('fc-resizing');
7839                }
7840            }
7841            return classes;
7842        };
7843        // Compute the text that should be displayed on an event's element.
7844        // `range` can be the Event object itself, or something range-like, with at least a `start`.
7845        // If event times are disabled, or the event has no time, will return a blank string.
7846        // If not specified, formatter will default to the eventTimeFormat setting,
7847        // and displayEnd will default to the displayEventEnd setting.
7848        FgEventRenderer.prototype.getTimeText = function (eventRange, formatter, displayEnd) {
7849            var def = eventRange.def, instance = eventRange.instance;
7850            return this._getTimeText(instance.range.start, def.hasEnd ? instance.range.end : null, def.allDay, formatter, displayEnd, instance.forcedStartTzo, instance.forcedEndTzo);
7851        };
7852        FgEventRenderer.prototype._getTimeText = function (start, end, allDay, formatter, displayEnd, forcedStartTzo, forcedEndTzo) {
7853            var dateEnv = this.context.dateEnv;
7854            if (formatter == null) {
7855                formatter = this.eventTimeFormat;
7856            }
7857            if (displayEnd == null) {
7858                displayEnd = this.displayEventEnd;
7859            }
7860            if (this.displayEventTime && !allDay) {
7861                if (displayEnd && end) {
7862                    return dateEnv.formatRange(start, end, formatter, {
7863                        forcedStartTzo: forcedStartTzo,
7864                        forcedEndTzo: forcedEndTzo
7865                    });
7866                }
7867                else {
7868                    return dateEnv.format(start, formatter, {
7869                        forcedTzo: forcedStartTzo
7870                    });
7871                }
7872            }
7873            return '';
7874        };
7875        FgEventRenderer.prototype.computeEventTimeFormat = function () {
7876            return {
7877                hour: 'numeric',
7878                minute: '2-digit',
7879                omitZeroMinute: true
7880            };
7881        };
7882        FgEventRenderer.prototype.computeDisplayEventTime = function () {
7883            return true;
7884        };
7885        FgEventRenderer.prototype.computeDisplayEventEnd = function () {
7886            return true;
7887        };
7888        // Utility for generating event skin-related CSS properties
7889        FgEventRenderer.prototype.getSkinCss = function (ui) {
7890            return {
7891                'background-color': ui.backgroundColor,
7892                'border-color': ui.borderColor,
7893                color: ui.textColor
7894            };
7895        };
7896        FgEventRenderer.prototype.sortEventSegs = function (segs) {
7897            var specs = this.context.view.eventOrderSpecs;
7898            var objs = segs.map(buildSegCompareObj);
7899            objs.sort(function (obj0, obj1) {
7900                return compareByFieldSpecs(obj0, obj1, specs);
7901            });
7902            return objs.map(function (c) {
7903                return c._seg;
7904            });
7905        };
7906        FgEventRenderer.prototype.computeSizes = function (force) {
7907            if (force || this.isSizeDirty) {
7908                this.computeSegSizes(this.segs);
7909            }
7910        };
7911        FgEventRenderer.prototype.assignSizes = function (force) {
7912            if (force || this.isSizeDirty) {
7913                this.assignSegSizes(this.segs);
7914                this.isSizeDirty = false;
7915            }
7916        };
7917        FgEventRenderer.prototype.computeSegSizes = function (segs) {
7918        };
7919        FgEventRenderer.prototype.assignSegSizes = function (segs) {
7920        };
7921        // Manipulation on rendered segs
7922        FgEventRenderer.prototype.hideByHash = function (hash) {
7923            if (hash) {
7924                for (var _i = 0, _a = this.segs; _i < _a.length; _i++) {
7925                    var seg = _a[_i];
7926                    if (hash[seg.eventRange.instance.instanceId]) {
7927                        seg.el.style.visibility = 'hidden';
7928                    }
7929                }
7930            }
7931        };
7932        FgEventRenderer.prototype.showByHash = function (hash) {
7933            if (hash) {
7934                for (var _i = 0, _a = this.segs; _i < _a.length; _i++) {
7935                    var seg = _a[_i];
7936                    if (hash[seg.eventRange.instance.instanceId]) {
7937                        seg.el.style.visibility = '';
7938                    }
7939                }
7940            }
7941        };
7942        FgEventRenderer.prototype.selectByInstanceId = function (instanceId) {
7943            if (instanceId) {
7944                for (var _i = 0, _a = this.segs; _i < _a.length; _i++) {
7945                    var seg = _a[_i];
7946                    var eventInstance = seg.eventRange.instance;
7947                    if (eventInstance && eventInstance.instanceId === instanceId &&
7948                        seg.el // necessary?
7949                    ) {
7950                        seg.el.classList.add('fc-selected');
7951                    }
7952                }
7953            }
7954        };
7955        FgEventRenderer.prototype.unselectByInstanceId = function (instanceId) {
7956            if (instanceId) {
7957                for (var _i = 0, _a = this.segs; _i < _a.length; _i++) {
7958                    var seg = _a[_i];
7959                    if (seg.el) { // necessary?
7960                        seg.el.classList.remove('fc-selected');
7961                    }
7962                }
7963            }
7964        };
7965        return FgEventRenderer;
7966    }());
7967    // returns a object with all primitive props that can be compared
7968    function buildSegCompareObj(seg) {
7969        var eventDef = seg.eventRange.def;
7970        var range = seg.eventRange.instance.range;
7971        var start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events
7972        var end = range.end ? range.end.valueOf() : 0; // "
7973        return __assign({}, eventDef.extendedProps, eventDef, { id: eventDef.publicId, start: start,
7974            end: end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg // for later retrieval
7975         });
7976    }
7977
7978    var FillRenderer = /** @class */ (function () {
7979        function FillRenderer(context) {
7980            this.fillSegTag = 'div';
7981            this.dirtySizeFlags = {};
7982            this.context = context;
7983            this.containerElsByType = {};
7984            this.segsByType = {};
7985        }
7986        FillRenderer.prototype.getSegsByType = function (type) {
7987            return this.segsByType[type] || [];
7988        };
7989        FillRenderer.prototype.renderSegs = function (type, segs) {
7990            var _a;
7991            var renderedSegs = this.renderSegEls(type, segs); // assignes `.el` to each seg. returns successfully rendered segs
7992            var containerEls = this.attachSegs(type, renderedSegs);
7993            if (containerEls) {
7994                (_a = (this.containerElsByType[type] || (this.containerElsByType[type] = []))).push.apply(_a, containerEls);
7995            }
7996            this.segsByType[type] = renderedSegs;
7997            if (type === 'bgEvent') {
7998                this.context.view.triggerRenderedSegs(renderedSegs, false); // isMirror=false
7999            }
8000            this.dirtySizeFlags[type] = true;
8001        };
8002        // Unrenders a specific type of fill that is currently rendered on the grid
8003        FillRenderer.prototype.unrender = function (type) {
8004            var segs = this.segsByType[type];
8005            if (segs) {
8006                if (type === 'bgEvent') {
8007                    this.context.view.triggerWillRemoveSegs(segs, false); // isMirror=false
8008                }
8009                this.detachSegs(type, segs);
8010            }
8011        };
8012        // Renders and assigns an `el` property for each fill segment. Generic enough to work with different types.
8013        // Only returns segments that successfully rendered.
8014        FillRenderer.prototype.renderSegEls = function (type, segs) {
8015            var _this = this;
8016            var html = '';
8017            var i;
8018            if (segs.length) {
8019                // build a large concatenation of segment HTML
8020                for (i = 0; i < segs.length; i++) {
8021                    html += this.renderSegHtml(type, segs[i]);
8022                }
8023                // Grab individual elements from the combined HTML string. Use each as the default rendering.
8024                // Then, compute the 'el' for each segment.
8025                htmlToElements(html).forEach(function (el, i) {
8026                    var seg = segs[i];
8027                    if (el) {
8028                        seg.el = el;
8029                    }
8030                });
8031                if (type === 'bgEvent') {
8032                    segs = filterSegsViaEls(this.context.view, segs, false // isMirror. background events can never be mirror elements
8033                    );
8034                }
8035                // correct element type? (would be bad if a non-TD were inserted into a table for example)
8036                segs = segs.filter(function (seg) {
8037                    return elementMatches(seg.el, _this.fillSegTag);
8038                });
8039            }
8040            return segs;
8041        };
8042        // Builds the HTML needed for one fill segment. Generic enough to work with different types.
8043        FillRenderer.prototype.renderSegHtml = function (type, seg) {
8044            var css = null;
8045            var classNames = [];
8046            if (type !== 'highlight' && type !== 'businessHours') {
8047                css = {
8048                    'background-color': seg.eventRange.ui.backgroundColor
8049                };
8050            }
8051            if (type !== 'highlight') {
8052                classNames = classNames.concat(seg.eventRange.ui.classNames);
8053            }
8054            if (type === 'businessHours') {
8055                classNames.push('fc-bgevent');
8056            }
8057            else {
8058                classNames.push('fc-' + type.toLowerCase());
8059            }
8060            return '<' + this.fillSegTag +
8061                (classNames.length ? ' class="' + classNames.join(' ') + '"' : '') +
8062                (css ? ' style="' + cssToStr(css) + '"' : '') +
8063                '></' + this.fillSegTag + '>';
8064        };
8065        FillRenderer.prototype.detachSegs = function (type, segs) {
8066            var containerEls = this.containerElsByType[type];
8067            if (containerEls) {
8068                containerEls.forEach(removeElement);
8069                delete this.containerElsByType[type];
8070            }
8071        };
8072        FillRenderer.prototype.computeSizes = function (force) {
8073            for (var type in this.segsByType) {
8074                if (force || this.dirtySizeFlags[type]) {
8075                    this.computeSegSizes(this.segsByType[type]);
8076                }
8077            }
8078        };
8079        FillRenderer.prototype.assignSizes = function (force) {
8080            for (var type in this.segsByType) {
8081                if (force || this.dirtySizeFlags[type]) {
8082                    this.assignSegSizes(this.segsByType[type]);
8083                }
8084            }
8085            this.dirtySizeFlags = {};
8086        };
8087        FillRenderer.prototype.computeSegSizes = function (segs) {
8088        };
8089        FillRenderer.prototype.assignSegSizes = function (segs) {
8090        };
8091        return FillRenderer;
8092    }());
8093
8094    var NamedTimeZoneImpl = /** @class */ (function () {
8095        function NamedTimeZoneImpl(timeZoneName) {
8096            this.timeZoneName = timeZoneName;
8097        }
8098        return NamedTimeZoneImpl;
8099    }());
8100
8101    /*
8102    An abstraction for a dragging interaction originating on an event.
8103    Does higher-level things than PointerDragger, such as possibly:
8104    - a "mirror" that moves with the pointer
8105    - a minimum number of pixels or other criteria for a true drag to begin
8106
8107    subclasses must emit:
8108    - pointerdown
8109    - dragstart
8110    - dragmove
8111    - pointerup
8112    - dragend
8113    */
8114    var ElementDragging = /** @class */ (function () {
8115        function ElementDragging(el) {
8116            this.emitter = new EmitterMixin();
8117        }
8118        ElementDragging.prototype.destroy = function () {
8119        };
8120        ElementDragging.prototype.setMirrorIsVisible = function (bool) {
8121            // optional if subclass doesn't want to support a mirror
8122        };
8123        ElementDragging.prototype.setMirrorNeedsRevert = function (bool) {
8124            // optional if subclass doesn't want to support a mirror
8125        };
8126        ElementDragging.prototype.setAutoScrollEnabled = function (bool) {
8127            // optional
8128        };
8129        return ElementDragging;
8130    }());
8131
8132    function formatDate(dateInput, settings) {
8133        if (settings === void 0) { settings = {}; }
8134        var dateEnv = buildDateEnv$1(settings);
8135        var formatter = createFormatter(settings);
8136        var dateMeta = dateEnv.createMarkerMeta(dateInput);
8137        if (!dateMeta) { // TODO: warning?
8138            return '';
8139        }
8140        return dateEnv.format(dateMeta.marker, formatter, {
8141            forcedTzo: dateMeta.forcedTzo
8142        });
8143    }
8144    function formatRange(startInput, endInput, settings // mixture of env and formatter settings
8145    ) {
8146        var dateEnv = buildDateEnv$1(typeof settings === 'object' && settings ? settings : {}); // pass in if non-null object
8147        var formatter = createFormatter(settings, globalDefaults.defaultRangeSeparator);
8148        var startMeta = dateEnv.createMarkerMeta(startInput);
8149        var endMeta = dateEnv.createMarkerMeta(endInput);
8150        if (!startMeta || !endMeta) { // TODO: warning?
8151            return '';
8152        }
8153        return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, {
8154            forcedStartTzo: startMeta.forcedTzo,
8155            forcedEndTzo: endMeta.forcedTzo,
8156            isEndExclusive: settings.isEndExclusive
8157        });
8158    }
8159    // TODO: more DRY and optimized
8160    function buildDateEnv$1(settings) {
8161        var locale = buildLocale(settings.locale || 'en', parseRawLocales([]).map); // TODO: don't hardcode 'en' everywhere
8162        // ensure required settings
8163        settings = __assign({ timeZone: globalDefaults.timeZone, calendarSystem: 'gregory' }, settings, { locale: locale });
8164        return new DateEnv(settings);
8165    }
8166
8167    var DRAG_META_PROPS = {
8168        startTime: createDuration,
8169        duration: createDuration,
8170        create: Boolean,
8171        sourceId: String
8172    };
8173    var DRAG_META_DEFAULTS = {
8174        create: true
8175    };
8176    function parseDragMeta(raw) {
8177        var leftoverProps = {};
8178        var refined = refineProps(raw, DRAG_META_PROPS, DRAG_META_DEFAULTS, leftoverProps);
8179        refined.leftoverProps = leftoverProps;
8180        return refined;
8181    }
8182
8183    // Computes a default column header formatting string if `colFormat` is not explicitly defined
8184    function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
8185        // if more than one week row, or if there are a lot of columns with not much space,
8186        // put just the day numbers will be in each cell
8187        if (!datesRepDistinctDays || dayCnt > 10) {
8188            return { weekday: 'short' }; // "Sat"
8189        }
8190        else if (dayCnt > 1) {
8191            return { weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }; // "Sat 11/12"
8192        }
8193        else {
8194            return { weekday: 'long' }; // "Saturday"
8195        }
8196    }
8197    function renderDateCell(dateMarker, dateProfile, datesRepDistinctDays, colCnt, colHeadFormat, context, colspan, otherAttrs) {
8198        var view = context.view, dateEnv = context.dateEnv, theme = context.theme, options = context.options;
8199        var isDateValid = rangeContainsMarker(dateProfile.activeRange, dateMarker); // TODO: called too frequently. cache somehow.
8200        var classNames = [
8201            'fc-day-header',
8202            theme.getClass('widgetHeader')
8203        ];
8204        var innerHtml;
8205        if (typeof options.columnHeaderHtml === 'function') {
8206            innerHtml = options.columnHeaderHtml(dateEnv.toDate(dateMarker));
8207        }
8208        else if (typeof options.columnHeaderText === 'function') {
8209            innerHtml = htmlEscape(options.columnHeaderText(dateEnv.toDate(dateMarker)));
8210        }
8211        else {
8212            innerHtml = htmlEscape(dateEnv.format(dateMarker, colHeadFormat));
8213        }
8214        // if only one row of days, the classNames on the header can represent the specific days beneath
8215        if (datesRepDistinctDays) {
8216            classNames = classNames.concat(
8217            // includes the day-of-week class
8218            // noThemeHighlight=true (don't highlight the header)
8219            getDayClasses(dateMarker, dateProfile, context, true));
8220        }
8221        else {
8222            classNames.push('fc-' + DAY_IDS[dateMarker.getUTCDay()]); // only add the day-of-week class
8223        }
8224        return '' +
8225            '<th class="' + classNames.join(' ') + '"' +
8226            ((isDateValid && datesRepDistinctDays) ?
8227                ' data-date="' + dateEnv.formatIso(dateMarker, { omitTime: true }) + '"' :
8228                '') +
8229            (colspan > 1 ?
8230                ' colspan="' + colspan + '"' :
8231                '') +
8232            (otherAttrs ?
8233                ' ' + otherAttrs :
8234                '') +
8235            '>' +
8236            (isDateValid ?
8237                // don't make a link if the heading could represent multiple days, or if there's only one day (forceOff)
8238                buildGotoAnchorHtml(view, { date: dateMarker, forceOff: !datesRepDistinctDays || colCnt === 1 }, innerHtml) :
8239                // if not valid, display text, but no link
8240                innerHtml) +
8241            '</th>';
8242    }
8243
8244    var DayHeader = /** @class */ (function (_super) {
8245        __extends(DayHeader, _super);
8246        function DayHeader(context, parentEl) {
8247            var _this = _super.call(this, context) || this;
8248            parentEl.innerHTML = ''; // because might be nbsp
8249            parentEl.appendChild(_this.el = htmlToElement('<div class="fc-row ' + _this.theme.getClass('headerRow') + '">' +
8250                '<table class="' + _this.theme.getClass('tableGrid') + '">' +
8251                '<thead></thead>' +
8252                '</table>' +
8253                '</div>'));
8254            _this.thead = _this.el.querySelector('thead');
8255            return _this;
8256        }
8257        DayHeader.prototype.destroy = function () {
8258            removeElement(this.el);
8259        };
8260        DayHeader.prototype.render = function (props) {
8261            var dates = props.dates, datesRepDistinctDays = props.datesRepDistinctDays;
8262            var parts = [];
8263            if (props.renderIntroHtml) {
8264                parts.push(props.renderIntroHtml());
8265            }
8266            var colHeadFormat = createFormatter(this.opt('columnHeaderFormat') ||
8267                computeFallbackHeaderFormat(datesRepDistinctDays, dates.length));
8268            for (var _i = 0, dates_1 = dates; _i < dates_1.length; _i++) {
8269                var date = dates_1[_i];
8270                parts.push(renderDateCell(date, props.dateProfile, datesRepDistinctDays, dates.length, colHeadFormat, this.context));
8271            }
8272            if (this.isRtl) {
8273                parts.reverse();
8274            }
8275            this.thead.innerHTML = '<tr>' + parts.join('') + '</tr>';
8276        };
8277        return DayHeader;
8278    }(Component));
8279
8280    var DaySeries = /** @class */ (function () {
8281        function DaySeries(range, dateProfileGenerator) {
8282            var date = range.start;
8283            var end = range.end;
8284            var indices = [];
8285            var dates = [];
8286            var dayIndex = -1;
8287            while (date < end) { // loop each day from start to end
8288                if (dateProfileGenerator.isHiddenDay(date)) {
8289                    indices.push(dayIndex + 0.5); // mark that it's between indices
8290                }
8291                else {
8292                    dayIndex++;
8293                    indices.push(dayIndex);
8294                    dates.push(date);
8295                }
8296                date = addDays(date, 1);
8297            }
8298            this.dates = dates;
8299            this.indices = indices;
8300            this.cnt = dates.length;
8301        }
8302        DaySeries.prototype.sliceRange = function (range) {
8303            var firstIndex = this.getDateDayIndex(range.start); // inclusive first index
8304            var lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index
8305            var clippedFirstIndex = Math.max(0, firstIndex);
8306            var clippedLastIndex = Math.min(this.cnt - 1, lastIndex);
8307            // deal with in-between indices
8308            clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell
8309            clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell
8310            if (clippedFirstIndex <= clippedLastIndex) {
8311                return {
8312                    firstIndex: clippedFirstIndex,
8313                    lastIndex: clippedLastIndex,
8314                    isStart: firstIndex === clippedFirstIndex,
8315                    isEnd: lastIndex === clippedLastIndex
8316                };
8317            }
8318            else {
8319                return null;
8320            }
8321        };
8322        // Given a date, returns its chronolocial cell-index from the first cell of the grid.
8323        // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.
8324        // If before the first offset, returns a negative number.
8325        // If after the last offset, returns an offset past the last cell offset.
8326        // Only works for *start* dates of cells. Will not work for exclusive end dates for cells.
8327        DaySeries.prototype.getDateDayIndex = function (date) {
8328            var indices = this.indices;
8329            var dayOffset = Math.floor(diffDays(this.dates[0], date));
8330            if (dayOffset < 0) {
8331                return indices[0] - 1;
8332            }
8333            else if (dayOffset >= indices.length) {
8334                return indices[indices.length - 1] + 1;
8335            }
8336            else {
8337                return indices[dayOffset];
8338            }
8339        };
8340        return DaySeries;
8341    }());
8342
8343    var DayTable = /** @class */ (function () {
8344        function DayTable(daySeries, breakOnWeeks) {
8345            var dates = daySeries.dates;
8346            var daysPerRow;
8347            var firstDay;
8348            var rowCnt;
8349            if (breakOnWeeks) {
8350                // count columns until the day-of-week repeats
8351                firstDay = dates[0].getUTCDay();
8352                for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow++) {
8353                    if (dates[daysPerRow].getUTCDay() === firstDay) {
8354                        break;
8355                    }
8356                }
8357                rowCnt = Math.ceil(dates.length / daysPerRow);
8358            }
8359            else {
8360                rowCnt = 1;
8361                daysPerRow = dates.length;
8362            }
8363            this.rowCnt = rowCnt;
8364            this.colCnt = daysPerRow;
8365            this.daySeries = daySeries;
8366            this.cells = this.buildCells();
8367            this.headerDates = this.buildHeaderDates();
8368        }
8369        DayTable.prototype.buildCells = function () {
8370            var rows = [];
8371            for (var row = 0; row < this.rowCnt; row++) {
8372                var cells = [];
8373                for (var col = 0; col < this.colCnt; col++) {
8374                    cells.push(this.buildCell(row, col));
8375                }
8376                rows.push(cells);
8377            }
8378            return rows;
8379        };
8380        DayTable.prototype.buildCell = function (row, col) {
8381            return {
8382                date: this.daySeries.dates[row * this.colCnt + col]
8383            };
8384        };
8385        DayTable.prototype.buildHeaderDates = function () {
8386            var dates = [];
8387            for (var col = 0; col < this.colCnt; col++) {
8388                dates.push(this.cells[0][col].date);
8389            }
8390            return dates;
8391        };
8392        DayTable.prototype.sliceRange = function (range) {
8393            var colCnt = this.colCnt;
8394            var seriesSeg = this.daySeries.sliceRange(range);
8395            var segs = [];
8396            if (seriesSeg) {
8397                var firstIndex = seriesSeg.firstIndex, lastIndex = seriesSeg.lastIndex;
8398                var index = firstIndex;
8399                while (index <= lastIndex) {
8400                    var row = Math.floor(index / colCnt);
8401                    var nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1);
8402                    segs.push({
8403                        row: row,
8404                        firstCol: index % colCnt,
8405                        lastCol: (nextIndex - 1) % colCnt,
8406                        isStart: seriesSeg.isStart && index === firstIndex,
8407                        isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex
8408                    });
8409                    index = nextIndex;
8410                }
8411            }
8412            return segs;
8413        };
8414        return DayTable;
8415    }());
8416
8417    var Slicer = /** @class */ (function () {
8418        function Slicer() {
8419            this.sliceBusinessHours = memoize(this._sliceBusinessHours);
8420            this.sliceDateSelection = memoize(this._sliceDateSpan);
8421            this.sliceEventStore = memoize(this._sliceEventStore);
8422            this.sliceEventDrag = memoize(this._sliceInteraction);
8423            this.sliceEventResize = memoize(this._sliceInteraction);
8424        }
8425        Slicer.prototype.sliceProps = function (props, dateProfile, nextDayThreshold, component) {
8426            var extraArgs = [];
8427            for (var _i = 4; _i < arguments.length; _i++) {
8428                extraArgs[_i - 4] = arguments[_i];
8429            }
8430            var eventUiBases = props.eventUiBases;
8431            var eventSegs = this.sliceEventStore.apply(this, [props.eventStore, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs));
8432            return {
8433                dateSelectionSegs: this.sliceDateSelection.apply(this, [props.dateSelection, eventUiBases, component].concat(extraArgs)),
8434                businessHourSegs: this.sliceBusinessHours.apply(this, [props.businessHours, dateProfile, nextDayThreshold, component].concat(extraArgs)),
8435                fgEventSegs: eventSegs.fg,
8436                bgEventSegs: eventSegs.bg,
8437                eventDrag: this.sliceEventDrag.apply(this, [props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)),
8438                eventResize: this.sliceEventResize.apply(this, [props.eventResize, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)),
8439                eventSelection: props.eventSelection
8440            }; // TODO: give interactionSegs?
8441        };
8442        Slicer.prototype.sliceNowDate = function (// does not memoize
8443        date, component) {
8444            var extraArgs = [];
8445            for (var _i = 2; _i < arguments.length; _i++) {
8446                extraArgs[_i - 2] = arguments[_i];
8447            }
8448            return this._sliceDateSpan.apply(this, [{ range: { start: date, end: addMs(date, 1) }, allDay: false },
8449                {},
8450                component].concat(extraArgs));
8451        };
8452        Slicer.prototype._sliceBusinessHours = function (businessHours, dateProfile, nextDayThreshold, component) {
8453            var extraArgs = [];
8454            for (var _i = 4; _i < arguments.length; _i++) {
8455                extraArgs[_i - 4] = arguments[_i];
8456            }
8457            if (!businessHours) {
8458                return [];
8459            }
8460            return this._sliceEventStore.apply(this, [expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), component.calendar),
8461                {},
8462                dateProfile,
8463                nextDayThreshold,
8464                component].concat(extraArgs)).bg;
8465        };
8466        Slicer.prototype._sliceEventStore = function (eventStore, eventUiBases, dateProfile, nextDayThreshold, component) {
8467            var extraArgs = [];
8468            for (var _i = 5; _i < arguments.length; _i++) {
8469                extraArgs[_i - 5] = arguments[_i];
8470            }
8471            if (eventStore) {
8472                var rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
8473                return {
8474                    bg: this.sliceEventRanges(rangeRes.bg, component, extraArgs),
8475                    fg: this.sliceEventRanges(rangeRes.fg, component, extraArgs)
8476                };
8477            }
8478            else {
8479                return { bg: [], fg: [] };
8480            }
8481        };
8482        Slicer.prototype._sliceInteraction = function (interaction, eventUiBases, dateProfile, nextDayThreshold, component) {
8483            var extraArgs = [];
8484            for (var _i = 5; _i < arguments.length; _i++) {
8485                extraArgs[_i - 5] = arguments[_i];
8486            }
8487            if (!interaction) {
8488                return null;
8489            }
8490            var rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
8491            return {
8492                segs: this.sliceEventRanges(rangeRes.fg, component, extraArgs),
8493                affectedInstances: interaction.affectedEvents.instances,
8494                isEvent: interaction.isEvent,
8495                sourceSeg: interaction.origSeg
8496            };
8497        };
8498        Slicer.prototype._sliceDateSpan = function (dateSpan, eventUiBases, component) {
8499            var extraArgs = [];
8500            for (var _i = 3; _i < arguments.length; _i++) {
8501                extraArgs[_i - 3] = arguments[_i];
8502            }
8503            if (!dateSpan) {
8504                return [];
8505            }
8506            var eventRange = fabricateEventRange(dateSpan, eventUiBases, component.calendar);
8507            var segs = this.sliceRange.apply(this, [dateSpan.range].concat(extraArgs));
8508            for (var _a = 0, segs_1 = segs; _a < segs_1.length; _a++) {
8509                var seg = segs_1[_a];
8510                seg.component = component;
8511                seg.eventRange = eventRange;
8512            }
8513            return segs;
8514        };
8515        /*
8516        "complete" seg means it has component and eventRange
8517        */
8518        Slicer.prototype.sliceEventRanges = function (eventRanges, component, // TODO: kill
8519        extraArgs) {
8520            var segs = [];
8521            for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) {
8522                var eventRange = eventRanges_1[_i];
8523                segs.push.apply(segs, this.sliceEventRange(eventRange, component, extraArgs));
8524            }
8525            return segs;
8526        };
8527        /*
8528        "complete" seg means it has component and eventRange
8529        */
8530        Slicer.prototype.sliceEventRange = function (eventRange, component, // TODO: kill
8531        extraArgs) {
8532            var segs = this.sliceRange.apply(this, [eventRange.range].concat(extraArgs));
8533            for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
8534                var seg = segs_2[_i];
8535                seg.component = component;
8536                seg.eventRange = eventRange;
8537                seg.isStart = eventRange.isStart && seg.isStart;
8538                seg.isEnd = eventRange.isEnd && seg.isEnd;
8539            }
8540            return segs;
8541        };
8542        return Slicer;
8543    }());
8544    /*
8545    for incorporating minTime/maxTime if appropriate
8546    TODO: should be part of DateProfile!
8547    TimelineDateProfile already does this btw
8548    */
8549    function computeActiveRange(dateProfile, isComponentAllDay) {
8550        var range = dateProfile.activeRange;
8551        if (isComponentAllDay) {
8552            return range;
8553        }
8554        return {
8555            start: addMs(range.start, dateProfile.minTime.milliseconds),
8556            end: addMs(range.end, dateProfile.maxTime.milliseconds - 864e5) // 864e5 = ms in a day
8557        };
8558    }
8559
8560    // exports
8561    // --------------------------------------------------------------------------------------------------
8562    var version = '4.3.1';
8563
8564    exports.Calendar = Calendar;
8565    exports.Component = Component;
8566    exports.DateComponent = DateComponent;
8567    exports.DateEnv = DateEnv;
8568    exports.DateProfileGenerator = DateProfileGenerator;
8569    exports.DayHeader = DayHeader;
8570    exports.DaySeries = DaySeries;
8571    exports.DayTable = DayTable;
8572    exports.ElementDragging = ElementDragging;
8573    exports.ElementScrollController = ElementScrollController;
8574    exports.EmitterMixin = EmitterMixin;
8575    exports.EventApi = EventApi;
8576    exports.FgEventRenderer = FgEventRenderer;
8577    exports.FillRenderer = FillRenderer;
8578    exports.Interaction = Interaction;
8579    exports.Mixin = Mixin;
8580    exports.NamedTimeZoneImpl = NamedTimeZoneImpl;
8581    exports.PositionCache = PositionCache;
8582    exports.ScrollComponent = ScrollComponent;
8583    exports.ScrollController = ScrollController;
8584    exports.Slicer = Slicer;
8585    exports.Splitter = Splitter;
8586    exports.Theme = Theme;
8587    exports.View = View;
8588    exports.WindowScrollController = WindowScrollController;
8589    exports.addDays = addDays;
8590    exports.addDurations = addDurations;
8591    exports.addMs = addMs;
8592    exports.addWeeks = addWeeks;
8593    exports.allowContextMenu = allowContextMenu;
8594    exports.allowSelection = allowSelection;
8595    exports.appendToElement = appendToElement;
8596    exports.applyAll = applyAll;
8597    exports.applyMutationToEventStore = applyMutationToEventStore;
8598    exports.applyStyle = applyStyle;
8599    exports.applyStyleProp = applyStyleProp;
8600    exports.asRoughMinutes = asRoughMinutes;
8601    exports.asRoughMs = asRoughMs;
8602    exports.asRoughSeconds = asRoughSeconds;
8603    exports.buildGotoAnchorHtml = buildGotoAnchorHtml;
8604    exports.buildSegCompareObj = buildSegCompareObj;
8605    exports.capitaliseFirstLetter = capitaliseFirstLetter;
8606    exports.combineEventUis = combineEventUis;
8607    exports.compareByFieldSpec = compareByFieldSpec;
8608    exports.compareByFieldSpecs = compareByFieldSpecs;
8609    exports.compareNumbers = compareNumbers;
8610    exports.compensateScroll = compensateScroll;
8611    exports.computeClippingRect = computeClippingRect;
8612    exports.computeEdges = computeEdges;
8613    exports.computeFallbackHeaderFormat = computeFallbackHeaderFormat;
8614    exports.computeHeightAndMargins = computeHeightAndMargins;
8615    exports.computeInnerRect = computeInnerRect;
8616    exports.computeRect = computeRect;
8617    exports.computeVisibleDayRange = computeVisibleDayRange;
8618    exports.config = config;
8619    exports.constrainPoint = constrainPoint;
8620    exports.createDuration = createDuration;
8621    exports.createElement = createElement;
8622    exports.createEmptyEventStore = createEmptyEventStore;
8623    exports.createEventInstance = createEventInstance;
8624    exports.createFormatter = createFormatter;
8625    exports.createPlugin = createPlugin;
8626    exports.cssToStr = cssToStr;
8627    exports.debounce = debounce;
8628    exports.diffDates = diffDates;
8629    exports.diffDayAndTime = diffDayAndTime;
8630    exports.diffDays = diffDays;
8631    exports.diffPoints = diffPoints;
8632    exports.diffWeeks = diffWeeks;
8633    exports.diffWholeDays = diffWholeDays;
8634    exports.diffWholeWeeks = diffWholeWeeks;
8635    exports.disableCursor = disableCursor;
8636    exports.distributeHeight = distributeHeight;
8637    exports.elementClosest = elementClosest;
8638    exports.elementMatches = elementMatches;
8639    exports.enableCursor = enableCursor;
8640    exports.eventTupleToStore = eventTupleToStore;
8641    exports.filterEventStoreDefs = filterEventStoreDefs;
8642    exports.filterHash = filterHash;
8643    exports.findChildren = findChildren;
8644    exports.findElements = findElements;
8645    exports.flexibleCompare = flexibleCompare;
8646    exports.forceClassName = forceClassName;
8647    exports.formatDate = formatDate;
8648    exports.formatIsoTimeString = formatIsoTimeString;
8649    exports.formatRange = formatRange;
8650    exports.getAllDayHtml = getAllDayHtml;
8651    exports.getClippingParents = getClippingParents;
8652    exports.getDayClasses = getDayClasses;
8653    exports.getElSeg = getElSeg;
8654    exports.getRectCenter = getRectCenter;
8655    exports.getRelevantEvents = getRelevantEvents;
8656    exports.globalDefaults = globalDefaults;
8657    exports.greatestDurationDenominator = greatestDurationDenominator;
8658    exports.hasBgRendering = hasBgRendering;
8659    exports.htmlEscape = htmlEscape;
8660    exports.htmlToElement = htmlToElement;
8661    exports.insertAfterElement = insertAfterElement;
8662    exports.interactionSettingsStore = interactionSettingsStore;
8663    exports.interactionSettingsToStore = interactionSettingsToStore;
8664    exports.intersectRanges = intersectRanges;
8665    exports.intersectRects = intersectRects;
8666    exports.isArraysEqual = isArraysEqual;
8667    exports.isDateSpansEqual = isDateSpansEqual;
8668    exports.isInt = isInt;
8669    exports.isInteractionValid = isInteractionValid;
8670    exports.isMultiDayRange = isMultiDayRange;
8671    exports.isPropsEqual = isPropsEqual;
8672    exports.isPropsValid = isPropsValid;
8673    exports.isSingleDay = isSingleDay;
8674    exports.isValidDate = isValidDate;
8675    exports.listenBySelector = listenBySelector;
8676    exports.mapHash = mapHash;
8677    exports.matchCellWidths = matchCellWidths;
8678    exports.memoize = memoize;
8679    exports.memoizeOutput = memoizeOutput;
8680    exports.memoizeRendering = memoizeRendering;
8681    exports.mergeEventStores = mergeEventStores;
8682    exports.multiplyDuration = multiplyDuration;
8683    exports.padStart = padStart;
8684    exports.parseBusinessHours = parseBusinessHours;
8685    exports.parseDragMeta = parseDragMeta;
8686    exports.parseEventDef = parseEventDef;
8687    exports.parseFieldSpecs = parseFieldSpecs;
8688    exports.parseMarker = parse;
8689    exports.pointInsideRect = pointInsideRect;
8690    exports.prependToElement = prependToElement;
8691    exports.preventContextMenu = preventContextMenu;
8692    exports.preventDefault = preventDefault;
8693    exports.preventSelection = preventSelection;
8694    exports.processScopedUiProps = processScopedUiProps;
8695    exports.rangeContainsMarker = rangeContainsMarker;
8696    exports.rangeContainsRange = rangeContainsRange;
8697    exports.rangesEqual = rangesEqual;
8698    exports.rangesIntersect = rangesIntersect;
8699    exports.refineProps = refineProps;
8700    exports.removeElement = removeElement;
8701    exports.removeExact = removeExact;
8702    exports.renderDateCell = renderDateCell;
8703    exports.requestJson = requestJson;
8704    exports.sliceEventStore = sliceEventStore;
8705    exports.startOfDay = startOfDay;
8706    exports.subtractInnerElHeight = subtractInnerElHeight;
8707    exports.translateRect = translateRect;
8708    exports.uncompensateScroll = uncompensateScroll;
8709    exports.undistributeHeight = undistributeHeight;
8710    exports.unpromisify = unpromisify;
8711    exports.version = version;
8712    exports.whenTransitionDone = whenTransitionDone;
8713    exports.wholeDivideDurations = wholeDivideDurations;
8714
8715    Object.defineProperty(exports, '__esModule', { value: true });
8716
8717}));
8718
8719/*!
8720FullCalendar Day Grid Plugin v4.3.0
8721Docs & License: https://fullcalendar.io/
8722(c) 2019 Adam Shaw
8723*/
8724
8725(function (global, factory) {
8726    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) :
8727    typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) :
8728    (global = global || self, factory(global.FullCalendarDayGrid = {}, global.FullCalendar));
8729}(this, function (exports, core) { 'use strict';
8730
8731    /*! *****************************************************************************
8732    Copyright (c) Microsoft Corporation. All rights reserved.
8733    Licensed under the Apache License, Version 2.0 (the "License"); you may not use
8734    this file except in compliance with the License. You may obtain a copy of the
8735    License at http://www.apache.org/licenses/LICENSE-2.0
8736
8737    THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8738    KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
8739    WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
8740    MERCHANTABLITY OR NON-INFRINGEMENT.
8741
8742    See the Apache Version 2.0 License for specific language governing permissions
8743    and limitations under the License.
8744    ***************************************************************************** */
8745    /* global Reflect, Promise */
8746
8747    var extendStatics = function(d, b) {
8748        extendStatics = Object.setPrototypeOf ||
8749            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
8750            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
8751        return extendStatics(d, b);
8752    };
8753
8754    function __extends(d, b) {
8755        extendStatics(d, b);
8756        function __() { this.constructor = d; }
8757        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
8758    }
8759
8760    var __assign = function() {
8761        __assign = Object.assign || function __assign(t) {
8762            for (var s, i = 1, n = arguments.length; i < n; i++) {
8763                s = arguments[i];
8764                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
8765            }
8766            return t;
8767        };
8768        return __assign.apply(this, arguments);
8769    };
8770
8771    var DayGridDateProfileGenerator = /** @class */ (function (_super) {
8772        __extends(DayGridDateProfileGenerator, _super);
8773        function DayGridDateProfileGenerator() {
8774            return _super !== null && _super.apply(this, arguments) || this;
8775        }
8776        // Computes the date range that will be rendered.
8777        DayGridDateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) {
8778            var dateEnv = this.dateEnv;
8779            var renderRange = _super.prototype.buildRenderRange.call(this, currentRange, currentRangeUnit, isRangeAllDay);
8780            var start = renderRange.start;
8781            var end = renderRange.end;
8782            var endOfWeek;
8783            // year and month views should be aligned with weeks. this is already done for week
8784            if (/^(year|month)$/.test(currentRangeUnit)) {
8785                start = dateEnv.startOfWeek(start);
8786                // make end-of-week if not already
8787                endOfWeek = dateEnv.startOfWeek(end);
8788                if (endOfWeek.valueOf() !== end.valueOf()) {
8789                    end = core.addWeeks(endOfWeek, 1);
8790                }
8791            }
8792            // ensure 6 weeks
8793            if (this.options.monthMode &&
8794                this.options.fixedWeekCount) {
8795                var rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
8796                core.diffWeeks(start, end));
8797                end = core.addWeeks(end, 6 - rowCnt);
8798            }
8799            return { start: start, end: end };
8800        };
8801        return DayGridDateProfileGenerator;
8802    }(core.DateProfileGenerator));
8803
8804    /* A rectangular panel that is absolutely positioned over other content
8805    ------------------------------------------------------------------------------------------------------------------------
8806    Options:
8807      - className (string)
8808      - content (HTML string, element, or element array)
8809      - parentEl
8810      - top
8811      - left
8812      - right (the x coord of where the right edge should be. not a "CSS" right)
8813      - autoHide (boolean)
8814      - show (callback)
8815      - hide (callback)
8816    */
8817    var Popover = /** @class */ (function () {
8818        function Popover(options) {
8819            var _this = this;
8820            this.isHidden = true;
8821            this.margin = 10; // the space required between the popover and the edges of the scroll container
8822            // Triggered when the user clicks *anywhere* in the document, for the autoHide feature
8823            this.documentMousedown = function (ev) {
8824                // only hide the popover if the click happened outside the popover
8825                if (_this.el && !_this.el.contains(ev.target)) {
8826                    _this.hide();
8827                }
8828            };
8829            this.options = options;
8830        }
8831        // Shows the popover on the specified position. Renders it if not already
8832        Popover.prototype.show = function () {
8833            if (this.isHidden) {
8834                if (!this.el) {
8835                    this.render();
8836                }
8837                this.el.style.display = '';
8838                this.position();
8839                this.isHidden = false;
8840                this.trigger('show');
8841            }
8842        };
8843        // Hides the popover, through CSS, but does not remove it from the DOM
8844        Popover.prototype.hide = function () {
8845            if (!this.isHidden) {
8846                this.el.style.display = 'none';
8847                this.isHidden = true;
8848                this.trigger('hide');
8849            }
8850        };
8851        // Creates `this.el` and renders content inside of it
8852        Popover.prototype.render = function () {
8853            var _this = this;
8854            var options = this.options;
8855            var el = this.el = core.createElement('div', {
8856                className: 'fc-popover ' + (options.className || ''),
8857                style: {
8858                    top: '0',
8859                    left: '0'
8860                }
8861            });
8862            if (typeof options.content === 'function') {
8863                options.content(el);
8864            }
8865            options.parentEl.appendChild(el);
8866            // when a click happens on anything inside with a 'fc-close' className, hide the popover
8867            core.listenBySelector(el, 'click', '.fc-close', function (ev) {
8868                _this.hide();
8869            });
8870            if (options.autoHide) {
8871                document.addEventListener('mousedown', this.documentMousedown);
8872            }
8873        };
8874        // Hides and unregisters any handlers
8875        Popover.prototype.destroy = function () {
8876            this.hide();
8877            if (this.el) {
8878                core.removeElement(this.el);
8879                this.el = null;
8880            }
8881            document.removeEventListener('mousedown', this.documentMousedown);
8882        };
8883        // Positions the popover optimally, using the top/left/right options
8884        Popover.prototype.position = function () {
8885            var options = this.options;
8886            var el = this.el;
8887            var elDims = el.getBoundingClientRect(); // only used for width,height
8888            var origin = core.computeRect(el.offsetParent);
8889            var clippingRect = core.computeClippingRect(options.parentEl);
8890            var top; // the "position" (not "offset") values for the popover
8891            var left; //
8892            // compute top and left
8893            top = options.top || 0;
8894            if (options.left !== undefined) {
8895                left = options.left;
8896            }
8897            else if (options.right !== undefined) {
8898                left = options.right - elDims.width; // derive the left value from the right value
8899            }
8900            else {
8901                left = 0;
8902            }
8903            // constrain to the view port. if constrained by two edges, give precedence to top/left
8904            top = Math.min(top, clippingRect.bottom - elDims.height - this.margin);
8905            top = Math.max(top, clippingRect.top + this.margin);
8906            left = Math.min(left, clippingRect.right - elDims.width - this.margin);
8907            left = Math.max(left, clippingRect.left + this.margin);
8908            core.applyStyle(el, {
8909                top: top - origin.top,
8910                left: left - origin.left
8911            });
8912        };
8913        // Triggers a callback. Calls a function in the option hash of the same name.
8914        // Arguments beyond the first `name` are forwarded on.
8915        // TODO: better code reuse for this. Repeat code
8916        // can kill this???
8917        Popover.prototype.trigger = function (name) {
8918            if (this.options[name]) {
8919                this.options[name].apply(this, Array.prototype.slice.call(arguments, 1));
8920            }
8921        };
8922        return Popover;
8923    }());
8924
8925    /* Event-rendering methods for the DayGrid class
8926    ----------------------------------------------------------------------------------------------------------------------*/
8927    // "Simple" is bad a name. has nothing to do with SimpleDayGrid
8928    var SimpleDayGridEventRenderer = /** @class */ (function (_super) {
8929        __extends(SimpleDayGridEventRenderer, _super);
8930        function SimpleDayGridEventRenderer() {
8931            return _super !== null && _super.apply(this, arguments) || this;
8932        }
8933        // Builds the HTML to be used for the default element for an individual segment
8934        SimpleDayGridEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) {
8935            var _a = this.context, view = _a.view, options = _a.options;
8936            var eventRange = seg.eventRange;
8937            var eventDef = eventRange.def;
8938            var eventUi = eventRange.ui;
8939            var allDay = eventDef.allDay;
8940            var isDraggable = view.computeEventDraggable(eventDef, eventUi);
8941            var isResizableFromStart = allDay && seg.isStart && view.computeEventStartResizable(eventDef, eventUi);
8942            var isResizableFromEnd = allDay && seg.isEnd && view.computeEventEndResizable(eventDef, eventUi);
8943            var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo);
8944            var skinCss = core.cssToStr(this.getSkinCss(eventUi));
8945            var timeHtml = '';
8946            var timeText;
8947            var titleHtml;
8948            classes.unshift('fc-day-grid-event', 'fc-h-event');
8949            // Only display a timed events time if it is the starting segment
8950            if (seg.isStart) {
8951                timeText = this.getTimeText(eventRange);
8952                if (timeText) {
8953                    timeHtml = '<span class="fc-time">' + core.htmlEscape(timeText) + '</span>';
8954                }
8955            }
8956            titleHtml =
8957                '<span class="fc-title">' +
8958                    (core.htmlEscape(eventDef.title || '') || '&nbsp;') + // we always want one line of height
8959                    '</span>';
8960            return '<a class="' + classes.join(' ') + '"' +
8961                (eventDef.url ?
8962                    ' href="' + core.htmlEscape(eventDef.url) + '"' :
8963                    '') +
8964                (skinCss ?
8965                    ' style="' + skinCss + '"' :
8966                    '') +
8967                '>' +
8968                '<div class="fc-content">' +
8969                (options.dir === 'rtl' ?
8970                    titleHtml + ' ' + timeHtml : // put a natural space in between
8971                    timeHtml + ' ' + titleHtml //
8972                ) +
8973                '</div>' +
8974                (isResizableFromStart ?
8975                    '<div class="fc-resizer fc-start-resizer"></div>' :
8976                    '') +
8977                (isResizableFromEnd ?
8978                    '<div class="fc-resizer fc-end-resizer"></div>' :
8979                    '') +
8980                '</a>';
8981        };
8982        // Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined
8983        SimpleDayGridEventRenderer.prototype.computeEventTimeFormat = function () {
8984            return {
8985                hour: 'numeric',
8986                minute: '2-digit',
8987                omitZeroMinute: true,
8988                meridiem: 'narrow'
8989            };
8990        };
8991        SimpleDayGridEventRenderer.prototype.computeDisplayEventEnd = function () {
8992            return false; // TODO: somehow consider the originating DayGrid's column count
8993        };
8994        return SimpleDayGridEventRenderer;
8995    }(core.FgEventRenderer));
8996
8997    /* Event-rendering methods for the DayGrid class
8998    ----------------------------------------------------------------------------------------------------------------------*/
8999    var DayGridEventRenderer = /** @class */ (function (_super) {
9000        __extends(DayGridEventRenderer, _super);
9001        function DayGridEventRenderer(dayGrid) {
9002            var _this = _super.call(this, dayGrid.context) || this;
9003            _this.dayGrid = dayGrid;
9004            return _this;
9005        }
9006        // Renders the given foreground event segments onto the grid
9007        DayGridEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
9008            var rowStructs = this.rowStructs = this.renderSegRows(segs);
9009            // append to each row's content skeleton
9010            this.dayGrid.rowEls.forEach(function (rowNode, i) {
9011                rowNode.querySelector('.fc-content-skeleton > table').appendChild(rowStructs[i].tbodyEl);
9012            });
9013            // removes the "more.." events popover
9014            if (!mirrorInfo) {
9015                this.dayGrid.removeSegPopover();
9016            }
9017        };
9018        // Unrenders all currently rendered foreground event segments
9019        DayGridEventRenderer.prototype.detachSegs = function () {
9020            var rowStructs = this.rowStructs || [];
9021            var rowStruct;
9022            while ((rowStruct = rowStructs.pop())) {
9023                core.removeElement(rowStruct.tbodyEl);
9024            }
9025            this.rowStructs = null;
9026        };
9027        // Uses the given events array to generate <tbody> elements that should be appended to each row's content skeleton.
9028        // Returns an array of rowStruct objects (see the bottom of `renderSegRow`).
9029        // PRECONDITION: each segment shoud already have a rendered and assigned `.el`
9030        DayGridEventRenderer.prototype.renderSegRows = function (segs) {
9031            var rowStructs = [];
9032            var segRows;
9033            var row;
9034            segRows = this.groupSegRows(segs); // group into nested arrays
9035            // iterate each row of segment groupings
9036            for (row = 0; row < segRows.length; row++) {
9037                rowStructs.push(this.renderSegRow(row, segRows[row]));
9038            }
9039            return rowStructs;
9040        };
9041        // Given a row # and an array of segments all in the same row, render a <tbody> element, a skeleton that contains
9042        // the segments. Returns object with a bunch of internal data about how the render was calculated.
9043        // NOTE: modifies rowSegs
9044        DayGridEventRenderer.prototype.renderSegRow = function (row, rowSegs) {
9045            var dayGrid = this.dayGrid;
9046            var colCnt = dayGrid.colCnt, isRtl = dayGrid.isRtl;
9047            var segLevels = this.buildSegLevels(rowSegs); // group into sub-arrays of levels
9048            var levelCnt = Math.max(1, segLevels.length); // ensure at least one level
9049            var tbody = document.createElement('tbody');
9050            var segMatrix = []; // lookup for which segments are rendered into which level+col cells
9051            var cellMatrix = []; // lookup for all <td> elements of the level+col matrix
9052            var loneCellMatrix = []; // lookup for <td> elements that only take up a single column
9053            var i;
9054            var levelSegs;
9055            var col;
9056            var tr;
9057            var j;
9058            var seg;
9059            var td;
9060            // populates empty cells from the current column (`col`) to `endCol`
9061            function emptyCellsUntil(endCol) {
9062                while (col < endCol) {
9063                    // try to grab a cell from the level above and extend its rowspan. otherwise, create a fresh cell
9064                    td = (loneCellMatrix[i - 1] || [])[col];
9065                    if (td) {
9066                        td.rowSpan = (td.rowSpan || 1) + 1;
9067                    }
9068                    else {
9069                        td = document.createElement('td');
9070                        tr.appendChild(td);
9071                    }
9072                    cellMatrix[i][col] = td;
9073                    loneCellMatrix[i][col] = td;
9074                    col++;
9075                }
9076            }
9077            for (i = 0; i < levelCnt; i++) { // iterate through all levels
9078                levelSegs = segLevels[i];
9079                col = 0;
9080                tr = document.createElement('tr');
9081                segMatrix.push([]);
9082                cellMatrix.push([]);
9083                loneCellMatrix.push([]);
9084                // levelCnt might be 1 even though there are no actual levels. protect against this.
9085                // this single empty row is useful for styling.
9086                if (levelSegs) {
9087                    for (j = 0; j < levelSegs.length; j++) { // iterate through segments in level
9088                        seg = levelSegs[j];
9089                        var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol;
9090                        var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol;
9091                        emptyCellsUntil(leftCol);
9092                        // create a container that occupies or more columns. append the event element.
9093                        td = core.createElement('td', { className: 'fc-event-container' }, seg.el);
9094                        if (leftCol !== rightCol) {
9095                            td.colSpan = rightCol - leftCol + 1;
9096                        }
9097                        else { // a single-column segment
9098                            loneCellMatrix[i][col] = td;
9099                        }
9100                        while (col <= rightCol) {
9101                            cellMatrix[i][col] = td;
9102                            segMatrix[i][col] = seg;
9103                            col++;
9104                        }
9105                        tr.appendChild(td);
9106                    }
9107                }
9108                emptyCellsUntil(colCnt); // finish off the row
9109                var introHtml = dayGrid.renderProps.renderIntroHtml();
9110                if (introHtml) {
9111                    if (dayGrid.isRtl) {
9112                        core.appendToElement(tr, introHtml);
9113                    }
9114                    else {
9115                        core.prependToElement(tr, introHtml);
9116                    }
9117                }
9118                tbody.appendChild(tr);
9119            }
9120            return {
9121                row: row,
9122                tbodyEl: tbody,
9123                cellMatrix: cellMatrix,
9124                segMatrix: segMatrix,
9125                segLevels: segLevels,
9126                segs: rowSegs
9127            };
9128        };
9129        // Stacks a flat array of segments, which are all assumed to be in the same row, into subarrays of vertical levels.
9130        // NOTE: modifies segs
9131        DayGridEventRenderer.prototype.buildSegLevels = function (segs) {
9132            var _a = this.dayGrid, isRtl = _a.isRtl, colCnt = _a.colCnt;
9133            var levels = [];
9134            var i;
9135            var seg;
9136            var j;
9137            // Give preference to elements with certain criteria, so they have
9138            // a chance to be closer to the top.
9139            segs = this.sortEventSegs(segs);
9140            for (i = 0; i < segs.length; i++) {
9141                seg = segs[i];
9142                // loop through levels, starting with the topmost, until the segment doesn't collide with other segments
9143                for (j = 0; j < levels.length; j++) {
9144                    if (!isDaySegCollision(seg, levels[j])) {
9145                        break;
9146                    }
9147                }
9148                // `j` now holds the desired subrow index
9149                seg.level = j;
9150                seg.leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; // for sorting only
9151                seg.rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol // for sorting only
9152                ;
9153                (levels[j] || (levels[j] = [])).push(seg);
9154            }
9155            // order segments left-to-right. very important if calendar is RTL
9156            for (j = 0; j < levels.length; j++) {
9157                levels[j].sort(compareDaySegCols);
9158            }
9159            return levels;
9160        };
9161        // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's row
9162        DayGridEventRenderer.prototype.groupSegRows = function (segs) {
9163            var segRows = [];
9164            var i;
9165            for (i = 0; i < this.dayGrid.rowCnt; i++) {
9166                segRows.push([]);
9167            }
9168            for (i = 0; i < segs.length; i++) {
9169                segRows[segs[i].row].push(segs[i]);
9170            }
9171            return segRows;
9172        };
9173        // Computes a default `displayEventEnd` value if one is not expliclty defined
9174        DayGridEventRenderer.prototype.computeDisplayEventEnd = function () {
9175            return this.dayGrid.colCnt === 1; // we'll likely have space if there's only one day
9176        };
9177        return DayGridEventRenderer;
9178    }(SimpleDayGridEventRenderer));
9179    // Computes whether two segments' columns collide. They are assumed to be in the same row.
9180    function isDaySegCollision(seg, otherSegs) {
9181        var i;
9182        var otherSeg;
9183        for (i = 0; i < otherSegs.length; i++) {
9184            otherSeg = otherSegs[i];
9185            if (otherSeg.firstCol <= seg.lastCol &&
9186                otherSeg.lastCol >= seg.firstCol) {
9187                return true;
9188            }
9189        }
9190        return false;
9191    }
9192    // A cmp function for determining the leftmost event
9193    function compareDaySegCols(a, b) {
9194        return a.leftCol - b.leftCol;
9195    }
9196
9197    var DayGridMirrorRenderer = /** @class */ (function (_super) {
9198        __extends(DayGridMirrorRenderer, _super);
9199        function DayGridMirrorRenderer() {
9200            return _super !== null && _super.apply(this, arguments) || this;
9201        }
9202        DayGridMirrorRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
9203            var sourceSeg = mirrorInfo.sourceSeg;
9204            var rowStructs = this.rowStructs = this.renderSegRows(segs);
9205            // inject each new event skeleton into each associated row
9206            this.dayGrid.rowEls.forEach(function (rowNode, row) {
9207                var skeletonEl = core.htmlToElement('<div class="fc-mirror-skeleton"><table></table></div>'); // will be absolutely positioned
9208                var skeletonTopEl;
9209                var skeletonTop;
9210                // If there is an original segment, match the top position. Otherwise, put it at the row's top level
9211                if (sourceSeg && sourceSeg.row === row) {
9212                    skeletonTopEl = sourceSeg.el;
9213                }
9214                else {
9215                    skeletonTopEl = rowNode.querySelector('.fc-content-skeleton tbody');
9216                    if (!skeletonTopEl) { // when no events
9217                        skeletonTopEl = rowNode.querySelector('.fc-content-skeleton table');
9218                    }
9219                }
9220                skeletonTop = skeletonTopEl.getBoundingClientRect().top -
9221                    rowNode.getBoundingClientRect().top; // the offsetParent origin
9222                skeletonEl.style.top = skeletonTop + 'px';
9223                skeletonEl.querySelector('table').appendChild(rowStructs[row].tbodyEl);
9224                rowNode.appendChild(skeletonEl);
9225            });
9226        };
9227        return DayGridMirrorRenderer;
9228    }(DayGridEventRenderer));
9229
9230    var EMPTY_CELL_HTML = '<td style="pointer-events:none"></td>';
9231    var DayGridFillRenderer = /** @class */ (function (_super) {
9232        __extends(DayGridFillRenderer, _super);
9233        function DayGridFillRenderer(dayGrid) {
9234            var _this = _super.call(this, dayGrid.context) || this;
9235            _this.fillSegTag = 'td'; // override the default tag name
9236            _this.dayGrid = dayGrid;
9237            return _this;
9238        }
9239        DayGridFillRenderer.prototype.renderSegs = function (type, segs) {
9240            // don't render timed background events
9241            if (type === 'bgEvent') {
9242                segs = segs.filter(function (seg) {
9243                    return seg.eventRange.def.allDay;
9244                });
9245            }
9246            _super.prototype.renderSegs.call(this, type, segs);
9247        };
9248        DayGridFillRenderer.prototype.attachSegs = function (type, segs) {
9249            var els = [];
9250            var i;
9251            var seg;
9252            var skeletonEl;
9253            for (i = 0; i < segs.length; i++) {
9254                seg = segs[i];
9255                skeletonEl = this.renderFillRow(type, seg);
9256                this.dayGrid.rowEls[seg.row].appendChild(skeletonEl);
9257                els.push(skeletonEl);
9258            }
9259            return els;
9260        };
9261        // Generates the HTML needed for one row of a fill. Requires the seg's el to be rendered.
9262        DayGridFillRenderer.prototype.renderFillRow = function (type, seg) {
9263            var dayGrid = this.dayGrid;
9264            var colCnt = dayGrid.colCnt, isRtl = dayGrid.isRtl;
9265            var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol;
9266            var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol;
9267            var startCol = leftCol;
9268            var endCol = rightCol + 1;
9269            var className;
9270            var skeletonEl;
9271            var trEl;
9272            if (type === 'businessHours') {
9273                className = 'bgevent';
9274            }
9275            else {
9276                className = type.toLowerCase();
9277            }
9278            skeletonEl = core.htmlToElement('<div class="fc-' + className + '-skeleton">' +
9279                '<table><tr></tr></table>' +
9280                '</div>');
9281            trEl = skeletonEl.getElementsByTagName('tr')[0];
9282            if (startCol > 0) {
9283                core.appendToElement(trEl, 
9284                // will create (startCol + 1) td's
9285                new Array(startCol + 1).join(EMPTY_CELL_HTML));
9286            }
9287            seg.el.colSpan = endCol - startCol;
9288            trEl.appendChild(seg.el);
9289            if (endCol < colCnt) {
9290                core.appendToElement(trEl, 
9291                // will create (colCnt - endCol) td's
9292                new Array(colCnt - endCol + 1).join(EMPTY_CELL_HTML));
9293            }
9294            var introHtml = dayGrid.renderProps.renderIntroHtml();
9295            if (introHtml) {
9296                if (dayGrid.isRtl) {
9297                    core.appendToElement(trEl, introHtml);
9298                }
9299                else {
9300                    core.prependToElement(trEl, introHtml);
9301                }
9302            }
9303            return skeletonEl;
9304        };
9305        return DayGridFillRenderer;
9306    }(core.FillRenderer));
9307
9308    var DayTile = /** @class */ (function (_super) {
9309        __extends(DayTile, _super);
9310        function DayTile(context, el) {
9311            var _this = _super.call(this, context, el) || this;
9312            var eventRenderer = _this.eventRenderer = new DayTileEventRenderer(_this);
9313            var renderFrame = _this.renderFrame = core.memoizeRendering(_this._renderFrame);
9314            _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderFrame]);
9315            _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]);
9316            _this.renderEventDrag = core.memoizeRendering(eventRenderer.hideByHash.bind(eventRenderer), eventRenderer.showByHash.bind(eventRenderer), [renderFrame]);
9317            _this.renderEventResize = core.memoizeRendering(eventRenderer.hideByHash.bind(eventRenderer), eventRenderer.showByHash.bind(eventRenderer), [renderFrame]);
9318            context.calendar.registerInteractiveComponent(_this, {
9319                el: _this.el,
9320                useEventCenter: false
9321            });
9322            return _this;
9323        }
9324        DayTile.prototype.render = function (props) {
9325            this.renderFrame(props.date);
9326            this.renderFgEvents(props.fgSegs);
9327            this.renderEventSelection(props.eventSelection);
9328            this.renderEventDrag(props.eventDragInstances);
9329            this.renderEventResize(props.eventResizeInstances);
9330        };
9331        DayTile.prototype.destroy = function () {
9332            _super.prototype.destroy.call(this);
9333            this.renderFrame.unrender(); // should unrender everything else
9334            this.calendar.unregisterInteractiveComponent(this);
9335        };
9336        DayTile.prototype._renderFrame = function (date) {
9337            var _a = this, theme = _a.theme, dateEnv = _a.dateEnv;
9338            var title = dateEnv.format(date, core.createFormatter(this.opt('dayPopoverFormat')) // TODO: cache
9339            );
9340            this.el.innerHTML =
9341                '<div class="fc-header ' + theme.getClass('popoverHeader') + '">' +
9342                    '<span class="fc-title">' +
9343                    core.htmlEscape(title) +
9344                    '</span>' +
9345                    '<span class="fc-close ' + theme.getIconClass('close') + '"></span>' +
9346                    '</div>' +
9347                    '<div class="fc-body ' + theme.getClass('popoverContent') + '">' +
9348                    '<div class="fc-event-container"></div>' +
9349                    '</div>';
9350            this.segContainerEl = this.el.querySelector('.fc-event-container');
9351        };
9352        DayTile.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) {
9353            var date = this.props.date; // HACK
9354            if (positionLeft < elWidth && positionTop < elHeight) {
9355                return {
9356                    component: this,
9357                    dateSpan: {
9358                        allDay: true,
9359                        range: { start: date, end: core.addDays(date, 1) }
9360                    },
9361                    dayEl: this.el,
9362                    rect: {
9363                        left: 0,
9364                        top: 0,
9365                        right: elWidth,
9366                        bottom: elHeight
9367                    },
9368                    layer: 1
9369                };
9370            }
9371        };
9372        return DayTile;
9373    }(core.DateComponent));
9374    var DayTileEventRenderer = /** @class */ (function (_super) {
9375        __extends(DayTileEventRenderer, _super);
9376        function DayTileEventRenderer(dayTile) {
9377            var _this = _super.call(this, dayTile.context) || this;
9378            _this.dayTile = dayTile;
9379            return _this;
9380        }
9381        DayTileEventRenderer.prototype.attachSegs = function (segs) {
9382            for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
9383                var seg = segs_1[_i];
9384                this.dayTile.segContainerEl.appendChild(seg.el);
9385            }
9386        };
9387        DayTileEventRenderer.prototype.detachSegs = function (segs) {
9388            for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
9389                var seg = segs_2[_i];
9390                core.removeElement(seg.el);
9391            }
9392        };
9393        return DayTileEventRenderer;
9394    }(SimpleDayGridEventRenderer));
9395
9396    var DayBgRow = /** @class */ (function () {
9397        function DayBgRow(context) {
9398            this.context = context;
9399        }
9400        DayBgRow.prototype.renderHtml = function (props) {
9401            var parts = [];
9402            if (props.renderIntroHtml) {
9403                parts.push(props.renderIntroHtml());
9404            }
9405            for (var _i = 0, _a = props.cells; _i < _a.length; _i++) {
9406                var cell = _a[_i];
9407                parts.push(renderCellHtml(cell.date, props.dateProfile, this.context, cell.htmlAttrs));
9408            }
9409            if (!props.cells.length) {
9410                parts.push('<td class="fc-day ' + this.context.theme.getClass('widgetContent') + '"></td>');
9411            }
9412            if (this.context.options.dir === 'rtl') {
9413                parts.reverse();
9414            }
9415            return '<tr>' + parts.join('') + '</tr>';
9416        };
9417        return DayBgRow;
9418    }());
9419    function renderCellHtml(date, dateProfile, context, otherAttrs) {
9420        var dateEnv = context.dateEnv, theme = context.theme;
9421        var isDateValid = core.rangeContainsMarker(dateProfile.activeRange, date); // TODO: called too frequently. cache somehow.
9422        var classes = core.getDayClasses(date, dateProfile, context);
9423        classes.unshift('fc-day', theme.getClass('widgetContent'));
9424        return '<td class="' + classes.join(' ') + '"' +
9425            (isDateValid ?
9426                ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' :
9427                '') +
9428            (otherAttrs ?
9429                ' ' + otherAttrs :
9430                '') +
9431            '></td>';
9432    }
9433
9434    var DAY_NUM_FORMAT = core.createFormatter({ day: 'numeric' });
9435    var WEEK_NUM_FORMAT = core.createFormatter({ week: 'numeric' });
9436    var DayGrid = /** @class */ (function (_super) {
9437        __extends(DayGrid, _super);
9438        function DayGrid(context, el, renderProps) {
9439            var _this = _super.call(this, context, el) || this;
9440            _this.bottomCoordPadding = 0; // hack for extending the hit area for the last row of the coordinate grid
9441            _this.isCellSizesDirty = false;
9442            var eventRenderer = _this.eventRenderer = new DayGridEventRenderer(_this);
9443            var fillRenderer = _this.fillRenderer = new DayGridFillRenderer(_this);
9444            _this.mirrorRenderer = new DayGridMirrorRenderer(_this);
9445            var renderCells = _this.renderCells = core.memoizeRendering(_this._renderCells, _this._unrenderCells);
9446            _this.renderBusinessHours = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'), [renderCells]);
9447            _this.renderDateSelection = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'highlight'), fillRenderer.unrender.bind(fillRenderer, 'highlight'), [renderCells]);
9448            _this.renderBgEvents = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'), [renderCells]);
9449            _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderCells]);
9450            _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]);
9451            _this.renderEventDrag = core.memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag, [renderCells]);
9452            _this.renderEventResize = core.memoizeRendering(_this._renderEventResize, _this._unrenderEventResize, [renderCells]);
9453            _this.renderProps = renderProps;
9454            return _this;
9455        }
9456        DayGrid.prototype.render = function (props) {
9457            var cells = props.cells;
9458            this.rowCnt = cells.length;
9459            this.colCnt = cells[0].length;
9460            this.renderCells(cells, props.isRigid);
9461            this.renderBusinessHours(props.businessHourSegs);
9462            this.renderDateSelection(props.dateSelectionSegs);
9463            this.renderBgEvents(props.bgEventSegs);
9464            this.renderFgEvents(props.fgEventSegs);
9465            this.renderEventSelection(props.eventSelection);
9466            this.renderEventDrag(props.eventDrag);
9467            this.renderEventResize(props.eventResize);
9468            if (this.segPopoverTile) {
9469                this.updateSegPopoverTile();
9470            }
9471        };
9472        DayGrid.prototype.destroy = function () {
9473            _super.prototype.destroy.call(this);
9474            this.renderCells.unrender(); // will unrender everything else
9475        };
9476        DayGrid.prototype.getCellRange = function (row, col) {
9477            var start = this.props.cells[row][col].date;
9478            var end = core.addDays(start, 1);
9479            return { start: start, end: end };
9480        };
9481        DayGrid.prototype.updateSegPopoverTile = function (date, segs) {
9482            var ownProps = this.props;
9483            this.segPopoverTile.receiveProps({
9484                date: date || this.segPopoverTile.props.date,
9485                fgSegs: segs || this.segPopoverTile.props.fgSegs,
9486                eventSelection: ownProps.eventSelection,
9487                eventDragInstances: ownProps.eventDrag ? ownProps.eventDrag.affectedInstances : null,
9488                eventResizeInstances: ownProps.eventResize ? ownProps.eventResize.affectedInstances : null
9489            });
9490        };
9491        /* Date Rendering
9492        ------------------------------------------------------------------------------------------------------------------*/
9493        DayGrid.prototype._renderCells = function (cells, isRigid) {
9494            var _a = this, view = _a.view, dateEnv = _a.dateEnv;
9495            var _b = this, rowCnt = _b.rowCnt, colCnt = _b.colCnt;
9496            var html = '';
9497            var row;
9498            var col;
9499            for (row = 0; row < rowCnt; row++) {
9500                html += this.renderDayRowHtml(row, isRigid);
9501            }
9502            this.el.innerHTML = html;
9503            this.rowEls = core.findElements(this.el, '.fc-row');
9504            this.cellEls = core.findElements(this.el, '.fc-day, .fc-disabled-day');
9505            if (this.isRtl) {
9506                this.cellEls.reverse();
9507            }
9508            this.rowPositions = new core.PositionCache(this.el, this.rowEls, false, true // vertical
9509            );
9510            this.colPositions = new core.PositionCache(this.el, this.cellEls.slice(0, colCnt), // only the first row
9511            true, false // horizontal
9512            );
9513            // trigger dayRender with each cell's element
9514            for (row = 0; row < rowCnt; row++) {
9515                for (col = 0; col < colCnt; col++) {
9516                    this.publiclyTrigger('dayRender', [
9517                        {
9518                            date: dateEnv.toDate(cells[row][col].date),
9519                            el: this.getCellEl(row, col),
9520                            view: view
9521                        }
9522                    ]);
9523                }
9524            }
9525            this.isCellSizesDirty = true;
9526        };
9527        DayGrid.prototype._unrenderCells = function () {
9528            this.removeSegPopover();
9529        };
9530        // Generates the HTML for a single row, which is a div that wraps a table.
9531        // `row` is the row number.
9532        DayGrid.prototype.renderDayRowHtml = function (row, isRigid) {
9533            var theme = this.theme;
9534            var classes = ['fc-row', 'fc-week', theme.getClass('dayRow')];
9535            if (isRigid) {
9536                classes.push('fc-rigid');
9537            }
9538            var bgRow = new DayBgRow(this.context);
9539            return '' +
9540                '<div class="' + classes.join(' ') + '">' +
9541                '<div class="fc-bg">' +
9542                '<table class="' + theme.getClass('tableGrid') + '">' +
9543                bgRow.renderHtml({
9544                    cells: this.props.cells[row],
9545                    dateProfile: this.props.dateProfile,
9546                    renderIntroHtml: this.renderProps.renderBgIntroHtml
9547                }) +
9548                '</table>' +
9549                '</div>' +
9550                '<div class="fc-content-skeleton">' +
9551                '<table>' +
9552                (this.getIsNumbersVisible() ?
9553                    '<thead>' +
9554                        this.renderNumberTrHtml(row) +
9555                        '</thead>' :
9556                    '') +
9557                '</table>' +
9558                '</div>' +
9559                '</div>';
9560        };
9561        DayGrid.prototype.getIsNumbersVisible = function () {
9562            return this.getIsDayNumbersVisible() ||
9563                this.renderProps.cellWeekNumbersVisible ||
9564                this.renderProps.colWeekNumbersVisible;
9565        };
9566        DayGrid.prototype.getIsDayNumbersVisible = function () {
9567            return this.rowCnt > 1;
9568        };
9569        /* Grid Number Rendering
9570        ------------------------------------------------------------------------------------------------------------------*/
9571        DayGrid.prototype.renderNumberTrHtml = function (row) {
9572            var intro = this.renderProps.renderNumberIntroHtml(row, this);
9573            return '' +
9574                '<tr>' +
9575                (this.isRtl ? '' : intro) +
9576                this.renderNumberCellsHtml(row) +
9577                (this.isRtl ? intro : '') +
9578                '</tr>';
9579        };
9580        DayGrid.prototype.renderNumberCellsHtml = function (row) {
9581            var htmls = [];
9582            var col;
9583            var date;
9584            for (col = 0; col < this.colCnt; col++) {
9585                date = this.props.cells[row][col].date;
9586                htmls.push(this.renderNumberCellHtml(date));
9587            }
9588            if (this.isRtl) {
9589                htmls.reverse();
9590            }
9591            return htmls.join('');
9592        };
9593        // Generates the HTML for the <td>s of the "number" row in the DayGrid's content skeleton.
9594        // The number row will only exist if either day numbers or week numbers are turned on.
9595        DayGrid.prototype.renderNumberCellHtml = function (date) {
9596            var _a = this, view = _a.view, dateEnv = _a.dateEnv;
9597            var html = '';
9598            var isDateValid = core.rangeContainsMarker(this.props.dateProfile.activeRange, date); // TODO: called too frequently. cache somehow.
9599            var isDayNumberVisible = this.getIsDayNumbersVisible() && isDateValid;
9600            var classes;
9601            var weekCalcFirstDow;
9602            if (!isDayNumberVisible && !this.renderProps.cellWeekNumbersVisible) {
9603                // no numbers in day cell (week number must be along the side)
9604                return '<td></td>'; //  will create an empty space above events :(
9605            }
9606            classes = core.getDayClasses(date, this.props.dateProfile, this.context);
9607            classes.unshift('fc-day-top');
9608            if (this.renderProps.cellWeekNumbersVisible) {
9609                weekCalcFirstDow = dateEnv.weekDow;
9610            }
9611            html += '<td class="' + classes.join(' ') + '"' +
9612                (isDateValid ?
9613                    ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' :
9614                    '') +
9615                '>';
9616            if (this.renderProps.cellWeekNumbersVisible && (date.getUTCDay() === weekCalcFirstDow)) {
9617                html += core.buildGotoAnchorHtml(view, { date: date, type: 'week' }, { 'class': 'fc-week-number' }, dateEnv.format(date, WEEK_NUM_FORMAT) // inner HTML
9618                );
9619            }
9620            if (isDayNumberVisible) {
9621                html += core.buildGotoAnchorHtml(view, date, { 'class': 'fc-day-number' }, dateEnv.format(date, DAY_NUM_FORMAT) // inner HTML
9622                );
9623            }
9624            html += '</td>';
9625            return html;
9626        };
9627        /* Sizing
9628        ------------------------------------------------------------------------------------------------------------------*/
9629        DayGrid.prototype.updateSize = function (isResize) {
9630            var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer;
9631            if (isResize ||
9632                this.isCellSizesDirty ||
9633                this.view.calendar.isEventsUpdated // hack
9634            ) {
9635                this.buildPositionCaches();
9636                this.isCellSizesDirty = false;
9637            }
9638            fillRenderer.computeSizes(isResize);
9639            eventRenderer.computeSizes(isResize);
9640            mirrorRenderer.computeSizes(isResize);
9641            fillRenderer.assignSizes(isResize);
9642            eventRenderer.assignSizes(isResize);
9643            mirrorRenderer.assignSizes(isResize);
9644        };
9645        DayGrid.prototype.buildPositionCaches = function () {
9646            this.buildColPositions();
9647            this.buildRowPositions();
9648        };
9649        DayGrid.prototype.buildColPositions = function () {
9650            this.colPositions.build();
9651        };
9652        DayGrid.prototype.buildRowPositions = function () {
9653            this.rowPositions.build();
9654            this.rowPositions.bottoms[this.rowCnt - 1] += this.bottomCoordPadding; // hack
9655        };
9656        /* Hit System
9657        ------------------------------------------------------------------------------------------------------------------*/
9658        DayGrid.prototype.positionToHit = function (leftPosition, topPosition) {
9659            var _a = this, colPositions = _a.colPositions, rowPositions = _a.rowPositions;
9660            var col = colPositions.leftToIndex(leftPosition);
9661            var row = rowPositions.topToIndex(topPosition);
9662            if (row != null && col != null) {
9663                return {
9664                    row: row,
9665                    col: col,
9666                    dateSpan: {
9667                        range: this.getCellRange(row, col),
9668                        allDay: true
9669                    },
9670                    dayEl: this.getCellEl(row, col),
9671                    relativeRect: {
9672                        left: colPositions.lefts[col],
9673                        right: colPositions.rights[col],
9674                        top: rowPositions.tops[row],
9675                        bottom: rowPositions.bottoms[row]
9676                    }
9677                };
9678            }
9679        };
9680        /* Cell System
9681        ------------------------------------------------------------------------------------------------------------------*/
9682        // FYI: the first column is the leftmost column, regardless of date
9683        DayGrid.prototype.getCellEl = function (row, col) {
9684            return this.cellEls[row * this.colCnt + col];
9685        };
9686        /* Event Drag Visualization
9687        ------------------------------------------------------------------------------------------------------------------*/
9688        DayGrid.prototype._renderEventDrag = function (state) {
9689            if (state) {
9690                this.eventRenderer.hideByHash(state.affectedInstances);
9691                this.fillRenderer.renderSegs('highlight', state.segs);
9692            }
9693        };
9694        DayGrid.prototype._unrenderEventDrag = function (state) {
9695            if (state) {
9696                this.eventRenderer.showByHash(state.affectedInstances);
9697                this.fillRenderer.unrender('highlight');
9698            }
9699        };
9700        /* Event Resize Visualization
9701        ------------------------------------------------------------------------------------------------------------------*/
9702        DayGrid.prototype._renderEventResize = function (state) {
9703            if (state) {
9704                this.eventRenderer.hideByHash(state.affectedInstances);
9705                this.fillRenderer.renderSegs('highlight', state.segs);
9706                this.mirrorRenderer.renderSegs(state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
9707            }
9708        };
9709        DayGrid.prototype._unrenderEventResize = function (state) {
9710            if (state) {
9711                this.eventRenderer.showByHash(state.affectedInstances);
9712                this.fillRenderer.unrender('highlight');
9713                this.mirrorRenderer.unrender(state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
9714            }
9715        };
9716        /* More+ Link Popover
9717        ------------------------------------------------------------------------------------------------------------------*/
9718        DayGrid.prototype.removeSegPopover = function () {
9719            if (this.segPopover) {
9720                this.segPopover.hide(); // in handler, will call segPopover's removeElement
9721            }
9722        };
9723        // Limits the number of "levels" (vertically stacking layers of events) for each row of the grid.
9724        // `levelLimit` can be false (don't limit), a number, or true (should be computed).
9725        DayGrid.prototype.limitRows = function (levelLimit) {
9726            var rowStructs = this.eventRenderer.rowStructs || [];
9727            var row; // row #
9728            var rowLevelLimit;
9729            for (row = 0; row < rowStructs.length; row++) {
9730                this.unlimitRow(row);
9731                if (!levelLimit) {
9732                    rowLevelLimit = false;
9733                }
9734                else if (typeof levelLimit === 'number') {
9735                    rowLevelLimit = levelLimit;
9736                }
9737                else {
9738                    rowLevelLimit = this.computeRowLevelLimit(row);
9739                }
9740                if (rowLevelLimit !== false) {
9741                    this.limitRow(row, rowLevelLimit);
9742                }
9743            }
9744        };
9745        // Computes the number of levels a row will accomodate without going outside its bounds.
9746        // Assumes the row is "rigid" (maintains a constant height regardless of what is inside).
9747        // `row` is the row number.
9748        DayGrid.prototype.computeRowLevelLimit = function (row) {
9749            var rowEl = this.rowEls[row]; // the containing "fake" row div
9750            var rowBottom = rowEl.getBoundingClientRect().bottom; // relative to viewport!
9751            var trEls = core.findChildren(this.eventRenderer.rowStructs[row].tbodyEl);
9752            var i;
9753            var trEl;
9754            // Reveal one level <tr> at a time and stop when we find one out of bounds
9755            for (i = 0; i < trEls.length; i++) {
9756                trEl = trEls[i];
9757                trEl.classList.remove('fc-limited'); // reset to original state (reveal)
9758                if (trEl.getBoundingClientRect().bottom > rowBottom) {
9759                    return i;
9760                }
9761            }
9762            return false; // should not limit at all
9763        };
9764        // Limits the given grid row to the maximum number of levels and injects "more" links if necessary.
9765        // `row` is the row number.
9766        // `levelLimit` is a number for the maximum (inclusive) number of levels allowed.
9767        DayGrid.prototype.limitRow = function (row, levelLimit) {
9768            var _this = this;
9769            var _a = this, colCnt = _a.colCnt, isRtl = _a.isRtl;
9770            var rowStruct = this.eventRenderer.rowStructs[row];
9771            var moreNodes = []; // array of "more" <a> links and <td> DOM nodes
9772            var col = 0; // col #, left-to-right (not chronologically)
9773            var levelSegs; // array of segment objects in the last allowable level, ordered left-to-right
9774            var cellMatrix; // a matrix (by level, then column) of all <td> elements in the row
9775            var limitedNodes; // array of temporarily hidden level <tr> and segment <td> DOM nodes
9776            var i;
9777            var seg;
9778            var segsBelow; // array of segment objects below `seg` in the current `col`
9779            var totalSegsBelow; // total number of segments below `seg` in any of the columns `seg` occupies
9780            var colSegsBelow; // array of segment arrays, below seg, one for each column (offset from segs's first column)
9781            var td;
9782            var rowSpan;
9783            var segMoreNodes; // array of "more" <td> cells that will stand-in for the current seg's cell
9784            var j;
9785            var moreTd;
9786            var moreWrap;
9787            var moreLink;
9788            // Iterates through empty level cells and places "more" links inside if need be
9789            var emptyCellsUntil = function (endCol) {
9790                while (col < endCol) {
9791                    segsBelow = _this.getCellSegs(row, col, levelLimit);
9792                    if (segsBelow.length) {
9793                        td = cellMatrix[levelLimit - 1][col];
9794                        moreLink = _this.renderMoreLink(row, col, segsBelow);
9795                        moreWrap = core.createElement('div', null, moreLink);
9796                        td.appendChild(moreWrap);
9797                        moreNodes.push(moreWrap);
9798                    }
9799                    col++;
9800                }
9801            };
9802            if (levelLimit && levelLimit < rowStruct.segLevels.length) { // is it actually over the limit?
9803                levelSegs = rowStruct.segLevels[levelLimit - 1];
9804                cellMatrix = rowStruct.cellMatrix;
9805                limitedNodes = core.findChildren(rowStruct.tbodyEl).slice(levelLimit); // get level <tr> elements past the limit
9806                limitedNodes.forEach(function (node) {
9807                    node.classList.add('fc-limited'); // hide elements and get a simple DOM-nodes array
9808                });
9809                // iterate though segments in the last allowable level
9810                for (i = 0; i < levelSegs.length; i++) {
9811                    seg = levelSegs[i];
9812                    var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol;
9813                    var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol;
9814                    emptyCellsUntil(leftCol); // process empty cells before the segment
9815                    // determine *all* segments below `seg` that occupy the same columns
9816                    colSegsBelow = [];
9817                    totalSegsBelow = 0;
9818                    while (col <= rightCol) {
9819                        segsBelow = this.getCellSegs(row, col, levelLimit);
9820                        colSegsBelow.push(segsBelow);
9821                        totalSegsBelow += segsBelow.length;
9822                        col++;
9823                    }
9824                    if (totalSegsBelow) { // do we need to replace this segment with one or many "more" links?
9825                        td = cellMatrix[levelLimit - 1][leftCol]; // the segment's parent cell
9826                        rowSpan = td.rowSpan || 1;
9827                        segMoreNodes = [];
9828                        // make a replacement <td> for each column the segment occupies. will be one for each colspan
9829                        for (j = 0; j < colSegsBelow.length; j++) {
9830                            moreTd = core.createElement('td', { className: 'fc-more-cell', rowSpan: rowSpan });
9831                            segsBelow = colSegsBelow[j];
9832                            moreLink = this.renderMoreLink(row, leftCol + j, [seg].concat(segsBelow) // count seg as hidden too
9833                            );
9834                            moreWrap = core.createElement('div', null, moreLink);
9835                            moreTd.appendChild(moreWrap);
9836                            segMoreNodes.push(moreTd);
9837                            moreNodes.push(moreTd);
9838                        }
9839                        td.classList.add('fc-limited');
9840                        core.insertAfterElement(td, segMoreNodes);
9841                        limitedNodes.push(td);
9842                    }
9843                }
9844                emptyCellsUntil(this.colCnt); // finish off the level
9845                rowStruct.moreEls = moreNodes; // for easy undoing later
9846                rowStruct.limitedEls = limitedNodes; // for easy undoing later
9847            }
9848        };
9849        // Reveals all levels and removes all "more"-related elements for a grid's row.
9850        // `row` is a row number.
9851        DayGrid.prototype.unlimitRow = function (row) {
9852            var rowStruct = this.eventRenderer.rowStructs[row];
9853            if (rowStruct.moreEls) {
9854                rowStruct.moreEls.forEach(core.removeElement);
9855                rowStruct.moreEls = null;
9856            }
9857            if (rowStruct.limitedEls) {
9858                rowStruct.limitedEls.forEach(function (limitedEl) {
9859                    limitedEl.classList.remove('fc-limited');
9860                });
9861                rowStruct.limitedEls = null;
9862            }
9863        };
9864        // Renders an <a> element that represents hidden event element for a cell.
9865        // Responsible for attaching click handler as well.
9866        DayGrid.prototype.renderMoreLink = function (row, col, hiddenSegs) {
9867            var _this = this;
9868            var _a = this, view = _a.view, dateEnv = _a.dateEnv;
9869            var a = core.createElement('a', { className: 'fc-more' });
9870            a.innerText = this.getMoreLinkText(hiddenSegs.length);
9871            a.addEventListener('click', function (ev) {
9872                var clickOption = _this.opt('eventLimitClick');
9873                var _col = _this.isRtl ? _this.colCnt - col - 1 : col; // HACK: props.cells has different dir system?
9874                var date = _this.props.cells[row][_col].date;
9875                var moreEl = ev.currentTarget;
9876                var dayEl = _this.getCellEl(row, col);
9877                var allSegs = _this.getCellSegs(row, col);
9878                // rescope the segments to be within the cell's date
9879                var reslicedAllSegs = _this.resliceDaySegs(allSegs, date);
9880                var reslicedHiddenSegs = _this.resliceDaySegs(hiddenSegs, date);
9881                if (typeof clickOption === 'function') {
9882                    // the returned value can be an atomic option
9883                    clickOption = _this.publiclyTrigger('eventLimitClick', [
9884                        {
9885                            date: dateEnv.toDate(date),
9886                            allDay: true,
9887                            dayEl: dayEl,
9888                            moreEl: moreEl,
9889                            segs: reslicedAllSegs,
9890                            hiddenSegs: reslicedHiddenSegs,
9891                            jsEvent: ev,
9892                            view: view
9893                        }
9894                    ]);
9895                }
9896                if (clickOption === 'popover') {
9897                    _this.showSegPopover(row, col, moreEl, reslicedAllSegs);
9898                }
9899                else if (typeof clickOption === 'string') { // a view name
9900                    view.calendar.zoomTo(date, clickOption);
9901                }
9902            });
9903            return a;
9904        };
9905        // Reveals the popover that displays all events within a cell
9906        DayGrid.prototype.showSegPopover = function (row, col, moreLink, segs) {
9907            var _this = this;
9908            var _a = this, calendar = _a.calendar, view = _a.view, theme = _a.theme;
9909            var _col = this.isRtl ? this.colCnt - col - 1 : col; // HACK: props.cells has different dir system?
9910            var moreWrap = moreLink.parentNode; // the <div> wrapper around the <a>
9911            var topEl; // the element we want to match the top coordinate of
9912            var options;
9913            if (this.rowCnt === 1) {
9914                topEl = view.el; // will cause the popover to cover any sort of header
9915            }
9916            else {
9917                topEl = this.rowEls[row]; // will align with top of row
9918            }
9919            options = {
9920                className: 'fc-more-popover ' + theme.getClass('popover'),
9921                parentEl: view.el,
9922                top: core.computeRect(topEl).top,
9923                autoHide: true,
9924                content: function (el) {
9925                    _this.segPopoverTile = new DayTile(_this.context, el);
9926                    _this.updateSegPopoverTile(_this.props.cells[row][_col].date, segs);
9927                },
9928                hide: function () {
9929                    _this.segPopoverTile.destroy();
9930                    _this.segPopoverTile = null;
9931                    _this.segPopover.destroy();
9932                    _this.segPopover = null;
9933                }
9934            };
9935            // Determine horizontal coordinate.
9936            // We use the moreWrap instead of the <td> to avoid border confusion.
9937            if (this.isRtl) {
9938                options.right = core.computeRect(moreWrap).right + 1; // +1 to be over cell border
9939            }
9940            else {
9941                options.left = core.computeRect(moreWrap).left - 1; // -1 to be over cell border
9942            }
9943            this.segPopover = new Popover(options);
9944            this.segPopover.show();
9945            calendar.releaseAfterSizingTriggers(); // hack for eventPositioned
9946        };
9947        // Given the events within an array of segment objects, reslice them to be in a single day
9948        DayGrid.prototype.resliceDaySegs = function (segs, dayDate) {
9949            var dayStart = dayDate;
9950            var dayEnd = core.addDays(dayStart, 1);
9951            var dayRange = { start: dayStart, end: dayEnd };
9952            var newSegs = [];
9953            for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
9954                var seg = segs_1[_i];
9955                var eventRange = seg.eventRange;
9956                var origRange = eventRange.range;
9957                var slicedRange = core.intersectRanges(origRange, dayRange);
9958                if (slicedRange) {
9959                    newSegs.push(__assign({}, seg, { eventRange: {
9960                            def: eventRange.def,
9961                            ui: __assign({}, eventRange.ui, { durationEditable: false }),
9962                            instance: eventRange.instance,
9963                            range: slicedRange
9964                        }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() }));
9965                }
9966            }
9967            return newSegs;
9968        };
9969        // Generates the text that should be inside a "more" link, given the number of events it represents
9970        DayGrid.prototype.getMoreLinkText = function (num) {
9971            var opt = this.opt('eventLimitText');
9972            if (typeof opt === 'function') {
9973                return opt(num);
9974            }
9975            else {
9976                return '+' + num + ' ' + opt;
9977            }
9978        };
9979        // Returns segments within a given cell.
9980        // If `startLevel` is specified, returns only events including and below that level. Otherwise returns all segs.
9981        DayGrid.prototype.getCellSegs = function (row, col, startLevel) {
9982            var segMatrix = this.eventRenderer.rowStructs[row].segMatrix;
9983            var level = startLevel || 0;
9984            var segs = [];
9985            var seg;
9986            while (level < segMatrix.length) {
9987                seg = segMatrix[level][col];
9988                if (seg) {
9989                    segs.push(seg);
9990                }
9991                level++;
9992            }
9993            return segs;
9994        };
9995        return DayGrid;
9996    }(core.DateComponent));
9997
9998    var WEEK_NUM_FORMAT$1 = core.createFormatter({ week: 'numeric' });
9999    /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.
10000    ----------------------------------------------------------------------------------------------------------------------*/
10001    // It is a manager for a DayGrid subcomponent, which does most of the heavy lifting.
10002    // It is responsible for managing width/height.
10003    var DayGridView = /** @class */ (function (_super) {
10004        __extends(DayGridView, _super);
10005        function DayGridView(context, viewSpec, dateProfileGenerator, parentEl) {
10006            var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this;
10007            /* Header Rendering
10008            ------------------------------------------------------------------------------------------------------------------*/
10009            // Generates the HTML that will go before the day-of week header cells
10010            _this.renderHeadIntroHtml = function () {
10011                var theme = _this.theme;
10012                if (_this.colWeekNumbersVisible) {
10013                    return '' +
10014                        '<th class="fc-week-number ' + theme.getClass('widgetHeader') + '" ' + _this.weekNumberStyleAttr() + '>' +
10015                        '<span>' + // needed for matchCellWidths
10016                        core.htmlEscape(_this.opt('weekLabel')) +
10017                        '</span>' +
10018                        '</th>';
10019                }
10020                return '';
10021            };
10022            /* Day Grid Rendering
10023            ------------------------------------------------------------------------------------------------------------------*/
10024            // Generates the HTML that will go before content-skeleton cells that display the day/week numbers
10025            _this.renderDayGridNumberIntroHtml = function (row, dayGrid) {
10026                var dateEnv = _this.dateEnv;
10027                var weekStart = dayGrid.props.cells[row][0].date;
10028                if (_this.colWeekNumbersVisible) {
10029                    return '' +
10030                        '<td class="fc-week-number" ' + _this.weekNumberStyleAttr() + '>' +
10031                        core.buildGotoAnchorHtml(// aside from link, important for matchCellWidths
10032                        _this, { date: weekStart, type: 'week', forceOff: dayGrid.colCnt === 1 }, dateEnv.format(weekStart, WEEK_NUM_FORMAT$1) // inner HTML
10033                        ) +
10034                        '</td>';
10035                }
10036                return '';
10037            };
10038            // Generates the HTML that goes before the day bg cells for each day-row
10039            _this.renderDayGridBgIntroHtml = function () {
10040                var theme = _this.theme;
10041                if (_this.colWeekNumbersVisible) {
10042                    return '<td class="fc-week-number ' + theme.getClass('widgetContent') + '" ' + _this.weekNumberStyleAttr() + '></td>';
10043                }
10044                return '';
10045            };
10046            // Generates the HTML that goes before every other type of row generated by DayGrid.
10047            // Affects mirror-skeleton and highlight-skeleton rows.
10048            _this.renderDayGridIntroHtml = function () {
10049                if (_this.colWeekNumbersVisible) {
10050                    return '<td class="fc-week-number" ' + _this.weekNumberStyleAttr() + '></td>';
10051                }
10052                return '';
10053            };
10054            _this.el.classList.add('fc-dayGrid-view');
10055            _this.el.innerHTML = _this.renderSkeletonHtml();
10056            _this.scroller = new core.ScrollComponent('hidden', // overflow x
10057            'auto' // overflow y
10058            );
10059            var dayGridContainerEl = _this.scroller.el;
10060            _this.el.querySelector('.fc-body > tr > td').appendChild(dayGridContainerEl);
10061            dayGridContainerEl.classList.add('fc-day-grid-container');
10062            var dayGridEl = core.createElement('div', { className: 'fc-day-grid' });
10063            dayGridContainerEl.appendChild(dayGridEl);
10064            var cellWeekNumbersVisible;
10065            if (_this.opt('weekNumbers')) {
10066                if (_this.opt('weekNumbersWithinDays')) {
10067                    cellWeekNumbersVisible = true;
10068                    _this.colWeekNumbersVisible = false;
10069                }
10070                else {
10071                    cellWeekNumbersVisible = false;
10072                    _this.colWeekNumbersVisible = true;
10073                }
10074            }
10075            else {
10076                _this.colWeekNumbersVisible = false;
10077                cellWeekNumbersVisible = false;
10078            }
10079            _this.dayGrid = new DayGrid(_this.context, dayGridEl, {
10080                renderNumberIntroHtml: _this.renderDayGridNumberIntroHtml,
10081                renderBgIntroHtml: _this.renderDayGridBgIntroHtml,
10082                renderIntroHtml: _this.renderDayGridIntroHtml,
10083                colWeekNumbersVisible: _this.colWeekNumbersVisible,
10084                cellWeekNumbersVisible: cellWeekNumbersVisible
10085            });
10086            return _this;
10087        }
10088        DayGridView.prototype.destroy = function () {
10089            _super.prototype.destroy.call(this);
10090            this.dayGrid.destroy();
10091            this.scroller.destroy();
10092        };
10093        // Builds the HTML skeleton for the view.
10094        // The day-grid component will render inside of a container defined by this HTML.
10095        DayGridView.prototype.renderSkeletonHtml = function () {
10096            var theme = this.theme;
10097            return '' +
10098                '<table class="' + theme.getClass('tableGrid') + '">' +
10099                (this.opt('columnHeader') ?
10100                    '<thead class="fc-head">' +
10101                        '<tr>' +
10102                        '<td class="fc-head-container ' + theme.getClass('widgetHeader') + '">&nbsp;</td>' +
10103                        '</tr>' +
10104                        '</thead>' :
10105                    '') +
10106                '<tbody class="fc-body">' +
10107                '<tr>' +
10108                '<td class="' + theme.getClass('widgetContent') + '"></td>' +
10109                '</tr>' +
10110                '</tbody>' +
10111                '</table>';
10112        };
10113        // Generates an HTML attribute string for setting the width of the week number column, if it is known
10114        DayGridView.prototype.weekNumberStyleAttr = function () {
10115            if (this.weekNumberWidth != null) {
10116                return 'style="width:' + this.weekNumberWidth + 'px"';
10117            }
10118            return '';
10119        };
10120        // Determines whether each row should have a constant height
10121        DayGridView.prototype.hasRigidRows = function () {
10122            var eventLimit = this.opt('eventLimit');
10123            return eventLimit && typeof eventLimit !== 'number';
10124        };
10125        /* Dimensions
10126        ------------------------------------------------------------------------------------------------------------------*/
10127        DayGridView.prototype.updateSize = function (isResize, viewHeight, isAuto) {
10128            _super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); // will call updateBaseSize. important that executes first
10129            this.dayGrid.updateSize(isResize);
10130        };
10131        // Refreshes the horizontal dimensions of the view
10132        DayGridView.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) {
10133            var dayGrid = this.dayGrid;
10134            var eventLimit = this.opt('eventLimit');
10135            var headRowEl = this.header ? this.header.el : null; // HACK
10136            var scrollerHeight;
10137            var scrollbarWidths;
10138            // hack to give the view some height prior to dayGrid's columns being rendered
10139            // TODO: separate setting height from scroller VS dayGrid.
10140            if (!dayGrid.rowEls) {
10141                if (!isAuto) {
10142                    scrollerHeight = this.computeScrollerHeight(viewHeight);
10143                    this.scroller.setHeight(scrollerHeight);
10144                }
10145                return;
10146            }
10147            if (this.colWeekNumbersVisible) {
10148                // Make sure all week number cells running down the side have the same width.
10149                this.weekNumberWidth = core.matchCellWidths(core.findElements(this.el, '.fc-week-number'));
10150            }
10151            // reset all heights to be natural
10152            this.scroller.clear();
10153            if (headRowEl) {
10154                core.uncompensateScroll(headRowEl);
10155            }
10156            dayGrid.removeSegPopover(); // kill the "more" popover if displayed
10157            // is the event limit a constant level number?
10158            if (eventLimit && typeof eventLimit === 'number') {
10159                dayGrid.limitRows(eventLimit); // limit the levels first so the height can redistribute after
10160            }
10161            // distribute the height to the rows
10162            // (viewHeight is a "recommended" value if isAuto)
10163            scrollerHeight = this.computeScrollerHeight(viewHeight);
10164            this.setGridHeight(scrollerHeight, isAuto);
10165            // is the event limit dynamically calculated?
10166            if (eventLimit && typeof eventLimit !== 'number') {
10167                dayGrid.limitRows(eventLimit); // limit the levels after the grid's row heights have been set
10168            }
10169            if (!isAuto) { // should we force dimensions of the scroll container?
10170                this.scroller.setHeight(scrollerHeight);
10171                scrollbarWidths = this.scroller.getScrollbarWidths();
10172                if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?
10173                    if (headRowEl) {
10174                        core.compensateScroll(headRowEl, scrollbarWidths);
10175                    }
10176                    // doing the scrollbar compensation might have created text overflow which created more height. redo
10177                    scrollerHeight = this.computeScrollerHeight(viewHeight);
10178                    this.scroller.setHeight(scrollerHeight);
10179                }
10180                // guarantees the same scrollbar widths
10181                this.scroller.lockOverflow(scrollbarWidths);
10182            }
10183        };
10184        // given a desired total height of the view, returns what the height of the scroller should be
10185        DayGridView.prototype.computeScrollerHeight = function (viewHeight) {
10186            return viewHeight -
10187                core.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
10188        };
10189        // Sets the height of just the DayGrid component in this view
10190        DayGridView.prototype.setGridHeight = function (height, isAuto) {
10191            if (this.opt('monthMode')) {
10192                // if auto, make the height of each row the height that it would be if there were 6 weeks
10193                if (isAuto) {
10194                    height *= this.dayGrid.rowCnt / 6;
10195                }
10196                core.distributeHeight(this.dayGrid.rowEls, height, !isAuto); // if auto, don't compensate for height-hogging rows
10197            }
10198            else {
10199                if (isAuto) {
10200                    core.undistributeHeight(this.dayGrid.rowEls); // let the rows be their natural height with no expanding
10201                }
10202                else {
10203                    core.distributeHeight(this.dayGrid.rowEls, height, true); // true = compensate for height-hogging rows
10204                }
10205            }
10206        };
10207        /* Scroll
10208        ------------------------------------------------------------------------------------------------------------------*/
10209        DayGridView.prototype.computeDateScroll = function (duration) {
10210            return { top: 0 };
10211        };
10212        DayGridView.prototype.queryDateScroll = function () {
10213            return { top: this.scroller.getScrollTop() };
10214        };
10215        DayGridView.prototype.applyDateScroll = function (scroll) {
10216            if (scroll.top !== undefined) {
10217                this.scroller.setScrollTop(scroll.top);
10218            }
10219        };
10220        return DayGridView;
10221    }(core.View));
10222    DayGridView.prototype.dateProfileGeneratorClass = DayGridDateProfileGenerator;
10223
10224    var SimpleDayGrid = /** @class */ (function (_super) {
10225        __extends(SimpleDayGrid, _super);
10226        function SimpleDayGrid(context, dayGrid) {
10227            var _this = _super.call(this, context, dayGrid.el) || this;
10228            _this.slicer = new DayGridSlicer();
10229            _this.dayGrid = dayGrid;
10230            context.calendar.registerInteractiveComponent(_this, { el: _this.dayGrid.el });
10231            return _this;
10232        }
10233        SimpleDayGrid.prototype.destroy = function () {
10234            _super.prototype.destroy.call(this);
10235            this.calendar.unregisterInteractiveComponent(this);
10236        };
10237        SimpleDayGrid.prototype.render = function (props) {
10238            var dayGrid = this.dayGrid;
10239            var dateProfile = props.dateProfile, dayTable = props.dayTable;
10240            dayGrid.receiveProps(__assign({}, this.slicer.sliceProps(props, dateProfile, props.nextDayThreshold, dayGrid, dayTable), { dateProfile: dateProfile, cells: dayTable.cells, isRigid: props.isRigid }));
10241        };
10242        SimpleDayGrid.prototype.buildPositionCaches = function () {
10243            this.dayGrid.buildPositionCaches();
10244        };
10245        SimpleDayGrid.prototype.queryHit = function (positionLeft, positionTop) {
10246            var rawHit = this.dayGrid.positionToHit(positionLeft, positionTop);
10247            if (rawHit) {
10248                return {
10249                    component: this.dayGrid,
10250                    dateSpan: rawHit.dateSpan,
10251                    dayEl: rawHit.dayEl,
10252                    rect: {
10253                        left: rawHit.relativeRect.left,
10254                        right: rawHit.relativeRect.right,
10255                        top: rawHit.relativeRect.top,
10256                        bottom: rawHit.relativeRect.bottom
10257                    },
10258                    layer: 0
10259                };
10260            }
10261        };
10262        return SimpleDayGrid;
10263    }(core.DateComponent));
10264    var DayGridSlicer = /** @class */ (function (_super) {
10265        __extends(DayGridSlicer, _super);
10266        function DayGridSlicer() {
10267            return _super !== null && _super.apply(this, arguments) || this;
10268        }
10269        DayGridSlicer.prototype.sliceRange = function (dateRange, dayTable) {
10270            return dayTable.sliceRange(dateRange);
10271        };
10272        return DayGridSlicer;
10273    }(core.Slicer));
10274
10275    var DayGridView$1 = /** @class */ (function (_super) {
10276        __extends(DayGridView, _super);
10277        function DayGridView(_context, viewSpec, dateProfileGenerator, parentEl) {
10278            var _this = _super.call(this, _context, viewSpec, dateProfileGenerator, parentEl) || this;
10279            _this.buildDayTable = core.memoize(buildDayTable);
10280            if (_this.opt('columnHeader')) {
10281                _this.header = new core.DayHeader(_this.context, _this.el.querySelector('.fc-head-container'));
10282            }
10283            _this.simpleDayGrid = new SimpleDayGrid(_this.context, _this.dayGrid);
10284            return _this;
10285        }
10286        DayGridView.prototype.destroy = function () {
10287            _super.prototype.destroy.call(this);
10288            if (this.header) {
10289                this.header.destroy();
10290            }
10291            this.simpleDayGrid.destroy();
10292        };
10293        DayGridView.prototype.render = function (props) {
10294            _super.prototype.render.call(this, props);
10295            var dateProfile = this.props.dateProfile;
10296            var dayTable = this.dayTable =
10297                this.buildDayTable(dateProfile, this.dateProfileGenerator);
10298            if (this.header) {
10299                this.header.receiveProps({
10300                    dateProfile: dateProfile,
10301                    dates: dayTable.headerDates,
10302                    datesRepDistinctDays: dayTable.rowCnt === 1,
10303                    renderIntroHtml: this.renderHeadIntroHtml
10304                });
10305            }
10306            this.simpleDayGrid.receiveProps({
10307                dateProfile: dateProfile,
10308                dayTable: dayTable,
10309                businessHours: props.businessHours,
10310                dateSelection: props.dateSelection,
10311                eventStore: props.eventStore,
10312                eventUiBases: props.eventUiBases,
10313                eventSelection: props.eventSelection,
10314                eventDrag: props.eventDrag,
10315                eventResize: props.eventResize,
10316                isRigid: this.hasRigidRows(),
10317                nextDayThreshold: this.nextDayThreshold
10318            });
10319        };
10320        return DayGridView;
10321    }(DayGridView));
10322    function buildDayTable(dateProfile, dateProfileGenerator) {
10323        var daySeries = new core.DaySeries(dateProfile.renderRange, dateProfileGenerator);
10324        return new core.DayTable(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
10325    }
10326
10327    var main = core.createPlugin({
10328        defaultView: 'dayGridMonth',
10329        views: {
10330            dayGrid: DayGridView$1,
10331            dayGridDay: {
10332                type: 'dayGrid',
10333                duration: { days: 1 }
10334            },
10335            dayGridWeek: {
10336                type: 'dayGrid',
10337                duration: { weeks: 1 }
10338            },
10339            dayGridMonth: {
10340                type: 'dayGrid',
10341                duration: { months: 1 },
10342                monthMode: true,
10343                fixedWeekCount: true
10344            }
10345        }
10346    });
10347
10348    exports.AbstractDayGridView = DayGridView;
10349    exports.DayBgRow = DayBgRow;
10350    exports.DayGrid = DayGrid;
10351    exports.DayGridSlicer = DayGridSlicer;
10352    exports.DayGridView = DayGridView$1;
10353    exports.SimpleDayGrid = SimpleDayGrid;
10354    exports.buildBasicDayTable = buildDayTable;
10355    exports.default = main;
10356
10357    Object.defineProperty(exports, '__esModule', { value: true });
10358
10359}));
10360
10361/*!
10362FullCalendar Google Calendar Plugin v4.3.0
10363Docs & License: https://fullcalendar.io/
10364(c) 2019 Adam Shaw
10365*/
10366
10367(function (global, factory) {
10368    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) :
10369    typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) :
10370    (global = global || self, factory(global.FullCalendarGoogleCalendar = {}, global.FullCalendar));
10371}(this, function (exports, core) { 'use strict';
10372
10373    /*! *****************************************************************************
10374    Copyright (c) Microsoft Corporation. All rights reserved.
10375    Licensed under the Apache License, Version 2.0 (the "License");
10375 you may not use
10376    this file except in compliance with the License. You may obtain a copy of the
10377    License at http://www.apache.org/licenses/LICENSE-2.0
10378
10379    THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
10380    KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
10381    WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10382    MERCHANTABLITY OR NON-INFRINGEMENT.
10383
10384    See the Apache Version 2.0 License for specific language governing permissions
10385    and limitations under the License.
10386    ***************************************************************************** */
10387
10388    var __assign = function() {
10389        __assign = Object.assign || function __assign(t) {
10390            for (var s, i = 1, n = arguments.length; i < n; i++) {
10391                s = arguments[i];
10392                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
10393            }
10394            return t;
10395        };
10396        return __assign.apply(this, arguments);
10397    };
10398
10399    // TODO: expose somehow
10400    var API_BASE = 'https://www.googleapis.com/calendar/v3/calendars';
10401    var STANDARD_PROPS = {
10402        url: String,
10403        googleCalendarApiKey: String,
10404        googleCalendarId: String,
10405        data: null
10406    };
10407    var eventSourceDef = {
10408        parseMeta: function (raw) {
10409            if (typeof raw === 'string') {
10410                raw = { url: raw };
10411            }
10412            if (typeof raw === 'object') {
10413                var standardProps = core.refineProps(raw, STANDARD_PROPS);
10414                if (!standardProps.googleCalendarId && standardProps.url) {
10415                    standardProps.googleCalendarId = parseGoogleCalendarId(standardProps.url);
10416                }
10417                delete standardProps.url;
10418                if (standardProps.googleCalendarId) {
10419                    return standardProps;
10420                }
10421            }
10422            return null;
10423        },
10424        fetch: function (arg, onSuccess, onFailure) {
10425            var calendar = arg.calendar;
10426            var meta = arg.eventSource.meta;
10427            var apiKey = meta.googleCalendarApiKey || calendar.opt('googleCalendarApiKey');
10428            if (!apiKey) {
10429                onFailure({
10430                    message: 'Specify a googleCalendarApiKey. See http://fullcalendar.io/docs/google_calendar/'
10431                });
10432            }
10433            else {
10434                var url = buildUrl(meta);
10435                var requestParams_1 = buildRequestParams(arg.range, apiKey, meta.data, calendar.dateEnv);
10436                core.requestJson('GET', url, requestParams_1, function (body, xhr) {
10437                    if (body.error) {
10438                        onFailure({
10439                            message: 'Google Calendar API: ' + body.error.message,
10440                            errors: body.error.errors,
10441                            xhr: xhr
10442                        });
10443                    }
10444                    else {
10445                        onSuccess({
10446                            rawEvents: gcalItemsToRawEventDefs(body.items, requestParams_1.timeZone),
10447                            xhr: xhr
10448                        });
10449                    }
10450                }, function (message, xhr) {
10451                    onFailure({ message: message, xhr: xhr });
10452                });
10453            }
10454        }
10455    };
10456    function parseGoogleCalendarId(url) {
10457        var match;
10458        // detect if the ID was specified as a single string.
10459        // will match calendars like "[email protected]" in addition to person email calendars.
10460        if (/^[^\/]+@([^\/\.]+\.)*(google|googlemail|gmail)\.com$/.test(url)) {
10461            return url;
10462        }
10463        else if ((match = /^https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/([^\/]*)/.exec(url)) ||
10464            (match = /^https?:\/\/www.google.com\/calendar\/feeds\/([^\/]*)/.exec(url))) {
10465            return decodeURIComponent(match[1]);
10466        }
10467    }
10468    function buildUrl(meta) {
10469        return API_BASE + '/' + encodeURIComponent(meta.googleCalendarId) + '/events';
10470    }
10471    function buildRequestParams(range, apiKey, extraParams, dateEnv) {
10472        var params;
10473        var startStr;
10474        var endStr;
10475        if (dateEnv.canComputeOffset) {
10476            // strings will naturally have offsets, which GCal needs
10477            startStr = dateEnv.formatIso(range.start);
10478            endStr = dateEnv.formatIso(range.end);
10479        }
10480        else {
10481            // when timezone isn't known, we don't know what the UTC offset should be, so ask for +/- 1 day
10482            // from the UTC day-start to guarantee we're getting all the events
10483            // (start/end will be UTC-coerced dates, so toISOString is okay)
10484            startStr = core.addDays(range.start, -1).toISOString();
10485            endStr = core.addDays(range.end, 1).toISOString();
10486        }
10487        params = __assign({}, (extraParams || {}), { key: apiKey, timeMin: startStr, timeMax: endStr, singleEvents: true, maxResults: 9999 });
10488        if (dateEnv.timeZone !== 'local') {
10489            params.timeZone = dateEnv.timeZone;
10490        }
10491        return params;
10492    }
10493    function gcalItemsToRawEventDefs(items, gcalTimezone) {
10494        return items.map(function (item) {
10495            return gcalItemToRawEventDef(item, gcalTimezone);
10496        });
10497    }
10498    function gcalItemToRawEventDef(item, gcalTimezone) {
10499        var url = item.htmlLink || null;
10500        // make the URLs for each event show times in the correct timezone
10501        if (url && gcalTimezone) {
10502            url = injectQsComponent(url, 'ctz=' + gcalTimezone);
10503        }
10504        return {
10505            id: item.id,
10506            title: item.summary,
10507            start: item.start.dateTime || item.start.date,
10508            end: item.end.dateTime || item.end.date,
10509            url: url,
10510            location: item.location,
10511            description: item.description
10512        };
10513    }
10514    // Injects a string like "arg=value" into the querystring of a URL
10515    // TODO: move to a general util file?
10516    function injectQsComponent(url, component) {
10517        // inject it after the querystring but before the fragment
10518        return url.replace(/(\?.*?)?(#|$)/, function (whole, qs, hash) {
10519            return (qs ? qs + '&' : '?') + component + hash;
10520        });
10521    }
10522    var main = core.createPlugin({
10523        eventSourceDefs: [eventSourceDef]
10524    });
10525
10526    exports.default = main;
10527
10528    Object.defineProperty(exports, '__esModule', { value: true });
10529
10530}));
10531
10532/*!
10533FullCalendar Interaction Plugin v4.3.0
10534Docs & License: https://fullcalendar.io/
10535(c) 2019 Adam Shaw
10536*/
10537
10538(function (global, factory) {
10539    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) :
10540    typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) :
10541    (global = global || self, factory(global.FullCalendarInteraction = {}, global.FullCalendar));
10542}(this, function (exports, core) { 'use strict';
10543
10544    /*! *****************************************************************************
10545    Copyright (c) Microsoft Corporation. All rights reserved.
10546    Licensed under the Apache License, Version 2.0 (the "License"); you may not use
10547    this file except in compliance with the License. You may obtain a copy of the
10548    License at http://www.apache.org/licenses/LICENSE-2.0
10549
10550    THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
10551    KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
10552    WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10553    MERCHANTABLITY OR NON-INFRINGEMENT.
10554
10555    See the Apache Version 2.0 License for specific language governing permissions
10556    and limitations under the License.
10557    ***************************************************************************** */
10558    /* global Reflect, Promise */
10559
10560    var extendStatics = function(d, b) {
10561        extendStatics = Object.setPrototypeOf ||
10562            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
10563            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
10564        return extendStatics(d, b);
10565    };
10566
10567    function __extends(d, b) {
10568        extendStatics(d, b);
10569        function __() { this.constructor = d; }
10570        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
10571    }
10572
10573    var __assign = function() {
10574        __assign = Object.assign || function __assign(t) {
10575            for (var s, i = 1, n = arguments.length; i < n; i++) {
10576                s = arguments[i];
10577                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
10578            }
10579            return t;
10580        };
10581        return __assign.apply(this, arguments);
10582    };
10583
10584    core.config.touchMouseIgnoreWait = 500;
10585    var ignoreMouseDepth = 0;
10586    var listenerCnt = 0;
10587    var isWindowTouchMoveCancelled = false;
10588    /*
10589    Uses a "pointer" abstraction, which monitors UI events for both mouse and touch.
10590    Tracks when the pointer "drags" on a certain element, meaning down+move+up.
10591
10592    Also, tracks if there was touch-scrolling.
10593    Also, can prevent touch-scrolling from happening.
10594    Also, can fire pointermove events when scrolling happens underneath, even when no real pointer movement.
10595
10596    emits:
10597    - pointerdown
10598    - pointermove
10599    - pointerup
10600    */
10601    var PointerDragging = /** @class */ (function () {
10602        function PointerDragging(containerEl) {
10603            var _this = this;
10604            this.subjectEl = null;
10605            this.downEl = null;
10606            // options that can be directly assigned by caller
10607            this.selector = ''; // will cause subjectEl in all emitted events to be this element
10608            this.handleSelector = '';
10609            this.shouldIgnoreMove = false;
10610            this.shouldWatchScroll = true; // for simulating pointermove on scroll
10611            // internal states
10612            this.isDragging = false;
10613            this.isTouchDragging = false;
10614            this.wasTouchScroll = false;
10615            // Mouse
10616            // ----------------------------------------------------------------------------------------------------
10617            this.handleMouseDown = function (ev) {
10618                if (!_this.shouldIgnoreMouse() &&
10619                    isPrimaryMouseButton(ev) &&
10620                    _this.tryStart(ev)) {
10621                    var pev = _this.createEventFromMouse(ev, true);
10622                    _this.emitter.trigger('pointerdown', pev);
10623                    _this.initScrollWatch(pev);
10624                    if (!_this.shouldIgnoreMove) {
10625                        document.addEventListener('mousemove', _this.handleMouseMove);
10626                    }
10627                    document.addEventListener('mouseup', _this.handleMouseUp);
10628                }
10629            };
10630            this.handleMouseMove = function (ev) {
10631                var pev = _this.createEventFromMouse(ev);
10632                _this.recordCoords(pev);
10633                _this.emitter.trigger('pointermove', pev);
10634            };
10635            this.handleMouseUp = function (ev) {
10636                document.removeEventListener('mousemove', _this.handleMouseMove);
10637                document.removeEventListener('mouseup', _this.handleMouseUp);
10638                _this.emitter.trigger('pointerup', _this.createEventFromMouse(ev));
10639                _this.cleanup(); // call last so that pointerup has access to props
10640            };
10641            // Touch
10642            // ----------------------------------------------------------------------------------------------------
10643            this.handleTouchStart = function (ev) {
10644                if (_this.tryStart(ev)) {
10645                    _this.isTouchDragging = true;
10646                    var pev = _this.createEventFromTouch(ev, true);
10647                    _this.emitter.trigger('pointerdown', pev);
10648                    _this.initScrollWatch(pev);
10649                    // unlike mouse, need to attach to target, not document
10650                    // https://stackoverflow.com/a/45760014
10651                    var target = ev.target;
10652                    if (!_this.shouldIgnoreMove) {
10653                        target.addEventListener('touchmove', _this.handleTouchMove);
10654                    }
10655                    target.addEventListener('touchend', _this.handleTouchEnd);
10656                    target.addEventListener('touchcancel', _this.handleTouchEnd); // treat it as a touch end
10657                    // attach a handler to get called when ANY scroll action happens on the page.
10658                    // this was impossible to do with normal on/off because 'scroll' doesn't bubble.
10659                    // http://stackoverflow.com/a/32954565/96342
10660                    window.addEventListener('scroll', _this.handleTouchScroll, true // useCapture
10661                    );
10662                }
10663            };
10664            this.handleTouchMove = function (ev) {
10665                var pev = _this.createEventFromTouch(ev);
10666                _this.recordCoords(pev);
10667                _this.emitter.trigger('pointermove', pev);
10668            };
10669            this.handleTouchEnd = function (ev) {
10670                if (_this.isDragging) { // done to guard against touchend followed by touchcancel
10671                    var target = ev.target;
10672                    target.removeEventListener('touchmove', _this.handleTouchMove);
10673                    target.removeEventListener('touchend', _this.handleTouchEnd);
10674                    target.removeEventListener('touchcancel', _this.handleTouchEnd);
10675                    window.removeEventListener('scroll', _this.handleTouchScroll, true); // useCaptured=true
10676                    _this.emitter.trigger('pointerup', _this.createEventFromTouch(ev));
10677                    _this.cleanup(); // call last so that pointerup has access to props
10678                    _this.isTouchDragging = false;
10679                    startIgnoringMouse();
10680                }
10681            };
10682            this.handleTouchScroll = function () {
10683                _this.wasTouchScroll = true;
10684            };
10685            this.handleScroll = function (ev) {
10686                if (!_this.shouldIgnoreMove) {
10687                    var pageX = (window.pageXOffset - _this.prevScrollX) + _this.prevPageX;
10688                    var pageY = (window.pageYOffset - _this.prevScrollY) + _this.prevPageY;
10689                    _this.emitter.trigger('pointermove', {
10690                        origEvent: ev,
10691                        isTouch: _this.isTouchDragging,
10692                        subjectEl: _this.subjectEl,
10693                        pageX: pageX,
10694                        pageY: pageY,
10695                        deltaX: pageX - _this.origPageX,
10696                        deltaY: pageY - _this.origPageY
10697                    });
10698                }
10699            };
10700            this.containerEl = containerEl;
10701            this.emitter = new core.EmitterMixin();
10702            containerEl.addEventListener('mousedown', this.handleMouseDown);
10703            containerEl.addEventListener('touchstart', this.handleTouchStart, { passive: true });
10704            listenerCreated();
10705        }
10706        PointerDragging.prototype.destroy = function () {
10707            this.containerEl.removeEventListener('mousedown', this.handleMouseDown);
10708            this.containerEl.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
10709            listenerDestroyed();
10710        };
10711        PointerDragging.prototype.tryStart = function (ev) {
10712            var subjectEl = this.querySubjectEl(ev);
10713            var downEl = ev.target;
10714            if (subjectEl &&
10715                (!this.handleSelector || core.elementClosest(downEl, this.handleSelector))) {
10716                this.subjectEl = subjectEl;
10717                this.downEl = downEl;
10718                this.isDragging = true; // do this first so cancelTouchScroll will work
10719                this.wasTouchScroll = false;
10720                return true;
10721            }
10722            return false;
10723        };
10724        PointerDragging.prototype.cleanup = function () {
10725            isWindowTouchMoveCancelled = false;
10726            this.isDragging = false;
10727            this.subjectEl = null;
10728            this.downEl = null;
10729            // keep wasTouchScroll around for later access
10730            this.destroyScrollWatch();
10731        };
10732        PointerDragging.prototype.querySubjectEl = function (ev) {
10733            if (this.selector) {
10734                return core.elementClosest(ev.target, this.selector);
10735            }
10736            else {
10737                return this.containerEl;
10738            }
10739        };
10740        PointerDragging.prototype.shouldIgnoreMouse = function () {
10741            return ignoreMouseDepth || this.isTouchDragging;
10742        };
10743        // can be called by user of this class, to cancel touch-based scrolling for the current drag
10744        PointerDragging.prototype.cancelTouchScroll = function () {
10745            if (this.isDragging) {
10746                isWindowTouchMoveCancelled = true;
10747            }
10748        };
10749        // Scrolling that simulates pointermoves
10750        // ----------------------------------------------------------------------------------------------------
10751        PointerDragging.prototype.initScrollWatch = function (ev) {
10752            if (this.shouldWatchScroll) {
10753                this.recordCoords(ev);
10754                window.addEventListener('scroll', this.handleScroll, true); // useCapture=true
10755            }
10756        };
10757        PointerDragging.prototype.recordCoords = function (ev) {
10758            if (this.shouldWatchScroll) {
10759                this.prevPageX = ev.pageX;
10760                this.prevPageY = ev.pageY;
10761                this.prevScrollX = window.pageXOffset;
10762                this.prevScrollY = window.pageYOffset;
10763            }
10764        };
10765        PointerDragging.prototype.destroyScrollWatch = function () {
10766            if (this.shouldWatchScroll) {
10767                window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true
10768            }
10769        };
10770        // Event Normalization
10771        // ----------------------------------------------------------------------------------------------------
10772        PointerDragging.prototype.createEventFromMouse = function (ev, isFirst) {
10773            var deltaX = 0;
10774            var deltaY = 0;
10775            // TODO: repeat code
10776            if (isFirst) {
10777                this.origPageX = ev.pageX;
10778                this.origPageY = ev.pageY;
10779            }
10780            else {
10781                deltaX = ev.pageX - this.origPageX;
10782                deltaY = ev.pageY - this.origPageY;
10783            }
10784            return {
10785                origEvent: ev,
10786                isTouch: false,
10787                subjectEl: this.subjectEl,
10788                pageX: ev.pageX,
10789                pageY: ev.pageY,
10790                deltaX: deltaX,
10791                deltaY: deltaY
10792            };
10793        };
10794        PointerDragging.prototype.createEventFromTouch = function (ev, isFirst) {
10795            var touches = ev.touches;
10796            var pageX;
10797            var pageY;
10798            var deltaX = 0;
10799            var deltaY = 0;
10800            // if touch coords available, prefer,
10801            // because FF would give bad ev.pageX ev.pageY
10802            if (touches && touches.length) {
10803                pageX = touches[0].pageX;
10804                pageY = touches[0].pageY;
10805            }
10806            else {
10807                pageX = ev.pageX;
10808                pageY = ev.pageY;
10809            }
10810            // TODO: repeat code
10811            if (isFirst) {
10812                this.origPageX = pageX;
10813                this.origPageY = pageY;
10814            }
10815            else {
10816                deltaX = pageX - this.origPageX;
10817                deltaY = pageY - this.origPageY;
10818            }
10819            return {
10820                origEvent: ev,
10821                isTouch: true,
10822                subjectEl: this.subjectEl,
10823                pageX: pageX,
10824                pageY: pageY,
10825                deltaX: deltaX,
10826                deltaY: deltaY
10827            };
10828        };
10829        return PointerDragging;
10830    }());
10831    // Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)
10832    function isPrimaryMouseButton(ev) {
10833        return ev.button === 0 && !ev.ctrlKey;
10834    }
10835    // Ignoring fake mouse events generated by touch
10836    // ----------------------------------------------------------------------------------------------------
10837    function startIgnoringMouse() {
10838        ignoreMouseDepth++;
10839        setTimeout(function () {
10840            ignoreMouseDepth--;
10841        }, core.config.touchMouseIgnoreWait);
10842    }
10843    // We want to attach touchmove as early as possible for Safari
10844    // ----------------------------------------------------------------------------------------------------
10845    function listenerCreated() {
10846        if (!(listenerCnt++)) {
10847            window.addEventListener('touchmove', onWindowTouchMove, { passive: false });
10848        }
10849    }
10850    function listenerDestroyed() {
10851        if (!(--listenerCnt)) {
10852            window.removeEventListener('touchmove', onWindowTouchMove, { passive: false });
10853        }
10854    }
10855    function onWindowTouchMove(ev) {
10856        if (isWindowTouchMoveCancelled) {
10857            ev.preventDefault();
10858        }
10859    }
10860
10861    /*
10862    An effect in which an element follows the movement of a pointer across the screen.
10863    The moving element is a clone of some other element.
10864    Must call start + handleMove + stop.
10865    */
10866    var ElementMirror = /** @class */ (function () {
10867        function ElementMirror() {
10868            this.isVisible = false; // must be explicitly enabled
10869            this.sourceEl = null;
10870            this.mirrorEl = null;
10871            this.sourceElRect = null; // screen coords relative to viewport
10872            // options that can be set directly by caller
10873            this.parentNode = document.body;
10874            this.zIndex = 9999;
10875            this.revertDuration = 0;
10876        }
10877        ElementMirror.prototype.start = function (sourceEl, pageX, pageY) {
10878            this.sourceEl = sourceEl;
10879            this.sourceElRect = this.sourceEl.getBoundingClientRect();
10880            this.origScreenX = pageX - window.pageXOffset;
10881            this.origScreenY = pageY - window.pageYOffset;
10882            this.deltaX = 0;
10883            this.deltaY = 0;
10884            this.updateElPosition();
10885        };
10886        ElementMirror.prototype.handleMove = function (pageX, pageY) {
10887            this.deltaX = (pageX - window.pageXOffset) - this.origScreenX;
10888            this.deltaY = (pageY - window.pageYOffset) - this.origScreenY;
10889            this.updateElPosition();
10890        };
10891        // can be called before start
10892        ElementMirror.prototype.setIsVisible = function (bool) {
10893            if (bool) {
10894                if (!this.isVisible) {
10895                    if (this.mirrorEl) {
10896                        this.mirrorEl.style.display = '';
10897                    }
10898                    this.isVisible = bool; // needs to happen before updateElPosition
10899                    this.updateElPosition(); // because was not updating the position while invisible
10900                }
10901            }
10902            else {
10903                if (this.isVisible) {
10904                    if (this.mirrorEl) {
10905                        this.mirrorEl.style.display = 'none';
10906                    }
10907                    this.isVisible = bool;
10908                }
10909            }
10910        };
10911        // always async
10912        ElementMirror.prototype.stop = function (needsRevertAnimation, callback) {
10913            var _this = this;
10914            var done = function () {
10915                _this.cleanup();
10916                callback();
10917            };
10918            if (needsRevertAnimation &&
10919                this.mirrorEl &&
10920                this.isVisible &&
10921                this.revertDuration && // if 0, transition won't work
10922                (this.deltaX || this.deltaY) // if same coords, transition won't work
10923            ) {
10924                this.doRevertAnimation(done, this.revertDuration);
10925            }
10926            else {
10927                setTimeout(done, 0);
10928            }
10929        };
10930        ElementMirror.prototype.doRevertAnimation = function (callback, revertDuration) {
10931            var mirrorEl = this.mirrorEl;
10932            var finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened
10933            mirrorEl.style.transition =
10934                'top ' + revertDuration + 'ms,' +
10935                    'left ' + revertDuration + 'ms';
10936            core.applyStyle(mirrorEl, {
10937                left: finalSourceElRect.left,
10938                top: finalSourceElRect.top
10939            });
10940            core.whenTransitionDone(mirrorEl, function () {
10941                mirrorEl.style.transition = '';
10942                callback();
10943            });
10944        };
10945        ElementMirror.prototype.cleanup = function () {
10946            if (this.mirrorEl) {
10947                core.removeElement(this.mirrorEl);
10948                this.mirrorEl = null;
10949            }
10950            this.sourceEl = null;
10951        };
10952        ElementMirror.prototype.updateElPosition = function () {
10953            if (this.sourceEl && this.isVisible) {
10954                core.applyStyle(this.getMirrorEl(), {
10955                    left: this.sourceElRect.left + this.deltaX,
10956                    top: this.sourceElRect.top + this.deltaY
10957                });
10958            }
10959        };
10960        ElementMirror.prototype.getMirrorEl = function () {
10961            var sourceElRect = this.sourceElRect;
10962            var mirrorEl = this.mirrorEl;
10963            if (!mirrorEl) {
10964                mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true
10965                // we don't want long taps or any mouse interaction causing selection/menus.
10966                // would use preventSelection(), but that prevents selectstart, causing problems.
10967                mirrorEl.classList.add('fc-unselectable');
10968                mirrorEl.classList.add('fc-dragging');
10969                core.applyStyle(mirrorEl, {
10970                    position: 'fixed',
10971                    zIndex: this.zIndex,
10972                    visibility: '',
10973                    boxSizing: 'border-box',
10974                    width: sourceElRect.right - sourceElRect.left,
10975                    height: sourceElRect.bottom - sourceElRect.top,
10976                    right: 'auto',
10977                    bottom: 'auto',
10978                    margin: 0
10979                });
10980                this.parentNode.appendChild(mirrorEl);
10981            }
10982            return mirrorEl;
10983        };
10984        return ElementMirror;
10985    }());
10986
10987    /*
10988    Is a cache for a given element's scroll information (all the info that ScrollController stores)
10989    in addition the "client rectangle" of the element.. the area within the scrollbars.
10990
10991    The cache can be in one of two modes:
10992    - doesListening:false - ignores when the container is scrolled by someone else
10993    - doesListening:true - watch for scrolling and update the cache
10994    */
10995    var ScrollGeomCache = /** @class */ (function (_super) {
10996        __extends(ScrollGeomCache, _super);
10997        function ScrollGeomCache(scrollController, doesListening) {
10998            var _this = _super.call(this) || this;
10999            _this.handleScroll = function () {
11000                _this.scrollTop = _this.scrollController.getScrollTop();
11001                _this.scrollLeft = _this.scrollController.getScrollLeft();
11002                _this.handleScrollChange();
11003            };
11004            _this.scrollController = scrollController;
11005            _this.doesListening = doesListening;
11006            _this.scrollTop = _this.origScrollTop = scrollController.getScrollTop();
11007            _this.scrollLeft = _this.origScrollLeft = scrollController.getScrollLeft();
11008            _this.scrollWidth = scrollController.getScrollWidth();
11009            _this.scrollHeight = scrollController.getScrollHeight();
11010            _this.clientWidth = scrollController.getClientWidth();
11011            _this.clientHeight = scrollController.getClientHeight();
11012            _this.clientRect = _this.computeClientRect(); // do last in case it needs cached values
11013            if (_this.doesListening) {
11014                _this.getEventTarget().addEventListener('scroll', _this.handleScroll);
11015            }
11016            return _this;
11017        }
11018        ScrollGeomCache.prototype.destroy = function () {
11019            if (this.doesListening) {
11020                this.getEventTarget().removeEventListener('scroll', this.handleScroll);
11021            }
11022        };
11023        ScrollGeomCache.prototype.getScrollTop = function () {
11024            return this.scrollTop;
11025        };
11026        ScrollGeomCache.prototype.getScrollLeft = function () {
11027            return this.scrollLeft;
11028        };
11029        ScrollGeomCache.prototype.setScrollTop = function (top) {
11030            this.scrollController.setScrollTop(top);
11031            if (!this.doesListening) {
11032                // we are not relying on the element to normalize out-of-bounds scroll values
11033                // so we need to sanitize ourselves
11034                this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0);
11035                this.handleScrollChange();
11036            }
11037        };
11038        ScrollGeomCache.prototype.setScrollLeft = function (top) {
11039            this.scrollController.setScrollLeft(top);
11040            if (!this.doesListening) {
11041                // we are not relying on the element to normalize out-of-bounds scroll values
11042                // so we need to sanitize ourselves
11043                this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0);
11044                this.handleScrollChange();
11045            }
11046        };
11047        ScrollGeomCache.prototype.getClientWidth = function () {
11048            return this.clientWidth;
11049        };
11050        ScrollGeomCache.prototype.getClientHeight = function () {
11051            return this.clientHeight;
11052        };
11053        ScrollGeomCache.prototype.getScrollWidth = function () {
11054            return this.scrollWidth;
11055        };
11056        ScrollGeomCache.prototype.getScrollHeight = function () {
11057            return this.scrollHeight;
11058        };
11059        ScrollGeomCache.prototype.handleScrollChange = function () {
11060        };
11061        return ScrollGeomCache;
11062    }(core.ScrollController));
11063    var ElementScrollGeomCache = /** @class */ (function (_super) {
11064        __extends(ElementScrollGeomCache, _super);
11065        function ElementScrollGeomCache(el, doesListening) {
11066            return _super.call(this, new core.ElementScrollController(el), doesListening) || this;
11067        }
11068        ElementScrollGeomCache.prototype.getEventTarget = function () {
11069            return this.scrollController.el;
11070        };
11071        ElementScrollGeomCache.prototype.computeClientRect = function () {
11072            return core.computeInnerRect(this.scrollController.el);
11073        };
11074        return ElementScrollGeomCache;
11075    }(ScrollGeomCache));
11076    var WindowScrollGeomCache = /** @class */ (function (_super) {
11077        __extends(WindowScrollGeomCache, _super);
11078        function WindowScrollGeomCache(doesListening) {
11079            return _super.call(this, new core.WindowScrollController(), doesListening) || this;
11080        }
11081        WindowScrollGeomCache.prototype.getEventTarget = function () {
11082            return window;
11083        };
11084        WindowScrollGeomCache.prototype.computeClientRect = function () {
11085            return {
11086                left: this.scrollLeft,
11087                right: this.scrollLeft + this.clientWidth,
11088                top: this.scrollTop,
11089                bottom: this.scrollTop + this.clientHeight
11090            };
11091        };
11092        // the window is the only scroll object that changes it's rectangle relative
11093        // to the document's topleft as it scrolls
11094        WindowScrollGeomCache.prototype.handleScrollChange = function () {
11095            this.clientRect = this.computeClientRect();
11096        };
11097        return WindowScrollGeomCache;
11098    }(ScrollGeomCache));
11099
11100    // If available we are using native "performance" API instead of "Date"
11101    // Read more about it on MDN:
11102    // https://developer.mozilla.org/en-US/docs/Web/API/Performance
11103    var getTime = typeof performance === 'function' ? performance.now : Date.now;
11104    /*
11105    For a pointer interaction, automatically scrolls certain scroll containers when the pointer
11106    approaches the edge.
11107
11108    The caller must call start + handleMove + stop.
11109    */
11110    var AutoScroller = /** @class */ (function () {
11111        function AutoScroller() {
11112            var _this = this;
11113            // options that can be set by caller
11114            this.isEnabled = true;
11115            this.scrollQuery = [window, '.fc-scroller'];
11116            this.edgeThreshold = 50; // pixels
11117            this.maxVelocity = 300; // pixels per second
11118            // internal state
11119            this.pointerScreenX = null;
11120            this.pointerScreenY = null;
11121            this.isAnimating = false;
11122            this.scrollCaches = null;
11123            // protect against the initial pointerdown being too close to an edge and starting the scroll
11124            this.everMovedUp = false;
11125            this.everMovedDown = false;
11126            this.everMovedLeft = false;
11127            this.everMovedRight = false;
11128            this.animate = function () {
11129                if (_this.isAnimating) { // wasn't cancelled between animation calls
11130                    var edge = _this.computeBestEdge(_this.pointerScreenX + window.pageXOffset, _this.pointerScreenY + window.pageYOffset);
11131                    if (edge) {
11132                        var now = getTime();
11133                        _this.handleSide(edge, (now - _this.msSinceRequest) / 1000);
11134                        _this.requestAnimation(now);
11135                    }
11136                    else {
11137                        _this.isAnimating = false; // will stop animation
11138                    }
11139                }
11140            };
11141        }
11142        AutoScroller.prototype.start = function (pageX, pageY) {
11143            if (this.isEnabled) {
11144                this.scrollCaches = this.buildCaches();
11145                this.pointerScreenX = null;
11146                this.pointerScreenY = null;
11147                this.everMovedUp = false;
11148                this.everMovedDown = false;
11149                this.everMovedLeft = false;
11150                this.everMovedRight = false;
11151                this.handleMove(pageX, pageY);
11152            }
11153        };
11154        AutoScroller.prototype.handleMove = function (pageX, pageY) {
11155            if (this.isEnabled) {
11156                var pointerScreenX = pageX - window.pageXOffset;
11157                var pointerScreenY = pageY - window.pageYOffset;
11158                var yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY;
11159                var xDelta = this.pointerScreenX === null ? 0 : pointerScreenX - this.pointerScreenX;
11160                if (yDelta < 0) {
11161                    this.everMovedUp = true;
11162                }
11163                else if (yDelta > 0) {
11164                    this.everMovedDown = true;
11165                }
11166                if (xDelta < 0) {
11167                    this.everMovedLeft = true;
11168                }
11169                else if (xDelta > 0) {
11170                    this.everMovedRight = true;
11171                }
11172                this.pointerScreenX = pointerScreenX;
11173                this.pointerScreenY = pointerScreenY;
11174                if (!this.isAnimating) {
11175                    this.isAnimating = true;
11176                    this.requestAnimation(getTime());
11177                }
11178            }
11179        };
11180        AutoScroller.prototype.stop = function () {
11181            if (this.isEnabled) {
11182                this.isAnimating = false; // will stop animation
11183                for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
11184                    var scrollCache = _a[_i];
11185                    scrollCache.destroy();
11186                }
11187                this.scrollCaches = null;
11188            }
11189        };
11190        AutoScroller.prototype.requestAnimation = function (now) {
11191            this.msSinceRequest = now;
11192            requestAnimationFrame(this.animate);
11193        };
11194        AutoScroller.prototype.handleSide = function (edge, seconds) {
11195            var scrollCache = edge.scrollCache;
11196            var edgeThreshold = this.edgeThreshold;
11197            var invDistance = edgeThreshold - edge.distance;
11198            var velocity = // the closer to the edge, the faster we scroll
11199             (invDistance * invDistance) / (edgeThreshold * edgeThreshold) * // quadratic
11200                this.maxVelocity * seconds;
11201            var sign = 1;
11202            switch (edge.name) {
11203                case 'left':
11204                    sign = -1;
11205                // falls through
11206                case 'right':
11207                    scrollCache.setScrollLeft(scrollCache.getScrollLeft() + velocity * sign);
11208                    break;
11209                case 'top':
11210                    sign = -1;
11211                // falls through
11212                case 'bottom':
11213                    scrollCache.setScrollTop(scrollCache.getScrollTop() + velocity * sign);
11214                    break;
11215            }
11216        };
11217        // left/top are relative to document topleft
11218        AutoScroller.prototype.computeBestEdge = function (left, top) {
11219            var edgeThreshold = this.edgeThreshold;
11220            var bestSide = null;
11221            for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
11222                var scrollCache = _a[_i];
11223                var rect = scrollCache.clientRect;
11224                var leftDist = left - rect.left;
11225                var rightDist = rect.right - left;
11226                var topDist = top - rect.top;
11227                var bottomDist = rect.bottom - top;
11228                // completely within the rect?
11229                if (leftDist >= 0 && rightDist >= 0 && topDist >= 0 && bottomDist >= 0) {
11230                    if (topDist <= edgeThreshold && this.everMovedUp && scrollCache.canScrollUp() &&
11231                        (!bestSide || bestSide.distance > topDist)) {
11232                        bestSide = { scrollCache: scrollCache, name: 'top', distance: topDist };
11233                    }
11234                    if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() &&
11235                        (!bestSide || bestSide.distance > bottomDist)) {
11236                        bestSide = { scrollCache: scrollCache, name: 'bottom', distance: bottomDist };
11237                    }
11238                    if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() &&
11239                        (!bestSide || bestSide.distance > leftDist)) {
11240                        bestSide = { scrollCache: scrollCache, name: 'left', distance: leftDist };
11241                    }
11242                    if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() &&
11243                        (!bestSide || bestSide.distance > rightDist)) {
11244                        bestSide = { scrollCache: scrollCache, name: 'right', distance: rightDist };
11245                    }
11246                }
11247            }
11248            return bestSide;
11249        };
11250        AutoScroller.prototype.buildCaches = function () {
11251            return this.queryScrollEls().map(function (el) {
11252                if (el === window) {
11253                    return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls
11254                }
11255                else {
11256                    return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls
11257                }
11258            });
11259        };
11260        AutoScroller.prototype.queryScrollEls = function () {
11261            var els = [];
11262            for (var _i = 0, _a = this.scrollQuery; _i < _a.length; _i++) {
11263                var query = _a[_i];
11264                if (typeof query === 'object') {
11265                    els.push(query);
11266                }
11267                else {
11268                    els.push.apply(els, Array.prototype.slice.call(document.querySelectorAll(query)));
11269                }
11270            }
11271            return els;
11272        };
11273        return AutoScroller;
11274    }());
11275
11276    /*
11277    Monitors dragging on an element. Has a number of high-level features:
11278    - minimum distance required before dragging
11279    - minimum wait time ("delay") before dragging
11280    - a mirror element that follows the pointer
11281    */
11282    var FeaturefulElementDragging = /** @class */ (function (_super) {
11283        __extends(FeaturefulElementDragging, _super);
11284        function FeaturefulElementDragging(containerEl) {
11285            var _this = _super.call(this, containerEl) || this;
11286            // options that can be directly set by caller
11287            // the caller can also set the PointerDragging's options as well
11288            _this.delay = null;
11289            _this.minDistance = 0;
11290            _this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag
11291            _this.mirrorNeedsRevert = false;
11292            _this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup
11293            _this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation
11294            _this.isDelayEnded = false;
11295            _this.isDistanceSurpassed = false;
11296            _this.delayTimeoutId = null;
11297            _this.onPointerDown = function (ev) {
11298                if (!_this.isDragging) { // so new drag doesn't happen while revert animation is going
11299                    _this.isInteracting = true;
11300                    _this.isDelayEnded = false;
11301                    _this.isDistanceSurpassed = false;
11302                    core.preventSelection(document.body);
11303                    core.preventContextMenu(document.body);
11304                    // prevent links from being visited if there's an eventual drag.
11305                    // also prevents selection in older browsers (maybe?).
11306                    // not necessary for touch, besides, browser would complain about passiveness.
11307                    if (!ev.isTouch) {
11308                        ev.origEvent.preventDefault();
11309                    }
11310                    _this.emitter.trigger('pointerdown', ev);
11311                    if (!_this.pointer.shouldIgnoreMove) {
11312                        // actions related to initiating dragstart+dragmove+dragend...
11313                        _this.mirror.setIsVisible(false); // reset. caller must set-visible
11314                        _this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down
11315                        _this.startDelay(ev);
11316                        if (!_this.minDistance) {
11317                            _this.handleDistanceSurpassed(ev);
11318                        }
11319                    }
11320                }
11321            };
11322            _this.onPointerMove = function (ev) {
11323                if (_this.isInteracting) { // if false, still waiting for previous drag's revert
11324                    _this.emitter.trigger('pointermove', ev);
11325                    if (!_this.isDistanceSurpassed) {
11326                        var minDistance = _this.minDistance;
11327                        var distanceSq = void 0; // current distance from the origin, squared
11328                        var deltaX = ev.deltaX, deltaY = ev.deltaY;
11329                        distanceSq = deltaX * deltaX + deltaY * deltaY;
11330                        if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem
11331                            _this.handleDistanceSurpassed(ev);
11332                        }
11333                    }
11334                    if (_this.isDragging) {
11335                        // a real pointer move? (not one simulated by scrolling)
11336                        if (ev.origEvent.type !== 'scroll') {
11337                            _this.mirror.handleMove(ev.pageX, ev.pageY);
11338                            _this.autoScroller.handleMove(ev.pageX, ev.pageY);
11339                        }
11340                        _this.emitter.trigger('dragmove', ev);
11341                    }
11342                }
11343            };
11344            _this.onPointerUp = function (ev) {
11345                if (_this.isInteracting) { // if false, still waiting for previous drag's revert
11346                    _this.isInteracting = false;
11347                    core.allowSelection(document.body);
11348                    core.allowContextMenu(document.body);
11349                    _this.emitter.trigger('pointerup', ev); // can potentially set mirrorNeedsRevert
11350                    if (_this.isDragging) {
11351                        _this.autoScroller.stop();
11352                        _this.tryStopDrag(ev); // which will stop the mirror
11353                    }
11354                    if (_this.delayTimeoutId) {
11355                        clearTimeout(_this.delayTimeoutId);
11356                        _this.delayTimeoutId = null;
11357                    }
11358                }
11359            };
11360            var pointer = _this.pointer = new PointerDragging(containerEl);
11361            pointer.emitter.on('pointerdown', _this.onPointerDown);
11362            pointer.emitter.on('pointermove', _this.onPointerMove);
11363            pointer.emitter.on('pointerup', _this.onPointerUp);
11364            _this.mirror = new ElementMirror();
11365            _this.autoScroller = new AutoScroller();
11366            return _this;
11367        }
11368        FeaturefulElementDragging.prototype.destroy = function () {
11369            this.pointer.destroy();
11370        };
11371        FeaturefulElementDragging.prototype.startDelay = function (ev) {
11372            var _this = this;
11373            if (typeof this.delay === 'number') {
11374                this.delayTimeoutId = setTimeout(function () {
11375                    _this.delayTimeoutId = null;
11376                    _this.handleDelayEnd(ev);
11377                }, this.delay); // not assignable to number!
11378            }
11379            else {
11380                this.handleDelayEnd(ev);
11381            }
11382        };
11383        FeaturefulElementDragging.prototype.handleDelayEnd = function (ev) {
11384            this.isDelayEnded = true;
11385            this.tryStartDrag(ev);
11386        };
11387        FeaturefulElementDragging.prototype.handleDistanceSurpassed = function (ev) {
11388            this.isDistanceSurpassed = true;
11389            this.tryStartDrag(ev);
11390        };
11391        FeaturefulElementDragging.prototype.tryStartDrag = function (ev) {
11392            if (this.isDelayEnded && this.isDistanceSurpassed) {
11393                if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) {
11394                    this.isDragging = true;
11395                    this.mirrorNeedsRevert = false;
11396                    this.autoScroller.start(ev.pageX, ev.pageY);
11397                    this.emitter.trigger('dragstart', ev);
11398                    if (this.touchScrollAllowed === false) {
11399                        this.pointer.cancelTouchScroll();
11400                    }
11401                }
11402            }
11403        };
11404        FeaturefulElementDragging.prototype.tryStopDrag = function (ev) {
11405            // .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events
11406            // that come from the document to fire beforehand. much more convenient this way.
11407            this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev) // bound with args
11408            );
11409        };
11410        FeaturefulElementDragging.prototype.stopDrag = function (ev) {
11411            this.isDragging = false;
11412            this.emitter.trigger('dragend', ev);
11413        };
11414        // fill in the implementations...
11415        FeaturefulElementDragging.prototype.setIgnoreMove = function (bool) {
11416            this.pointer.shouldIgnoreMove = bool;
11417        };
11418        FeaturefulElementDragging.prototype.setMirrorIsVisible = function (bool) {
11419            this.mirror.setIsVisible(bool);
11420        };
11421        FeaturefulElementDragging.prototype.setMirrorNeedsRevert = function (bool) {
11422            this.mirrorNeedsRevert = bool;
11423        };
11424        FeaturefulElementDragging.prototype.setAutoScrollEnabled = function (bool) {
11425            this.autoScroller.isEnabled = bool;
11426        };
11427        return FeaturefulElementDragging;
11428    }(core.ElementDragging));
11429
11430    /*
11431    When this class is instantiated, it records the offset of an element (relative to the document topleft),
11432    and continues to monitor scrolling, updating the cached coordinates if it needs to.
11433    Does not access the DOM after instantiation, so highly performant.
11434
11435    Also keeps track of all scrolling/overflow:hidden containers that are parents of the given element
11436    and an determine if a given point is inside the combined clipping rectangle.
11437    */
11438    var OffsetTracker = /** @class */ (function () {
11439        function OffsetTracker(el) {
11440            this.origRect = core.computeRect(el);
11441            // will work fine for divs that have overflow:hidden
11442            this.scrollCaches = core.getClippingParents(el).map(function (el) {
11443                return new ElementScrollGeomCache(el, true); // listen=true
11444            });
11445        }
11446        OffsetTracker.prototype.destroy = function () {
11447            for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
11448                var scrollCache = _a[_i];
11449                scrollCache.destroy();
11450            }
11451        };
11452        OffsetTracker.prototype.computeLeft = function () {
11453            var left = this.origRect.left;
11454            for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
11455                var scrollCache = _a[_i];
11456                left += scrollCache.origScrollLeft - scrollCache.getScrollLeft();
11457            }
11458            return left;
11459        };
11460        OffsetTracker.prototype.computeTop = function () {
11461            var top = this.origRect.top;
11462            for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
11463                var scrollCache = _a[_i];
11464                top += scrollCache.origScrollTop - scrollCache.getScrollTop();
11465            }
11466            return top;
11467        };
11468        OffsetTracker.prototype.isWithinClipping = function (pageX, pageY) {
11469            var point = { left: pageX, top: pageY };
11470            for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
11471                var scrollCache = _a[_i];
11472                if (!isIgnoredClipping(scrollCache.getEventTarget()) &&
11473                    !core.pointInsideRect(point, scrollCache.clientRect)) {
11474                    return false;
11475                }
11476            }
11477            return true;
11478        };
11479        return OffsetTracker;
11480    }());
11481    // certain clipping containers should never constrain interactions, like <html> and <body>
11482    // https://github.com/fullcalendar/fullcalendar/issues/3615
11483    function isIgnoredClipping(node) {
11484        var tagName = node.tagName;
11485        return tagName === 'HTML' || tagName === 'BODY';
11486    }
11487
11488    /*
11489    Tracks movement over multiple droppable areas (aka "hits")
11490    that exist in one or more DateComponents.
11491    Relies on an existing draggable.
11492
11493    emits:
11494    - pointerdown
11495    - dragstart
11496    - hitchange - fires initially, even if not over a hit
11497    - pointerup
11498    - (hitchange - again, to null, if ended over a hit)
11499    - dragend
11500    */
11501    var HitDragging = /** @class */ (function () {
11502        function HitDragging(dragging, droppableStore) {
11503            var _this = this;
11504            // options that can be set by caller
11505            this.useSubjectCenter = false;
11506            this.requireInitial = true; // if doesn't start out on a hit, won't emit any events
11507            this.initialHit = null;
11508            this.movingHit = null;
11509            this.finalHit = null; // won't ever be populated if shouldIgnoreMove
11510            this.handlePointerDown = function (ev) {
11511                var dragging = _this.dragging;
11512                _this.initialHit = null;
11513                _this.movingHit = null;
11514                _this.finalHit = null;
11515                _this.prepareHits();
11516                _this.processFirstCoord(ev);
11517                if (_this.initialHit || !_this.requireInitial) {
11518                    dragging.setIgnoreMove(false);
11519                    _this.emitter.trigger('pointerdown', ev); // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :(
11520                }
11521                else {
11522                    dragging.setIgnoreMove(true);
11523                }
11524            };
11525            this.handleDragStart = function (ev) {
11526                _this.emitter.trigger('dragstart', ev);
11527                _this.handleMove(ev, true); // force = fire even if initially null
11528            };
11529            this.handleDragMove = function (ev) {
11530                _this.emitter.trigger('dragmove', ev);
11531                _this.handleMove(ev);
11532            };
11533            this.handlePointerUp = function (ev) {
11534                _this.releaseHits();
11535                _this.emitter.trigger('pointerup', ev);
11536            };
11537            this.handleDragEnd = function (ev) {
11538                if (_this.movingHit) {
11539                    _this.emitter.trigger('hitupdate', null, true, ev);
11540                }
11541                _this.finalHit = _this.movingHit;
11542                _this.movingHit = null;
11543                _this.emitter.trigger('dragend', ev);
11544            };
11545            this.droppableStore = droppableStore;
11546            dragging.emitter.on('pointerdown', this.handlePointerDown);
11547            dragging.emitter.on('dragstart', this.handleDragStart);
11548            dragging.emitter.on('dragmove', this.handleDragMove);
11549            dragging.emitter.on('pointerup', this.handlePointerUp);
11550            dragging.emitter.on('dragend', this.handleDragEnd);
11551            this.dragging = dragging;
11552            this.emitter = new core.EmitterMixin();
11553        }
11554        // sets initialHit
11555        // sets coordAdjust
11556        HitDragging.prototype.processFirstCoord = function (ev) {
11557            var origPoint = { left: ev.pageX, top: ev.pageY };
11558            var adjustedPoint = origPoint;
11559            var subjectEl = ev.subjectEl;
11560            var subjectRect;
11561            if (subjectEl !== document) {
11562                subjectRect = core.computeRect(subjectEl);
11563                adjustedPoint = core.constrainPoint(adjustedPoint, subjectRect);
11564            }
11565            var initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top);
11566            if (initialHit) {
11567                if (this.useSubjectCenter && subjectRect) {
11568                    var slicedSubjectRect = core.intersectRects(subjectRect, initialHit.rect);
11569                    if (slicedSubjectRect) {
11570                        adjustedPoint = core.getRectCenter(slicedSubjectRect);
11571                    }
11572                }
11573                this.coordAdjust = core.diffPoints(adjustedPoint, origPoint);
11574            }
11575            else {
11576                this.coordAdjust = { left: 0, top: 0 };
11577            }
11578        };
11579        HitDragging.prototype.handleMove = function (ev, forceHandle) {
11580            var hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top);
11581            if (forceHandle || !isHitsEqual(this.movingHit, hit)) {
11582                this.movingHit = hit;
11583                this.emitter.trigger('hitupdate', hit, false, ev);
11584            }
11585        };
11586        HitDragging.prototype.prepareHits = function () {
11587            this.offsetTrackers = core.mapHash(this.droppableStore, function (interactionSettings) {
11588                interactionSettings.component.buildPositionCaches();
11589                return new OffsetTracker(interactionSettings.el);
11590            });
11591        };
11592        HitDragging.prototype.releaseHits = function () {
11593            var offsetTrackers = this.offsetTrackers;
11594            for (var id in offsetTrackers) {
11595                offsetTrackers[id].destroy();
11596            }
11597            this.offsetTrackers = {};
11598        };
11599        HitDragging.prototype.queryHitForOffset = function (offsetLeft, offsetTop) {
11600            var _a = this, droppableStore = _a.droppableStore, offsetTrackers = _a.offsetTrackers;
11601            var bestHit = null;
11602            for (var id in droppableStore) {
11603                var component = droppableStore[id].component;
11604                var offsetTracker = offsetTrackers[id];
11605                if (offsetTracker.isWithinClipping(offsetLeft, offsetTop)) {
11606                    var originLeft = offsetTracker.computeLeft();
11607                    var originTop = offsetTracker.computeTop();
11608                    var positionLeft = offsetLeft - originLeft;
11609                    var positionTop = offsetTop - originTop;
11610                    var origRect = offsetTracker.origRect;
11611                    var width = origRect.right - origRect.left;
11612                    var height = origRect.bottom - origRect.top;
11613                    if (
11614                    // must be within the element's bounds
11615                    positionLeft >= 0 && positionLeft < width &&
11616                        positionTop >= 0 && positionTop < height) {
11617                        var hit = component.queryHit(positionLeft, positionTop, width, height);
11618                        if (hit &&
11619                            (
11620                            // make sure the hit is within activeRange, meaning it's not a deal cell
11621                            !component.props.dateProfile || // hack for DayTile
11622                                core.rangeContainsRange(component.props.dateProfile.activeRange, hit.dateSpan.range)) &&
11623                            (!bestHit || hit.layer > bestHit.layer)) {
11624                            // TODO: better way to re-orient rectangle
11625                            hit.rect.left += originLeft;
11626                            hit.rect.right += originLeft;
11627                            hit.rect.top += originTop;
11628                            hit.rect.bottom += originTop;
11629                            bestHit = hit;
11630                        }
11631                    }
11632                }
11633            }
11634            return bestHit;
11635        };
11636        return HitDragging;
11637    }());
11638    function isHitsEqual(hit0, hit1) {
11639        if (!hit0 && !hit1) {
11640            return true;
11641        }
11642        if (Boolean(hit0) !== Boolean(hit1)) {
11643            return false;
11644        }
11645        return core.isDateSpansEqual(hit0.dateSpan, hit1.dateSpan);
11646    }
11647
11648    /*
11649    Monitors when the user clicks on a specific date/time of a component.
11650    A pointerdown+pointerup on the same "hit" constitutes a click.
11651    */
11652    var DateClicking = /** @class */ (function (_super) {
11653        __extends(DateClicking, _super);
11654        function DateClicking(settings) {
11655            var _this = _super.call(this, settings) || this;
11656            _this.handlePointerDown = function (ev) {
11657                var dragging = _this.dragging;
11658                // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired
11659                dragging.setIgnoreMove(!_this.component.isValidDateDownEl(dragging.pointer.downEl));
11660            };
11661            // won't even fire if moving was ignored
11662            _this.handleDragEnd = function (ev) {
11663                var component = _this.component;
11664                var pointer = _this.dragging.pointer;
11665                if (!pointer.wasTouchScroll) {
11666                    var _a = _this.hitDragging, initialHit = _a.initialHit, finalHit = _a.finalHit;
11667                    if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) {
11668                        component.calendar.triggerDateClick(initialHit.dateSpan, initialHit.dayEl, component.view, ev.origEvent);
11669                    }
11670                }
11671            };
11672            var component = settings.component;
11673            // we DO want to watch pointer moves because otherwise finalHit won't get populated
11674            _this.dragging = new FeaturefulElementDragging(component.el);
11675            _this.dragging.autoScroller.isEnabled = false;
11676            var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, core.interactionSettingsToStore(settings));
11677            hitDragging.emitter.on('pointerdown', _this.handlePointerDown);
11678            hitDragging.emitter.on('dragend', _this.handleDragEnd);
11679            return _this;
11680        }
11681        DateClicking.prototype.destroy = function () {
11682            this.dragging.destroy();
11683        };
11684        return DateClicking;
11685    }(core.Interaction));
11686
11687    /*
11688    Tracks when the user selects a portion of time of a component,
11689    constituted by a drag over date cells, with a possible delay at the beginning of the drag.
11690    */
11691    var DateSelecting = /** @class */ (function (_super) {
11692        __extends(DateSelecting, _super);
11693        function DateSelecting(settings) {
11694            var _this = _super.call(this, settings) || this;
11695            _this.dragSelection = null;
11696            _this.handlePointerDown = function (ev) {
11697                var _a = _this, component = _a.component, dragging = _a.dragging;
11698                var canSelect = component.opt('selectable') &&
11699                    component.isValidDateDownEl(ev.origEvent.target);
11700                // don't bother to watch expensive moves if component won't do selection
11701                dragging.setIgnoreMove(!canSelect);
11702                // if touch, require user to hold down
11703                dragging.delay = ev.isTouch ? getComponentTouchDelay(component) : null;
11704            };
11705            _this.handleDragStart = function (ev) {
11706                _this.component.calendar.unselect(ev); // unselect previous selections
11707            };
11708            _this.handleHitUpdate = function (hit, isFinal) {
11709                var calendar = _this.component.calendar;
11710                var dragSelection = null;
11711                var isInvalid = false;
11712                if (hit) {
11713                    dragSelection = joinHitsIntoSelection(_this.hitDragging.initialHit, hit, calendar.pluginSystem.hooks.dateSelectionTransformers);
11714                    if (!dragSelection || !_this.component.isDateSelectionValid(dragSelection)) {
11715                        isInvalid = true;
11716                        dragSelection = null;
11717                    }
11718                }
11719                if (dragSelection) {
11720                    calendar.dispatch({ type: 'SELECT_DATES', selection: dragSelection });
11721                }
11722                else if (!isFinal) { // only unselect if moved away while dragging
11723                    calendar.dispatch({ type: 'UNSELECT_DATES' });
11724                }
11725                if (!isInvalid) {
11726                    core.enableCursor();
11727                }
11728                else {
11729                    core.disableCursor();
11730                }
11731                if (!isFinal) {
11732                    _this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging
11733                }
11734            };
11735            _this.handlePointerUp = function (pev) {
11736                if (_this.dragSelection) {
11737                    // selection is already rendered, so just need to report selection
11738                    _this.component.calendar.triggerDateSelect(_this.dragSelection, pev);
11739                    _this.dragSelection = null;
11740                }
11741            };
11742            var component = settings.component;
11743            var dragging = _this.dragging = new FeaturefulElementDragging(component.el);
11744            dragging.touchScrollAllowed = false;
11745            dragging.minDistance = component.opt('selectMinDistance') || 0;
11746            dragging.autoScroller.isEnabled = component.opt('dragScroll');
11747            var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, core.interactionSettingsToStore(settings));
11748            hitDragging.emitter.on('pointerdown', _this.handlePointerDown);
11749            hitDragging.emitter.on('dragstart', _this.handleDragStart);
11750            hitDragging.emitter.on('hitupdate', _this.handleHitUpdate);
11751            hitDragging.emitter.on('pointerup', _this.handlePointerUp);
11752            return _this;
11753        }
11754        DateSelecting.prototype.destroy = function () {
11755            this.dragging.destroy();
11756        };
11757        return DateSelecting;
11758    }(core.Interaction));
11759    function getComponentTouchDelay(component) {
11760        var delay = component.opt('selectLongPressDelay');
11761        if (delay == null) {
11762            delay = component.opt('longPressDelay');
11763        }
11764        return delay;
11765    }
11766    function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) {
11767        var dateSpan0 = hit0.dateSpan;
11768        var dateSpan1 = hit1.dateSpan;
11769        var ms = [
11770            dateSpan0.range.start,
11771            dateSpan0.range.end,
11772            dateSpan1.range.start,
11773            dateSpan1.range.end
11774        ];
11775        ms.sort(core.compareNumbers);
11776        var props = {};
11777        for (var _i = 0, dateSelectionTransformers_1 = dateSelectionTransformers; _i < dateSelectionTransformers_1.length; _i++) {
11778            var transformer = dateSelectionTransformers_1[_i];
11779            var res = transformer(hit0, hit1);
11780            if (res === false) {
11781                return null;
11782            }
11783            else if (res) {
11784                __assign(props, res);
11785            }
11786        }
11787        props.range = { start: ms[0], end: ms[3] };
11788        props.allDay = dateSpan0.allDay;
11789        return props;
11790    }
11791
11792    var EventDragging = /** @class */ (function (_super) {
11793        __extends(EventDragging, _super);
11794        function EventDragging(settings) {
11795            var _this = _super.call(this, settings) || this;
11796            // internal state
11797            _this.subjectSeg = null; // the seg being selected/dragged
11798            _this.isDragging = false;
11799            _this.eventRange = null;
11800            _this.relevantEvents = null; // the events being dragged
11801            _this.receivingCalendar = null;
11802            _this.validMutation = null;
11803            _this.mutatedRelevantEvents = null;
11804            _this.handlePointerDown = function (ev) {
11805                var origTarget = ev.origEvent.target;
11806                var _a = _this, component = _a.component, dragging = _a.dragging;
11807                var mirror = dragging.mirror;
11808                var initialCalendar = component.calendar;
11809                var subjectSeg = _this.subjectSeg = core.getElSeg(ev.subjectEl);
11810                var eventRange = _this.eventRange = subjectSeg.eventRange;
11811                var eventInstanceId = eventRange.instance.instanceId;
11812                _this.relevantEvents = core.getRelevantEvents(initialCalendar.state.eventStore, eventInstanceId);
11813                dragging.minDistance = ev.isTouch ? 0 : component.opt('eventDragMinDistance');
11814                dragging.delay =
11815                    // only do a touch delay if touch and this event hasn't been selected yet
11816                    (ev.isTouch && eventInstanceId !== component.props.eventSelection) ?
11817                        getComponentTouchDelay$1(component) :
11818                        null;
11819                mirror.parentNode = initialCalendar.el;
11820                mirror.revertDuration = component.opt('dragRevertDuration');
11821                var isValid = component.isValidSegDownEl(origTarget) &&
11822                    !core.elementClosest(origTarget, '.fc-resizer'); // NOT on a resizer
11823                dragging.setIgnoreMove(!isValid);
11824                // disable dragging for elements that are resizable (ie, selectable)
11825                // but are not draggable
11826                _this.isDragging = isValid &&
11827                    ev.subjectEl.classList.contains('fc-draggable');
11828            };
11829            _this.handleDragStart = function (ev) {
11830                var initialCalendar = _this.component.calendar;
11831                var eventRange = _this.eventRange;
11832                var eventInstanceId = eventRange.instance.instanceId;
11833                if (ev.isTouch) {
11834                    // need to select a different event?
11835                    if (eventInstanceId !== _this.component.props.eventSelection) {
11836                        initialCalendar.dispatch({ type: 'SELECT_EVENT', eventInstanceId: eventInstanceId });
11837                    }
11838                }
11839                else {
11840                    // if now using mouse, but was previous touch interaction, clear selected event
11841                    initialCalendar.dispatch({ type: 'UNSELECT_EVENT' });
11842                }
11843                if (_this.isDragging) {
11844                    initialCalendar.unselect(ev); // unselect *date* selection
11845                    initialCalendar.publiclyTrigger('eventDragStart', [
11846                        {
11847                            el: _this.subjectSeg.el,
11848                            event: new core.EventApi(initialCalendar, eventRange.def, eventRange.instance),
11849                            jsEvent: ev.origEvent,
11850                            view: _this.component.view
11851                        }
11852                    ]);
11853                }
11854            };
11855            _this.handleHitUpdate = function (hit, isFinal) {
11856                if (!_this.isDragging) {
11857                    return;
11858                }
11859                var relevantEvents = _this.relevantEvents;
11860                var initialHit = _this.hitDragging.initialHit;
11861                var initialCalendar = _this.component.calendar;
11862                // states based on new hit
11863                var receivingCalendar = null;
11864                var mutation = null;
11865                var mutatedRelevantEvents = null;
11866                var isInvalid = false;
11867                var interaction = {
11868                    affectedEvents: relevantEvents,
11869                    mutatedEvents: core.createEmptyEventStore(),
11870                    isEvent: true,
11871                    origSeg: _this.subjectSeg
11872                };
11873                if (hit) {
11874                    var receivingComponent = hit.component;
11875                    receivingCalendar = receivingComponent.calendar;
11876                    if (initialCalendar === receivingCalendar ||
11877                        receivingComponent.opt('editable') && receivingComponent.opt('droppable')) {
11878                        mutation = computeEventMutation(initialHit, hit, receivingCalendar.pluginSystem.hooks.eventDragMutationMassagers);
11879                        if (mutation) {
11880                            mutatedRelevantEvents = core.applyMutationToEventStore(relevantEvents, receivingCalendar.eventUiBases, mutation, receivingCalendar);
11881                            interaction.mutatedEvents = mutatedRelevantEvents;
11882                            if (!receivingComponent.isInteractionValid(interaction)) {
11883                                isInvalid = true;
11884                                mutation = null;
11885                                mutatedRelevantEvents = null;
11886                                interaction.mutatedEvents = core.createEmptyEventStore();
11887                            }
11888                        }
11889                    }
11890                    else {
11891                        receivingCalendar = null;
11892                    }
11893                }
11894                _this.displayDrag(receivingCalendar, interaction);
11895                if (!isInvalid) {
11896                    core.enableCursor();
11897                }
11898                else {
11899                    core.disableCursor();
11900                }
11901                if (!isFinal) {
11902                    if (initialCalendar === receivingCalendar && // TODO: write test for this
11903                        isHitsEqual(initialHit, hit)) {
11904                        mutation = null;
11905                    }
11906                    _this.dragging.setMirrorNeedsRevert(!mutation);
11907                    // render the mirror if no already-rendered mirror
11908                    // TODO: wish we could somehow wait for dispatch to guarantee render
11909                    _this.dragging.setMirrorIsVisible(!hit || !document.querySelector('.fc-mirror'));
11910                    // assign states based on new hit
11911                    _this.receivingCalendar = receivingCalendar;
11912                    _this.validMutation = mutation;
11913                    _this.mutatedRelevantEvents = mutatedRelevantEvents;
11914                }
11915            };
11916            _this.handlePointerUp = function () {
11917                if (!_this.isDragging) {
11918                    _this.cleanup(); // because handleDragEnd won't fire
11919                }
11920            };
11921            _this.handleDragEnd = function (ev) {
11922                if (_this.isDragging) {
11923                    var initialCalendar_1 = _this.component.calendar;
11924                    var initialView = _this.component.view;
11925                    var _a = _this, receivingCalendar = _a.receivingCalendar, validMutation = _a.validMutation;
11926                    var eventDef = _this.eventRange.def;
11927                    var eventInstance = _this.eventRange.instance;
11928                    var eventApi = new core.EventApi(initialCalendar_1, eventDef, eventInstance);
11929                    var relevantEvents_1 = _this.relevantEvents;
11930                    var mutatedRelevantEvents = _this.mutatedRelevantEvents;
11931                    var finalHit = _this.hitDragging.finalHit;
11932                    _this.clearDrag(); // must happen after revert animation
11933                    initialCalendar_1.publiclyTrigger('eventDragStop', [
11934                        {
11935                            el: _this.subjectSeg.el,
11936                            event: eventApi,
11937                            jsEvent: ev.origEvent,
11938                            view: initialView
11939                        }
11940                    ]);
11941                    if (validMutation) {
11942                        // dropped within same calendar
11943                        if (receivingCalendar === initialCalendar_1) {
11944                            initialCalendar_1.dispatch({
11945                                type: 'MERGE_EVENTS',
11946                                eventStore: mutatedRelevantEvents
11947                            });
11948                            var transformed = {};
11949                            for (var _i = 0, _b = initialCalendar_1.pluginSystem.hooks.eventDropTransformers; _i < _b.length; _i++) {
11950                                var transformer = _b[_i];
11951                                __assign(transformed, transformer(validMutation, initialCalendar_1));
11952                            }
11953                            var eventDropArg = __assign({}, transformed, { el: ev.subjectEl, delta: validMutation.datesDelta, oldEvent: eventApi, event: new core.EventApi(// the data AFT
11953ER the mutation
11954                                initialCalendar_1, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null), revert: function () {
11955                                    initialCalendar_1.dispatch({
11956                                        type: 'MERGE_EVENTS',
11957                                        eventStore: relevantEvents_1
11958                                    });
11959                                }, jsEvent: ev.origEvent, view: initialView });
11960                            initialCalendar_1.publiclyTrigger('eventDrop', [eventDropArg]);
11961                            // dropped in different calendar
11962                        }
11963                        else if (receivingCalendar) {
11964                            initialCalendar_1.publiclyTrigger('eventLeave', [
11965                                {
11966                                    draggedEl: ev.subjectEl,
11967                                    event: eventApi,
11968                                    view: initialView
11969                                }
11970                            ]);
11971                            initialCalendar_1.dispatch({
11972                                type: 'REMOVE_EVENT_INSTANCES',
11973                                instances: _this.mutatedRelevantEvents.instances
11974                            });
11975                            receivingCalendar.dispatch({
11976                                type: 'MERGE_EVENTS',
11977                                eventStore: _this.mutatedRelevantEvents
11978                            });
11979                            if (ev.isTouch) {
11980                                receivingCalendar.dispatch({
11981                                    type: 'SELECT_EVENT',
11982                                    eventInstanceId: eventInstance.instanceId
11983                                });
11984                            }
11985                            var dropArg = __assign({}, receivingCalendar.buildDatePointApi(finalHit.dateSpan), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.component // should this be finalHit.component.view? See #4644
11986                             });
11987                            receivingCalendar.publiclyTrigger('drop', [dropArg]);
11988                            receivingCalendar.publiclyTrigger('eventReceive', [
11989                                {
11990                                    draggedEl: ev.subjectEl,
11991                                    event: new core.EventApi(// the data AFTER the mutation
11992                                    receivingCalendar, mutatedRelevantEvents.defs[eventDef.defId], mutatedRelevantEvents.instances[eventInstance.instanceId]),
11993                                    view: finalHit.component // should this be finalHit.component.view? See #4644
11994                                }
11995                            ]);
11996                        }
11997                    }
11998                    else {
11999                        initialCalendar_1.publiclyTrigger('_noEventDrop');
12000                    }
12001                }
12002                _this.cleanup();
12003            };
12004            var component = _this.component;
12005            var dragging = _this.dragging = new FeaturefulElementDragging(component.el);
12006            dragging.pointer.selector = EventDragging.SELECTOR;
12007            dragging.touchScrollAllowed = false;
12008            dragging.autoScroller.isEnabled = component.opt('dragScroll');
12009            var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, core.interactionSettingsStore);
12010            hitDragging.useSubjectCenter = settings.useEventCenter;
12011            hitDragging.emitter.on('pointerdown', _this.handlePointerDown);
12012            hitDragging.emitter.on('dragstart', _this.handleDragStart);
12013            hitDragging.emitter.on('hitupdate', _this.handleHitUpdate);
12014            hitDragging.emitter.on('pointerup', _this.handlePointerUp);
12015            hitDragging.emitter.on('dragend', _this.handleDragEnd);
12016            return _this;
12017        }
12018        EventDragging.prototype.destroy = function () {
12019            this.dragging.destroy();
12020        };
12021        // render a drag state on the next receivingCalendar
12022        EventDragging.prototype.displayDrag = function (nextCalendar, state) {
12023            var initialCalendar = this.component.calendar;
12024            var prevCalendar = this.receivingCalendar;
12025            // does the previous calendar need to be cleared?
12026            if (prevCalendar && prevCalendar !== nextCalendar) {
12027                // does the initial calendar need to be cleared?
12028                // if so, don't clear all the way. we still need to to hide the affectedEvents
12029                if (prevCalendar === initialCalendar) {
12030                    prevCalendar.dispatch({
12031                        type: 'SET_EVENT_DRAG',
12032                        state: {
12033                            affectedEvents: state.affectedEvents,
12034                            mutatedEvents: core.createEmptyEventStore(),
12035                            isEvent: true,
12036                            origSeg: state.origSeg
12037                        }
12038                    });
12039                    // completely clear the old calendar if it wasn't the initial
12040                }
12041                else {
12042                    prevCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
12043                }
12044            }
12045            if (nextCalendar) {
12046                nextCalendar.dispatch({ type: 'SET_EVENT_DRAG', state: state });
12047            }
12048        };
12049        EventDragging.prototype.clearDrag = function () {
12050            var initialCalendar = this.component.calendar;
12051            var receivingCalendar = this.receivingCalendar;
12052            if (receivingCalendar) {
12053                receivingCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
12054            }
12055            // the initial calendar might have an dummy drag state from displayDrag
12056            if (initialCalendar !== receivingCalendar) {
12057                initialCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
12058            }
12059        };
12060        EventDragging.prototype.cleanup = function () {
12061            this.subjectSeg = null;
12062            this.isDragging = false;
12063            this.eventRange = null;
12064            this.relevantEvents = null;
12065            this.receivingCalendar = null;
12066            this.validMutation = null;
12067            this.mutatedRelevantEvents = null;
12068        };
12069        EventDragging.SELECTOR = '.fc-draggable, .fc-resizable'; // TODO: test this in IE11
12070        return EventDragging;
12071    }(core.Interaction));
12072    function computeEventMutation(hit0, hit1, massagers) {
12073        var dateSpan0 = hit0.dateSpan;
12074        var dateSpan1 = hit1.dateSpan;
12075        var date0 = dateSpan0.range.start;
12076        var date1 = dateSpan1.range.start;
12077        var standardProps = {};
12078        if (dateSpan0.allDay !== dateSpan1.allDay) {
12079            standardProps.allDay = dateSpan1.allDay;
12080            standardProps.hasEnd = hit1.component.opt('allDayMaintainDuration');
12081            if (dateSpan1.allDay) {
12082                // means date1 is already start-of-day,
12083                // but date0 needs to be converted
12084                date0 = core.startOfDay(date0);
12085            }
12086        }
12087        var delta = core.diffDates(date0, date1, hit0.component.dateEnv, hit0.component === hit1.component ?
12088            hit0.component.largeUnit :
12089            null);
12090        if (delta.milliseconds) { // has hours/minutes/seconds
12091            standardProps.allDay = false;
12092        }
12093        var mutation = {
12094            datesDelta: delta,
12095            standardProps: standardProps
12096        };
12097        for (var _i = 0, massagers_1 = massagers; _i < massagers_1.length; _i++) {
12098            var massager = massagers_1[_i];
12099            massager(mutation, hit0, hit1);
12100        }
12101        return mutation;
12102    }
12103    function getComponentTouchDelay$1(component) {
12104        var delay = component.opt('eventLongPressDelay');
12105        if (delay == null) {
12106            delay = component.opt('longPressDelay');
12107        }
12108        return delay;
12109    }
12110
12111    var EventDragging$1 = /** @class */ (function (_super) {
12112        __extends(EventDragging, _super);
12113        function EventDragging(settings) {
12114            var _this = _super.call(this, settings) || this;
12115            // internal state
12116            _this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg?
12117            _this.eventRange = null;
12118            _this.relevantEvents = null;
12119            _this.validMutation = null;
12120            _this.mutatedRelevantEvents = null;
12121            _this.handlePointerDown = function (ev) {
12122                var component = _this.component;
12123                var seg = _this.querySeg(ev);
12124                var eventRange = _this.eventRange = seg.eventRange;
12125                _this.dragging.minDistance = component.opt('eventDragMinDistance');
12126                // if touch, need to be working with a selected event
12127                _this.dragging.setIgnoreMove(!_this.component.isValidSegDownEl(ev.origEvent.target) ||
12128                    (ev.isTouch && _this.component.props.eventSelection !== eventRange.instance.instanceId));
12129            };
12130            _this.handleDragStart = function (ev) {
12131                var calendar = _this.component.calendar;
12132                var eventRange = _this.eventRange;
12133                _this.relevantEvents = core.getRelevantEvents(calendar.state.eventStore, _this.eventRange.instance.instanceId);
12134                _this.draggingSeg = _this.querySeg(ev);
12135                calendar.unselect();
12136                calendar.publiclyTrigger('eventResizeStart', [
12137                    {
12138                        el: _this.draggingSeg.el,
12139                        event: new core.EventApi(calendar, eventRange.def, eventRange.instance),
12140                        jsEvent: ev.origEvent,
12141                        view: _this.component.view
12142                    }
12143                ]);
12144            };
12145            _this.handleHitUpdate = function (hit, isFinal, ev) {
12146                var calendar = _this.component.calendar;
12147                var relevantEvents = _this.relevantEvents;
12148                var initialHit = _this.hitDragging.initialHit;
12149                var eventInstance = _this.eventRange.instance;
12150                var mutation = null;
12151                var mutatedRelevantEvents = null;
12152                var isInvalid = false;
12153                var interaction = {
12154                    affectedEvents: relevantEvents,
12155                    mutatedEvents: core.createEmptyEventStore(),
12156                    isEvent: true,
12157                    origSeg: _this.draggingSeg
12158                };
12159                if (hit) {
12160                    mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-start-resizer'), eventInstance.range, calendar.pluginSystem.hooks.eventResizeJoinTransforms);
12161                }
12162                if (mutation) {
12163                    mutatedRelevantEvents = core.applyMutationToEventStore(relevantEvents, calendar.eventUiBases, mutation, calendar);
12164                    interaction.mutatedEvents = mutatedRelevantEvents;
12165                    if (!_this.component.isInteractionValid(interaction)) {
12166                        isInvalid = true;
12167                        mutation = null;
12168                        mutatedRelevantEvents = null;
12169                        interaction.mutatedEvents = null;
12170                    }
12171                }
12172                if (mutatedRelevantEvents) {
12173                    calendar.dispatch({
12174                        type: 'SET_EVENT_RESIZE',
12175                        state: interaction
12176                    });
12177                }
12178                else {
12179                    calendar.dispatch({ type: 'UNSET_EVENT_RESIZE' });
12180                }
12181                if (!isInvalid) {
12182                    core.enableCursor();
12183                }
12184                else {
12185                    core.disableCursor();
12186                }
12187                if (!isFinal) {
12188                    if (mutation && isHitsEqual(initialHit, hit)) {
12189                        mutation = null;
12190                    }
12191                    _this.validMutation = mutation;
12192                    _this.mutatedRelevantEvents = mutatedRelevantEvents;
12193                }
12194            };
12195            _this.handleDragEnd = function (ev) {
12196                var calendar = _this.component.calendar;
12197                var view = _this.component.view;
12198                var eventDef = _this.eventRange.def;
12199                var eventInstance = _this.eventRange.instance;
12200                var eventApi = new core.EventApi(calendar, eventDef, eventInstance);
12201                var relevantEvents = _this.relevantEvents;
12202                var mutatedRelevantEvents = _this.mutatedRelevantEvents;
12203                calendar.publiclyTrigger('eventResizeStop', [
12204                    {
12205                        el: _this.draggingSeg.el,
12206                        event: eventApi,
12207                        jsEvent: ev.origEvent,
12208                        view: view
12209                    }
12210                ]);
12211                if (_this.validMutation) {
12212                    calendar.dispatch({
12213                        type: 'MERGE_EVENTS',
12214                        eventStore: mutatedRelevantEvents
12215                    });
12216                    calendar.publiclyTrigger('eventResize', [
12217                        {
12218                            el: _this.draggingSeg.el,
12219                            startDelta: _this.validMutation.startDelta || core.createDuration(0),
12220                            endDelta: _this.validMutation.endDelta || core.createDuration(0),
12221                            prevEvent: eventApi,
12222                            event: new core.EventApi(// the data AFTER the mutation
12223                            calendar, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null),
12224                            revert: function () {
12225                                calendar.dispatch({
12226                                    type: 'MERGE_EVENTS',
12227                                    eventStore: relevantEvents
12228                                });
12229                            },
12230                            jsEvent: ev.origEvent,
12231                            view: view
12232                        }
12233                    ]);
12234                }
12235                else {
12236                    calendar.publiclyTrigger('_noEventResize');
12237                }
12238                // reset all internal state
12239                _this.draggingSeg = null;
12240                _this.relevantEvents = null;
12241                _this.validMutation = null;
12242                // okay to keep eventInstance around. useful to set it in handlePointerDown
12243            };
12244            var component = settings.component;
12245            var dragging = _this.dragging = new FeaturefulElementDragging(component.el);
12246            dragging.pointer.selector = '.fc-resizer';
12247            dragging.touchScrollAllowed = false;
12248            dragging.autoScroller.isEnabled = component.opt('dragScroll');
12249            var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, core.interactionSettingsToStore(settings));
12250            hitDragging.emitter.on('pointerdown', _this.handlePointerDown);
12251            hitDragging.emitter.on('dragstart', _this.handleDragStart);
12252            hitDragging.emitter.on('hitupdate', _this.handleHitUpdate);
12253            hitDragging.emitter.on('dragend', _this.handleDragEnd);
12254            return _this;
12255        }
12256        EventDragging.prototype.destroy = function () {
12257            this.dragging.destroy();
12258        };
12259        EventDragging.prototype.querySeg = function (ev) {
12260            return core.getElSeg(core.elementClosest(ev.subjectEl, this.component.fgSegSelector));
12261        };
12262        return EventDragging;
12263    }(core.Interaction));
12264    function computeMutation(hit0, hit1, isFromStart, instanceRange, transforms) {
12265        var dateEnv = hit0.component.dateEnv;
12266        var date0 = hit0.dateSpan.range.start;
12267        var date1 = hit1.dateSpan.range.start;
12268        var delta = core.diffDates(date0, date1, dateEnv, hit0.component.largeUnit);
12269        var props = {};
12270        for (var _i = 0, transforms_1 = transforms; _i < transforms_1.length; _i++) {
12271            var transform = transforms_1[_i];
12272            var res = transform(hit0, hit1);
12273            if (res === false) {
12274                return null;
12275            }
12276            else if (res) {
12277                __assign(props, res);
12278            }
12279        }
12280        if (isFromStart) {
12281            if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) {
12282                props.startDelta = delta;
12283                return props;
12284            }
12285        }
12286        else {
12287            if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) {
12288                props.endDelta = delta;
12289                return props;
12290            }
12291        }
12292        return null;
12293    }
12294
12295    var UnselectAuto = /** @class */ (function () {
12296        function UnselectAuto(calendar) {
12297            var _this = this;
12298            this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system
12299            this.onSelect = function (selectInfo) {
12300                if (selectInfo.jsEvent) {
12301                    _this.isRecentPointerDateSelect = true;
12302                }
12303            };
12304            this.onDocumentPointerUp = function (pev) {
12305                var _a = _this, calendar = _a.calendar, documentPointer = _a.documentPointer;
12306                var state = calendar.state;
12307                // touch-scrolling should never unfocus any type of selection
12308                if (!documentPointer.wasTouchScroll) {
12309                    if (state.dateSelection && // an existing date selection?
12310                        !_this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp?
12311                    ) {
12312                        var unselectAuto = calendar.viewOpt('unselectAuto');
12313                        var unselectCancel = calendar.viewOpt('unselectCancel');
12314                        if (unselectAuto && (!unselectAuto || !core.elementClosest(documentPointer.downEl, unselectCancel))) {
12315                            calendar.unselect(pev);
12316                        }
12317                    }
12318                    if (state.eventSelection && // an existing event selected?
12319                        !core.elementClosest(documentPointer.downEl, EventDragging.SELECTOR) // interaction DIDN'T start on an event
12320                    ) {
12321                        calendar.dispatch({ type: 'UNSELECT_EVENT' });
12322                    }
12323                }
12324                _this.isRecentPointerDateSelect = false;
12325            };
12326            this.calendar = calendar;
12327            var documentPointer = this.documentPointer = new PointerDragging(document);
12328            documentPointer.shouldIgnoreMove = true;
12329            documentPointer.shouldWatchScroll = false;
12330            documentPointer.emitter.on('pointerup', this.onDocumentPointerUp);
12331            /*
12332            TODO: better way to know about whether there was a selection with the pointer
12333            */
12334            calendar.on('select', this.onSelect);
12335        }
12336        UnselectAuto.prototype.destroy = function () {
12337            this.calendar.off('select', this.onSelect);
12338            this.documentPointer.destroy();
12339        };
12340        return UnselectAuto;
12341    }());
12342
12343    /*
12344    Given an already instantiated draggable object for one-or-more elements,
12345    Interprets any dragging as an attempt to drag an events that lives outside
12346    of a calendar onto a calendar.
12347    */
12348    var ExternalElementDragging = /** @class */ (function () {
12349        function ExternalElementDragging(dragging, suppliedDragMeta) {
12350            var _this = this;
12351            this.receivingCalendar = null;
12352            this.droppableEvent = null; // will exist for all drags, even if create:false
12353            this.suppliedDragMeta = null;
12354            this.dragMeta = null;
12355            this.handleDragStart = function (ev) {
12356                _this.dragMeta = _this.buildDragMeta(ev.subjectEl);
12357            };
12358            this.handleHitUpdate = function (hit, isFinal, ev) {
12359                var dragging = _this.hitDragging.dragging;
12360                var receivingCalendar = null;
12361                var droppableEvent = null;
12362                var isInvalid = false;
12363                var interaction = {
12364                    affectedEvents: core.createEmptyEventStore(),
12365                    mutatedEvents: core.createEmptyEventStore(),
12366                    isEvent: _this.dragMeta.create,
12367                    origSeg: null
12368                };
12369                if (hit) {
12370                    receivingCalendar = hit.component.calendar;
12371                    if (_this.canDropElOnCalendar(ev.subjectEl, receivingCalendar)) {
12372                        droppableEvent = computeEventForDateSpan(hit.dateSpan, _this.dragMeta, receivingCalendar);
12373                        interaction.mutatedEvents = core.eventTupleToStore(droppableEvent);
12374                        isInvalid = !core.isInteractionValid(interaction, receivingCalendar);
12375                        if (isInvalid) {
12376                            interaction.mutatedEvents = core.createEmptyEventStore();
12377                            droppableEvent = null;
12378                        }
12379                    }
12380                }
12381                _this.displayDrag(receivingCalendar, interaction);
12382                // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?)
12383                // TODO: wish we could somehow wait for dispatch to guarantee render
12384                dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-mirror'));
12385                if (!isInvalid) {
12386                    core.enableCursor();
12387                }
12388                else {
12389                    core.disableCursor();
12390                }
12391                if (!isFinal) {
12392                    dragging.setMirrorNeedsRevert(!droppableEvent);
12393                    _this.receivingCalendar = receivingCalendar;
12394                    _this.droppableEvent = droppableEvent;
12395                }
12396            };
12397            this.handleDragEnd = function (pev) {
12398                var _a = _this, receivingCalendar = _a.receivingCalendar, droppableEvent = _a.droppableEvent;
12399                _this.clearDrag();
12400                if (receivingCalendar && droppableEvent) {
12401                    var finalHit = _this.hitDragging.finalHit;
12402                    var finalView = finalHit.component.view;
12403                    var dragMeta = _this.dragMeta;
12404                    var arg = __assign({}, receivingCalendar.buildDatePointApi(finalHit.dateSpan), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView });
12405                    receivingCalendar.publiclyTrigger('drop', [arg]);
12406                    if (dragMeta.create) {
12407                        receivingCalendar.dispatch({
12408                            type: 'MERGE_EVENTS',
12409                            eventStore: core.eventTupleToStore(droppableEvent)
12410                        });
12411                        if (pev.isTouch) {
12412                            receivingCalendar.dispatch({
12413                                type: 'SELECT_EVENT',
12414                                eventInstanceId: droppableEvent.instance.instanceId
12415                            });
12416                        }
12417                        // signal that an external event landed
12418                        receivingCalendar.publiclyTrigger('eventReceive', [
12419                            {
12420                                draggedEl: pev.subjectEl,
12421                                event: new core.EventApi(receivingCalendar, droppableEvent.def, droppableEvent.instance),
12422                                view: finalView
12423                            }
12424                        ]);
12425                    }
12426                }
12427                _this.receivingCalendar = null;
12428                _this.droppableEvent = null;
12429            };
12430            var hitDragging = this.hitDragging = new HitDragging(dragging, core.interactionSettingsStore);
12431            hitDragging.requireInitial = false; // will start outside of a component
12432            hitDragging.emitter.on('dragstart', this.handleDragStart);
12433            hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
12434            hitDragging.emitter.on('dragend', this.handleDragEnd);
12435            this.suppliedDragMeta = suppliedDragMeta;
12436        }
12437        ExternalElementDragging.prototype.buildDragMeta = function (sub
12437jectEl) {
12438            if (typeof this.suppliedDragMeta === 'object') {
12439                return core.parseDragMeta(this.suppliedDragMeta);
12440            }
12441            else if (typeof this.suppliedDragMeta === 'function') {
12442                return core.parseDragMeta(this.suppliedDragMeta(subjectEl));
12443            }
12444            else {
12445                return getDragMetaFromEl(subjectEl);
12446            }
12447        };
12448        ExternalElementDragging.prototype.displayDrag = function (nextCalendar, state) {
12449            var prevCalendar = this.receivingCalendar;
12450            if (prevCalendar && prevCalendar !== nextCalendar) {
12451                prevCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
12452            }
12453            if (nextCalendar) {
12454                nextCalendar.dispatch({ type: 'SET_EVENT_DRAG', state: state });
12455            }
12456        };
12457        ExternalElementDragging.prototype.clearDrag = function () {
12458            if (this.receivingCalendar) {
12459                this.receivingCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
12460            }
12461        };
12462        ExternalElementDragging.prototype.canDropElOnCalendar = function (el, receivingCalendar) {
12463            var dropAccept = receivingCalendar.opt('dropAccept');
12464            if (typeof dropAccept === 'function') {
12465                return dropAccept(el);
12466            }
12467            else if (typeof dropAccept === 'string' && dropAccept) {
12468                return Boolean(core.elementMatches(el, dropAccept));
12469            }
12470            return true;
12471        };
12472        return ExternalElementDragging;
12473    }());
12474    // Utils for computing event store from the DragMeta
12475    // ----------------------------------------------------------------------------------------------------
12476    function computeEventForDateSpan(dateSpan, dragMeta, calendar) {
12477        var defProps = __assign({}, dragMeta.leftoverProps);
12478        for (var _i = 0, _a = calendar.pluginSystem.hooks.externalDefTransforms; _i < _a.length; _i++) {
12479            var transform = _a[_i];
12480            __assign(defProps, transform(dateSpan, dragMeta));
12481        }
12482        var def = core.parseEventDef(defProps, dragMeta.sourceId, dateSpan.allDay, calendar.opt('forceEventDuration') || Boolean(dragMeta.duration), // hasEnd
12483        calendar);
12484        var start = dateSpan.range.start;
12485        // only rely on time info if drop zone is all-day,
12486        // otherwise, we already know the time
12487        if (dateSpan.allDay && dragMeta.startTime) {
12488            start = calendar.dateEnv.add(start, dragMeta.startTime);
12489        }
12490        var end = dragMeta.duration ?
12491            calendar.dateEnv.add(start, dragMeta.duration) :
12492            calendar.getDefaultEventEnd(dateSpan.allDay, start);
12493        var instance = core.createEventInstance(def.defId, { start: start, end: end });
12494        return { def: def, instance: instance };
12495    }
12496    // Utils for extracting data from element
12497    // ----------------------------------------------------------------------------------------------------
12498    function getDragMetaFromEl(el) {
12499        var str = getEmbeddedElData(el, 'event');
12500        var obj = str ?
12501            JSON.parse(str) :
12502            { create: false }; // if no embedded data, assume no event creation
12503        return core.parseDragMeta(obj);
12504    }
12505    core.config.dataAttrPrefix = '';
12506    function getEmbeddedElData(el, name) {
12507        var prefix = core.config.dataAttrPrefix;
12508        var prefixedName = (prefix ? prefix + '-' : '') + name;
12509        return el.getAttribute('data-' + prefixedName) || '';
12510    }
12511
12512    /*
12513    Makes an element (that is *external* to any calendar) draggable.
12514    Can pass in data that determines how an event will be created when dropped onto a calendar.
12515    Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system.
12516    */
12517    var ExternalDraggable = /** @class */ (function () {
12518        function ExternalDraggable(el, settings) {
12519            var _this = this;
12520            if (settings === void 0) { settings = {}; }
12521            this.handlePointerDown = function (ev) {
12522                var dragging = _this.dragging;
12523                var _a = _this.settings, minDistance = _a.minDistance, longPressDelay = _a.longPressDelay;
12524                dragging.minDistance =
12525                    minDistance != null ?
12526                        minDistance :
12527                        (ev.isTouch ? 0 : core.globalDefaults.eventDragMinDistance);
12528                dragging.delay =
12529                    ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv
12530                        (longPressDelay != null ? longPressDelay : core.globalDefaults.longPressDelay) :
12531                        0;
12532            };
12533            this.handleDragStart = function (ev) {
12534                if (ev.isTouch &&
12535                    _this.dragging.delay &&
12536                    ev.subjectEl.classList.contains('fc-event')) {
12537                    _this.dragging.mirror.getMirrorEl().classList.add('fc-selected');
12538                }
12539            };
12540            this.settings = settings;
12541            var dragging = this.dragging = new FeaturefulElementDragging(el);
12542            dragging.touchScrollAllowed = false;
12543            if (settings.itemSelector != null) {
12544                dragging.pointer.selector = settings.itemSelector;
12545            }
12546            if (settings.appendTo != null) {
12547                dragging.mirror.parentNode = settings.appendTo; // TODO: write tests
12548            }
12549            dragging.emitter.on('pointerdown', this.handlePointerDown);
12550            dragging.emitter.on('dragstart', this.handleDragStart);
12551            new ExternalElementDragging(dragging, settings.eventData);
12552        }
12553        ExternalDraggable.prototype.destroy = function () {
12554            this.dragging.destroy();
12555        };
12556        return ExternalDraggable;
12557    }());
12558
12559    /*
12560    Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements.
12561    The third-party system is responsible for drawing the visuals effects of the drag.
12562    This class simply monitors for pointer movements and fires events.
12563    It also has the ability to hide the moving element (the "mirror") during the drag.
12564    */
12565    var InferredElementDragging = /** @class */ (function (_super) {
12566        __extends(InferredElementDragging, _super);
12567        function InferredElementDragging(containerEl) {
12568            var _this = _super.call(this, containerEl) || this;
12569            _this.shouldIgnoreMove = false;
12570            _this.mirrorSelector = '';
12571            _this.currentMirrorEl = null;
12572            _this.handlePointerDown = function (ev) {
12573                _this.emitter.trigger('pointerdown', ev);
12574                if (!_this.shouldIgnoreMove) {
12575                    // fire dragstart right away. does not support delay or min-distance
12576                    _this.emitter.trigger('dragstart', ev);
12577                }
12578            };
12579            _this.handlePointerMove = function (ev) {
12580                if (!_this.shouldIgnoreMove) {
12581                    _this.emitter.trigger('dragmove', ev);
12582                }
12583            };
12584            _this.handlePointerUp = function (ev) {
12585                _this.emitter.trigger('pointerup', ev);
12586                if (!_this.shouldIgnoreMove) {
12587                    // fire dragend right away. does not support a revert animation
12588                    _this.emitter.trigger('dragend', ev);
12589                }
12590            };
12591            var pointer = _this.pointer = new PointerDragging(containerEl);
12592            pointer.emitter.on('pointerdown', _this.handlePointerDown);
12593            pointer.emitter.on('pointermove', _this.handlePointerMove);
12594            pointer.emitter.on('pointerup', _this.handlePointerUp);
12595            return _this;
12596        }
12597        InferredElementDragging.prototype.destroy = function () {
12598            this.pointer.destroy();
12599        };
12600        InferredElementDragging.prototype.setIgnoreMove = function (bool) {
12601            this.shouldIgnoreMove = bool;
12602        };
12603        InferredElementDragging.prototype.setMirrorIsVisible = function (bool) {
12604            if (bool) {
12605                // restore a previously hidden element.
12606                // use the reference in case the selector class has already been removed.
12607                if (this.currentMirrorEl) {
12608                    this.currentMirrorEl.style.visibility = '';
12609                    this.currentMirrorEl = null;
12610                }
12611            }
12612            else {
12613                var mirrorEl = this.mirrorSelector ?
12614                    document.querySelector(this.mirrorSelector) :
12615                    null;
12616                if (mirrorEl) {
12617                    this.currentMirrorEl = mirrorEl;
12618                    mirrorEl.style.visibility = 'hidden';
12619                }
12620            }
12621        };
12622        return InferredElementDragging;
12623    }(core.ElementDragging));
12624
12625    /*
12626    Bridges third-party drag-n-drop systems with FullCalendar.
12627    Must be instantiated and destroyed by caller.
12628    */
12629    var ThirdPartyDraggable = /** @class */ (function () {
12630        function ThirdPartyDraggable(containerOrSettings, settings) {
12631            var containerEl = document;
12632            if (
12633            // wish we could just test instanceof EventTarget, but doesn't work in IE11
12634            containerOrSettings === document ||
12635                containerOrSettings instanceof Element) {
12636                containerEl = containerOrSettings;
12637                settings = settings || {};
12638            }
12639            else {
12640                settings = (containerOrSettings || {});
12641            }
12642            var dragging = this.dragging = new InferredElementDragging(containerEl);
12643            if (typeof settings.itemSelector === 'string') {
12644                dragging.pointer.selector = settings.itemSelector;
12645            }
12646            else if (containerEl === document) {
12647                dragging.pointer.selector = '[data-event]';
12648            }
12649            if (typeof settings.mirrorSelector === 'string') {
12650                dragging.mirrorSelector = settings.mirrorSelector;
12651            }
12652            new ExternalElementDragging(dragging, settings.eventData);
12653        }
12654        ThirdPartyDraggable.prototype.destroy = function () {
12655            this.dragging.destroy();
12656        };
12657        return ThirdPartyDraggable;
12658    }());
12659
12660    var main = core.createPlugin({
12661        componentInteractions: [DateClicking, DateSelecting, EventDragging, EventDragging$1],
12662        calendarInteractions: [UnselectAuto],
12663        elementDraggingImpl: FeaturefulElementDragging
12664    });
12665
12666    exports.Draggable = ExternalDraggable;
12667    exports.FeaturefulElementDragging = FeaturefulElementDragging;
12668    exports.PointerDragging = PointerDragging;
12669    exports.ThirdPartyDraggable = ThirdPartyDraggable;
12670    exports.default = main;
12671
12672    Object.defineProperty(exports, '__esModule', { value: true });
12673
12674}));
12675
12676/*!
12677FullCalendar List View Plugin v4.3.0
12678Docs & License: https://fullcalendar.io/
12679(c) 2019 Adam Shaw
12680*/
12681
12682(function (global, factory) {
12683    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) :
12684    typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) :
12685    (global = global || self, factory(global.FullCalendarList = {}, global.FullCalendar));
12686}(this, function (exports, core) { 'use strict';
12687
12688    /*! *****************************************************************************
12689    Copyright (c) Microsoft Corporation. All rights reserved.
12690    Licensed under the Apache License, Version 2.0 (the "License"); you may not use
12691    this file except in compliance with the License. You may obtain a copy of the
12692    License at http://www.apache.org/licenses/LICENSE-2.0
12693
12694    THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
12695    KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
12696    WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
12697    MERCHANTABLITY OR NON-INFRINGEMENT.
12698
12699    See the Apache Version 2.0 License for specific language governing permissions
12700    and limitations under the License.
12701    ***************************************************************************** */
12702    /* global Reflect, Promise */
12703
12704    var extendStatics = function(d, b) {
12705        extendStatics = Object.setPrototypeOf ||
12706            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
12707            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
12708        return extendStatics(d, b);
12709    };
12710
12711    function __extends(d, b) {
12712        extendStatics(d, b);
12713        function __() { this.constructor = d; }
12714        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
12715    }
12716
12717    var ListEventRenderer = /** @class */ (function (_super) {
12718        __extends(ListEventRenderer, _super);
12719        function ListEventRenderer(listView) {
12720            var _this = _super.call(this, listView.context) || this;
12721            _this.listView = listView;
12722            return _this;
12723        }
12724        ListEventRenderer.prototype.attachSegs = function (segs) {
12725            if (!segs.length) {
12726                this.listView.renderEmptyMessage();
12727            }
12728            else {
12729                this.listView.renderSegList(segs);
12730            }
12731        };
12732        ListEventRenderer.prototype.detachSegs = function () {
12733        };
12734        // generates the HTML for a single event row
12735        ListEventRenderer.prototype.renderSegHtml = function (seg) {
12736            var _a = this.context, view = _a.view, theme = _a.theme;
12737            var eventRange = seg.eventRange;
12738            var eventDef = eventRange.def;
12739            var eventInstance = eventRange.instance;
12740            var eventUi = eventRange.ui;
12741            var url = eventDef.url;
12742            var classes = ['fc-list-item'].concat(eventUi.classNames);
12743            var bgColor = eventUi.backgroundColor;
12744            var timeHtml;
12745            if (eventDef.allDay) {
12746                timeHtml = core.getAllDayHtml(view);
12747            }
12748            else if (core.isMultiDayRange(eventRange.range)) {
12749                if (seg.isStart) {
12750                    timeHtml = core.htmlEscape(this._getTimeText(eventInstance.range.start, seg.end, false // allDay
12751                    ));
12752                }
12753                else if (seg.isEnd) {
12754                    timeHtml = core.htmlEscape(this._getTimeText(seg.start, eventInstance.range.end, false // allDay
12755                    ));
12756                }
12757                else { // inner segment that lasts the whole day
12758                    timeHtml = core.getAllDayHtml(view);
12759                }
12760            }
12761            else {
12762                // Display the normal time text for the *event's* times
12763                timeHtml = core.htmlEscape(this.getTimeText(eventRange));
12764            }
12765            if (url) {
12766                classes.push('fc-has-url');
12767            }
12768            return '<tr class="' + classes.join(' ') + '">' +
12769                (this.displayEventTime ?
12770                    '<td class="fc-list-item-time ' + theme.getClass('widgetContent') + '">' +
12771                        (timeHtml || '') +
12772                        '</td>' :
12773                    '') +
12774                '<td class="fc-list-item-marker ' + theme.getClass('widgetContent') + '">' +
12775                '<span class="fc-event-dot"' +
12776                (bgColor ?
12777                    ' style="background-color:' + bgColor + '"' :
12778                    '') +
12779                '></span>' +
12780                '</td>' +
12781                '<td class="fc-list-item-title ' + theme.getClass('widgetContent') + '">' +
12782                '<a' + (url ? ' href="' + core.htmlEscape(url) + '"' : '') + '>
12782' +
12783                core.htmlEscape(eventDef.title || '') +
12784                '</a>' +
12785                '</td>' +
12786                '</tr>';
12787        };
12788        // like "4:00am"
12789        ListEventRenderer.prototype.computeEventTimeFormat = function () {
12790            return {
12791                hour: 'numeric',
12792                minute: '2-digit',
12793                meridiem: 'short'
12794            };
12795        };
12796        return ListEventRenderer;
12797    }(core.FgEventRenderer));
12798
12799    /*
12800    Responsible for the scroller, and forwarding event-related actions into the "grid".
12801    */
12802    var ListView = /** @class */ (function (_super) {
12803        __extends(ListView, _super);
12804        function ListView(context, viewSpec, dateProfileGenerator, parentEl) {
12805            var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this;
12806            _this.computeDateVars = core.memoize(computeDateVars);
12807            _this.eventStoreToSegs = core.memoize(_this._eventStoreToSegs);
12808            var eventRenderer = _this.eventRenderer = new ListEventRenderer(_this);
12809            _this.renderContent = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer));
12810            _this.el.classList.add('fc-list-view');
12811            var listViewClassNames = (_this.theme.getClass('listView') || '').split(' '); // wish we didn't have to do this
12812            for (var _i = 0, listViewClassNames_1 = listViewClassNames; _i < listViewClassNames_1.length; _i++) {
12813                var listViewClassName = listViewClassNames_1[_i];
12814                if (listViewClassName) { // in case input was empty string
12815                    _this.el.classList.add(listViewClassName);
12816                }
12817            }
12818            _this.scroller = new core.ScrollComponent('hidden', // overflow x
12819            'auto' // overflow y
12820            );
12821            _this.el.appendChild(_this.scroller.el);
12822            _this.contentEl = _this.scroller.el; // shortcut
12823            context.calendar.registerInteractiveComponent(_this, {
12824                el: _this.el
12825                // TODO: make aware that it doesn't do Hits
12826            });
12827            return _this;
12828        }
12829        ListView.prototype.render = function (props) {
12830            var _a = this.computeDateVars(props.dateProfile), dayDates = _a.dayDates, dayRanges = _a.dayRanges;
12831            this.dayDates = dayDates;
12832            this.renderContent(this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges));
12833        };
12834        ListView.prototype.destroy = function () {
12835            _super.prototype.destroy.call(this);
12836            this.renderContent.unrender();
12837            this.scroller.destroy(); // will remove the Grid too
12838            this.calendar.unregisterInteractiveComponent(this);
12839        };
12840        ListView.prototype.updateSize = function (isResize, viewHeight, isAuto) {
12841            _super.prototype.updateSize.call(this, isResize, viewHeight, isAuto);
12842            this.eventRenderer.computeSizes(isResize);
12843            this.eventRenderer.assignSizes(isResize);
12844            this.scroller.clear(); // sets height to 'auto' and clears overflow
12845            if (!isAuto) {
12846                this.scroller.setHeight(this.computeScrollerHeight(viewHeight));
12847            }
12848        };
12849        ListView.prototype.computeScrollerHeight = function (viewHeight) {
12850            return viewHeight -
12851                core.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
12852        };
12853        ListView.prototype._eventStoreToSegs = function (eventStore, eventUiBases, dayRanges) {
12854            return this.eventRangesToSegs(core.sliceEventStore(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.nextDayThreshold).fg, dayRanges);
12855        };
12856        ListView.prototype.eventRangesToSegs = function (eventRanges, dayRanges) {
12857            var segs = [];
12858            for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) {
12859                var eventRange = eventRanges_1[_i];
12860                segs.push.apply(segs, this.eventRangeToSegs(eventRange, dayRanges));
12861            }
12862            return segs;
12863        };
12864        ListView.prototype.eventRangeToSegs = function (eventRange, dayRanges) {
12865            var _a = this, dateEnv = _a.dateEnv, nextDayThreshold = _a.nextDayThreshold;
12866            var range = eventRange.range;
12867            var allDay = eventRange.def.allDay;
12868            var dayIndex;
12869            var segRange;
12870            var seg;
12871            var segs = [];
12872            for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex++) {
12873                segRange = core.intersectRanges(range, dayRanges[dayIndex]);
12874                if (segRange) {
12875                    seg = {
12876                        component: this,
12877                        eventRange: eventRange,
12878                        start: segRange.start,
12879                        end: segRange.end,
12880                        isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(),
12881                        isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(),
12882                        dayIndex: dayIndex
12883                    };
12884                    segs.push(seg);
12885                    // detect when range won't go fully into the next day,
12886                    // and mutate the latest seg to the be the end.
12887                    if (!seg.isEnd && !allDay &&
12888                        dayIndex + 1 < dayRanges.length &&
12889                        range.end <
12890                            dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) {
12891                        seg.end = range.end;
12892                        seg.isEnd = true;
12893                        break;
12894                    }
12895                }
12896            }
12897            return segs;
12898        };
12899        ListView.prototype.renderEmptyMessage = function () {
12900            this.contentEl.innerHTML =
12901                '<div class="fc-list-empty-wrap2">' + // TODO: try less wraps
12902                    '<div class="fc-list-empty-wrap1">' +
12903                    '<div class="fc-list-empty">' +
12904                    core.htmlEscape(this.opt('noEventsMessage')) +
12905                    '</div>' +
12906                    '</div>' +
12907                    '</div>';
12908        };
12909        // called by ListEventRenderer
12910        ListView.prototype.renderSegList = function (allSegs) {
12911            var segsByDay = this.groupSegsByDay(allSegs); // sparse array
12912            var dayIndex;
12913            var daySegs;
12914            var i;
12915            var tableEl = core.htmlToElement('<table class="fc-list-table ' + this.calendar.theme.getClass('tableList') + '"><tbody></tbody></table>');
12916            var tbodyEl = tableEl.querySelector('tbody');
12917            for (dayIndex = 0; dayIndex < segsByDay.length; dayIndex++) {
12918                daySegs = segsByDay[dayIndex];
12919                if (daySegs) { // sparse array, so might be undefined
12920                    // append a day header
12921                    tbodyEl.appendChild(this.buildDayHeaderRow(this.dayDates[dayIndex]));
12922                    daySegs = this.eventRenderer.sortEventSegs(daySegs);
12923                    for (i = 0;
12923 i < daySegs.length; i++) {
12924                        tbodyEl.appendChild(daySegs[i].el); // append event row
12925                    }
12926                }
12927            }
12928            this.contentEl.innerHTML = '';
12929            this.contentEl.appendChild(tableEl);
12930        };
12931        // Returns a sparse array of arrays, segs grouped by their dayIndex
12932        ListView.prototype.groupSegsByDay = function (segs) {
12933            var segsByDay = []; // sparse array
12934            var i;
12935            var seg;
12936            for (i = 0; i < segs.length; i++) {
12937                seg = segs[i];
12938                (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = []))
12939                    .push(seg);
12940            }
12941            return segsByDay;
12942        };
12943        // generates the HTML for the day headers that live amongst the event rows
12944        ListView.prototype.buildDayHeaderRow = function (dayDate) {
12945            var dateEnv = this.dateEnv;
12946            var mainFormat = core.createFormatter(this.opt('listDayFormat')); // TODO: cache
12947            var altFormat = core.createFormatter(this.opt('listDayAltFormat')); // TODO: cache
12948            return core.createElement('tr', {
12949                className: 'fc-list-heading',
12950                'data-date': dateEnv.formatIso(dayDate, { omitTime: true })
12951            }, '<td class="' + (this.calendar.theme.getClass('tableListHeading') ||
12952                this.calendar.theme.getClass('widgetHeader')) + '" colspan="3">' +
12953                (mainFormat ?
12954                    core.buildGotoAnchorHtml(this, dayDate, { 'class': 'fc-list-heading-main' }, core.htmlEscape(dateEnv.format(dayDate, mainFormat)) // inner HTML
12955                    ) :
12956                    '') +
12957                (altFormat ?
12958                    core.buildGotoAnchorHtml(this, dayDate, { 'class': 'fc-list-heading-alt' }, core.htmlEscape(dateEnv.format(dayDate, altFormat)) // inner HTML
12959                    ) :
12960                    '') +
12961                '</td>');
12962        };
12963        return ListView;
12964    }(core.View));
12965    ListView.prototype.fgSegSelector = '.fc-list-item'; // which elements accept event actions
12966    function computeDateVars(dateProfile) {
12967        var dayStart = core.startOfDay(dateProfile.renderRange.start);
12968        var viewEnd = dateProfile.renderRange.end;
12969        var dayDates = [];
12970        var dayRanges = [];
12971        while (dayStart < viewEnd) {
12972            dayDates.push(dayStart);
12973            dayRanges.push({
12974                start: dayStart,
12975                end: core.addDays(dayStart, 1)
12976            });
12977            dayStart = core.addDays(dayStart, 1);
12978        }
12979        return { dayDates: dayDates, dayRanges: dayRanges };
12980    }
12981
12982    var main = core.createPlugin({
12983        views: {
12984            list: {
12985                class: ListView,
12986                buttonTextKey: 'list',
12987                listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' } // like "January 1, 2016"
12988            },
12989            listDay: {
12990                type: 'list',
12991                duration: { days: 1 },
12992                listDayFormat: { weekday: 'long' } // day-of-week is all we need. full date is probably in header
12993            },
12994            listWeek: {
12995                type: 'list',
12996                duration: { weeks: 1 },
12997                listDayFormat: { weekday: 'long' },
12998                listDayAltFormat: { month: 'long', day: 'numeric', year: 'numeric' }
12999            },
13000            listMonth: {
13001                type: 'list',
13002                duration: { month: 1 },
13003                listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have
13004            },
13005            listYear: {
13006                type: 'list',
13007                duration: { year: 1 },
13008                listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have
13009            }
13010        }
13011    });
13012
13013    exports.ListView = ListView;
13014    exports.default = main;
13015
13016    Object.defineProperty(exports, '__esModule', { value: true });
13017
13018}));
13019
13020/*!
13021FullCalendar Time Grid Plugin v4.3.0
13022Docs & License: https://fullcalendar.io/
13023(c) 2019 Adam Shaw
13024*/
13025
13026(function (global, factory) {
13027    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core'), require('@fullcalendar/daygri
13027d')) :
13028    typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core', '@fullcalendar/daygrid'], factory) :
13029    (global = global || self, factory(global.FullCalendarTimeGrid = {}, global.FullCalendar, global.FullCalendarDayGrid));
13030}(this, function (exports, core, daygrid) { 'use strict';
13031
13032    /*! *****************************************************************************
13033    Copyright (c) Microsoft Corporation. All rights reserved.
13034    Licensed under the Apache License, Version 2.0 (the "License"); you may not use
13035    this file except in compliance with the License. You may obtain a copy of the
13036    License at http://www.apache.org/licenses/LICENSE-2.0
13037
13038    THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13039    KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
13040    WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
13041    MERCHANTABLITY OR NON-INFRINGEMENT.
13042
13043    See the Apache Version 2.0 License for specific language governing permissions
13044    and limitations under the License.
13045    ***************************************************************************** */
13046    /* global Reflect, Promise */
13047
13048    var extendStatics = function(d, b) {
13049        extendStatics = Object.setPrototypeOf ||
13050            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
13051            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
13052        return extendStatics(d, b);
13053    };
13054
13055    function __extends(d, b) {
13056        extendStatics(d, b);
13057        function __() { this.constructor = d; }
13058        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13059    }
13060
13061    var __assign = function() {
13062        __assign = Object.assign || function __assign(t) {
13063            for (var s, i = 1, n = arguments.length; i < n; i++) {
13064                s = arguments[i];
13065                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
13066            }
13067            return t;
13068        };
13069        return __assign.apply(this, arguments);
13070    };
13071
13072    /*
13073    Only handles foreground segs.
13074    Does not own rendering. Use for low-level util methods by TimeGrid.
13075    */
13076    var TimeGridEventRenderer = /** @class */ (function (_super) {
13077        __extends(TimeGridEventRenderer, _super);
13078        function TimeGridEventRenderer(timeGrid) {
13079            var _this = _super.call(this, timeGrid.context) || this;
13080            _this.timeGrid = timeGrid;
13081            _this.fullTimeFormat = core.createFormatter({
13082                hour: 'numeric',
13083                minute: '2-digit',
13084                separator: _this.context.options.defaultRangeSeparator
13085            });
13086            return _this;
13087        }
13088        // Given an array of foreground segments, render a DOM element for each, computes position,
13089        // and attaches to the column inner-container elements.
13090        TimeGridEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
13091            var segsByCol = this.timeGrid.groupSegsByCol(segs);
13092            // order the segs within each column
13093            // TODO: have groupSegsByCol do this?
13094            for (var col = 0; col < segsByCol.length; col++) {
13095                segsByCol[col] = this.sortEventSegs(segsByCol[col]);
13096            }
13097            this.segsByCol = segsByCol;
13098            this.timeGrid.attachSegsByCol(segsByCol, this.timeGrid.fgContainerEls);
13099        };
13100        TimeGridEventRenderer.prototype.detachSegs = function (segs) {
13101            segs.forEach(function (seg) {
13102                core.removeElement(seg.el);
13103            });
13104            this.segsByCol = null;
13105        };
13106        TimeGridEventRenderer.prototype.computeSegSizes = function (allSegs) {
13107            var _a = this, timeGrid = _a.timeGrid, segsByCol = _a.segsByCol;
13108            var colCnt = timeGrid.colCnt;
13109            timeGrid.computeSegVerticals(allSegs); // horizontals relies on this
13110            if (segsByCol) {
13111                for (var col = 0; col < colCnt; col++) {
13112                    this.computeSegHorizontals(segsByCol[col]); // compute horizontal coordinates, z-index's, and reorder the array
13113                }
13114            }
13115        };
13116        TimeGridEventRenderer.prototype.assignSegSizes = function (allSegs) {
13117            var _a = this, timeGrid = _a.timeGrid, segsByCol = _a.segsByCol;
13118            var colCnt = timeGrid.colCnt;
13119            timeGrid.assignSegVerticals(allSegs); // horizontals relies on this
13120            if (segsByCol) {
13121                for (var col = 0; col < colCnt; col++) {
13122                    this.assignSegCss(segsByCol[col]);
13123                }
13124            }
13125        };
13126        // Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined
13127        TimeGridEventRenderer.prototype.computeEventTimeFormat = function () {
13128            return {
13129                hour: 'numeric',
13130                minute: '2-digit',
13131                meridiem: false
13132            };
13133        };
13134        // Computes a default `displayEventEnd` value if one is not expliclty defined
13135        TimeGridEventRenderer.prototype.computeDisplayEventEnd = function () {
13136            return true;
13137        };
13138        // Renders the HTML for a single event segment's default rendering
13139        TimeGridEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) {
13140            var view = this.context.view;
13141            var eventRange = seg.eventRange;
13142            var eventDef = eventRange.def;
13143            var eventUi = eventRange.ui;
13144            var allDay = eventDef.allDay;
13145            var isDraggable = view.computeEventDraggable(eventDef, eventUi);
13146            var isResizableFromStart = seg.isStart && view.computeEventStartResizable(eventDef, eventUi);
13147            var isResizableFromEnd = seg.isEnd && view.computeEventEndResizable(eventDef, eventUi);
13148            var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo);
13149            var skinCss = core.cssToStr(this.getSkinCss(eventUi));
13150            var timeText;
13151            var fullTimeText; // more verbose time text. for the print stylesheet
13152            var startTimeText; // just the start time text
13153            classes.unshift('fc-time-grid-event');
13154            // if the event appears to span more than one day...
13155            if (core.isMultiDayRange(eventRange.range)) {
13156                // Don't display time text on segments that run entirely through a day.
13157                // That would appear as midnight-midnight and would look dumb.
13158                // Otherwise, display the time text for the *segment's* times (like 6pm-midnight or midnight-10am)
13159                if (seg.isStart || seg.isEnd) {
13160                    var unzonedStart = seg.start;
13161                    var unzonedEnd = seg.end;
13162                    timeText = this._getTimeText(unzonedStart, unzonedEnd, allDay); // TODO: give the timezones
13163                    fullTimeText = this._getTimeText(unzonedStart, unzonedEnd, allDay, this.fullTimeFormat);
13164                    startTimeText = this._getTimeText(unzonedStart, unzonedEnd, allDay, null, false); // displayEnd=false
13165                }
13166            }
13167            else {
13168                // Display the normal time text for the *event's* times
13169                timeText = this.getTimeText(eventRange);
13170                fullTimeText = this.getTimeText(eventRange, this.fullTimeFormat);
13171                startTimeText = this.getTimeText(eventRange, null, false); // displayEnd=false
13172            }
13173            return '<a class="' + classes.join(' ') + '"' +
13174                (eventDef.url ?
13175                    ' href="' + core.htmlEscape(eventDef.url) + '"' :
13176                    '') +
13177                (skinCss ?
13178                    ' style="' + skinCss + '"' :
13179                    '') +
13180                '>' +
13181                '<div class="fc-content">' +
13182                (timeText ?
13183                    '<div class="fc-time"' +
13184                        ' data-start="' + core.htmlEscape(startTimeText) + '"' +
13185                        ' data-full="' + core.htmlEscape(fullTimeText) + '"' +
13186                        '>' +
13187                        '<span>' + core.htmlEscape(timeText) + '</span>' +
13188                        '</div>' :
13189                    '') +
13190                (eventDef.title ?
13191                    '<div class="fc-title">' +
13192                        core.htmlEscape(eventDef.title) +
13193                        '</div>' :
13194                    '') +
13195                '</div>' +
13196                /* TODO: write CSS for this
13197                (isResizableFromStart ?
13198                  '<div class="fc-resizer fc-start-resizer"></div>' :
13199                  ''
13200                  ) +
13201                */
13202                (isResizableFromEnd ?
13203                    '<div class="fc-resizer fc-end-resizer"></div>' :
13204                    '') +
13205                '</a>';
13206        };
13207        // Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each.
13208        // Assumed the segs are already ordered.
13209        // NOTE: Also reorders the given array by date!
13210        TimeGridEventRenderer.prototype.computeSegHorizontals = function (segs) {
13211            var levels;
13212            var level0;
13213            var i;
13214            levels = buildSlotSegLevels(segs);
13215            computeForwardSlotSegs(levels);
13216            if ((level0 = levels[0])) {
13217                for (i = 0; i < level0.length; i++) {
13218                    computeSlotSegPressures(level0[i]);
13219                }
13220                for (i = 0; i < level0.length; i++) {
13221                    this.computeSegForwardBack(level0[i], 0, 0);
13222                }
13223            }
13224        };
13225        // Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range
13226        // from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and
13227        // seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left.
13228        //
13229        // The segment might be part of a "series", which means consecutive segments with the same pressure
13230        // who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of
13231        // segments behind this one in the current series, and `seriesBackwardCoord` is the starting
13232        // coordinate of the first segment in the series.
13233        TimeGridEventRenderer.prototype.computeSegForwardBack = function (seg, seriesBackwardPressure, seriesBackwardCoord) {
13234            var forwardSegs = seg.forwardSegs;
13235            var i;
13236            if (seg.forwardCoord === undefined) { // not already computed
13237                if (!forwardSegs.length) {
13238                    // if there are no forward segments, this segment should butt up against the edge
13239                    seg.forwardCoord = 1;
13240                }
13241                else {
13242                    // sort highest pressure first
13243                    this.sortForwardSegs(forwardSegs);
13244                    // this segment's forwardCoord will be calculated from the backwardCoord of the
13245                    // highest-pressure forward segment.
13246                    this.computeSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord);
13247                    seg.forwardCoord = forwardSegs[0].backwardCoord;
13248                }
13249                // calculate the backwardCoord from the forwardCoord. consider the series
13250                seg.backwardCoord = seg.forwardCoord -
13251                    (seg.forwardCoord - seriesBackwardCoord) / // available width for series
13252                        (seriesBackwardPressure + 1); // # of segments in the series
13253                // use this segment's coordinates to computed the coordinates of the less-pressurized
13254                // forward segments
13255                for (i = 0; i < forwardSegs.length; i++) {
13256                    this.computeSegForwardBack(forwardSegs[i], 0, seg.forwardCoord);
13257                }
13258            }
13259        };
13260        TimeGridEventRenderer.prototype.sortForwardSegs = function (forwardSegs) {
13261            var objs = forwardSegs.map(buildTimeGridSegCompareObj);
13262            var specs = [
13263                // put higher-pressure first
13264                { field: 'forwardPressure', order: -1 },
13265                // put segments that are closer to initial edge first (and favor ones with no coords yet)
13266                { field: 'backwardCoord', order: 1 }
13267            ].concat(this.context.view.eventOrderSpecs);
13268            objs.sort(function (obj0, obj1) {
13269                return core.compareByFieldSpecs(obj0, obj1, specs);
13270            });
13271            return objs.map(function (c) {
13272                return c._seg;
13273            });
13274        };
13275        // Given foreground event segments that have already had their position coordinates computed,
13276        // assigns position-related CSS values to their elements.
13277        TimeGridEventRenderer.prototype.assignSegCss = function (segs) {
13278            for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
13279                var seg = segs_1[_i];
13280                core.applyStyle(seg.el, this.generateSegCss(seg));
13281                if (seg.level > 0) {
13282                    seg.el.classList.add('fc-time-grid-event-inset');
13283                }
13284                // if the event is short that the title will be cut off,
13285                // attach a className that condenses the title into the time area.
13286                if (seg.eventRange.def.title && seg.bottom - seg.top < 30) {
13287                    seg.el.classList.add('fc-short'); // TODO: "condensed" is a better name
13288                }
13289            }
13290        };
13291        // Generates an object with CSS properties/values that should be applied to an event segment element.
13292        // Contains important positioning-related properties that should be applied to any event element, customized or not.
13293        TimeGridEventRenderer.prototype.generateSegCss = function (seg) {
13294            var shouldOverlap = this.context.options.slotEventOverlap;
13295            var backwardCoord = seg.backwardCoord; // the left side if LTR. the right side if RTL. floating-point
13296            var forwardCoord = seg.forwardCoord; // the right side if LTR. the left side if RTL. floating-point
13297            var props = this.timeGrid.generateSegVerticalCss(seg); // get top/bottom first
13298            var isRtl = this.timeGrid.isRtl;
13299            var left; // amount of space from left edge, a fraction of the total width
13300            var right; // amount of space from right edge, a fraction of the total width
13301            if (shouldOverlap) {
13302                // double the width, but don't go beyond the maximum forward coordinate (1.0)
13303                forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2);
13304            }
13305            if (isRtl) {
13306                left = 1 - forwardCoord;
13307                right = backwardCoord;
13308            }
13309            else {
13310                left = backwardCoord;
13311                right = 1 - forwardCoord;
13312            }
13313            props.zIndex = seg.level + 1; // convert from 0-base to 1-based
13314            props.left = left * 100 + '%';
13315            props.right = right * 100 + '%';
13316            if (shouldOverlap && seg.forwardPressure) {
13317                // add padding to the edge so that forward stacked events don't cover the resizer's icon
13318                props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
13319            }
13320            return props;
13321        };
13322        return TimeGridEventRenderer;
13323    }(core.FgEventRenderer));
13324    // Builds an array of segments "levels". The first level will be the leftmost tier of segments if the calendar is
13325    // left-to-right, or the rightmost if the calendar is right-to-left. Assumes the segments are already ordered by date.
13326    function buildSlotSegLevels(segs) {
13327        var levels = [];
13328        var i;
13329        var seg;
13330        var j;
13331        for (i = 0; i < segs.length; i++) {
13332            seg = segs[i];
13333            // go through all the levels and stop on the first level where there are no collisions
13334            for (j = 0; j < levels.length; j++) {
13335                if (!computeSlotSegCollisions(seg, levels[j]).length) {
13336                    break;
13337                }
13338            }
13339            seg.level = j;
13340            (levels[j] || (levels[j] = [])).push(seg);
13341        }
13342        return levels;
13343    }
13344    // For every segment, figure out the other segments that are in subsequent
13345    // levels that also occupy the same vertical space. Accumulate in seg.forwardSegs
13346    function computeForwardSlotSegs(levels) {
13347        var i;
13348        var level;
13349        var j;
13350        var seg;
13351        var k;
13352        for (i = 0; i < levels.length; i++) {
13353            level = levels[i];
13354            for (j = 0; j < level.length; j++) {
13355                seg = level[j];
13356                seg.forwardSegs = [];
13357                for (k = i + 1; k < levels.length; k++) {
13358                    computeSlotSegCollisions(seg, levels[k], seg.forwardSegs);
13359                }
13360            }
13361        }
13362    }
13363    // Figure out which path forward (via seg.forwardSegs) results in the longest path until
13364    // the furthest edge is reached. The number of segments in this path will be seg.forwardPressure
13365    function computeSlotSegPressures(seg) {
13366        var forwardSegs = seg.forwardSegs;
13367        var forwardPressure = 0;
13368        var i;
13369        var forwardSeg;
13370        if (seg.forwardPressure === undefined) { // not already computed
13371            for (i = 0; i < forwardSegs.length; i++) {
13372                forwardSeg = forwardSegs[i];
13373                // figure out the child's maximum forward path
13374                computeSlotSegPressures(forwardSeg);
13375                // either use the existing maximum, or use the child's forward pressure
13376                // plus one (for the forwardSeg itself)
13377                forwardPressure = Math.max(forwardPressure, 1 + forwardSeg.forwardPressure);
13378            }
13379            seg.forwardPressure = forwardPressure;
13380        }
13381    }
13382    // Find all the segments in `otherSegs` that vertically collide with `seg`.
13383    // Append into an optionally-supplied `results` array and return.
13384    function computeSlotSegCollisions(seg, otherSegs, results) {
13385        if (results === void 0) { results = []; }
13386        for (var i = 0; i < otherSegs.length; i++) {
13387            if (isSlotSegCollision(seg, otherSegs[i])) {
13388                results.push(otherSegs[i]);
13389            }
13390        }
13391        return results;
13392    }
13393    // Do these segments occupy the same vertical space?
13394    function isSlotSegCollision(seg1, seg2) {
13395        return seg1.bottom > seg2.top && seg1.top < seg2.bottom;
13396    }
13397    function buildTimeGridSegCompareObj(seg) {
13398        var obj = core.buildSegCompareObj(seg);
13399        obj.forwardPressure = seg.forwardPressure;
13400        obj.backwardCoord = seg.backwardCoord;
13401        return obj;
13402    }
13403
13404    var TimeGridMirrorRenderer = /** @class */ (function (_super) {
13405        __extends(TimeGridMirrorRenderer, _super);
13406        function TimeGridMirrorRenderer() {
13407            return _super !== null && _super.apply(this, arguments) || this;
13408        }
13409        TimeGridMirrorRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
13410            this.segsByCol = this.timeGrid.groupSegsByCol(segs);
13411            this.timeGrid.attachSegsByCol(this.segsByCol, this.timeGrid.mirrorContainerEls);
13412            this.sourceSeg = mirrorInfo.sourceSeg;
13413        };
13414        TimeGridMirrorRenderer.prototype.generateSegCss = function (seg) {
13415            var props = _super.prototype.generateSegCss.call(this, seg);
13416            var sourceSeg = this.sourceSeg;
13417            if (sourceSeg && sourceSeg.col === seg.col) {
13418                var sourceSegProps = _super.prototype.generateSegCss.call(this, sourceSeg);
13419                props.left = sourceSegProps.left;
13420                props.right = sourceSegProps.right;
13421                props.marginLeft = sourceSegProps.marginLeft;
13422                props.marginRight = sourceSegProps.marginRight;
13423            }
13424            return props;
13425        };
13426        return TimeGridMirrorRenderer;
13427    }(TimeGridEventRenderer));
13428
13429    var TimeGridFillRenderer = /** @class */ (function (_super) {
13430        __extends(TimeGridFillRenderer, _super);
13431        function TimeGridFillRenderer(timeGrid) {
13432            var _this = _super.call(this, timeGrid.context) || this;
13433            _this.timeGrid = timeGrid;
13434            return _this;
13435        }
13436        TimeGridFillRenderer.prototype.attachSegs = function (type, segs) {
13437            var timeGrid = this.timeGrid;
13438            var containerEls;
13439            // TODO: more efficient lookup
13440            if (type === 'bgEvent') {
13441                containerEls = timeGrid.bgContainerEls;
13442            }
13443            else if (type === 'businessHours') {
13444                containerEls = timeGrid.businessContainerEls;
13445            }
13446            else if (type === 'highlight') {
13447                containerEls = timeGrid.highlightContainerEls;
13448            }
13449            timeGrid.attachSegsByCol(timeGrid.groupSegsByCol(segs), containerEls);
13450            return segs.map(function (seg) {
13451                return seg.el;
13452            });
13453        };
13454        TimeGridFillRenderer.prototype.computeSegSizes = function (segs) {
13455            this.timeGrid.computeSegVerticals(segs);
13456        };
13457        TimeGridFillRenderer.prototype.assignSegSizes = function (segs) {
13458            this.timeGrid.assignSegVerticals(segs);
13459        };
13460        return TimeGridFillRenderer;
13461    }(core.FillRenderer));
13462
13463    /* A component that renders one or more columns of vertical time slots
13464    ----------------------------------------------------------------------------------------------------------------------*/
13465    // potential nice values for the slot-duration and interval-duration
13466    // from largest to smallest
13467    var AGENDA_STOCK_SUB_DURATIONS = [
13468        { hours: 1 },
13469        { minutes: 30 },
13470        { minutes: 15 },
13471        { seconds: 30 },
13472        { seconds: 15 }
13473    ];
13474    var TimeGrid = /** @class */ (function (_super) {
13475        __extends(TimeGrid, _super);
13476        function TimeGrid(context, el, renderProps) {
13477            var _this = _super.call(this, context, el) || this;
13478            _this.isSlatSizesDirty = false;
13479            _this.isColSizesDirty = false;
13480            _this.renderSlats = core.memoizeRendering(_this._renderSlats);
13481            var eventRenderer = _this.eventRenderer = new TimeGridEventRenderer(_this);
13482            var fillRenderer = _this.fillRenderer = new TimeGridFillRenderer(_this);
13483            _this.mirrorRenderer = new TimeGridMirrorRenderer(_this);
13484            var renderColumns = _this.renderColumns = core.memoizeRendering(_this._renderColumns, _this._unrenderColumns);
13485            _this.renderBusinessHours = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'), [renderColumns]);
13486            _this.renderDateSelection = core.memoizeRendering(_this._renderDateSelection, _this._unrenderDateSelection, [renderColumns]);
13487            _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderColumns]);
13488            _this.renderBgEvents = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'), [renderColumns]);
13489            _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]);
13490            _this.renderEventDrag = core.memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag, [renderColumns]);
13491            _this.renderEventResize = core.memoizeRendering(_this._renderEventResize, _this._unrenderEventResize, [renderColumns]);
13492            _this.processOptions();
13493            el.innerHTML =
13494                '<div class="fc-bg"></div>' +
13495                    '<div class="fc-slats"></div>' +
13496                    '<hr class="fc-divider ' + _this.theme.getClass('widgetHeader') + '" style="display:none" />';
13497            _this.rootBgContainerEl = el.querySelector('.fc-bg');
13498            _this.slatContainerEl = el.querySelector('.fc-slats');
13499            _this.bottomRuleEl = el.querySelector('.fc-divider');
13500            _this.renderProps = renderProps;
13501            return _this;
13502        }
13503        /* Options
13504        ------------------------------------------------------------------------------------------------------------------*/
13505        // Parses various options into properties of this object
13506        TimeGrid.prototype.processOptions = function () {
13507            var slotDuration = this.opt('slotDuration');
13508            var snapDuration = this.opt('snapDuration');
13509            var snapsPerSlot;
13510            var input;
13511            slotDuration = core.createDuration(slotDuration);
13512            snapDuration = snapDuration ? core.createDuration(snapDuration) : slotDuration;
13513            snapsPerSlot = core.wholeDivideDurations(slotDuration, snapDuration);
13514            if (snapsPerSlot === null) {
13515                snapDuration = slotDuration;
13516                snapsPerSlot = 1;
13517                // TODO: say warning?
13518            }
13519            this.slotDuration = slotDuration;
13520            this.snapDuration = snapDuration;
13521            this.snapsPerSlot = snapsPerSlot;
13522            // might be an array value (for TimelineView).
13523            // if so, getting the most granular entry (the last one probably).
13524            input = this.opt('slotLabelFormat');
13525            if (Array.isArray(input)) {
13526                input = input[input.length - 1];
13527            }
13528            this.labelFormat = core.createFormatter(input || {
13529                hour: 'numeric',
13530                minute: '2-digit',
13531                omitZeroMinute: true,
13532                meridiem: 'short'
13533            });
13534            input = this.opt('slotLabelInterval');
13535            this.labelInterval = input ?
13536                core.createDuration(input) :
13537                this.computeLabelInterval(slotDuration);
13538        };
13539        // Computes an automatic value for slotLabelInterval
13540        TimeGrid.prototype.computeLabelInterval = function (slotDuration) {
13541            var i;
13542            var labelInterval;
13543            var slotsPerLabel;
13544            // find the smallest stock label interval that results in more than one slots-per-label
13545            for (i = AGENDA_STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) {
13546                labelInterval = core.createDuration(AGENDA_STOCK_SUB_DURATIONS[i]);
13547                slotsPerLabel = core.wholeDivideDurations(labelInterval, slotDuration);
13548                if (slotsPerLabel !== null && slotsPerLabel > 1) {
13549                    return labelInterval;
13550                }
13551            }
13552            return slotDuration; // fall back
13553        };
13554        /* Rendering
13555        ------------------------------------------------------------------------------------------------------------------*/
13556        TimeGrid.prototype.render = function (props) {
13557            var cells = props.cells;
13558            this.colCnt = cells.length;
13559            this.renderSlats(props.dateProfile);
13560            this.renderColumns(props.cells, props.dateProfile);
13561            this.renderBusinessHours(props.businessHourSegs);
13562            this.renderDateSelection(props.dateSelectionSegs);
13563            this.renderFgEvents(props.fgEventSegs);
13564            this.renderBgEvents(props.bgEventSegs);
13565            this.renderEventSelection(props.eventSelection);
13566            this.renderEventDrag(props.eventDrag);
13567            this.renderEventResize(props.eventResize);
13568        };
13569        TimeGrid.prototype.destroy = function () {
13570            _super.prototype.destroy.call(this);
13571            // should unrender everything else too
13572            this.renderSlats.unrender();
13573            this.renderColumns.unrender();
13574        };
13575        TimeGrid.prototype.updateSize = function (isResize) {
13576            var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer;
13577            if (isResize || this.isSlatSizesDirty) {
13578                this.buildSlatPositions();
13579                this.isSlatSizesDirty = false;
13580            }
13581            if (isResize || this.isColSizesDirty) {
13582                this.buildColPositions();
13583                this.isColSizesDirty = false;
13584            }
13585            fillRenderer.computeSizes(isResize);
13586            eventRenderer.computeSizes(isResize);
13587            mirrorRenderer.computeSizes(isResize);
13588            fillRenderer.assignSizes(isResize);
13589            eventRenderer.assignSizes(isResize);
13590            mirrorRenderer.assignSizes(isResize);
13591        };
13592        TimeGrid.prototype._renderSlats = function (dateProfile) {
13593            var theme = this.theme;
13594            this.slatContainerEl.innerHTML =
13595                '<table class="' + theme.getClass('tableGrid') + '">' +
13596                    this.renderSlatRowHtml(dateProfile) +
13597                    '</table>';
13598            this.slatEls = core.findElements(this.slatContainerEl, 'tr');
13599            this.slatPositions = new core.PositionCache(this.el, this.slatEls, false, true // vertical
13600            );
13601            this.isSlatSizesDirty = true;
13602        };
13603        // Generates the HTML for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL.
13604        TimeGrid.prototype.renderSlatRowHtml = function (dateProfile) {
13605            var _a = this, dateEnv = _a.dateEnv, theme = _a.theme, isRtl = _a.isRtl;
13606            var html = '';
13607            var dayStart = core.startOfDay(dateProfile.renderRange.start);
13608            var slotTime = dateProfile.minTime;
13609            var slotIterator = core.createDuration(0);
13610            var slotDate; // will be on the view's first day, but we only care about its time
13611            var isLabeled;
13612            var axisHtml;
13613            // Calculate the time for each slot
13614            while (core.asRoughMs(slotTime) < core.asRoughMs(dateProfile.maxTime)) {
13615                slotDate = dateEnv.add(dayStart, slotTime);
13616                isLabeled = core.wholeDivideDurations(slotIterator, this.labelInterval) !== null;
13617                axisHtml =
13618                    '<td class="fc-axis fc-time ' + theme.getClass('widgetContent') + '">' +
13619                        (isLabeled ?
13620                            '<span>' + // for matchCellWidths
13621                                core.htmlEscape(dateEnv.format(slotDate, this.labelFormat)) +
13622                                '</span>' :
13623                            '') +
13624                        '</td>';
13625                html +=
13626                    '<tr data-time="' + core.formatIsoTimeString(slotDate) + '"' +
13627                        (isLabeled ? '' : ' class="fc-minor"') +
13628                        '>' +
13629                        (!isRtl ? axisHtml : '') +
13630                        '<td class="' + theme.getClass('widgetContent') + '"></td>' +
13631                        (isRtl ? axisHtml : '') +
13632                        '</tr>';
13633                slotTime = core.addDurations(slotTime, this.slotDuration);
13634                slotIterator = core.addDurations(slotIterator, this.slotDuration);
13635            }
13636            return html;
13637        };
13638        TimeGrid.prototype._renderColumns = function (cells, dateProfile) {
13639            var _a = this, theme = _a.theme, dateEnv = _a.dateEnv, view = _a.view;
13640            var bgRow = new daygrid.DayBgRow(this.context);
13641            this.rootBgContainerEl.innerHTML =
13642                '<table class="' + theme.getClass('tableGrid') + '">' +
13643                    bgRow.renderHtml({
13644                        cells: cells,
13645                        dateProfile: dateProfile,
13646                        renderIntroHtml: this.renderProps.renderBgIntroHtml
13647                    }) +
13648                    '</table>';
13649            this.colEls = core.findElements(this.el, '.fc-day, .fc-disabled-day');
13650            for (var col = 0; col < this.colCnt; col++) {
13651                this.publiclyTrigger('dayRender', [
13652                    {
13653                        date: dateEnv.toDate(cells[col].date),
13654                        el: this.colEls[col],
13655                        view: view
13656                    }
13657                ]);
13658            }
13659            if (this.isRtl) {
13660                this.colEls.reverse();
13661            }
13662            this.colPositions = new core.PositionCache(this.el, this.colEls, true, // horizontal
13663            false);
13664            this.renderContentSkeleton();
13665            this.isColSizesDirty = true;
13666        };
13667        TimeGrid.prototype._unrenderColumns = function () {
13668            this.unrenderContentSkeleton();
13669        };
13670        /* Content Skeleton
13671        ------------------------------------------------------------------------------------------------------------------*/
13672        // Renders the DOM that the view's content will live in
13673        TimeGrid.prototype.renderContentSkeleton = function () {
13674            var parts = [];
13675            var skeletonEl;
13676            parts.push(this.renderProps.renderIntroHtml());
13677            for (var i = 0; i < this.colCnt; i++) {
13678                parts.push('<td>' +
13679                    '<div class="fc-content-col">' +
13680                    '<div class="fc-event-container fc-mirror-container"></div>' +
13681                    '<div class="fc-event-container"></div>' +
13682                    '<div class="fc-highlight-container"></div>' +
13683                    '<div class="fc-bgevent-container"></div>' +
13684                    '<div class="fc-business-container"></div>' +
13685                    '</div>' +
13686                    '</td>');
13687            }
13688            if (this.isRtl) {
13689                parts.reverse();
13690            }
13691            skeletonEl = this.contentSkeletonEl = core.htmlToElement('<div class="fc-content-skeleton">' +
13692                '<table>' +
13693                '<tr>' + parts.join('') + '</tr>' +
13694                '</table>' +
13695                '</div>');
13696            this.colContainerEls = core.findElements(skeletonEl, '.fc-content-col');
13697            this.mirrorContainerEls = core.findElements(skeletonEl, '.fc-mirror-container');
13698            this.fgContainerEls = core.findElements(skeletonEl, '.fc-event-container:not(.fc-mirror-container)');
13699            this.bgContainerEls = core.findElements(skeletonEl, '.fc-bgevent-container');
13700            this.highlightContainerEls = core.findElements(skeletonEl, '.fc-highlight-container');
13701            this.businessContainerEls = core.findElements(skeletonEl, '.fc-business-container');
13702            if (this.isRtl) {
13703                this.colContainerEls.reverse();
13704                this.mirrorContainerEls.reverse();
13705                this.fgContainerEls.reverse();
13706                this.bgContainerEls.reverse();
13707                this.highlightContainerEls.reverse();
13708                this.businessContainerEls.reverse();
13709            }
13710            this.el.appendChild(skeletonEl);
13711        };
13712        TimeGrid.prototype.unrenderContentSkeleton = function () {
13713            core.removeElement(this.contentSkeletonEl);
13714        };
13715        // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's col
13716        TimeGrid.prototype.groupSegsByCol = function (segs) {
13717            var segsByCol = [];
13718            var i;
13719            for (i = 0; i < this.colCnt; i++) {
13720                segsByCol.push([]);
13721            }
13722            for (i = 0; i < segs.length; i++) {
13723                segsByCol[segs[i].col].push(segs[i]);
13724            }
13725            return segsByCol;
13726        };
13727        // Given segments grouped by column, insert the segments' elements into a parallel array of container
13728        // elements, each living within a column.
13729        TimeGrid.prototype.attachSegsByCol = function (segsByCol, containerEls) {
13730            var col;
13731            var segs;
13732            var i;
13733            for (col = 0; col < this.colCnt; col++) { // iterate each column grouping
13734                segs = segsByCol[col];
13735                for (i = 0; i < segs.length; i++) {
13736                    containerEls[col].appendChild(segs[i].el);
13737                }
13738            }
13739        };
13740        /* Now Indicator
13741        ------------------------------------------------------------------------------------------------------------------*/
13742        TimeGrid.prototype.getNowIndicatorUnit = function () {
13743            return 'minute'; // will refresh on the minute
13744        };
13745        TimeGrid.prototype.renderNowIndicator = function (segs, date) {
13746            // HACK: if date columns not ready for some reason (scheduler)
13747            if (!this.colContainerEls) {
13748                return;
13749            }
13750            var top = this.computeDateTop(date);
13751            var nodes = [];
13752            var i;
13753            // render lines within the columns
13754            for (i = 0; i < segs.length; i++) {
13755                var lineEl = core.createElement('div', { className: 'fc-now-indicator fc-now-indicator-line' });
13756                lineEl.style.top = top + 'px';
13757                this.colContainerEls[segs[i].col].appendChild(lineEl);
13758                nodes.push(lineEl);
13759            }
13760            // render an arrow over the axis
13761            if (segs.length > 0) { // is the current time in view?
13762                var arrowEl = core.createElement('div', { className: 'fc-now-indicator fc-now-indicator-arrow' });
13763                arrowEl.style.top = top + 'px';
13764                this.contentSkeletonEl.appendChild(arrowEl);
13765                nodes.push(arrowEl);
13766            }
13767            this.nowIndicatorEls = nodes;
13768        };
13769        TimeGrid.prototype.unrenderNowIndicator = function () {
13770            if (this.nowIndicatorEls) {
13771                this.nowIndicatorEls.forEach(core.removeElement);
13772                this.nowIndicatorEls = null;
13773            }
13774        };
13775        /* Coordinates
13776        ------------------------------------------------------------------------------------------------------------------*/
13777        TimeGrid.prototype.getTotalSlatHeight = function () {
13778            return this.slatContainerEl.getBoundingClientRect().height;
13779        };
13780        // Computes the top coordinate, relative to the bounds of the grid, of the given date.
13781        // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.
13782        TimeGrid.prototype.computeDateTop = function (when, startOfDayDate) {
13783            if (!startOfDayDate) {
13784                startOfDayDate = core.startOfDay(when);
13785            }
13786            return this.computeTimeTop(core.createDuration(when.valueOf() - startOfDayDate.valueOf()));
13787        };
13788        // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).
13789        TimeGrid.prototype.computeTimeTop = function (duration) {
13790            var len = this.slatEls.length;
13791            var dateProfile = this.props.dateProfile;
13792            var slatCoverage = (duration.milliseconds - core.asRoughMs(dateProfile.minTime)) / core.asRoughMs(this.slotDuration); // floating-point value of # of slots covered
13793            var slatIndex;
13794            var slatRemainder;
13795            // compute a floating-point number for how many slats should be progressed through.
13796            // from 0 to number of slats (inclusive)
13797            // constrained because minTime/maxTime might be customized.
13798            slatCoverage = Math.max(0, slatCoverage);
13799            slatCoverage = Math.min(len, slatCoverage);
13800            // an integer index of the furthest whole slat
13801            // from 0 to number slats (*exclusive*, so len-1)
13802            slatIndex = Math.floor(slatCoverage);
13803            slatIndex = Math.min(slatIndex, len - 1);
13804            // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.
13805            // could be 1.0 if slatCoverage is covering *all* the slots
13806            slatRemainder = slatCoverage - slatIndex;
13807            return this.slatPositions.tops[slatIndex] +
13808                this.slatPositions.getHeight(slatIndex) * slatRemainder;
13809        };
13810        // For each segment in an array, computes and assigns its top and bottom properties
13811        TimeGrid.prototype.computeSegVerticals = function (segs) {
13812            var eventMinHeight = this.opt('timeGridEventMinHeight');
13813            var i;
13814            var seg;
13815            var dayDate;
13816            for (i = 0; i < segs.length; i++) {
13817                seg = segs[i];
13818                dayDate = this.props.cells[seg.col].date;
13819                seg.top = this.computeDateTop(seg.start, dayDate);
13820                seg.bottom = Math.max(seg.top + eventMinHeight, this.computeDateTop(seg.end, dayDate));
13821            }
13822        };
13823        // Given segments that already have their top/bottom properties computed, applies those values to
13824        // the segments' elements.
13825        TimeGrid.prototype.assignSegVerticals = function (segs) {
13826            var i;
13827            var seg;
13828            for (i = 0; i < segs.length; i++) {
13829                seg = segs[i];
13830                core.applyStyle(seg.el, this.generateSegVerticalCss(seg));
13831            }
13832        };
13833        // Generates an object with CSS properties for the top/bottom coordinates of a segment element
13834        TimeGrid.prototype.generateSegVerticalCss = function (seg) {
13835            return {
13836                top: seg.top,
13837                bottom: -seg.bottom // flipped because needs to be space beyond bottom edge of event container
13838            };
13839        };
13840        /* Sizing
13841        ------------------------------------------------------------------------------------------------------------------*/
13842        TimeGrid.prototype.buildPositionCaches = function () {
13843            this.buildColPositions();
13844            this.buildSlatPositions();
13845        };
13846        TimeGrid.prototype.buildColPositions = function () {
13847            this.colPositions.build();
13848        };
13849        TimeGrid.prototype.buildSlatPositions = function () {
13850            this.slatPositions.build();
13851        };
13852        /* Hit System
13853        ------------------------------------------------------------------------------------------------------------------*/
13854        TimeGrid.prototype.positionToHit = function (positionLeft, positionTop) {
13855            var _a = this, dateEnv = _a.dateEnv, snapsPerSlot = _a.snapsPerSlot, slatPositions = _a.slatPositions, colPositions = _a.colPositions;
13856            var colIndex = colPositions.leftToIndex(positionLeft);
13857            var slatIndex = slatPositions.topToIndex(positionTop);
13858            if (colIndex != null && slatIndex != null) {
13859                var slatTop = slatPositions.tops[slatIndex];
13860                var slatHeight = slatPositions.getHeight(slatIndex);
13861                var partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1
13862                var localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat
13863                var snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
13864                var dayDate = this.props.cells[colIndex].date;
13865                var time = core.addDurations(this.props.dateProfile.minTime, core.multiplyDuration(this.snapDuration, snapIndex));
13866                var start = dateEnv.add(dayDate, time);
13867                var end = dateEnv.add(start, this.snapDuration);
13868                return {
13869                    col: colIndex,
13870                    dateSpan: {
13871                        range: { start: start, end: end },
13872                        allDay: false
13873                    },
13874                    dayEl: this.colEls[colIndex],
13875                    relativeRect: {
13876                        left: colPositions.lefts[colIndex],
13877                        right: colPositions.rights[colIndex],
13878                        top: slatTop,
13879                        bottom: slatTop + slatHeight
13880                    }
13881                };
13882            }
13883        };
13884        /* Event Drag Visualization
13885        ------------------------------------------------------------------------------------------------------------------*/
13886        TimeGrid.prototype._renderEventDrag = function (state) {
13887            if (state) {
13888                this.eventRenderer.hideByHash(state.affectedInstances);
13889                if (state.isEvent) {
13890                    this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
13891                }
13892                else {
13893                    this.fillRenderer.renderSegs('highlight', state.segs);
13894                }
13895            }
13896        };
13897        TimeGrid.prototype._unrenderEventDrag = function (state) {
13898            if (state) {
13899                this.eventRenderer.showByHash(state.affectedInstances);
13900                this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
13901                this.fillRenderer.unrender('highlight');
13902            }
13903        };
13904        /* Event Resize Visualization
13905        ------------------------------------------------------------------------------------------------------------------*/
13906        TimeGrid.prototype._renderEventResize = function (state) {
13907            if (state) {
13908                this.eventRenderer.hideByHash(state.affectedInstances);
13909                this.mirrorRenderer.renderSegs(state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
13910            }
13911        };
13912        TimeGrid.prototype._unrenderEventResize = function (state) {
13913            if (state) {
13914                this.eventRenderer.showByHash(state.affectedInstances);
13915                this.mirrorRenderer.unrender(state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
13916            }
13917        };
13918        /* Selection
13919        ------------------------------------------------------------------------------------------------------------------*/
13920        // Renders a visual indication of a selection. Overrides the default, which was to simply render a highlight.
13921        TimeGrid.prototype._renderDateSelection = function (segs) {
13922            if (segs) {
13923                if (this.opt('selectMirror')) {
13924                    this.mirrorRenderer.renderSegs(segs, { isSelecting: true });
13925                }
13926                else {
13927                    this.fillRenderer.renderSegs('highlight', segs);
13928                }
13929            }
13930        };
13931        TimeGrid.prototype._unrenderDateSelection = function (segs) {
13932            this.mirrorRenderer.unrender(segs, { isSelecting: true });
13933            this.fillRenderer.unrender('highlight');
13934        };
13935        return TimeGrid;
13936    }(core.DateComponent));
13937
13938    var AllDaySplitter = /** @class */ (function (_super) {
13939        __extends(AllDaySplitter, _super);
13940        function AllDaySplitter() {
13941            return _super !== null && _super.apply(this, arguments) || this;
13942        }
13943        AllDaySplitter.prototype.getKeyInfo = function () {
13944            return {
13945                allDay: {},
13946                timed: {}
13947            };
13948        };
13949        AllDaySplitter.prototype.getKeysForDateSpan = function (dateSpan) {
13950            if (dateSpan.allDay) {
13951                return ['allDay'];
13952            }
13953            else {
13954                return ['timed'];
13955            }
13956        };
13957        AllDaySplitter.prototype.getKeysForEventDef = function (eventDef) {
13958            if (!eventDef.allDay) {
13959                return ['timed'];
13960            }
13961            else if (core.hasBgRendering(eventDef)) {
13962                return ['timed', 'allDay'];
13963            }
13964            else {
13965                return ['allDay'];
13966            }
13967        };
13968        return AllDaySplitter;
13969    }(core.Splitter));
13970
13971    var TIMEGRID_ALL_DAY_EVENT_LIMIT = 5;
13972    var WEEK_HEADER_FORMAT = core.createFormatter({ week: 'short' });
13973    /* An abstract class for all timegrid-related views. Displays one more columns with time slots running vertically.
13974    ----------------------------------------------------------------------------------------------------------------------*/
13975    // Is a manager for the TimeGrid subcomponent and possibly the DayGrid subcomponent (if allDaySlot is on).
13976    // Responsible for managing width/height.
13977    var TimeGridView = /** @class */ (function (_super) {
13978        __extends(TimeGridView, _super);
13979        function TimeGridView(context, viewSpec, dateProfileGenerator, parentEl) {
13980            var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this;
13981            _this.splitter = new AllDaySplitter();
13982            /* Header Render Methods
13983            ------------------------------------------------------------------------------------------------------------------*/
13984            // Generates the HTML that will go before the day-of week header cells
13985            _this.renderHeadIntroHtml = function () {
13986                var _a = _this, theme = _a.theme, dateEnv = _a.dateEnv;
13987                var range = _this.props.dateProfile.renderRange;
13988                var dayCnt = core.diffDays(range.start, range.end);
13989                var weekText;
13990                if (_this.opt('weekNumbers')) {
13991                    weekText = dateEnv.format(range.start, WEEK_HEADER_FORMAT);
13992                    return '' +
13993                        '<th class="fc-axis fc-week-number ' + theme.getClass('widgetHeader') + '" ' + _this.axisStyleAttr() + '>' +
13994                        core.buildGotoAnchorHtml(// aside from link, important for matchCellWidths
13995                        _this, { date: range.start, type: 'week', forceOff: dayCnt > 1 }, core.htmlEscape(weekText) // inner HTML
13996                        ) +
13997                        '</th>';
13998                }
13999                else {
14000                    return '<th class="fc-axis ' + theme.getClass('widgetHeader') + '" ' + _this.axisStyleAttr() + '></th>';
14001                }
14002            };
14003            /* Time Grid Render Methods
14004            ------------------------------------------------------------------------------------------------------------------*/
14005            // Generates the HTML that goes before the bg of the TimeGrid slot area. Long vertical column.
14006            _this.renderTimeGridBgIntroHtml = function () {
14007                var theme = _this.theme;
14008                return '<td class="fc-axis ' + theme.getClass('widgetContent') + '" ' + _this.axisStyleAttr() + '></td>';
14009            };
14010            // Generates the HTML that goes before all other types of cells.
14011            // Affects content-skeleton, mirror-skeleton, highlight-skeleton for both the time-grid and day-grid.
14012            _this.renderTimeGridIntroHtml = function () {
14013                return '<td class="fc-axis" ' + _this.axisStyleAttr() + '></td>';
14014            };
14015            /* Day Grid Render Methods
14016            ------------------------------------------------------------------------------------------------------------------*/
14017            // Generates the HTML that goes before the all-day cells
14018            _this.renderDayGridBgIntroHtml = function () {
14019                var theme = _this.theme;
14020                return '' +
14021                    '<td class="fc-axis ' + theme.getClass('widgetContent') + '" ' + _this.axisStyleAttr() + '>' +
14022                    '<span>' + // needed for matchCellWidths
14023                    core.getAllDayHtml(_this) +
14024                    '</span>' +
14025                    '</td>';
14026            };
14027            // Generates the HTML that goes before all other types of cells.
14028            // Affects content-skeleton, mirror-skeleton, highlight-skeleton for both the time-grid and day-grid.
14029            _this.renderDayGridIntroHtml = function () {
14030                return '<td class="fc-axis" ' + _this.axisStyleAttr() + '></td>';
14031            };
14032            _this.el.classList.add('fc-timeGrid-view');
14033            _this.el.innerHTML = _this.renderSkeletonHtml();
14034            _this.scroller = new core.ScrollComponent('hidden', // overflow x
14035            'auto' // overflow y
14036            );
14037            var timeGridWrapEl = _this.scroller.el;
14038            _this.el.querySelector('.fc-body > tr > td').appendChild(timeGridWrapEl);
14039            timeGridWrapEl.classList.add('fc-time-grid-container');
14040            var timeGridEl = core.createElement('div', { className: 'fc-time-grid' });
14041            timeGridWrapEl.appendChild(timeGridEl);
14042            _this.timeGrid = new TimeGrid(_this.context, timeGridEl, {
14043                renderBgIntroHtml: _this.renderTimeGridBgIntroHtml,
14044                renderIntroHtml: _this.renderTimeGridIntroHtml
14045            });
14046            if (_this.opt('allDaySlot')) { // should we display the "all-day" area?
14047                _this.dayGrid = new daygrid.DayGrid(// the all-day subcomponent of this view
14048                _this.context, _this.el.querySelector('.fc-day-grid'), {
14049                    renderNumberIntroHtml: _this.renderDayGridIntroHtml,
14050                    renderBgIntroHtml: _this.renderDayGridBgIntroHtml,
14051                    renderIntroHtml: _this.renderDayGridIntroHtml,
14052                    colWeekNumbersVisible: false,
14053                    cellWeekNumbersVisible: false
14054                });
14055                // have the day-grid extend it's coordinate area over the <hr> dividing the two grids
14056                var dividerEl = _this.el.querySelector('.fc-divider');
14057                _this.dayGrid.bottomCoordPadding = dividerEl.getBoundingClientRect().height;
14058            }
14059            return _this;
14060        }
14061        TimeGridView.prototype.destroy = function () {
14062            _super.prototype.destroy.call(this);
14063            this.timeGrid.destroy();
14064            if (this.dayGrid) {
14065                this.dayGrid.destroy();
14066            }
14067            this.scroller.destroy();
14068        };
14069        /* Rendering
14070        ------------------------------------------------------------------------------------------------------------------*/
14071        // Builds the HTML skeleton for the view.
14072        // The day-grid and time-grid components will render inside containers defined by this HTML.
14073        TimeGridView.prototype.renderSkeletonHtml = function () {
14074            var theme = this.theme;
14075            return '' +
14076                '<table class="' + theme.getClass('tableGrid') + '">' +
14077                (this.opt('columnHeader') ?
14078                    '<thead class="fc-head">' +
14079                        '<tr>' +
14080                        '<td class="fc-head-container ' + theme.getClass('widgetHeader') + '">&nbsp;</td>' +
14081                        '</tr>' +
14082                        '</thead>' :
14083                    '') +
14084                '<tbody class="fc-body">' +
14085                '<tr>' +
14086                '<td class="' + theme.getClass('widgetContent') + '">' +
14087                (this.opt('allDaySlot') ?
14088                    '<div class="fc-day-grid"></div>' +
14089                        '<hr class="fc-divider ' + theme.getClass('widgetHeader') + '" />' :
14090                    '') +
14091                '</td>' +
14092                '</tr>' +
14093                '</tbody>' +
14094                '</table>';
14095        };
14096        /* Now Indicator
14097        ------------------------------------------------------------------------------------------------------------------*/
14098        TimeGridView.prototype.getNowIndicatorUnit = function () {
14099            return this.timeGrid.getNowIndicatorUnit();
14100        };
14101        // subclasses should implement
14102        // renderNowIndicator(date: DateMarker) {
14103        // }
14104        TimeGridView.prototype.unrenderNowIndicator = function () {
14105            this.timeGrid.unrenderNowIndicator();
14106        };
14107        /* Dimensions
14108        ------------------------------------------------------------------------------------------------------------------*/
14109        TimeGridView.prototype.updateSize = function (isResize, viewHeight, isAuto) {
14110            _super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); // will call updateBaseSize. important that executes first
14111            this.timeGrid.updateSize(isResize);
14112            if (this.dayGrid) {
14113                this.dayGrid.updateSize(isResize);
14114            }
14115        };
14116        // Adjusts the vertical dimensions of the view to the specified values
14117        TimeGridView.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) {
14118            var _this = this;
14119            var eventLimit;
14120            var scrollerHeight;
14121            var scrollbarWidths;
14122            // make all axis cells line up
14123            this.axisWidth = core.matchCellWidths(core.findElements(this.el, '.fc-axis'));
14124            // hack to give the view some height prior to timeGrid's columns being rendered
14125            // TODO: separate setting height from scroller VS timeGrid.
14126            if (!this.timeGrid.colEls) {
14127                if (!isAuto) {
14128                    scrollerHeight = this.computeScrollerHeight(viewHeight);
14129                    this.scroller.setHeight(scrollerHeight);
14130                }
14131                return;
14132            }
14133            // set of fake row elements that must compensate when scroller has scrollbars
14134            var noScrollRowEls = core.findElements(this.el, '.fc-row').filter(function (node) {
14135                return !_this.scroller.el.contains(node);
14136            });
14137            // reset all dimensions back to the original state
14138            this.timeGrid.bottomRuleEl.style.display = 'none'; // will be shown later if this <hr> is necessary
14139            this.scroller.clear(); // sets height to 'auto' and clears overflow
14140            noScrollRowEls.forEach(core.uncompensateScroll);
14141            // limit number of events in the all-day area
14142            if (this.dayGrid) {
14143                this.dayGrid.removeSegPopover(); // kill the "more" popover if displayed
14144                eventLimit = this.opt('eventLimit');
14145                if (eventLimit && typeof eventLimit !== 'number') {
14146                    eventLimit = TIMEGRID_ALL_DAY_EVENT_LIMIT; // make sure "auto" goes to a real number
14147                }
14148                if (eventLimit) {
14149                    this.dayGrid.limitRows(eventLimit);
14150                }
14151            }
14152            if (!isAuto) { // should we force dimensions of the scroll container?
14153                scrollerHeight = this.computeScrollerHeight(viewHeight);
14154                this.scroller.setHeight(scrollerHeight);
14155                scrollbarWidths = this.scroller.getScrollbarWidths();
14156                if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?
14157                    // make the all-day and header rows lines up
14158                    noScrollRowEls.forEach(function (rowEl) {
14159                        core.compensateScroll(rowEl, scrollbarWidths);
14160                    });
14161                    // the scrollbar compensation might have changed text flow, which might affect height, so recalculate
14162                    // and reapply the desired height to the scroller.
14163                    scrollerHeight = this.computeScrollerHeight(viewHeight);
14164                    this.scroller.setHeight(scrollerHeight);
14165                }
14166                // guarantees the same scrollbar widths
14167                this.scroller.lockOverflow(scrollbarWidths);
14168                // if there's any space below the slats, show the horizontal rule.
14169                // this won't cause any new overflow, because lockOverflow already called.
14170                if (this.timeGrid.getTotalSlatHeight() < scrollerHeight) {
14171                    this.timeGrid.bottomRuleEl.style.display = '';
14172                }
14173            }
14174        };
14175        // given a desired total height of the view, returns what the height of the scroller should be
14176        TimeGridView.prototype.computeScrollerHeight = function (viewHeight) {
14177            return viewHeight -
14178                core.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
14179        };
14180        /* Scroll
14181        ------------------------------------------------------------------------------------------------------------------*/
14182        // Computes the initial pre-configured scroll state prior to allowing the user to change it
14183        TimeGridView.prototype.computeDateScroll = function (duration) {
14184            var top = this.timeGrid.computeTimeTop(duration);
14185            // zoom can give weird floating-point values. rather scroll a little bit further
14186            top = Math.ceil(top);
14187            if (top) {
14188                top++; // to overcome top border that slots beyond the first have. looks better
14189            }
14190            return { top: top };
14191        };
14192        TimeGridView.prototype.queryDateScroll = function () {
14193            return { top: this.scroller.getScrollTop() };
14194        };
14195        TimeGridView.prototype.applyDateScroll = function (scroll) {
14196            if (scroll.top !== undefined) {
14197                this.scroller.setScrollTop(scroll.top);
14198            }
14199        };
14200        // Generates an HTML attribute string for setting the width of the axis, if it is known
14201        TimeGridView.prototype.axisStyleAttr = function () {
14202            if (this.axisWidth != null) {
14203                return 'style="width:' + this.axisWidth + 'px"';
14204            }
14205            return '';
14206        };
14207        return TimeGridView;
14208    }(core.View));
14209    TimeGridView.prototype.usesMinMaxTime = true; // indicates that minTime/maxTime affects rendering
14210
14211    var SimpleTimeGrid = /** @class */ (function (_super) {
14212        __extends(SimpleTimeGrid, _super);
14213        function SimpleTimeGrid(context, timeGrid) {
14214            var _this = _super.call(this, context, timeGrid.el) || this;
14215            _this.buildDayRanges = core.memoize(buildDayRanges);
14216            _this.slicer = new TimeGridSlicer();
14217            _this.timeGrid = timeGrid;
14218            context.calendar.registerInteractiveComponent(_this, {
14219                el: _this.timeGrid.el
14220            });
14221            return _this;
14222        }
14223        SimpleTimeGrid.prototype.destroy = function () {
14224            _super.prototype.destroy.call(this);
14225            this.calendar.unregisterInteractiveComponent(this);
14226        };
14227        SimpleTimeGrid.prototype.render = function (props) {
14228            var dateProfile = props.dateProfile, dayTable = props.dayTable;
14229            var dayRanges = this.dayRanges = this.buildDayRanges(dayTable, dateProfile, this.dateEnv);
14230            this.timeGrid.receiveProps(__assign({}, this.slicer.sliceProps(props, dateProfile, null, this.timeGrid, dayRanges), { dateProfile: dateProfile, cells: dayTable.cells[0] }));
14231        };
14232        SimpleTimeGrid.prototype.renderNowIndicator = function (date) {
14233            this.timeGrid.renderNowIndicator(this.slicer.sliceNowDate(date, this.timeGrid, this.dayRanges), date);
14234        };
14235        SimpleTimeGrid.prototype.buildPositionCaches = function () {
14236            this.timeGrid.buildPositionCaches();
14237        };
14238        SimpleTimeGrid.prototype.queryHit = function (positionLeft, positionTop) {
14239            var rawHit = this.timeGrid.positionToHit(positionLeft, positionTop);
14240            if (rawHit) {
14241                return {
14242                    component: this.timeGrid,
14243                    dateSpan: rawHit.dateSpan,
14244                    dayEl: rawHit.dayEl,
14245                    rect: {
14246                        left: rawHit.relativeRect.left,
14247                        right: rawHit.relativeRect.right,
14248                        top: rawHit.relativeRect.top,
14249                        bottom: rawHit.relativeRect.bottom
14250                    },
14251                    layer: 0
14252                };
14253            }
14254        };
14255        return SimpleTimeGrid;
14256    }(core.DateComponent));
14257    function buildDayRanges(dayTable, dateProfile, dateEnv) {
14258        var ranges = [];
14259        for (var _i = 0, _a = dayTable.headerDates; _i < _a.length; _i++) {
14260            var date = _a[_i];
14261            ranges.push({
14262                start: dateEnv.add(date, dateProfile.minTime),
14263                end: dateEnv.add(date, dateProfile.maxTime)
14264            });
14265        }
14266        return ranges;
14267    }
14268    var TimeGridSlicer = /** @class */ (function (_super) {
14269        __extends(TimeGridSlicer, _super);
14270        function TimeGridSlicer() {
14271            return _super !== null && _super.apply(this, arguments) || this;
14272        }
14273        TimeGridSlicer.prototype.sliceRange = function (range, dayRanges) {
14274            var segs = [];
14275            for (var col = 0; col < dayRanges.length; col++) {
14276                var segRange = core.intersectRanges(range, dayRanges[col]);
14277                if (segRange) {
14278                    segs.push({
14279                        start: segRange.start,
14280                        end: segRange.end,
14281                        isStart: segRange.start.valueOf() === range.start.valueOf(),
14282                        isEnd: segRange.end.valueOf() === range.end.valueOf(),
14283                        col: col
14284                    });
14285                }
14286            }
14287            return segs;
14288        };
14289        return TimeGridSlicer;
14290    }(core.Slicer));
14291
14292    var TimeGridView$1 = /** @class */ (function (_super) {
14293        __extends(TimeGridView, _super);
14294        function TimeGridView(_context, viewSpec, dateProfileGenerator, parentEl) {
14295            var _this = _super.call(this, _context, viewSpec, dateProfileGenerator, parentEl) || this;
14296            _this.buildDayTable = core.memoize(buildDayTable);
14297            if (_this.opt('columnHeader')) {
14298                _this.header = new core.DayHeader(_this.context, _this.el.querySelector('.fc-head-container'));
14299            }
14300            _this.simpleTimeGrid = new SimpleTimeGrid(_this.context, _this.timeGrid);
14301            if (_this.dayGrid) {
14302                _this.simpleDayGrid = new daygrid.SimpleDayGrid(_this.context, _this.dayGrid);
14303            }
14304            return _this;
14305        }
14306        TimeGridView.prototype.destroy = function () {
14307            _super.prototype.destroy.call(this);
14308            if (this.header) {
14309                this.header.destroy();
14310            }
14311            this.simpleTimeGrid.destroy();
14312            if (this.simpleDayGrid) {
14313                this.simpleDayGrid.destroy();
14314            }
14315        };
14316        TimeGridView.prototype.render = function (props) {
14317            _super.prototype.render.call(this, props); // for flags for updateSize
14318            var dateProfile = this.props.dateProfile;
14319            var dayTable = this.buildDayTable(dateProfile, this.dateProfileGenerator);
14320            var splitProps = this.splitter.splitProps(props);
14321            if (this.header) {
14322                this.header.receiveProps({
14323                    dateProfile: dateProfile,
14324                    dates: dayTable.headerDates,
14325                    datesRepDistinctDays: true,
14326                    renderIntroHtml: this.renderHeadIntroHtml
14327                });
14328            }
14329            this.simpleTimeGrid.receiveProps(__assign({}, splitProps['timed'], { dateProfile: dateProfile,
14330                dayTable: dayTable }));
14331            if (this.simpleDayGrid) {
14332                this.simpleDayGrid.receiveProps(__assign({}, splitProps['allDay'], { dateProfile: dateProfile,
14333                    dayTable: dayTable, nextDayThreshold: this.nextDayThreshold, isRigid: false }));
14334            }
14335        };
14336        TimeGridView.prototype.renderNowIndicator = function (date) {
14337            this.simpleTimeGrid.renderNowIndicator(date);
14338        };
14339        return TimeGridView;
14340    }(TimeGridView));
14341    function buildDayTable(dateProfile, dateProfileGenerator) {
14342        var daySeries = new core.DaySeries(dateProfile.renderRange, dateProfileGenerator);
14343        return new core.DayTable(daySeries, false);
14344    }
14345
14346    var main = core.createPlugin({
14347        defaultView: 'timeGridWeek',
14348        views: {
14349            timeGrid: {
14350                class: TimeGridView$1,
14351                allDaySlot: true,
14352                slotDuration: '00:30:00',
14353                slotEventOverlap: true // a bad name. confused with overlap/constraint system
14354            },
14355            timeGridDay: {
14356                type: 'timeGrid',
14357                duration: { days: 1 }
14358            },
14359            timeGridWeek: {
14360                type: 'timeGrid',
14361                duration: { weeks: 1 }
14362            }
14363        }
14364    });
14365
14366    exports.AbstractTimeGridView = TimeGridView;
14367    exports.TimeGrid = TimeGrid;
14368    exports.TimeGridSlicer = TimeGridSlicer;
14369    exports.TimeGridView = TimeGridView$1;
14370    exports.buildDayRanges = buildDayRanges;
14371    exports.buildDayTable = buildDayTable;
14372    exports.default = main;
14373
14374    Object.defineProperty(exports, '__esModule', { value: true });
14375
14376}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.