Skip to content
Snippets Groups Projects
main.js 918 KiB
Newer Older
  • Learn to ignore specific revisions
  •             removeResizeHandler: function (handler) {
                    emitter.off('_resize', handler);
                },
                createScrollResponder: function (execFunc) {
                    return new ScrollResponder(execFunc, emitter, createDuration(viewOptions.scrollTime));
                },
                registerInteractiveComponent: registerInteractiveComponent,
    
                unregisterInteractiveComponent: unregisterInteractiveComponent,
    
        /* eslint max-classes-per-file: off */
    
        var PureComponent = /** @class */ (function (_super) {
            __extends(PureComponent, _super);
            function PureComponent() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            PureComponent.prototype.shouldComponentUpdate = function (nextProps, nextState) {
                if (this.debug) {
    
                    // eslint-disable-next-line no-console
    
                    console.log(getUnequalProps(nextProps, this.props), getUnequalProps(nextState, this.state));
                }
                return !compareObjs(this.props, nextProps, this.propEquality) ||
                    !compareObjs(this.state, nextState, this.stateEquality);
            };
            PureComponent.addPropsEquality = addPropsEquality;
            PureComponent.addStateEquality = addStateEquality;
            PureComponent.contextType = ViewContextType;
            return PureComponent;
        }(Component));
        PureComponent.prototype.propEquality = {};
        PureComponent.prototype.stateEquality = {};
        var BaseComponent = /** @class */ (function (_super) {
            __extends(BaseComponent, _super);
            function BaseComponent() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            BaseComponent.contextType = ViewContextType;
            return BaseComponent;
        }(PureComponent));
        function addPropsEquality(propEquality) {
            var hash = Object.create(this.prototype.propEquality);
            __assign(hash, propEquality);
            this.prototype.propEquality = hash;
        }
        function addStateEquality(stateEquality) {
            var hash = Object.create(this.prototype.stateEquality);
            __assign(hash, stateEquality);
            this.prototype.stateEquality = hash;
        }
        // use other one
        function setRef(ref, current) {
            if (typeof ref === 'function') {
                ref(current);
            }
            else if (ref) {
                // see https://github.com/facebook/react/issues/13029
                ref.current = current;
            }
        }
    
        function reduceEventStore(eventStore, action, eventSources, dateProfile, context) {
            switch (action.type) {
                case 'RECEIVE_EVENTS': // raw
                    return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, context);
                case 'ADD_EVENTS': // already parsed, but not expanded
                    return addEvent(eventStore, action.eventStore, // new ones
                    dateProfile ? dateProfile.activeRange : null, context);
    
                case 'RESET_EVENTS':
                    return action.eventStore;
    
                case 'MERGE_EVENTS': // already parsed and expanded
                    return mergeEventStores(eventStore, action.eventStore);
                case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
                case 'NEXT':
                case 'CHANGE_DATE':
                case 'CHANGE_VIEW_TYPE':
                    if (dateProfile) {
                        return expandRecurring(eventStore, dateProfile.activeRange, context);
                    }
    
                    return eventStore;
    
                case 'REMOVE_EVENTS':
                    return excludeSubEventStore(eventStore, action.eventStore);
                case 'REMOVE_EVENT_SOURCE':
                    return excludeEventsBySourceId(eventStore, action.sourceId);
                case 'REMOVE_ALL_EVENT_SOURCES':
    
                    return filterEventStoreDefs(eventStore, function (eventDef) { return (!eventDef.sourceId // only keep events with no source id
                    ); });
    
                case 'REMOVE_ALL_EVENTS':
                    return createEmptyEventStore();
                default:
                    return eventStore;
            }
        }
        function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, context) {
            if (eventSource && // not already removed
                fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources
            ) {
                var subset = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context);
                if (fetchRange) {
                    subset = expandRecurring(subset, fetchRange, context);
                }
                return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset);
            }
            return eventStore;
        }
        function transformRawEvents(rawEvents, eventSource, context) {
            var calEachTransform = context.options.eventDataTransform;
            var sourceEachTransform = eventSource ? eventSource.eventDataTransform : null;
            if (sourceEachTransform) {
                rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform);
            }
            if (calEachTransform) {
                rawEvents = transformEachRawEvent(rawEvents, calEachTransform);
            }
            return rawEvents;
        }
        function transformEachRawEvent(rawEvents, func) {
            var refinedEvents;
            if (!func) {
                refinedEvents = rawEvents;
            }
            else {
                refinedEvents = [];
                for (var _i = 0, rawEvents_1 = rawEvents; _i < rawEvents_1.length; _i++) {
                    var rawEvent = rawEvents_1[_i];
                    var refinedEvent = func(rawEvent);
                    if (refinedEvent) {
                        refinedEvents.push(refinedEvent);
                    }
                    else if (refinedEvent == null) {
                        refinedEvents.push(rawEvent);
                    } // if a different falsy value, do nothing
                }
            }
            return refinedEvents;
        }
        function addEvent(eventStore, subset, expandRange, context) {
            if (expandRange) {
                subset = expandRecurring(subset, expandRange, context);
            }
            return mergeEventStores(eventStore, subset);
        }
        function rezoneEventStoreDates(eventStore, oldDateEnv, newDateEnv) {
            var defs = eventStore.defs;
            var instances = mapHash(eventStore.instances, function (instance) {
                var def = defs[instance.defId];
                if (def.allDay || def.recurringDef) {
                    return instance; // isn't dependent on timezone
                }
    
                return __assign(__assign({}, instance), { range: {
                        start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)),
                        end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo)),
                    }, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo });
    
            });
            return { defs: defs, instances: instances };
        }
        function excludeEventsBySourceId(eventStore, sourceId) {
    
            return filterEventStoreDefs(eventStore, function (eventDef) { return eventDef.sourceId !== sourceId; });
    
        }
        // QUESTION: why not just return instances? do a general object-property-exclusion util
        function excludeInstances(eventStore, removals) {
            return {
                defs: eventStore.defs,
    
                instances: filterHash(eventStore.instances, function (instance) { return !removals[instance.instanceId]; }),
    
            };
        }
    
        // high-level segmenting-aware tester functions
        // ------------------------------------------------------------------------------------------------------------------------
        function isInteractionValid(interaction, context) {
            return isNewPropsValid({ eventDrag: interaction }, context); // HACK: the eventDrag props is used for ALL interactions
        }
        function isDateSelectionValid(dateSelection, context) {
            return isNewPropsValid({ dateSelection: dateSelection }, context);
        }
        function isNewPropsValid(newProps, context) {
            var calendarState = context.getCurrentData();
            var props = __assign({ businessHours: calendarState.businessHours, dateSelection: '', eventStore: calendarState.eventStore, eventUiBases: calendarState.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps);
            return (context.pluginHooks.isPropsValid || isPropsValid)(props, context);
        }
        function isPropsValid(state, context, dateSpanMeta, filterConfig) {
            if (dateSpanMeta === void 0) { dateSpanMeta = {}; }
            if (state.eventDrag && !isInteractionPropsValid(state, context, dateSpanMeta, filterConfig)) {
                return false;
            }
            if (state.dateSelection && !isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig)) {
                return false;
            }
            return true;
        }
        // Moving Event Validation
        // ------------------------------------------------------------------------------------------------------------------------
        function isInteractionPropsValid(state, context, dateSpanMeta, filterConfig) {
            var currentState = context.getCurrentData();
            var interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions
            var subjectEventStore = interaction.mutatedEvents;
            var subjectDefs = subjectEventStore.defs;
            var subjectInstances = subjectEventStore.instances;
            var subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ?
                state.eventUiBases :
    
                { '': currentState.selectionConfig });
    
            if (filterConfig) {
                subjectConfigs = mapHash(subjectConfigs, filterConfig);
            }
    
            // exclude the subject events. TODO: exclude defs too?
            var otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances);
    
            var otherDefs = otherEventStore.defs;
            var otherInstances = otherEventStore.instances;
            var otherConfigs = compileEventUis(otherDefs, state.eventUiBases);
            for (var subjectInstanceId in subjectInstances) {
                var subjectInstance = subjectInstances[subjectInstanceId];
                var subjectRange = subjectInstance.range;
                var subjectConfig = subjectConfigs[subjectInstance.defId];
                var subjectDef = subjectDefs[subjectInstance.defId];
                // constraint
                if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, context)) {
                    return false;
                }
                // overlap
                var eventOverlap = context.options.eventOverlap;
                var eventOverlapFunc = typeof eventOverlap === 'function' ? eventOverlap : null;
                for (var otherInstanceId in otherInstances) {
                    var otherInstance = otherInstances[otherInstanceId];
                    // intersect! evaluate
                    if (rangesIntersect(subjectRange, otherInstance.range)) {
                        var otherOverlap = otherConfigs[otherInstance.defId].overlap;
                        // consider the other event's overlap. only do this if the subject event is a "real" event
                        if (otherOverlap === false && interaction.isEvent) {
                            return false;
                        }
                        if (subjectConfig.overlap === false) {
                            return false;
                        }
                        if (eventOverlapFunc && !eventOverlapFunc(new EventApi(context, otherDefs[otherInstance.defId], otherInstance), // still event
    
                        new EventApi(context, subjectDef, subjectInstance))) {
    
                            return false;
                        }
                    }
                }
                // allow (a function)
                var calendarEventStore = currentState.eventStore; // need global-to-calendar, not local to component (splittable)state
                for (var _i = 0, _a = subjectConfig.allows; _i < _a.length; _i++) {
                    var subjectAllow = _a[_i];
                    var subjectDateSpan = __assign(__assign({}, dateSpanMeta), { range: subjectInstance.range, allDay: subjectDef.allDay });
                    var origDef = calendarEventStore.defs[subjectDef.defId];
                    var origInstance = calendarEventStore.instances[subjectInstanceId];
                    var eventApi = void 0;
                    if (origDef) { // was previously in the calendar
                        eventApi = new EventApi(context, origDef, origInstance);
                    }
                    else { // was an external event
                        eventApi = new EventApi(context, subjectDef); // no instance, because had no dates
                    }
                    if (!subjectAllow(buildDateSpanApiWithContext(subjectDateSpan, context), eventApi)) {
                        return false;
                    }
                }
            }
            return true;
        }
        // Date Selection Validation
        // ------------------------------------------------------------------------------------------------------------------------
        function isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig) {
            var relevantEventStore = state.eventStore;
            var relevantDefs = relevantEventStore.defs;
            var relevantInstances = relevantEventStore.instances;
            var selection = state.dateSelection;
            var selectionRange = selection.range;
            var selectionConfig = context.getCurrentData().selectionConfig;
            if (filterConfig) {
                selectionConfig = filterConfig(selectionConfig);
            }
            // constraint
            if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, context)) {
                return false;
            }
            // overlap
            var selectOverlap = context.options.selectOverlap;
            var selectOverlapFunc = typeof selectOverlap === 'function' ? selectOverlap : null;
            for (var relevantInstanceId in relevantInstances) {
                var relevantInstance = relevantInstances[relevantInstanceId];
                // intersect! evaluate
                if (rangesIntersect(selectionRange, relevantInstance.range)) {
                    if (selectionConfig.overlap === false) {
                        return false;
                    }
                    if (selectOverlapFunc && !selectOverlapFunc(new EventApi(context, relevantDefs[relevantInstance.defId], relevantInstance), null)) {
                        return false;
                    }
                }
            }
            // allow (a function)
            for (var _i = 0, _a = selectionConfig.allows; _i < _a.length; _i++) {
                var selectionAllow = _a[_i];
                var fullDateSpan = __assign(__assign({}, dateSpanMeta), selection);
                if (!selectionAllow(buildDateSpanApiWithContext(fullDateSpan, context), null)) {
                    return false;
                }
            }
            return true;
        }
        // Constraint Utils
        // ------------------------------------------------------------------------------------------------------------------------
        function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, context) {
            for (var _i = 0, constraints_1 = constraints; _i < constraints_1.length; _i++) {
                var constraint = constraints_1[_i];
                if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, context), subjectRange)) {
                    return false;
                }
            }
            return true;
        }
        function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours
        otherEventStore, // for if constraint is an even group ID
        businessHoursUnexpanded, // for if constraint is 'businessHours'
    
        context) {
    
            if (constraint === 'businessHours') {
                return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, context));
            }
    
            if (typeof constraint === 'string') { // an group ID
                return eventStoreToRanges(filterEventStoreDefs(otherEventStore, function (eventDef) { return eventDef.groupId === constraint; }));
    
            if (typeof constraint === 'object' && constraint) { // non-null object
    
                return eventStoreToRanges(expandRecurring(constraint, subjectRange, context));
            }
            return []; // if it's false
        }
        // TODO: move to event-store file?
        function eventStoreToRanges(eventStore) {
            var instances = eventStore.instances;
            var ranges = [];
            for (var instanceId in instances) {
                ranges.push(instances[instanceId].range);
            }
            return ranges;
        }
        // TODO: move to geom file?
        function anyRangesContainRange(outerRanges, innerRange) {
            for (var _i = 0, outerRanges_1 = outerRanges; _i < outerRanges_1.length; _i++) {
                var outerRange = outerRanges_1[_i];
                if (rangeContainsRange(outerRange, innerRange)) {
                    return true;
                }
            }
            return false;
        }
    
        /*
        an INTERACTABLE date component
    
        PURPOSES:
        - hook up to fg, fill, and mirror renderers
        - interface for dragging and hits
        */
        var DateComponent = /** @class */ (function (_super) {
            __extends(DateComponent, _super);
            function DateComponent() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.uid = guid();
                return _this;
            }
            // Hit System
            // -----------------------------------------------------------------------------------------------------------------
            DateComponent.prototype.prepareHits = function () {
            };
            DateComponent.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) {
                return null; // this should be abstract
            };
            // Validation
            // -----------------------------------------------------------------------------------------------------------------
            DateComponent.prototype.isInteractionValid = function (interaction) {
                var dateProfile = this.props.dateProfile; // HACK
                var instances = interaction.mutatedEvents.instances;
                if (dateProfile) { // HACK for MorePopover
                    for (var instanceId in instances) {
                        if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) {
                            return false;
                        }
                    }
                }
                return isInteractionValid(interaction, this.context);
            };
            DateComponent.prototype.isDateSelectionValid = function (selection) {
                var dateProfile = this.props.dateProfile; // HACK
                if (dateProfile && // HACK for MorePopover
                    !rangeContainsRange(dateProfile.validRange, selection.range)) {
                    return false;
                }
                return isDateSelectionValid(selection, this.context);
            };
            // Pointer Interaction Utils
            // -----------------------------------------------------------------------------------------------------------------
            DateComponent.prototype.isValidSegDownEl = function (el) {
                return !this.props.eventDrag && // HACK
                    !this.props.eventResize && // HACK
    
                    !elementClosest(el, '.fc-event-mirror');
    
            };
            DateComponent.prototype.isValidDateDownEl = function (el) {
                return !elementClosest(el, '.fc-event:not(.fc-bg-event)') &&
                    !elementClosest(el, '.fc-daygrid-more-link') && // a "more.." link
                    !elementClosest(el, 'a[data-navlink]') && // a clickable nav link
    
                    !elementClosest(el, '.fc-popover'); // hack
    
            };
            return DateComponent;
        }(BaseComponent));
    
        // TODO: easier way to add new hooks? need to update a million things
        function createPlugin(input) {
            return {
                id: guid(),
                deps: input.deps || [],
                reducers: input.reducers || [],
    
                isLoadingFuncs: input.isLoadingFuncs || [],
    
                contextInit: [].concat(input.contextInit || []),
                eventRefiners: input.eventRefiners || {},
                eventDefMemberAdders: input.eventDefMemberAdders || [],
                eventSourceRefiners: input.eventSourceRefiners || {},
                isDraggableTransformers: input.isDraggableTransformers || [],
                eventDragMutationMassagers: input.eventDragMutationMassagers || [],
                eventDefMutationAppliers: input.eventDefMutationAppliers || [],
                dateSelectionTransformers: input.dateSelectionTransformers || [],
                datePointTransforms: input.datePointTransforms || [],
                dateSpanTransforms: input.dateSpanTransforms || [],
                views: input.views || {},
                viewPropsTransformers: input.viewPropsTransformers || [],
                isPropsValid: input.isPropsValid || null,
                externalDefTransforms: input.externalDefTransforms || [],
                eventResizeJoinTransforms: input.eventResizeJoinTransforms || [],
                viewContainerAppends: input.viewContainerAppends || [],
                eventDropTransformers: input.eventDropTransformers || [],
                componentInteractions: input.componentInteractions || [],
                calendarInteractions: input.calendarInteractions || [],
                themeClasses: input.themeClasses || {},
                eventSourceDefs: input.eventSourceDefs || [],
                cmdFormatter: input.cmdFormatter,
                recurringTypes: input.recurringTypes || [],
                namedTimeZonedImpl: input.namedTimeZonedImpl,
                initialView: input.initialView || '',
                elementDraggingImpl: input.elementDraggingImpl,
                optionChangeHandlers: input.optionChangeHandlers || {},
                scrollGridImpl: input.scrollGridImpl || null,
                contentTypeHandlers: input.contentTypeHandlers || {},
                listenerRefiners: input.listenerRefiners || {},
                optionRefiners: input.optionRefiners || {},
    
                propSetHandlers: input.propSetHandlers || {},
    
            };
        }
        function buildPluginHooks(pluginDefs, globalDefs) {
            var isAdded = {};
            var hooks = {
                reducers: [],
    
                isLoadingFuncs: [],
    
                contextInit: [],
                eventRefiners: {},
                eventDefMemberAdders: [],
                eventSourceRefiners: {},
                isDraggableTransformers: [],
                eventDragMutationMassagers: [],
                eventDefMutationAppliers: [],
                dateSelectionTransformers: [],
                datePointTransforms: [],
                dateSpanTransforms: [],
                views: {},
                viewPropsTransformers: [],
                isPropsValid: null,
                externalDefTransforms: [],
                eventResizeJoinTransforms: [],
                viewContainerAppends: [],
                eventDropTransformers: [],
                componentInteractions: [],
                calendarInteractions: [],
                themeClasses: {},
                eventSourceDefs: [],
                cmdFormatter: null,
                recurringTypes: [],
                namedTimeZonedImpl: null,
                initialView: '',
                elementDraggingImpl: null,
                optionChangeHandlers: {},
                scrollGridImpl: null,
                contentTypeHandlers: {},
                listenerRefiners: {},
                optionRefiners: {},
    
                propSetHandlers: {},
    
            };
            function addDefs(defs) {
                for (var _i = 0, defs_1 = defs; _i < defs_1.length; _i++) {
                    var def = defs_1[_i];
                    if (!isAdded[def.id]) {
                        isAdded[def.id] = true;
                        addDefs(def.deps);
                        hooks = combineHooks(hooks, def);
                    }
                }
            }
            if (pluginDefs) {
                addDefs(pluginDefs);
            }
            addDefs(globalDefs);
            return hooks;
        }
        function buildBuildPluginHooks() {
            var currentOverrideDefs = [];
            var currentGlobalDefs = [];
            var currentHooks;
            return function (overrideDefs, globalDefs) {
                if (!currentHooks || !isArraysEqual(overrideDefs, currentOverrideDefs) || !isArraysEqual(globalDefs, currentGlobalDefs)) {
                    currentHooks = buildPluginHooks(overrideDefs, globalDefs);
                }
                currentOverrideDefs = overrideDefs;
                currentGlobalDefs = globalDefs;
                return currentHooks;
            };
        }
        function combineHooks(hooks0, hooks1) {
            return {
                reducers: hooks0.reducers.concat(hooks1.reducers),
    
                isLoadingFuncs: hooks0.isLoadingFuncs.concat(hooks1.isLoadingFuncs),
    
                contextInit: hooks0.contextInit.concat(hooks1.contextInit),
                eventRefiners: __assign(__assign({}, hooks0.eventRefiners), hooks1.eventRefiners),
                eventDefMemberAdders: hooks0.eventDefMemberAdders.concat(hooks1.eventDefMemberAdders),
                eventSourceRefiners: __assign(__assign({}, hooks0.eventSourceRefiners), hooks1.eventSourceRefiners),
                isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers),
                eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers),
                eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers),
                dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers),
                datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms),
                dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms),
                views: __assign(__assign({}, hooks0.views), hooks1.views),
                viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers),
                isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid,
                externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms),
                eventResizeJoinTransforms: hooks0.eventResizeJoinTransforms.concat(hooks1.eventResizeJoinTransforms),
                viewContainerAppends: hooks0.viewContainerAppends.concat(hooks1.viewContainerAppends),
                eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers),
                calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions),
                componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions),
                themeClasses: __assign(__assign({}, hooks0.themeClasses), hooks1.themeClasses),
                eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs),
                cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter,
                recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes),
                namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl,
                initialView: hooks0.initialView || hooks1.initialView,
                elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl,
                optionChangeHandlers: __assign(__assign({}, hooks0.optionChangeHandlers), hooks1.optionChangeHandlers),
                scrollGridImpl: hooks1.scrollGridImpl || hooks0.scrollGridImpl,
                contentTypeHandlers: __assign(__assign({}, hooks0.contentTypeHandlers), hooks1.contentTypeHandlers),
                listenerRefiners: __assign(__assign({}, hooks0.listenerRefiners), hooks1.listenerRefiners),
                optionRefiners: __assign(__assign({}, hooks0.optionRefiners), hooks1.optionRefiners),
    
                propSetHandlers: __assign(__assign({}, hooks0.propSetHandlers), hooks1.propSetHandlers),
    
            };
        }
    
        var StandardTheme = /** @class */ (function (_super) {
            __extends(StandardTheme, _super);
            function StandardTheme() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            return StandardTheme;
        }(Theme));
        StandardTheme.prototype.classes = {
            root: 'fc-theme-standard',
            tableCellShaded: 'fc-cell-shaded',
            buttonGroup: 'fc-button-group',
            button: 'fc-button fc-button-primary',
    
            buttonActive: 'fc-button-active',
    
        };
        StandardTheme.prototype.baseIconClass = 'fc-icon';
        StandardTheme.prototype.iconClasses = {
            close: 'fc-icon-x',
            prev: 'fc-icon-chevron-left',
            next: 'fc-icon-chevron-right',
            prevYear: 'fc-icon-chevrons-left',
    
            nextYear: 'fc-icon-chevrons-right',
    
        };
        StandardTheme.prototype.rtlIconClasses = {
            prev: 'fc-icon-chevron-right',
            next: 'fc-icon-chevron-left',
            prevYear: 'fc-icon-chevrons-right',
    
            nextYear: 'fc-icon-chevrons-left',
    
        };
        StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; // TODO: make TS-friendly
        StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon';
        StandardTheme.prototype.iconOverridePrefix = 'fc-icon-';
    
        function compileViewDefs(defaultConfigs, overrideConfigs) {
            var hash = {};
            var viewType;
            for (viewType in defaultConfigs) {
                ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
            }
            for (viewType in overrideConfigs) {
                ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
            }
            return hash;
        }
        function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
            if (hash[viewType]) {
                return hash[viewType];
            }
            var viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs);
            if (viewDef) {
                hash[viewType] = viewDef;
            }
            return viewDef;
        }
        function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
            var defaultConfig = defaultConfigs[viewType];
            var overrideConfig = overrideConfigs[viewType];
    
            var queryProp = function (name) { return ((defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] :
                ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null)); };
    
            var theComponent = queryProp('component');
            var superType = queryProp('superType');
            var superDef = null;
            if (superType) {
                if (superType === viewType) {
                    throw new Error('Can\'t have a custom view type that references itself');
                }
                superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs);
            }
            if (!theComponent && superDef) {
                theComponent = superDef.component;
            }
            if (!theComponent) {
                return null; // don't throw a warning, might be settings for a single-unit view
            }
            return {
                type: viewType,
                component: theComponent,
                defaults: __assign(__assign({}, (superDef ? superDef.defaults : {})), (defaultConfig ? defaultConfig.rawOptions : {})),
    
                overrides: __assign(__assign({}, (superDef ? superDef.overrides : {})), (overrideConfig ? overrideConfig.rawOptions : {})),
    
        /* eslint max-classes-per-file: off */
    
        // NOTE: in JSX, you should always use this class with <HookProps> arg. otherwise, will default to any???
        var RenderHook = /** @class */ (function (_super) {
            __extends(RenderHook, _super);
            function RenderHook() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.rootElRef = createRef();
                _this.handleRootEl = function (el) {
                    setRef(_this.rootElRef, el);
                    if (_this.props.elRef) {
                        setRef(_this.props.elRef, el);
                    }
                };
                return _this;
            }
            RenderHook.prototype.render = function () {
                var _this = this;
                var props = this.props;
                var hookProps = props.hookProps;
                return (createElement(MountHook, { hookProps: hookProps, didMount: props.didMount, willUnmount: props.willUnmount, elRef: this.handleRootEl }, function (rootElRef) { return (createElement(ContentHook, { hookProps: hookProps, content: props.content, defaultContent: props.defaultContent, backupElRef: _this.rootElRef }, function (innerElRef, innerContent) { return props.children(rootElRef, normalizeClassNames(props.classNames, hookProps), innerElRef, innerContent); })); }));
            };
            return RenderHook;
        }(BaseComponent));
    
        // TODO: rename to be about function, not default. use in above type
    
        // for forcing rerender of components that use the ContentHook
        var CustomContentRenderContext = createContext$1(0);
    
        function ContentHook(props) {
            return (createElement(CustomContentRenderContext.Consumer, null, function (renderId) { return (createElement(ContentHookInner, __assign({ renderId: renderId }, props))); }));
        }
        var ContentHookInner = /** @class */ (function (_super) {
            __extends(ContentHookInner, _super);
            function ContentHookInner() {
    
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.innerElRef = createRef();
                return _this;
            }
    
            ContentHookInner.prototype.render = function () {
                return this.props.children(this.innerElRef, this.renderInnerContent());
    
            ContentHookInner.prototype.componentDidMount = function () {
    
                this.updateCustomContent();
            };
    
            ContentHookInner.prototype.componentDidUpdate = function () {
    
                this.updateCustomContent();
            };
    
            ContentHookInner.prototype.componentWillUnmount = function () {
                if (this.customContentInfo && this.customContentInfo.destroy) {
                    this.customContentInfo.destroy();
                }
            };
            ContentHookInner.prototype.renderInnerContent = function () {
    
                var contentTypeHandlers = this.context.pluginHooks.contentTypeHandlers;
                var _a = this, props = _a.props, customContentInfo = _a.customContentInfo;
                var rawVal = props.content;
                var innerContent = normalizeContent(rawVal, props.hookProps);
                var innerContentVDom = null;
                if (innerContent === undefined) { // use the default
                    innerContent = normalizeContent(props.defaultContent, props.hookProps);
                }
                if (innerContent !== undefined) { // we allow custom content handlers to return nothing
                    if (customContentInfo) {
                        customContentInfo.contentVal = innerContent[customContentInfo.contentKey];
                    }
                    else if (typeof innerContent === 'object') {
                        // look for a prop that would indicate a custom content handler is needed
                        for (var contentKey in contentTypeHandlers) {
                            if (innerContent[contentKey] !== undefined) {
    
                                var stuff = contentTypeHandlers[contentKey]();
                                customContentInfo = this.customContentInfo = __assign({ contentKey: contentKey, contentVal: innerContent[contentKey] }, stuff);
    
                                break;
                            }
                        }
                    }
                    if (customContentInfo) {
                        innerContentVDom = []; // signal that something was specified
                    }
                    else {
                        innerContentVDom = innerContent; // assume a [p]react vdom node. use it
                    }
                }
                return innerContentVDom;
            };
    
            ContentHookInner.prototype.updateCustomContent = function () {
    
                if (this.customContentInfo) {
    
                    this.customContentInfo.render(this.innerElRef.current || this.props.backupElRef.current, // the element to render into
    
                    this.customContentInfo.contentVal);
                }
            };
    
            return ContentHookInner;
    
        }(BaseComponent));
        var MountHook = /** @class */ (function (_super) {
            __extends(MountHook, _super);
            function MountHook() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.handleRootEl = function (rootEl) {
                    _this.rootEl = rootEl;
                    if (_this.props.elRef) {
                        setRef(_this.props.elRef, rootEl);
                    }
                };
                return _this;
            }
            MountHook.prototype.render = function () {
                return this.props.children(this.handleRootEl);
            };
            MountHook.prototype.componentDidMount = function () {
                var callback = this.props.didMount;
    
                if (callback) {
                    callback(__assign(__assign({}, this.props.hookProps), { el: this.rootEl }));
                }
    
            };
            MountHook.prototype.componentWillUnmount = function () {
                var callback = this.props.willUnmount;
    
                if (callback) {
                    callback(__assign(__assign({}, this.props.hookProps), { el: this.rootEl }));
                }
    
            };
            return MountHook;
        }(BaseComponent));
        function buildClassNameNormalizer() {
            var currentGenerator;
            var currentHookProps;
            var currentClassNames = [];
            return function (generator, hookProps) {
                if (!currentHookProps || !isPropsEqual(currentHookProps, hookProps) || generator !== currentGenerator) {
                    currentGenerator = generator;
                    currentHookProps = hookProps;
                    currentClassNames = normalizeClassNames(generator, hookProps);
                }
                return currentClassNames;
            };
        }
        function normalizeClassNames(classNames, hookProps) {
            if (typeof classNames === 'function') {
                classNames = classNames(hookProps);
            }
            return parseClassNames(classNames);
        }
        function normalizeContent(input, hookProps) {
            if (typeof input === 'function') {
                return input(hookProps, createElement); // give the function the vdom-creation func
            }
    
            return input;
    
        }
    
        var ViewRoot = /** @class */ (function (_super) {
            __extends(ViewRoot, _super);
            function ViewRoot() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.normalizeClassNames = buildClassNameNormalizer();
                return _this;
            }
            ViewRoot.prototype.render = function () {
                var _a = this, props = _a.props, context = _a.context;
                var options = context.options;
                var hookProps = { view: context.viewApi };
                var customClassNames = this.normalizeClassNames(options.viewClassNames, hookProps);
                return (createElement(MountHook, { hookProps: hookProps, didMount: options.viewDidMount, willUnmount: options.viewWillUnmount, elRef: props.elRef }, function (rootElRef) { return props.children(rootElRef, ["fc-" + props.viewSpec.type + "-view", 'fc-view'].concat(customClassNames)); }));
            };
            return ViewRoot;
        }(BaseComponent));
    
        function parseViewConfigs(inputs) {
            return mapHash(inputs, parseViewConfig);
        }
        function parseViewConfig(input) {
            var rawOptions = typeof input === 'function' ?
                { component: input } :
                input;
            var component = rawOptions.component;
            if (rawOptions.content) {
                component = createViewHookComponent(rawOptions);
                // TODO: remove content/classNames/didMount/etc from options?
            }
            return {
                superType: rawOptions.type,
                component: component,
    
                rawOptions: rawOptions,
    
            };
        }
        function createViewHookComponent(options) {
    
            return function (viewProps) { return (createElement(ViewContextType.Consumer, null, function (context) { return (createElement(ViewRoot, { viewSpec: context.viewSpec }, function (viewElRef, viewClassNames) {
                var hookProps = __assign(__assign({}, viewProps), { nextDayThreshold: context.options.nextDayThreshold });
                return (createElement(RenderHook, { hookProps: hookProps, classNames: options.classNames, content: options.content, didMount: options.didMount, willUnmount: options.willUnmount, elRef: viewElRef }, function (rootElRef, customClassNames, innerElRef, innerContent) { return (createElement("div", { className: viewClassNames.concat(customClassNames).join(' '), ref: rootElRef }, innerContent)); }));
            })); })); };
    
        }
    
        function buildViewSpecs(defaultInputs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
            var defaultConfigs = parseViewConfigs(defaultInputs);
            var overrideConfigs = parseViewConfigs(optionOverrides.views);
            var viewDefs = compileViewDefs(defaultConfigs, overrideConfigs);
    
            return mapHash(viewDefs, function (viewDef) { return buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults); });
    
        }
        function buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
            var durationInput = viewDef.overrides.duration ||
                viewDef.defaults.duration ||
                dynamicOptionOverrides.duration ||
                optionOverrides.duration;
            var duration = null;
            var durationUnit = '';
            var singleUnit = '';
            var singleUnitOverrides = {};
            if (durationInput) {
                duration = createDurationCached(durationInput);
                if (duration) { // valid?
                    var denom = greatestDurationDenominator(duration);
                    durationUnit = denom.unit;
                    if (denom.value === 1) {
                        singleUnit = durationUnit;
                        singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].rawOptions : {};
                    }
                }
            }
            var queryButtonText = function (optionsSubset) {
                var buttonTextMap = optionsSubset.buttonText || {};
                var buttonTextKey = viewDef.defaults.buttonTextKey;
                if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) {
                    return buttonTextMap[buttonTextKey];
                }
                if (buttonTextMap[viewDef.type] != null) {
                    return buttonTextMap[viewDef.type];
                }
                if (buttonTextMap[singleUnit] != null) {
                    return buttonTextMap[singleUnit];
                }
    
                return null;
    
            };
            return {
                type: viewDef.type,
                component: viewDef.component,
                duration: duration,
                durationUnit: durationUnit,
                singleUnit: singleUnit,
                optionDefaults: viewDef.defaults,
                optionOverrides: __assign(__assign({}, singleUnitOverrides), viewDef.overrides),
                buttonTextOverride: queryButtonText(dynamicOptionOverrides) ||
                    queryButtonText(optionOverrides) || // constructor-specified buttonText lookup hash takes precedence
                    viewDef.overrides.buttonText,
                buttonTextDefault: queryButtonText(localeDefaults) ||
                    viewDef.defaults.buttonText ||
                    queryButtonText(BASE_OPTION_DEFAULTS) ||
    
                    viewDef.type,
    
            };
        }
        // hack to get memoization working
        var durationInputMap = {};
        function createDurationCached(durationInput) {
            var json = JSON.stringify(durationInput);
            var res = durationInputMap[json];
            if (res === undefined) {
                res = createDuration(durationInput);
                durationInputMap[json] = res;
            }
            return res;
        }
    
        var DateProfileGenerator = /** @class */ (function () {
            function DateProfileGenerator(props) {
                this.props = props;
                this.nowDate = getNow(props.nowInput, props.dateEnv);
                this.initHiddenDays();
            }
            /* Date Range Computation
            ------------------------------------------------------------------------------------------------------------------*/
            // Builds a structure with info about what the dates/ranges will be for the "prev" view.
            DateProfileGenerator.prototype.buildPrev = function (currentDateProfile, currentDate, forceToValid) {
                var dateEnv = this.props.dateEnv;
                var prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
                currentDateProfile.dateIncrement);
                return this.build(prevDate, -1, forceToValid);
            };
            // Builds a structure with info about what the dates/ranges will be for the "next" view.
            DateProfileGenerator.prototype.buildNext = function (currentDateProfile, currentDate, forceToValid) {
                var dateEnv = this.props.dateEnv;
                var nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
                currentDateProfile.dateIncrement);
                return this.build(nextDate, 1, forceToValid);
            };
            // Builds a structure holding dates/ranges for rendering around the given date.
            // Optional direction param indicates whether the date is being incremented/decremented
            // from its previous value. decremented = -1, incremented = 1 (default).
            DateProfileGenerator.prototype.build = function (currentDate, direction, forceToValid) {
                if (forceToValid === void 0) { forceToValid = true; }
                var props = this.props;
                var validRange;
                var currentInfo;
                var isRangeAllDay;
                var renderRange;
                var activeRange;
                var isValid;
                validRange = this.buildValidRange();
                validRange = this.trimHiddenDays(validRange);
                if (forceToValid) {
                    currentDate = constrainMarkerToRange(currentDate, validRange);
                }
                currentInfo = this.buildCurrentRangeInfo(currentDate, direction);
                isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit);
                renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay);
                renderRange = this.trimHiddenDays(renderRange);
                activeRange = renderRange;
                if (!props.showNonCurrentDates) {
                    activeRange = intersectRanges(activeRange, currentInfo.range);
                }
                activeRange = this.adjustActiveRange(activeRange);
                activeRange = intersectRanges(activeRange, validRange); // might return null
                // it's invalid if the originally requested date is not contained,
                // or if the range is completely outside of the valid range.
                isValid = rangesIntersect(currentInfo.range, validRange);
                return {
                    // constraint for where prev/next operations can go and where events can be dragged/resized to.
                    // an object with optional start and end properties.
                    validRange: validRange,
                    // range the view is formally responsible for.
                    // for example, a month view might have 1st-31st, excluding padded dates
                    currentRange: currentInfo.range,
                    // name of largest unit being displayed, like "month" or "week"
                    currentRangeUnit: currentInfo.unit,
                    isRangeAllDay: isRangeAllDay,
                    // dates that display events and accept drag-n-drop
                    // will be `null` if no dates accept events
                    activeRange: activeRange,
                    // date range with a rendered skeleton
                    // includes not-active days that need some sort of DOM
                    renderRange: renderRange,
                    // Duration object that denotes the first visible time of any given day
                    slotMinTime: props.slotMinTime,
                    // Duration object that denotes the exclusive visible end time of any given day
                    slotMaxTime: props.slotMaxTime,
                    isValid: isValid,
                    // how far the current date will move for a prev/next operation
    
                    dateIncrement: this.buildDateIncrement(currentInfo.duration),
    
                };
            };
            // Builds an object with optional start/end properties.
            // Indicates the minimum/maximum dates to display.
            // not responsible for trimming hidden days.
            DateProfileGenerator.prototype.buildValidRange = function () {
                var input = this.props.validRangeInput;
                var simpleInput = typeof input === 'function'
                    ? input.call(this.props.calendarApi, this.nowDate)
                    : input;
                return this.refineRange(simpleInput) ||
                    { start: null, end: null }; // completely open-ended
            };
            // Builds a structure with info about the "current" range, the range that is
            // highlighted as being the current month for example.
            // See build() for a description of `direction`.
            // Guaranteed to have `range` and `unit` properties. `duration` is optional.
            DateProfileGenerator.prototype.buildCurrentRangeInfo = function (date, direction) {
                var props = this.props;
                var duration = null;
                var unit = null;
                var range = null;
                var dayCount;
                if (props.duration) {
                    duration = props.duration;
                    unit = props.durationUnit;
                    range = this.buildRangeFromDuration(date, direction, duration, unit);
                }
                else if ((dayCount = this.props.dayCount)) {
                    unit = 'day';
                    range = this.buildRangeFromDayCount(date, direction, dayCount);
                }
                else if ((range = this.buildCustomVisibleRange(date))) {
                    unit = props.dateEnv.greatestWholeUnit(range.start, range.end).unit;
                }