Skip to content
Snippets Groups Projects
main.js 918 KiB
Newer Older
  • Learn to ignore specific revisions
  •             var scrollSyncer = this.scrollSyncersByColumn[col];
                if (scrollSyncer) {
                    scrollSyncer.forceScrollLeft(scrollLeft);
                }
            };
            ScrollGrid.prototype.forceScrollTop = function (sectionI, scrollTop) {
                var scrollSyncer = this.scrollSyncersBySection[sectionI];
                if (scrollSyncer) {
                    scrollSyncer.forceScrollTop(scrollTop);
                }
            };
            ScrollGrid.prototype._handleChunkEl = function (chunkEl, key) {
                var chunkConfig = this.getChunkConfigByIndex(parseInt(key, 10));
                if (chunkConfig) { // null if section disappeared. bad, b/c won't null-set the elRef
                    setRef(chunkConfig.elRef, chunkEl);
                }
            };
            ScrollGrid.prototype._handleScrollerEl = function (scrollerEl, key) {
                var chunkConfig = this.getChunkConfigByIndex(parseInt(key, 10));
                if (chunkConfig) { // null if section disappeared. bad, b/c won't null-set the elRef
                    setRef(chunkConfig.scrollerElRef, scrollerEl);
                }
            };
            ScrollGrid.prototype.getDims = function () {
                var sectionCnt = this.props.sections.length;
                var chunksPerSection = sectionCnt ? this.props.sections[0].chunks.length : 0;
                return [sectionCnt, chunksPerSection];
            };
            return ScrollGrid;
        }(BaseComponent));
        ScrollGrid.addStateEquality({
            shrinkWidths: isArraysEqual,
            scrollerClientWidths: isPropsEqual,
    
            scrollerClientHeights: isPropsEqual,
    
        });
        function sumNumbers(numbers) {
            var sum = 0;
            for (var _i = 0, numbers_1 = numbers; _i < numbers_1.length; _i++) {
                var n = numbers_1[_i];
                sum += n;
            }
            return sum;
        }
        function getRowInnerMaxHeight(rowEl) {
            var innerHeights = findElements(rowEl, '.fc-scrollgrid-sync-inner').map(getElHeight);
            if (innerHeights.length) {
                return Math.max.apply(Math, innerHeights);
            }
            return 0;
        }
        function getElHeight(el) {
            return el.offsetHeight; // better to deal with integers, for rounding, for PureComponent
        }
        function renderMacroColGroup(colGroupStats, shrinkWidths) {
            var children = colGroupStats.map(function (colGroupStat, i) {
                var width = colGroupStat.width;
                if (width === 'shrink') {
                    width = colGroupStat.totalColWidth + sanitizeShrinkWidth(shrinkWidths[i]) + 1; // +1 for border :(
                }
                return ( // eslint-disable-next-line react/jsx-key
                createElement("col", { style: { width: width } }));
            });
            return createElement.apply(void 0, __spreadArrays(['colgroup', {}], children));
        }
        function compileColGroupStat(colGroupConfig) {
            var totalColWidth = sumColProp(colGroupConfig.cols, 'width'); // excludes "shrink"
            var totalColMinWidth = sumColProp(colGroupConfig.cols, 'minWidth');
            var hasShrinkCol = hasShrinkWidth(colGroupConfig.cols);
            var allowXScrolling = colGroupConfig.width !== 'shrink' && Boolean(totalColWidth || totalColMinWidth || hasShrinkCol);
            return {
                hasShrinkCol: hasShrinkCol,
                totalColWidth: totalColWidth,
                totalColMinWidth: totalColMinWidth,
                allowXScrolling: allowXScrolling,
                cols: colGroupConfig.cols,
    
                width: colGroupConfig.width,
    
            };
        }
        function sumColProp(cols, propName) {
            var total = 0;
            for (var _i = 0, cols_1 = cols; _i < cols_1.length; _i++) {
                var col = cols_1[_i];
                var val = col[propName];
                if (typeof val === 'number') {
                    total += val * (col.span || 1);
                }
            }
            return total;
        }
        var COL_GROUP_STAT_EQUALITY = {
    
            cols: isColPropsEqual,
    
        };
        function isColGroupStatsEqual(stat0, stat1) {
            return compareObjs(stat0, stat1, COL_GROUP_STAT_EQUALITY);
        }
        // for memoizers...
        function initScrollSyncer(isVertical) {
            var scrollEls = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                scrollEls[_i - 1] = arguments[_i];
            }
            return new ScrollSyncer(isVertical, scrollEls);
        }
        function destroyScrollSyncer(scrollSyncer) {
            scrollSyncer.destroy();
        }
        function initStickyScrolling(scrollEl, isRtl) {
            return new StickyScrolling(scrollEl, isRtl);
        }
        function destroyStickyScrolling(stickyScrolling) {
            stickyScrolling.destroy();
        }
    
        var scrollGridPlugin = createPlugin({
            deps: [
    
                premiumCommonPlugin,
    
            scrollGridImpl: ScrollGrid,
    
        });
    
        var contexts = [];
        var undoFuncs = [];
        var adaptivePlugin = createPlugin({
            deps: [
    
                premiumCommonPlugin,
    
            ],
            contextInit: function (context) {
                if (!contexts.length) {
                    attachGlobalHandlers();
                }
                contexts.push(context);
                context.calendarApi.on('_unmount', function () {
                    removeExact(contexts, context);
                    if (!contexts.length) {
                        removeGlobalHandlers();
                    }
                });
    
        });
        function attachGlobalHandlers() {
            window.addEventListener('beforeprint', handleBeforePrint);
            window.addEventListener('afterprint', handleAfterPrint);
            // // for testing
            // let forPrint = false
            // document.addEventListener('keypress', (ev) => {
            //   if (ev.key === 'p') {
            //     forPrint = !forPrint
            //     if (forPrint) {
            //       handleBeforePrint()
            //     } else {
            //       handleAfterPrint()
            //     }
            //   }
            // })
        }
        function removeGlobalHandlers() {
            window.removeEventListener('beforeprint', handleBeforePrint);
            window.removeEventListener('afterprint', handleAfterPrint);
        }
        function handleBeforePrint() {
            var scrollEls = queryScrollerEls();
            var scrollCoords = queryScrollerCoords(scrollEls);
            for (var _i = 0, contexts_1 = contexts; _i < contexts_1.length; _i++) {
                var context = contexts_1[_i];
                context.emitter.trigger('_beforeprint');
            }
            flushToDom$1(); // because printing grabs DOM immediately after
            killHorizontalScrolling(scrollEls, scrollCoords);
            undoFuncs.push(function () { return restoreScrollerCoords(scrollEls, scrollCoords); });
            undoFuncs.push(freezeScrollgridWidths());
        }
        function handleAfterPrint() {
            for (var _i = 0, contexts_2 = contexts; _i < contexts_2.length; _i++) {
                var context = contexts_2[_i];
                context.emitter.trigger('_afterprint');
            }
            flushToDom$1(); // guarantee that there are real scrollers
            while (undoFuncs.length) {
                undoFuncs.shift()();
            }
        }
        // scrollgrid widths
        function freezeScrollgridWidths() {
            var els = findElements(document.body, '.fc-scrollgrid');
            els.forEach(freezeScrollGridWidth);
            return function () { return els.forEach(unfreezeScrollGridWidth); };
        }
        function freezeScrollGridWidth(el) {
            el.style.width = el.getBoundingClientRect().width + 'px';
        }
        function unfreezeScrollGridWidth(el) {
            el.style.width = '';
        }
        // scrollers
        // TODO: use scroll normalization!? yes
        function queryScrollerEls() {
            return findElements(document.body, '.fc-scroller-harness > .fc-scroller');
        }
        function queryScrollerCoords(els) {
            return els.map(function (el) {
                var computedStyle = window.getComputedStyle(el);
                return {
                    scrollLeft: el.scrollLeft,
                    scrollTop: el.scrollTop,
                    overflowX: computedStyle.overflowX,
                    overflowY: computedStyle.overflowY,
    
                    marginBottom: computedStyle.marginBottom,
    
                };
            });
        }
        function killHorizontalScrolling(els, coords) {
            els.forEach(function (el, i) {
                el.style.overflowX = 'visible'; // need to clear X/Y to get true overflow
                el.style.overflowY = 'visible'; // "
                el.style.marginBottom = ''; // for clipping away scrollbar. disable
                el.style.left = -coords[i].scrollLeft + 'px'; // simulate scrollLeft! will be position:relative
            });
        }
        function restoreScrollerCoords(els, coords) {
            els.forEach(function (el, i) {
                var c = coords[i];
                el.style.overflowX = c.overflowX;
                el.style.overflowY = c.overflowY;
                el.style.marginBottom = c.marginBottom;
                el.style.left = '';
                el.scrollLeft = c.scrollLeft;
                el.scrollTop = c.scrollTop;
            });
        }
    
        var MIN_AUTO_LABELS = 18; // more than `12` months but less that `24` hours
        var MAX_AUTO_SLOTS_PER_LABEL = 6; // allows 6 10-min slots in an hour
        var MAX_AUTO_CELLS = 200; // allows 4-days to have a :30 slot duration
        config.MAX_TIMELINE_SLOTS = 1000;
        // potential nice values for slot-duration and interval-duration
        var STOCK_SUB_DURATIONS$1 = [
            { years: 1 },
            { months: 1 },
            { days: 1 },
            { hours: 1 },
            { minutes: 30 },
            { minutes: 15 },
            { minutes: 10 },
            { minutes: 5 },
            { minutes: 1 },
            { seconds: 30 },
            { seconds: 15 },
            { seconds: 10 },
            { seconds: 5 },
            { seconds: 1 },
            { milliseconds: 500 },
            { milliseconds: 100 },
            { milliseconds: 10 },
    
            { milliseconds: 1 },
    
        ];
        function buildTimelineDateProfile(dateProfile, dateEnv, allOptions, dateProfileGenerator) {
            var tDateProfile = {
                labelInterval: allOptions.slotLabelInterval,
    
                slotDuration: allOptions.slotDuration,
    
            };
            validateLabelAndSlot(tDateProfile, dateProfile, dateEnv); // validate after computed grid duration
            ensureLabelInterval(tDateProfile, dateProfile, dateEnv);
            ensureSlotDuration(tDateProfile, dateProfile, dateEnv);
            var input = allOptions.slotLabelFormat;
            var rawFormats = Array.isArray(input) ? input :
                (input != null) ? [input] :
                    computeHeaderFormats(tDateProfile, dateProfile, dateEnv, allOptions);
    
            tDateProfile.headerFormats = rawFormats.map(function (rawFormat) { return createFormatter(rawFormat); });
    
            tDateProfile.isTimeScale = Boolean(tDateProfile.slotDuration.milliseconds);
            var largeUnit = null;
            if (!tDateProfile.isTimeScale) {
                var slotUnit = greatestDurationDenominator(tDateProfile.slotDuration).unit;
                if (/year|month|week/.test(slotUnit)) {
                    largeUnit = slotUnit;
                }
            }
            tDateProfile.largeUnit = largeUnit;
            tDateProfile.emphasizeWeeks =
    
                asCleanDays(tDateProfile.slotDuration) === 1 &&
    
                    currentRangeAs('weeks', dateProfile, dateEnv) >= 2 &&
                    !allOptions.businessHours;
            /*
            console.log('label interval =', timelineView.labelInterval.humanize())
            console.log('slot duration =', timelineView.slotDuration.humanize())
            console.log('header formats =', timelineView.headerFormats)
            console.log('isTimeScale', timelineView.isTimeScale)
            console.log('largeUnit', timelineView.largeUnit)
            */
            var rawSnapDuration = allOptions.snapDuration;
            var snapDuration;
            var snapsPerSlot;
            if (rawSnapDuration) {
                snapDuration = createDuration(rawSnapDuration);
                snapsPerSlot = wholeDivideDurations(tDateProfile.slotDuration, snapDuration);
                // ^ TODO: warning if not whole?
            }
            if (snapsPerSlot == null) {
                snapDuration = tDateProfile.slotDuration;
                snapsPerSlot = 1;
            }
            tDateProfile.snapDuration = snapDuration;
            tDateProfile.snapsPerSlot = snapsPerSlot;
            // more...
            var timeWindowMs = asRoughMs(dateProfile.slotMaxTime) - asRoughMs(dateProfile.slotMinTime);
            // TODO: why not use normalizeRange!?
            var normalizedStart = normalizeDate(dateProfile.renderRange.start, tDateProfile, dateEnv);
            var normalizedEnd = normalizeDate(dateProfile.renderRange.end, tDateProfile, dateEnv);
            // apply slotMinTime/slotMaxTime
            // TODO: View should be responsible.
            if (tDateProfile.isTimeScale) {
                normalizedStart = dateEnv.add(normalizedStart, dateProfile.slotMinTime);
                normalizedEnd = dateEnv.add(addDays(normalizedEnd, -1), dateProfile.slotMaxTime);
            }
            tDateProfile.timeWindowMs = timeWindowMs;
            tDateProfile.normalizedRange = { start: normalizedStart, end: normalizedEnd };
            var slotDates = [];
            var date = normalizedStart;
            while (date < normalizedEnd) {
                if (isValidDate$1(date, tDateProfile, dateProfile, dateProfileGenerator)) {
                    slotDates.push(date);
                }
                date = dateEnv.add(date, tDateProfile.slotDuration);
            }
            tDateProfile.slotDates = slotDates;
            // more...
            var snapIndex = -1;
            var snapDiff = 0; // index of the diff :(
            var snapDiffToIndex = [];
            var snapIndexToDiff = [];
            date = normalizedStart;
            while (date < normalizedEnd) {
                if (isValidDate$1(date, tDateProfile, dateProfile, dateProfileGenerator)) {
    
                    snapIndex += 1;
    
                    snapDiffToIndex.push(snapIndex);
                    snapIndexToDiff.push(snapDiff);
                }
                else {
                    snapDiffToIndex.push(snapIndex + 0.5);
                }
                date = dateEnv.add(date, tDateProfile.snapDuration);
    
                snapDiff += 1;
    
            }
            tDateProfile.snapDiffToIndex = snapDiffToIndex;
            tDateProfile.snapIndexToDiff = snapIndexToDiff;
            tDateProfile.snapCnt = snapIndex + 1; // is always one behind
            tDateProfile.slotCnt = tDateProfile.snapCnt / tDateProfile.snapsPerSlot;
            // more...
            tDateProfile.isWeekStarts = buildIsWeekStarts(tDateProfile, dateEnv);
            tDateProfile.cellRows = buildCellRows(tDateProfile, dateEnv);
            tDateProfile.slotsPerLabel = wholeDivideDurations(tDateProfile.labelInterval, tDateProfile.slotDuration);
            return tDateProfile;
        }
        /*
        snaps to appropriate unit
        */
        function normalizeDate(date, tDateProfile, dateEnv) {
            var normalDate = date;
            if (!tDateProfile.isTimeScale) {
                normalDate = startOfDay(normalDate);
                if (tDateProfile.largeUnit) {
                    normalDate = dateEnv.startOf(normalDate, tDateProfile.largeUnit);
                }
            }
            return normalDate;
        }
        /*
        snaps to appropriate unit
        */
        function normalizeRange(range, tDateProfile, dateEnv) {
            if (!tDateProfile.isTimeScale) {
                range = computeVisibleDayRange(range);
                if (tDateProfile.largeUnit) {
                    var dayRange = range; // preserve original result
                    range = {
                        start: dateEnv.startOf(range.start, tDateProfile.largeUnit),
    
                        end: dateEnv.startOf(range.end, tDateProfile.largeUnit),
    
                    };
                    // if date is partially through the interval, or is in the same interval as the start,
                    // make the exclusive end be the *next* interval
                    if (range.end.valueOf() !== dayRange.end.valueOf() || range.end <= range.start) {
                        range = {
                            start: range.start,
    
                            end: dateEnv.add(range.end, tDateProfile.slotDuration),
    
                        };
                    }
                }
            }
            return range;
        }
        function isValidDate$1(date, tDateProfile, dateProfile, dateProfileGenerator) {
            if (dateProfileGenerator.isHiddenDay(date)) {
                return false;
            }
    
            if (tDateProfile.isTimeScale) {
    
                // determine if the time is within slotMinTime/slotMaxTime, which may have wacky values
                var day = startOfDay(date);
                var timeMs = date.valueOf() - day.valueOf();
                var ms = timeMs - asRoughMs(dateProfile.slotMinTime); // milliseconds since slotMinTime
                ms = ((ms % 86400000) + 86400000) % 86400000; // make negative values wrap to 24hr clock
                return ms < tDateProfile.timeWindowMs; // before the slotMaxTime?
            }
    
            return true;
    
        }
        function validateLabelAndSlot(tDateProfile, dateProfile, dateEnv) {
            var currentRange = dateProfile.currentRange;
            // make sure labelInterval doesn't exceed the max number of cells
            if (tDateProfile.labelInterval) {
                var labelCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, tDateProfile.labelInterval);
                if (labelCnt > config.MAX_TIMELINE_SLOTS) {
                    console.warn('slotLabelInterval results in too many cells');
                    tDateProfile.labelInterval = null;
                }
            }
            // make sure slotDuration doesn't exceed the maximum number of cells
            if (tDateProfile.slotDuration) {
                var slotCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, tDateProfile.slotDuration);
                if (slotCnt > config.MAX_TIMELINE_SLOTS) {
                    console.warn('slotDuration results in too many cells');
                    tDateProfile.slotDuration = null;
                }
            }
            // make sure labelInterval is a multiple of slotDuration
            if (tDateProfile.labelInterval && tDateProfile.slotDuration) {
                var slotsPerLabel = wholeDivideDurations(tDateProfile.labelInterval, tDateProfile.slotDuration);
                if (slotsPerLabel === null || slotsPerLabel < 1) {
                    console.warn('slotLabelInterval must be a multiple of slotDuration');
                    tDateProfile.slotDuration = null;
                }
            }
        }
        function ensureLabelInterval(tDateProfile, dateProfile, dateEnv) {
            var currentRange = dateProfile.currentRange;
            var labelInterval = tDateProfile.labelInterval;
            if (!labelInterval) {
                // compute based off the slot duration
                // find the largest label interval with an acceptable slots-per-label
                var input = void 0;
                if (tDateProfile.slotDuration) {
                    for (var _i = 0, STOCK_SUB_DURATIONS_1 = STOCK_SUB_DURATIONS$1; _i < STOCK_SUB_DURATIONS_1.length; _i++) {
                        input = STOCK_SUB_DURATIONS_1[_i];
                        var tryLabelInterval = createDuration(input);
                        var slotsPerLabel = wholeDivideDurations(tryLabelInterval, tDateProfile.slotDuration);
                        if (slotsPerLabel !== null && slotsPerLabel <= MAX_AUTO_SLOTS_PER_LABEL) {
                            labelInterval = tryLabelInterval;
                            break;
                        }
                    }
                    // use the slot duration as a last resort
                    if (!labelInterval) {
                        labelInterval = tDateProfile.slotDuration;
                    }
                    // compute based off the view's duration
                    // find the largest label interval that yields the minimum number of labels
                }
                else {
                    for (var _a = 0, STOCK_SUB_DURATIONS_2 = STOCK_SUB_DURATIONS$1; _a < STOCK_SUB_DURATIONS_2.length; _a++) {
                        input = STOCK_SUB_DURATIONS_2[_a];
                        labelInterval = createDuration(input);
                        var labelCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, labelInterval);
                        if (labelCnt >= MIN_AUTO_LABELS) {
                            break;
                        }
                    }
                }
                tDateProfile.labelInterval = labelInterval;
            }
            return labelInterval;
        }
        function ensureSlotDuration(tDateProfile, dateProfile, dateEnv) {
            var currentRange = dateProfile.currentRange;
            var slotDuration = tDateProfile.slotDuration;
            if (!slotDuration) {
                var labelInterval = ensureLabelInterval(tDateProfile, dateProfile, dateEnv); // will compute if necessary
                // compute based off the label interval
                // find the largest slot duration that is different from labelInterval, but still acceptable
                for (var _i = 0, STOCK_SUB_DURATIONS_3 = STOCK_SUB_DURATIONS$1; _i < STOCK_SUB_DURATIONS_3.length; _i++) {
                    var input = STOCK_SUB_DURATIONS_3[_i];
                    var trySlotDuration = createDuration(input);
                    var slotsPerLabel = wholeDivideDurations(labelInterval, trySlotDuration);
                    if (slotsPerLabel !== null && slotsPerLabel > 1 && slotsPerLabel <= MAX_AUTO_SLOTS_PER_LABEL) {
                        slotDuration = trySlotDuration;
                        break;
                    }
                }
                // only allow the value if it won't exceed the view's # of slots limit
                if (slotDuration) {
                    var slotCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, slotDuration);
                    if (slotCnt > MAX_AUTO_CELLS) {
                        slotDuration = null;
                    }
                }
                // use the label interval as a last resort
                if (!slotDuration) {
                    slotDuration = labelInterval;
                }
                tDateProfile.slotDuration = slotDuration;
            }
            return slotDuration;
        }
        function computeHeaderFormats(tDateProfile, dateProfile, dateEnv, allOptions) {
            var format1;
            var format2;
            var labelInterval = tDateProfile.labelInterval;
            var unit = greatestDurationDenominator(labelInterval).unit;
            var weekNumbersVisible = allOptions.weekNumbers;
            var format0 = (format1 = (format2 = null));
            // NOTE: weekNumber computation function wont work
            if ((unit === 'week') && !weekNumbersVisible) {
                unit = 'day';
            }
            switch (unit) {
                case 'year':
                    format0 = { year: 'numeric' }; // '2015'
                    break;
                case 'month':
                    if (currentRangeAs('years', dateProfile, dateEnv) > 1) {
                        format0 = { year: 'numeric' }; // '2015'
                    }
                    format1 = { month: 'short' }; // 'Jan'
                    break;
                case 'week':
                    if (currentRangeAs('years', dateProfile, dateEnv) > 1) {
                        format0 = { year: 'numeric' }; // '2015'
                    }
                    format1 = { week: 'narrow' }; // 'Wk4'
                    break;
                case 'day':
                    if (currentRangeAs('years', dateProfile, dateEnv) > 1) {
                        format0 = { year: 'numeric', month: 'long' }; // 'January 2014'
                    }
                    else if (currentRangeAs('months', dateProfile, dateEnv) > 1) {
                        format0 = { month: 'long' }; // 'January'
                    }
                    if (weekNumbersVisible) {
                        format1 = { week: 'short' }; // 'Wk 4'
                    }
                    format2 = { weekday: 'narrow', day: 'numeric' }; // 'Su 9'
                    break;
                case 'hour':
                    if (weekNumbersVisible) {
                        format0 = { week: 'short' }; // 'Wk 4'
                    }
                    if (currentRangeAs('days', dateProfile, dateEnv) > 1) {
                        format1 = { weekday: 'short', day: 'numeric', month: 'numeric', omitCommas: true }; // Sat 4/7
                    }
                    format2 = {
                        hour: 'numeric',
                        minute: '2-digit',
                        omitZeroMinute: true,
    
                        meridiem: 'short',
    
                    };
                    break;
                case 'minute':
                    // sufficiently large number of different minute cells?
                    if ((asRoughMinutes(labelInterval) / 60) >= MAX_AUTO_SLOTS_PER_LABEL) {
                        format0 = {
                            hour: 'numeric',
    
                            meridiem: 'short',
    
                        format1 = function (params) { return (':' + padStart(params.date.minute, 2) // ':30'
                        ); };
    
                    }
                    else {
                        format0 = {
                            hour: 'numeric',
                            minute: 'numeric',
    
                            meridiem: 'short',
    
                        };
                    }
                    break;
                case 'second':
                    // sufficiently large number of different second cells?
                    if ((asRoughSeconds(labelInterval) / 60) >= MAX_AUTO_SLOTS_PER_LABEL) {
                        format0 = { hour: 'numeric', minute: '2-digit', meridiem: 'lowercase' }; // '8:30 PM'
    
                        format1 = function (params) { return (':' + padStart(params.date.second, 2) // ':30'
                        ); };
    
                    }
                    else {
                        format0 = { hour: 'numeric', minute: '2-digit', second: '2-digit', meridiem: 'lowercase' }; // '8:30:45 PM'
                    }
                    break;
                case 'millisecond':
                    format0 = { hour: 'numeric', minute: '2-digit', second: '2-digit', meridiem: 'lowercase' }; // '8:30:45 PM'
    
                    format1 = function (params) { return ('.' + padStart(params.millisecond, 3)); };
    
                    break;
            }
            return [].concat(format0 || [], format1 || [], format2 || []);
        }
        // Compute the number of the give units in the "current" range.
        // Won't go more precise than days.
        // Will return `0` if there's not a clean whole interval.
        function currentRangeAs(unit, dateProfile, dateEnv) {
            var range = dateProfile.currentRange;
            var res = null;
            if (unit === 'years') {
                res = dateEnv.diffWholeYears(range.start, range.end);
            }
            else if (unit === 'months') {
                res = dateEnv.diffWholeMonths(range.start, range.end);
            }
            else if (unit === 'weeks') {
                res = dateEnv.diffWholeMonths(range.start, range.end);
            }
            else if (unit === 'days') {
                res = diffWholeDays(range.start, range.end);
            }
            return res || 0;
        }
        function buildIsWeekStarts(tDateProfile, dateEnv) {
            var slotDates = tDateProfile.slotDates, emphasizeWeeks = tDateProfile.emphasizeWeeks;
            var prevWeekNumber = null;
            var isWeekStarts = [];
            for (var _i = 0, slotDates_1 = slotDates; _i < slotDates_1.length; _i++) {
                var slotDate = slotDates_1[_i];
                var weekNumber = dateEnv.computeWeekNumber(slotDate);
                var isWeekStart = emphasizeWeeks && (prevWeekNumber !== null) && (prevWeekNumber !== weekNumber);
                prevWeekNumber = weekNumber;
                isWeekStarts.push(isWeekStart);
            }
            return isWeekStarts;
        }
        function buildCellRows(tDateProfile, dateEnv) {
            var slotDates = tDateProfile.slotDates;
            var formats = tDateProfile.headerFormats;
    
            var cellRows = formats.map(function () { return []; }); // indexed by row,col
            var slotAsDays = asCleanDays(tDateProfile.slotDuration);
            var guessedSlotUnit = slotAsDays === 7 ? 'week' :
                slotAsDays === 1 ? 'day' :
                    null;
    
            // specifically for navclicks
    
            var rowUnitsFromFormats = formats.map(function (format) { return (format.getLargestUnit ? format.getLargestUnit() : null); });
    
            // builds cellRows and slotCells
    
            for (var i = 0; i < slotDates.length; i += 1) {
    
                var date = slotDates[i];
                var isWeekStart = tDateProfile.isWeekStarts[i];
    
                for (var row = 0; row < formats.length; row += 1) {
    
                    var format = formats[row];
                    var rowCells = cellRows[row];
                    var leadingCell = rowCells[rowCells.length - 1];
    
                    var isLastRow = row === formats.length - 1;
                    var isSuperRow = formats.length > 1 && !isLastRow; // more than one row and not the last
    
                    var rowUnit = rowUnitsFromFormats[row] || (isLastRow ? guessedSlotUnit : null);
    
                    if (isSuperRow) {
                        var text = dateEnv.format(date, format);
                        if (!leadingCell || (leadingCell.text !== text)) {
    
                            newCell = buildCellObject(date, text, rowUnit);
    
                    else if (!leadingCell ||
                        isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.labelInterval))) {
                        var text = dateEnv.format(date, format);
                        newCell = buildCellObject(date, text, rowUnit);
                    }
    
                        leadingCell.colspan += 1;
    
                    }
                    if (newCell) {
                        newCell.weekStart = isWeekStart;
                        rowCells.push(newCell);
                    }
                }
            }
            return cellRows;
        }
        function buildCellObject(date, text, rowUnit) {
            return { date: date, text: text, rowUnit: rowUnit, colspan: 1, isWeekStart: false };
        }
    
    
        var TimelineHeaderThInner = /** @class */ (function (_super) {
            __extends(TimelineHeaderThInner, _super);
            function TimelineHeaderThInner() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            TimelineHeaderThInner.prototype.render = function () {
                var _a = this, props = _a.props, context = _a.context;
                var navLinkAttrs = props.navLinkData
                    ? { 'data-navlink': props.navLinkData, tabIndex: 0 }
                    : {};
                return (createElement(ContentHook, { hookProps: props.hookProps, content: context.options.slotLabelContent, defaultContent: renderInnerContent$5 }, function (innerElRef, innerContent) { return (createElement("a", __assign({ ref: innerElRef, className: 'fc-timeline-slot-cushion fc-scrollgrid-sync-inner' + (props.isSticky ? ' fc-sticky' : '') }, navLinkAttrs), innerContent)); }));
            };
            return TimelineHeaderThInner;
        }(BaseComponent));
        function renderInnerContent$5(props) {
            return props.text;
        }
        function refineHookProps(input) {
            return {
                level: input.level,
                date: input.dateEnv.toDate(input.dateMarker),
                view: input.viewApi,
                text: input.text,
            };
        }
    
    
        var TimelineHeaderTh = /** @class */ (function (_super) {
            __extends(TimelineHeaderTh, _super);
            function TimelineHeaderTh() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
    
                _this.refineHookProps = memoizeObjArg(refineHookProps);
    
                _this.normalizeClassNames = buildClassNameNormalizer();
                return _this;
            }
            TimelineHeaderTh.prototype.render = function () {
                var _a = this, props = _a.props, context = _a.context;
                var dateEnv = context.dateEnv, options = context.options;
                var cell = props.cell, dateProfile = props.dateProfile, tDateProfile = props.tDateProfile;
                // the cell.rowUnit is f'd
                // giving 'month' for a 3-day view
                // workaround: to infer day, do NOT time
                var dateMeta = getDateMeta(cell.date, props.todayRange, props.nowDate, dateProfile);
                var classNames = ['fc-timeline-slot', 'fc-timeline-slot-label'].concat(cell.rowUnit === 'time' // TODO: so slot classnames for week/month/bigger. see note above about rowUnit
                    ? getSlotClassNames(dateMeta, context.theme)
                    : getDayClassNames(dateMeta, context.theme));
                if (cell.isWeekStart) {
                    classNames.push('fc-timeline-slot-em');
                }
                var navLinkData = (options.navLinks && cell.rowUnit && cell.rowUnit !== 'time')
                    ? buildNavLinkData(cell.date, cell.rowUnit)
                    : null;
                var hookProps = this.refineHookProps({
    
                    level: props.rowLevel,
    
                    dateMarker: cell.date,
                    text: cell.text,
                    dateEnv: context.dateEnv,
    
                    viewApi: context.viewApi,
    
                });
                var customClassNames = this.normalizeClassNames(options.slotLabelClassNames, hookProps);
                return (createElement(MountHook, { hookProps: hookProps, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, function (rootElRef) { return (createElement("th", { ref: rootElRef, className: classNames.concat(customClassNames).join(' '), "data-date": dateEnv.formatIso(cell.date, { omitTime: !tDateProfile.isTimeScale, omitTimeZoneOffset: true }), colSpan: cell.colspan },
    
                    createElement("div", { className: "fc-timeline-slot-frame", style: { height: props.rowInnerHeight } },
    
                        createElement(TimelineHeaderThInner, { hookProps: hookProps, isSticky: props.isSticky, navLinkData: navLinkData })))); }));
            };
            return TimelineHeaderTh;
        }(BaseComponent));
    
        var TimelineHeaderRows = /** @class */ (function (_super) {
            __extends(TimelineHeaderRows, _super);
            function TimelineHeaderRows() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            TimelineHeaderRows.prototype.render = function () {
                var _a = this.props, dateProfile = _a.dateProfile, tDateProfile = _a.tDateProfile, rowInnerHeights = _a.rowInnerHeights, todayRange = _a.todayRange, nowDate = _a.nowDate;
                var cellRows = tDateProfile.cellRows;
    
                return (createElement(Fragment, null, cellRows.map(function (rowCells, rowLevel) {
                    var isLast = rowLevel === cellRows.length - 1;
    
                    var isChrono = tDateProfile.isTimeScale && isLast; // the final row, with times?
                    var classNames = [
                        'fc-timeline-header-row',
    
                        isChrono ? 'fc-timeline-header-row-chrono' : '',
    
                    return ( // eslint-disable-next-line react/no-array-index-key
                    createElement("tr", { key: rowLevel, className: classNames.join(' ') }, rowCells.map(function (cell) { return (createElement(TimelineHeaderTh, { key: cell.date.toISOString(), cell: cell, rowLevel: rowLevel, dateProfile: dateProfile, tDateProfile: tDateProfile, todayRange: todayRange, nowDate: nowDate, rowInnerHeight: rowInnerHeights && rowInnerHeights[rowLevel], isSticky: !isLast })); })));
    
                })));
            };
            return TimelineHeaderRows;
        }(BaseComponent));
    
        var TimelineHeader = /** @class */ (function (_super) {
            __extends(TimelineHeader, _super);
            function TimelineHeader() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.rootElRef = createRef();
                return _this;
            }
            TimelineHeader.prototype.render = function () {
                var _this = this;
                var _a = this, props = _a.props, context = _a.context;
                // TODO: very repetitive
                // TODO: make part of tDateProfile?
                var timerUnit = greatestDurationDenominator(props.tDateProfile.slotDuration).unit;
    
                // WORKAROUND: make ignore slatCoords when out of sync with dateProfile
                var slatCoords = props.slatCoords && props.slatCoords.dateProfile === props.dateProfile ? props.slatCoords : null;
                return (createElement(NowTimer, { unit: timerUnit }, function (nowDate, todayRange) { return (createElement("div", { className: "fc-timeline-header", ref: _this.rootElRef },
                    createElement("table", { className: "fc-scrollgrid-sync-table", style: { minWidth: props.tableMinWidth, width: props.clientWidth } },
    
                        props.tableColGroupNode,
                        createElement("tbody", null,
                            createElement(TimelineHeaderRows, { dateProfile: props.dateProfile, tDateProfile: props.tDateProfile, nowDate: nowDate, todayRange: todayRange, rowInnerHeights: props.rowInnerHeights }))),
    
                    context.options.nowIndicator && (
                    // need to have a container regardless of whether the current view has a visible now indicator
                    // because apparently removal of the element resets the scroll for some reasons (issue #5351).
                    // this issue doesn't happen for the timeline body however (
                    createElement("div", { className: "fc-timeline-now-indicator-container" }, (slatCoords && slatCoords.isDateInRange(nowDate)) && (createElement(NowIndicatorRoot, { isAxis: true, date: nowDate }, function (rootElRef, classNames, innerElRef, innerContent) { return (createElement("div", { ref: rootElRef, className: ['fc-timeline-now-indicator-arrow'].concat(classNames).join(' '), style: { left: slatCoords.dateToCoord(nowDate) } }, innerContent)); })))))); }));
    
            };
            TimelineHeader.prototype.componentDidMount = function () {
                this.updateSize();
            };
            TimelineHeader.prototype.componentDidUpdate = function () {
                this.updateSize();
            };
            TimelineHeader.prototype.updateSize = function () {
                if (this.props.onMaxCushionWidth) {
                    this.props.onMaxCushionWidth(this.computeMaxCushionWidth());
                }
            };
            TimelineHeader.prototype.computeMaxCushionWidth = function () {
                return Math.max.apply(Math, findElements(this.rootElRef.current, '.fc-timeline-header-row:last-child .fc-timeline-slot-cushion').map(function (el) { return el.getBoundingClientRect().width; }));
            };
            return TimelineHeader;
        }(BaseComponent));
    
        var TimelineCoords = /** @class */ (function () {
            function TimelineCoords(slatRootEl, // okay to expose?
            slatEls, dateProfile, tDateProfile, dateEnv, isRtl) {
                this.slatRootEl = slatRootEl;
                this.dateProfile = dateProfile;
                this.tDateProfile = tDateProfile;
                this.dateEnv = dateEnv;
                this.isRtl = isRtl;
                this.outerCoordCache = new PositionCache(slatRootEl, slatEls, true, // isHorizontal
    
                // for the inner divs within the slats
                // used for event rendering and scrollTime, to disregard slat border
                this.innerCoordCache = new PositionCache(slatRootEl, findDirectChildren(slatEls, 'div'), true, // isHorizontal
    
            }
            TimelineCoords.prototype.rangeToCoords = function (range) {
                if (this.isRtl) {
                    return { right: this.dateToCoord(range.start), left: this.dateToCoord(range.end) };
                }
    
                return { left: this.dateToCoord(range.start), right: this.dateToCoord(range.end) };
    
            };
            TimelineCoords.prototype.isDateInRange = function (date) {
                return rangeContainsMarker(this.dateProfile.currentRange, date);
            };
            // for LTR, results range from 0 to width of area
            // for RTL, results range from negative width of area to 0
            TimelineCoords.prototype.dateToCoord = function (date) {
                var tDateProfile = this.tDateProfile;
                var snapCoverage = this.computeDateSnapCoverage(date);
                var slotCoverage = snapCoverage / tDateProfile.snapsPerSlot;
                var slotIndex = Math.floor(slotCoverage);
                slotIndex = Math.min(slotIndex, tDateProfile.slotCnt - 1);
                var partial = slotCoverage - slotIndex;
                var _a = this, innerCoordCache = _a.innerCoordCache, outerCoordCache = _a.outerCoordCache;
                if (this.isRtl) {
                    return (outerCoordCache.rights[slotIndex] -
                        (innerCoordCache.getWidth(slotIndex) * partial)) - outerCoordCache.originClientRect.width;
                }
    
                return (outerCoordCache.lefts[slotIndex] +
                    (innerCoordCache.getWidth(slotIndex) * partial));
    
            };
            // returned value is between 0 and the number of snaps
            TimelineCoords.prototype.computeDateSnapCoverage = function (date) {
                return computeDateSnapCoverage(date, this.tDateProfile, this.dateEnv);
            };
            TimelineCoords.prototype.computeDurationLeft = function (duration) {
    
                var _a = this, dateProfile = _a.dateProfile, tDateProfile = _a.tDateProfile, dateEnv = _a.dateEnv, isRtl = _a.isRtl;
    
                var left = 0;
                if (dateProfile) {
    
                    var date = dateEnv.add(dateProfile.activeRange.start, duration);
                    if (!tDateProfile.isTimeScale) {
                        date = startOfDay(date);
                    }
                    left = this.dateToCoord(date);
    
                    // hack to overcome the left borders of non-first slat
                    if (!isRtl && left) {
                        left += 1;
                    }
                }
                return left;
            };
            return TimelineCoords;
        }());
        // returned value is between 0 and the number of snaps
        function computeDateSnapCoverage(date, tDateProfile, dateEnv) {
            var snapDiff = dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.snapDuration);
            if (snapDiff < 0) {
                return 0;
            }
    
            if (snapDiff >= tDateProfile.snapDiffToIndex.length) {
    
                return tDateProfile.snapCnt;
            }
    
            var snapDiffInt = Math.floor(snapDiff);
            var snapCoverage = tDateProfile.snapDiffToIndex[snapDiffInt];
            if (isInt(snapCoverage)) { // not an in-between value
                snapCoverage += snapDiff - snapDiffInt; // add the remainder
            }
            else {
                // a fractional value, meaning the date is not visible
                // always round up in this case. works for start AND end dates in a range.
                snapCoverage = Math.ceil(snapCoverage);
            }
            return snapCoverage;
        }
    
        var TimelineSlatCell = /** @class */ (function (_super) {
            __extends(TimelineSlatCell, _super);
            function TimelineSlatCell() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            TimelineSlatCell.prototype.render = function () {
                var _a = this, props = _a.props, context = _a.context;
                var dateEnv = context.dateEnv, options = context.options, theme = context.theme;
                var date = props.date, tDateProfile = props.tDateProfile, isEm = props.isEm;
                var dateMeta = getDateMeta(props.date, props.todayRange, props.nowDate, props.dateProfile);
                var classNames = ['fc-timeline-slot', 'fc-timeline-slot-lane'];
                var dataAttrs = { 'data-date': dateEnv.formatIso(date, { omitTimeZoneOffset: true, omitTime: !tDateProfile.isTimeScale }) };
                var hookProps = __assign(__assign({ date: dateEnv.toDate(props.date) }, dateMeta), { view: context.viewApi });
                if (isEm) {
                    classNames.push('fc-timeline-slot-em');
    
                if (tDateProfile.isTimeScale) {
                    classNames.push(isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, props.date, tDateProfile.labelInterval)) ?
                        'fc-timeline-slot-major' :
                        'fc-timeline-slot-minor');
    
                classNames.push.apply(classNames, (props.isDay
                    ? getDayClassNames(dateMeta, theme)
                    : getSlotClassNames(dateMeta, theme)));
                return (createElement(RenderHook, { hookProps: hookProps, classNames: options.slotLaneClassNames, content: options.slotLaneContent, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount, elRef: props.elRef }, function (rootElRef, customClassNames, innerElRef, innerContent) { return (createElement("td", __assign({ ref: rootElRef, className: classNames.concat(customClassNames).join(' ') }, dataAttrs),
                    createElement("div", { ref: innerElRef }, innerContent))); }));
            };
            return TimelineSlatCell;
        }(BaseComponent));
    
        var TimelineSlatsBody = /** @class */ (function (_super) {
            __extends(TimelineSlatsBody, _super);
            function TimelineSlatsBody() {
                return _super !== null && _super.apply(this, arguments) || this;
    
            TimelineSlatsBody.prototype.render = function () {
                var props = this.props;
                var tDateProfile = props.tDateProfile, cellElRefs = props.cellElRefs;
                var slotDates = tDateProfile.slotDates, isWeekStarts = tDateProfile.isWeekStarts;
                var isDay = !tDateProfile.isTimeScale && !tDateProfile.largeUnit;
                return (createElement("tbody", null,
                    createElement("tr", null, slotDates.map(function (slotDate, i) {
                        var key = slotDate.toISOString();
                        return (createElement(TimelineSlatCell, { key: key, elRef: cellElRefs.createRef(key), date: slotDate, dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: props.nowDate, todayRange: props.todayRange, isEm: isWeekStarts[i], isDay: isDay }));
                    }))));
            };
            return TimelineSlatsBody;
        }(BaseComponent));
    
    
        var TimelineSlats = /** @class */ (function (_super) {
            __extends(TimelineSlats, _super);
            function TimelineSlats() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.rootElRef = createRef();
                _this.cellElRefs = new RefMap();
                _this.handleScrollRequest = function (request) {
                    var onScrollLeftRequest = _this.props.onScrollLeftRequest;
                    var coords = _this.coords;
                    if (onScrollLeftRequest && coords) {
                        if (request.time) {
                            var scrollLeft = coords.computeDurationLeft(request.time);
                            onScrollLeftRequest(scrollLeft);
                        }
                        return true;
                    }
    
                    return null; // best?
    
                };
                return _this;
            }
            TimelineSlats.prototype.render = function () {
                var _a = this, props = _a.props, context = _a.context;
    
                return (createElement("div", { className: "fc-timeline-slots", ref: this.rootElRef },
    
                    createElement("table", { className: context.theme.getClass('table'), style: {
                            minWidth: props.tableMinWidth,
    
                            width: props.clientWidth,
    
                        } },
                        props.tableColGroupNode,
                        createElement(TimelineSlatsBody, { cellElRefs: this.cellElRefs, dateProfile: props.dateProfile, tDateProfile: props.tDateProfile, nowDate: props.nowDate, todayRange: props.todayRange }))));
            };
            TimelineSlats.prototype.componentDidMount = function () {
                this.updateSizing();
                this.scrollResponder = this.context.createScrollResponder(this.handleScrollRequest);
            };
            TimelineSlats.prototype.componentDidUpdate = function (prevProps) {
                this.updateSizing();
                this.scrollResponder.update(prevProps.dateProfile !== this.props.dateProfile);
            };
            TimelineSlats.prototype.componentWillUnmount = function () {
                this.scrollResponder.detach();
                if (this.props.onCoords) {
                    this.props.onCoords(null);
                }
            };
            TimelineSlats.prototype.updateSizing = function () {
                var _a = this, props = _a.props, context = _a.context;
                if (props.clientWidth !== null && // is sizing stable?
    
                    this.scrollResponder
                // ^it's possible to have clientWidth immediately after mount (when returning from print view), but w/o scrollResponder
    
                ) {
                    var rootEl = this.rootElRef.current;
                    if (rootEl.offsetWidth) {
                        this.coords = new TimelineCoords(this.rootElRef.current, collectCellEls$1(this.cellElRefs.currentMap, props.tDateProfile.slotDates), props.dateProfile, props.tDateProfile, context.dateEnv, context.isRtl);
                        if (props.onCoords) {
                            props.onCoords(this.coords);
                        }
                        this.scrollResponder.update(false); // TODO: wouldn't have to do this if coords were in state
                    }
                }
            };
            TimelineSlats.prototype.positionToHit = function (leftPosition) {
                var outerCoordCache = this.coords.outerCoordCache;
                var _a = this.context, dateEnv = _a.dateEnv, isRtl = _a.isRtl;