Skip to content
Snippets Groups Projects
main.js 918 KiB
Newer Older
  • Learn to ignore specific revisions
  •             var tDateProfile = this.props.tDateProfile;
                var slatIndex = outerCoordCache.leftToIndex(leftPosition);
                if (slatIndex != null) {
                    // somewhat similar to what TimeGrid does. consolidate?
                    var slatWidth = outerCoordCache.getWidth(slatIndex);
                    var partial = isRtl ?
                        (outerCoordCache.rights[slatIndex] - leftPosition) / slatWidth :
                        (leftPosition - outerCoordCache.lefts[slatIndex]) / slatWidth;
                    var localSnapIndex = Math.floor(partial * tDateProfile.snapsPerSlot);
                    var start = dateEnv.add(tDateProfile.slotDates[slatIndex], multiplyDuration(tDateProfile.snapDuration, localSnapIndex));
                    var end = dateEnv.add(start, tDateProfile.snapDuration);
                    return {
                        dateSpan: {
                            range: { start: start, end: end },
    
                            allDay: !this.props.tDateProfile.isTimeScale,
    
                        },
                        dayEl: this.cellElRefs.currentMap[slatIndex],
                        left: outerCoordCache.lefts[slatIndex],
    
                        right: outerCoordCache.rights[slatIndex],
    
                    };
                }
                return null;
            };
            return TimelineSlats;
        }(BaseComponent));
        function collectCellEls$1(elMap, slotDates) {
            return slotDates.map(function (slotDate) {
                var key = slotDate.toISOString();
                return elMap[key];
            });
        }
    
        var TimelineLaneBg = /** @class */ (function (_super) {
            __extends(TimelineLaneBg, _super);
            function TimelineLaneBg() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            TimelineLaneBg.prototype.render = function () {
                var props = this.props;
                var highlightSeg = [].concat(props.eventResizeSegs, props.dateSelectionSegs);
    
                return props.timelineCoords && (createElement("div", { className: "fc-timeline-bg" },
    
                    this.renderSegs(props.businessHourSegs || [], props.timelineCoords, 'non-business'),
                    this.renderSegs(props.bgEventSegs || [], props.timelineCoords, 'bg-event'),
                    this.renderSegs(highlightSeg, props.timelineCoords, 'highlight')));
            };
            TimelineLaneBg.prototype.renderSegs = function (segs, timelineCoords, fillType) {
                var _a = this.props, todayRange = _a.todayRange, nowDate = _a.nowDate;
                var children = segs.map(function (seg) {
                    var coords = timelineCoords.rangeToCoords(seg); // seg has { start, end }
    
                    return (createElement("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-timeline-bg-harness", style: {
    
                            right: -coords.right,
    
                        } }, fillType === 'bg-event' ?
                        createElement(BgEvent, __assign({ seg: seg }, getSegMeta(seg, todayRange, nowDate))) :
                        renderFill(fillType)));
                });
                return createElement(Fragment, null, children);
            };
            return TimelineLaneBg;
        }(BaseComponent));
    
        var TimelineLaneSlicer = /** @class */ (function (_super) {
            __extends(TimelineLaneSlicer, _super);
            function TimelineLaneSlicer() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            TimelineLaneSlicer.prototype.sliceRange = function (origRange, dateProfile, dateProfileGenerator, tDateProfile, dateEnv) {
                var normalRange = normalizeRange(origRange, tDateProfile, dateEnv);
                var segs = [];
                // protect against when the span is entirely in an invalid date region
    
                if (computeDateSnapCoverage(normalRange.start, tDateProfile, dateEnv)
                    < computeDateSnapCoverage(normalRange.end, tDateProfile, dateEnv)) {
    
                    // intersect the footprint's range with the grid's range
                    var slicedRange = intersectRanges(normalRange, tDateProfile.normalizedRange);
                    if (slicedRange) {
                        segs.push({
                            start: slicedRange.start,
                            end: slicedRange.end,
    
                            isStart: slicedRange.start.valueOf() === normalRange.start.valueOf()
                                && isValidDate$1(slicedRange.start, tDateProfile, dateProfile, dateProfileGenerator),
                            isEnd: slicedRange.end.valueOf() === normalRange.end.valueOf()
                                && isValidDate$1(addMs(slicedRange.end, -1), tDateProfile, dateProfile, dateProfileGenerator),
    
                        });
                    }
                }
                return segs;
            };
            return TimelineLaneSlicer;
        }(Slicer));
    
        var DEFAULT_TIME_FORMAT$2 = createFormatter({
            hour: 'numeric',
            minute: '2-digit',
            omitZeroMinute: true,
    
            meridiem: 'narrow',
    
        });
        var TimelineEvent = /** @class */ (function (_super) {
            __extends(TimelineEvent, _super);
            function TimelineEvent() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            TimelineEvent.prototype.render = function () {
                var props = this.props;
                return (createElement(StandardEvent, __assign({}, props, { extraClassNames: ['fc-timeline-event', 'fc-h-event'], defaultTimeFormat: DEFAULT_TIME_FORMAT$2, defaultDisplayEventTime: !props.isTimeScale })));
            };
            return TimelineEvent;
        }(BaseComponent));
    
        function computeSegHorizontals$1(segs, timelineCoords) {
            var horizontals = {};
            if (timelineCoords) {
                for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
                    var seg = segs_1[_i];
                    var instanceId = seg.eventRange.instance.instanceId;
                    horizontals[instanceId] = timelineCoords.rangeToCoords(seg); // seg has { start, end }
                }
            }
            return horizontals;
        }
        function computeSegVerticals$1(segs, eventOrderSpecs, dimHash) {
            var placements = []; // sorted by top
            var maxBottom = 0;
            if (dimHash) { // protection for if dims not computed yet
                segs = sortEventSegs(segs, eventOrderSpecs);
                for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
                    var seg = segs_2[_i];
                    var key = seg.eventRange.instance.instanceId;
                    var dims = dimHash[key];
                    if (dims) { // MORE-link protection
                        var top_1 = 0;
                        var insertI = 0; // where to start searching for an insert position
    
                        for (var i = 0; i < placements.length; i += 1) { // loop through existing placements
    
                            var placement = placements[i];
                            if (testCollide(dims, top_1, placement.dims, placement.top)) {
                                top_1 = placement.top + placement.dims.height;
                                insertI = i;
                            }
                        }
                        // move insertI along to be after the placement whos top is below the current top
                        while (insertI < placements.length && top_1 >= placements[insertI].top) {
    
                            insertI += 1;
    
                        }
                        placements.splice(insertI, 0, { key: key, dims: dims, top: top_1 }); // insert
                        maxBottom = Math.max(maxBottom, top_1 + dims.height);
                    }
                }
            }
            var topHash = {};
            for (var _a = 0, placements_1 = placements; _a < placements_1.length; _a++) {
                var placement = placements_1[_a];
                topHash[placement.key] = placement.top;
            }
            return { segTops: topHash, height: maxBottom };
        }
        function testCollide(dims0, top0, dims1, top1) {
            return dims0.right > dims1.left &&
                dims0.left < dims1.right &&
                top0 + dims0.height > top1 &&
                top0 < top1 + dims1.height;
        }
    
        var TimelineLane = /** @class */ (function (_super) {
            __extends(TimelineLane, _super);
            function TimelineLane() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.slicer = new TimelineLaneSlicer();
                _this.computeFgSegHorizontals = memoize(computeSegHorizontals$1); // only for fg event segs, not mirror
                _this.computeSegVerticals = memoize(computeSegVerticals$1);
                _this.harnessElRefs = new RefMap();
                _this.innerElRef = createRef();
                _this.state = {
    
                    segDims: null,
    
                };
                return _this;
            }
            TimelineLane.prototype.render = function () {
                var _a = this, props = _a.props, state = _a.state, context = _a.context;
                var dateProfile = props.dateProfile, tDateProfile = props.tDateProfile;
                var slicedProps = this.slicer.sliceProps(props, dateProfile, tDateProfile.isTimeScale ? null : props.nextDayThreshold, context, // wish we didn't have to pass in the rest of the args...
                dateProfile, context.dateProfileGenerator, tDateProfile, context.dateEnv);
                var mirrorSegs = (slicedProps.eventDrag ? slicedProps.eventDrag.segs : null) ||
                    (slicedProps.eventResize ? slicedProps.eventResize.segs : null) ||
                    [];
                var segHorizontals = this.computeFgSegHorizontals(slicedProps.fgEventSegs, props.timelineCoords); // ONLY for non-mirror. needed?
                var _b = this.computeSegVerticals(slicedProps.fgEventSegs, context.options.eventOrder, state.segDims), segTops = _b.segTops, height = _b.height;
                var hiddenSegs = // TODO: more convenient
                 (slicedProps.eventDrag ? slicedProps.eventDrag.affectedInstances : null) ||
                    (slicedProps.eventResize ? slicedProps.eventResize.affectedInstances : null) ||
                    {};
                return (createElement(Fragment, null,
                    createElement(TimelineLaneBg, { businessHourSegs: slicedProps.businessHourSegs, bgEventSegs: slicedProps.bgEventSegs, timelineCoords: props.timelineCoords, eventResizeSegs: slicedProps.eventResize ? slicedProps.eventResize.segs : [] /* bad new empty array? */, dateSelectionSegs: slicedProps.dateSelectionSegs, nowDate: props.nowDate, todayRange: props.todayRange }),
    
                    createElement("div", { className: "fc-timeline-events fc-scrollgrid-sync-inner", ref: this.innerElRef, style: { height: height /* computed by computeSegVerticals */ } },
    
                        this.renderFgSegs(slicedProps.fgEventSegs, segHorizontals, segTops, hiddenSegs, false, false, false),
                        this.renderFgSegs(mirrorSegs, computeSegHorizontals$1(mirrorSegs, props.timelineCoords), // not memoized
                        segTops, // reuse same tops for mirror
    
                        {}, Boolean(slicedProps.eventDrag), Boolean(slicedProps.eventResize), false))));
    
            };
            TimelineLane.prototype.componentDidMount = function () {
                this.updateSize();
            };
            TimelineLane.prototype.componentDidUpdate = function (prevProps, prevState) {
                if (prevProps.eventStore !== this.props.eventStore ||
                    prevProps.timelineCoords !== this.props.timelineCoords
                // won't trigger on a segDims change
                ) {
                    this.updateSize();
                }
            };
            TimelineLane.prototype.updateSize = function () {
                var _this = this;
                var props = this.props;
                var timelineCoords = props.timelineCoords;
                if (props.onHeightChange) {
                    props.onHeightChange(this.innerElRef.current, false);
                }
                if (timelineCoords) {
                    var originRect_1 = timelineCoords.slatRootEl.getBoundingClientRect();
                    this.setState({
                        segDims: mapHash(this.harnessElRefs.currentMap, function (harnessEl) {
                            var harnessRect = harnessEl.getBoundingClientRect();
                            return {
                                left: Math.round(harnessRect.left - originRect_1.left),
                                right: Math.round(harnessRect.right - originRect_1.left),
    
                                height: Math.round(harnessRect.height),
    
                    }, function () {
                        if (props.onHeightChange) {
                            props.onHeightChange(_this.innerElRef.current, true);
                        }
                    });
                }
            };
            TimelineLane.prototype.renderFgSegs = function (segs, segHorizontals, segTops, hiddenSegs, isDragging, isResizing, isDateSelecting) {
                var _this = this;
                var _a = this, harnessElRefs = _a.harnessElRefs, props = _a.props;
                var isMirror = isDragging || isResizing || isDateSelecting;
                return (createElement(Fragment, null, segs.map(function (seg) {
                    var instanceId = seg.eventRange.instance.instanceId;
                    var horizontalCoords = segHorizontals[instanceId];
                    var top = segTops[instanceId];
    
                    return (createElement("div", { key: instanceId, ref: isMirror ? null : harnessElRefs.createRef(instanceId), className: "fc-timeline-event-harness", style: {
    
                            left: horizontalCoords ? horizontalCoords.left : '',
                            right: horizontalCoords ? -horizontalCoords.right : '',
                            top: top != null ? top : '',
    
                            visibility: hiddenSegs[instanceId] ? 'hidden' : '' /* wtf, file @types/react bug */,
    
                        } },
                        createElement(TimelineEvent, __assign({ isTimeScale: _this.props.tDateProfile.isTimeScale, seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === _this.props.eventSelection /* TODO: bad for mirror? */ }, getSegMeta(seg, props.todayRange, props.nowDate)))));
                })));
            };
            return TimelineLane;
        }(BaseComponent));
    
        var TimelineGrid = /** @class */ (function (_super) {
            __extends(TimelineGrid, _super);
            function TimelineGrid() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.slatsRef = createRef();
                _this.state = {
    
                    coords: null,
    
                };
                _this.handeEl = function (el) {
                    if (el) {
                        _this.context.registerInteractiveComponent(_this, { el: el });
                    }
                    else {
                        _this.context.unregisterInteractiveComponent(_this);
                    }
                };
                _this.handleCoords = function (coords) {
                    _this.setState({ coords: coords });
                    if (_this.props.onSlatCoords) {
                        _this.props.onSlatCoords(coords);
                    }
                };
                return _this;
            }
            TimelineGrid.prototype.render = function () {
                var _this = this;
                var _a = this, props = _a.props, state = _a.state, context = _a.context;
                var options = context.options;
                var dateProfile = props.dateProfile, tDateProfile = props.tDateProfile;
                var timerUnit = greatestDurationDenominator(tDateProfile.slotDuration).unit;
    
                return (createElement("div", { className: "fc-timeline-body", ref: this.handeEl, style: {
    
                        minWidth: props.tableMinWidth,
                        height: props.clientHeight,
    
                        width: props.clientWidth,
    
                    } },
                    createElement(NowTimer, { unit: timerUnit }, function (nowDate, todayRange) { return (createElement(Fragment, null,
                        createElement(TimelineSlats, { ref: _this.slatsRef, dateProfile: dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange, clientWidth: props.clientWidth, tableColGroupNode: props.tableColGroupNode, tableMinWidth: props.tableMinWidth, onCoords: _this.handleCoords, onScrollLeftRequest: props.onScrollLeftRequest }),
                        createElement(TimelineLane, { dateProfile: dateProfile, tDateProfile: props.tDateProfile, nowDate: nowDate, todayRange: todayRange, nextDayThreshold: options.nextDayThreshold, businessHours: props.businessHours, eventStore: props.eventStore, eventUiBases: props.eventUiBases, dateSelection: props.dateSelection, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, timelineCoords: state.coords }),
    
                        (options.nowIndicator && state.coords && state.coords.isDateInRange(nowDate)) && (createElement("div", { className: "fc-timeline-now-indicator-container" },
                            createElement(NowIndicatorRoot, { isAxis: false, date: nowDate }, function (rootElRef, classNames, innerElRef, innerContent) { return (createElement("div", { ref: rootElRef, className: ['fc-timeline-now-indicator-line'].concat(classNames).join(' '), style: { left: state.coords.dateToCoord(nowDate) } }, innerContent)); }))))); })));
    
            };
            // Hit System
            // ------------------------------------------------------------------------------------------
            TimelineGrid.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) {
                var slats = this.slatsRef.current;
                var slatHit = slats.positionToHit(positionLeft);
                if (slatHit) {
                    return {
                        component: this,
                        dateSpan: slatHit.dateSpan,
                        rect: {
                            left: slatHit.left,
                            right: slatHit.right,
                            top: 0,
    
                            bottom: elHeight,
    
                return null;
    
            };
            return TimelineGrid;
        }(DateComponent));
    
        var TimelineView = /** @class */ (function (_super) {
            __extends(TimelineView, _super);
            function TimelineView() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.buildTimelineDateProfile = memoize(buildTimelineDateProfile);
                _this.scrollGridRef = createRef();
                _this.state = {
                    slatCoords: null,
    
                    slotCushionMaxWidth: null,
    
                };
                _this.handleSlatCoords = function (slatCoords) {
                    _this.setState({ slatCoords: slatCoords });
                };
                _this.handleScrollLeftRequest = function (scrollLeft) {
                    var scrollGrid = _this.scrollGridRef.current;
                    scrollGrid.forceScrollLeft(0, scrollLeft);
                };
                _this.handleMaxCushionWidth = function (slotCushionMaxWidth) {
                    _this.setState({
    
                        slotCushionMaxWidth: Math.ceil(slotCushionMaxWidth),
    
                    });
                };
                return _this;
            }
            TimelineView.prototype.render = function () {
                var _this = this;
                var _a = this, props = _a.props, state = _a.state, context = _a.context;
                var options = context.options;
                var stickyHeaderDates = !props.forPrint && getStickyHeaderDates(options);
                var stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(options);
                var tDateProfile = this.buildTimelineDateProfile(props.dateProfile, context.dateEnv, options, context.dateProfileGenerator);
                var extraClassNames = [
                    'fc-timeline',
    
                    options.eventOverlap === false ? 'fc-timeline-overlap-disabled' : '',
    
                ];
                var slotMinWidth = options.slotMinWidth;
                var slatCols = buildSlatCols(tDateProfile, slotMinWidth || this.computeFallbackSlotMinWidth(tDateProfile));
                var sections = [
                    {
                        type: 'header',
                        key: 'header',
                        isSticky: stickyHeaderDates,
                        chunks: [{
                                key: 'timeline',
    
                                content: function (contentArg) { return (createElement(TimelineHeader, { dateProfile: props.dateProfile, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, tableMinWidth: contentArg.tableMinWidth, tableColGroupNode: contentArg.tableColGroupNode, tDateProfile: tDateProfile, slatCoords: state.slatCoords, onMaxCushionWidth: slotMinWidth ? null : _this.handleMaxCushionWidth })); },
                            }],
    
                    },
                    {
                        type: 'body',
                        key: 'body',
                        liquid: true,
                        chunks: [{
                                key: 'timeline',
    
                                content: function (contentArg) { return (createElement(TimelineGrid, __assign({}, props, { clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, tableMinWidth: contentArg.tableMinWidth, tableColGroupNode: contentArg.tableColGroupNode, tDateProfile: tDateProfile, onSlatCoords: _this.handleSlatCoords, onScrollLeftRequest: _this.handleScrollLeftRequest }))); },
                            }],
                    },
    
                ];
                if (stickyFooterScrollbar) {
                    sections.push({
                        type: 'footer',
                        key: 'footer',
                        isSticky: true,
                        chunks: [{
                                key: 'timeline',
    
                                content: renderScrollShim,
                            }],
    
                    });
                }
                return (createElement(ViewRoot, { viewSpec: context.viewSpec }, function (rootElRef, classNames) { return (createElement("div", { ref: rootElRef, className: extraClassNames.concat(classNames).join(' ') },
                    createElement(ScrollGrid, { ref: _this.scrollGridRef, liquid: !props.isHeightAuto && !props.forPrint, colGroups: [
    
                            { cols: slatCols },
    
                        ], sections: sections }))); }));
            };
            TimelineView.prototype.computeFallbackSlotMinWidth = function (tDateProfile) {
                return Math.max(30, ((this.state.slotCushionMaxWidth || 0) / tDateProfile.slotsPerLabel));
            };
            return TimelineView;
        }(DateComponent));
        function buildSlatCols(tDateProfile, slotMinWidth) {
            return [{
                    span: tDateProfile.slotCnt,
    
                    minWidth: slotMinWidth || 1,
    
                }];
        }
    
        var timelinePlugin = createPlugin({
            deps: [
    
                premiumCommonPlugin,
    
            ],
            initialView: 'timelineDay',
            views: {
                timeline: {
                    component: TimelineView,
    
                    usesMinMaxTime: true,
                    eventResizableFromStart: true,
    
                },
                timelineDay: {
                    type: 'timeline',
    
                    duration: { days: 1 },
    
                },
                timelineWeek: {
                    type: 'timeline',
    
                    duration: { weeks: 1 },
    
                },
                timelineMonth: {
                    type: 'timeline',
    
                    duration: { months: 1 },
    
                },
                timelineYear: {
                    type: 'timeline',
    
                    duration: { years: 1 },
                },
            },
    
        });
    
        function massageEventDragMutation(eventMutation, hit0, hit1) {
            var resource0 = hit0.dateSpan.resourceId;
            var resource1 = hit1.dateSpan.resourceId;
            if (resource0 && resource1 &&
                resource0 !== resource1) {
                eventMutation.resourceMutation = {
                    matchResourceId: resource0,
    
                    setResourceId: resource1,
    
                };
            }
        }
        /*
        TODO: all this would be much easier if we were using a hash!
        */
        function applyEventDefMutation(eventDef, mutation, context) {
            var resourceMutation = mutation.resourceMutation;
            if (resourceMutation && computeResourceEditable(eventDef, context)) {
                var index = eventDef.resourceIds.indexOf(resourceMutation.matchResourceId);
                if (index !== -1) {
                    var resourceIds = eventDef.resourceIds.slice(); // copy
                    resourceIds.splice(index, 1); // remove
                    if (resourceIds.indexOf(resourceMutation.setResourceId) === -1) { // not already in there
                        resourceIds.push(resourceMutation.setResourceId); // add
                    }
                    eventDef.resourceIds = resourceIds;
                }
            }
        }
        /*
        HACK
        TODO: use EventUi system instead of this
        */
        function computeResourceEditable(eventDef, context) {
            var resourceEditable = eventDef.resourceEditable;
            if (resourceEditable == null) {
                var source = eventDef.sourceId && context.getCurrentData().eventSources[eventDef.sourceId];
                if (source) {
                    resourceEditable = source.extendedProps.resourceEditable; // used the Source::extendedProps hack
                }
                if (resourceEditable == null) {
                    resourceEditable = context.options.eventResourceEditable;
                    if (resourceEditable == null) {
                        resourceEditable = context.options.editable; // TODO: use defaults system instead
                    }
                }
            }
            return resourceEditable;
        }
        function transformEventDrop(mutation, context) {
            var resourceMutation = mutation.resourceMutation;
            if (resourceMutation) {
                var calendarApi = context.calendarApi;
                return {
                    oldResource: calendarApi.getResourceById(resourceMutation.matchResourceId),
    
                    newResource: calendarApi.getResourceById(resourceMutation.setResourceId),
    
            return {
                oldResource: null,
                newResource: null,
            };
    
        }
    
        var ResourceDataAdder = /** @class */ (function () {
            function ResourceDataAdder() {
                this.filterResources = memoize(filterResources);
            }
            ResourceDataAdder.prototype.transform = function (viewProps, calendarProps) {
                if (calendarProps.viewSpec.optionDefaults.needsResourceData) {
                    return {
                        resourceStore: this.filterResources(calendarProps.resourceStore, calendarProps.options.filterResourcesWithEvents, calendarProps.eventStore, calendarProps.dateProfile.activeRange),
    
                        resourceEntityExpansions: calendarProps.resourceEntityExpansions,
    
                return null;
    
            };
            return ResourceDataAdder;
        }());
        function filterResources(resourceStore, doFilterResourcesWithEvents, eventStore, activeRange) {
            if (doFilterResourcesWithEvents) {
                var instancesInRange = filterEventInstancesInRange(eventStore.instances, activeRange);
                var hasEvents_1 = computeHasEvents(instancesInRange, eventStore.defs);
                __assign(hasEvents_1, computeAncestorHasEvents(hasEvents_1, resourceStore));
    
                return filterHash(resourceStore, function (resource, resourceId) { return hasEvents_1[resourceId]; });
    
            return resourceStore;
    
        }
        function filterEventInstancesInRange(eventInstances, activeRange) {
    
            return filterHash(eventInstances, function (eventInstance) { return rangesIntersect(eventInstance.range, activeRange); });
    
        }
        function computeHasEvents(eventInstances, eventDefs) {
            var hasEvents = {};
            for (var instanceId in eventInstances) {
                var instance = eventInstances[instanceId];
                for (var _i = 0, _a = eventDefs[instance.defId].resourceIds; _i < _a.length; _i++) {
                    var resourceId = _a[_i];
                    hasEvents[resourceId] = true;
                }
            }
            return hasEvents;
        }
        /*
        mark resources as having events if any of their ancestors have them
        NOTE: resourceStore might not have all the resources that hasEvents{} has keyed
        */
        function computeAncestorHasEvents(hasEvents, resourceStore) {
            var res = {};
            for (var resourceId in hasEvents) {
                var resource = void 0;
                while ((resource = resourceStore[resourceId])) {
                    resourceId = resource.parentId; // now functioning as the parentId
                    if (resourceId) {
                        res[resourceId] = true;
                    }
                    else {
                        break;
                    }
                }
            }
            return res;
        }
    
        /*
        for making sure events that have editable resources are always draggable in resource views
        */
        function transformIsDraggable(val, eventDef, eventUi, context) {
            if (!val) {
                var state = context.getCurrentData();
                var viewSpec = state.viewSpecs[state.currentViewType];
                if (viewSpec.optionDefaults.needsResourceData) {
                    if (computeResourceEditable(eventDef, context)) {
                        return true;
                    }
                }
            }
            return val;
        }
    
    
        // for when non-resource view should be given EventUi info (for event coloring/constraints based off of resource data)
        var ResourceEventConfigAdder = /** @class */ (function () {
            function ResourceEventConfigAdder() {
                this.buildResourceEventUis = memoize(buildResourceEventUis, isPropsEqual);
                this.injectResourceEventUis = memoize(injectResourceEventUis);
            }
            ResourceEventConfigAdder.prototype.transform = function (viewProps, calendarProps) {
                if (!calendarProps.viewSpec.optionDefaults.needsResourceData) {
                    return {
    
                        eventUiBases: this.injectResourceEventUis(viewProps.eventUiBases, viewProps.eventStore.defs, this.buildResourceEventUis(calendarProps.resourceStore)),
    
                return null;
    
            };
            return ResourceEventConfigAdder;
        }());
        function buildResourceEventUis(resourceStore) {
    
            return mapHash(resourceStore, function (resource) { return resource.ui; });
    
        }
        function injectResourceEventUis(eventUiBases, eventDefs, resourceEventUis) {
            return mapHash(eventUiBases, function (eventUi, defId) {
                if (defId) { // not the '' key
                    return injectResourceEventUi(eventUi, eventDefs[defId], resourceEventUis);
                }
    
                return eventUi;
    
            });
        }
        function injectResourceEventUi(origEventUi, eventDef, resourceEventUis) {
            var parts = [];
            // first resource takes precedence, which fights with the ordering of combineEventUis, thus the unshifts
            for (var _i = 0, _a = eventDef.resourceIds; _i < _a.length; _i++) {
                var resourceId = _a[_i];
                if (resourceEventUis[resourceId]) {
                    parts.unshift(resourceEventUis[resourceId]);
                }
            }
            parts.unshift(origEventUi);
            return combineEventUis(parts);
        }
    
        var defs = []; // TODO: use plugin system
        function registerResourceSourceDef(def) {
            defs.push(def);
        }
        function getResourceSourceDef(id) {
            return defs[id];
        }
        function getResourceSourceDefs() {
            return defs;
        }
    
        // TODO: make this a plugin-able parser
        // TODO: success/failure
        var RESOURCE_SOURCE_REFINERS = {
            id: String,
            // for array. TODO: move to resource-array
            resources: identity,
            // for json feed. TODO: move to resource-json-feed
            url: String,
            method: String,
            startParam: String,
            endParam: String,
            timeZoneParam: String,
    
            extraParams: identity,
    
        };
        function parseResourceSource(input) {
            var inputObj;
            if (typeof input === 'string') {
                inputObj = { url: input };
            }
            else if (typeof input === 'function' || Array.isArray(input)) {
                inputObj = { resources: input };
            }
            else if (typeof input === 'object' && input) { // non-null object
                inputObj = input;
            }
            if (inputObj) {
                var _a = refineProps(inputObj, RESOURCE_SOURCE_REFINERS), refined = _a.refined, extra = _a.extra;
                warnUnknownProps(extra);
                var metaRes = buildResourceSourceMeta(refined);
                if (metaRes) {
                    return {
                        _raw: input,
                        sourceId: guid(),
                        sourceDefId: metaRes.sourceDefId,
                        meta: metaRes.meta,
                        publicId: refined.id || '',
                        isFetching: false,
                        latestFetchId: '',
    
                        fetchRange: null,
    
                    };
                }
            }
            return null;
        }
        function buildResourceSourceMeta(refined) {
            var defs = getResourceSourceDefs();
    
            for (var i = defs.length - 1; i >= 0; i -= 1) { // later-added plugins take precedence
    
                var def = defs[i];
                var meta = def.parseMeta(refined);
                if (meta) {
                    return { meta: meta, sourceDefId: i };
                }
            }
    
            return null;
    
        }
        function warnUnknownProps(props) {
            for (var propName in props) {
                console.warn("Unknown resource prop '" + propName + "'");
            }
        }
    
        function reduceResourceSource(source, action, context) {
            var options = context.options, dateProfile = context.dateProfile;
            if (!source || !action) {
                return createSource(options.initialResources || options.resources, dateProfile.activeRange, options.refetchResourcesOnNavigate, context);
            }
            switch (action.type) {
                case 'RESET_RESOURCE_SOURCE':
                    return createSource(action.resourceSourceInput, dateProfile.activeRange, options.refetchResourcesOnNavigate, context);
                case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
                case 'NEXT':
                case 'CHANGE_DATE':
                case 'CHANGE_VIEW_TYPE':
                    return handleRangeChange(source, dateProfile.activeRange, options.refetchResourcesOnNavigate, context);
                case 'RECEIVE_RESOURCES':
                case 'RECEIVE_RESOURCE_ERROR':
                    return receiveResponse$1(source, action.fetchId, action.fetchRange);
                case 'REFETCH_RESOURCES':
                    return fetchSource$1(source, dateProfile.activeRange, context);
                default:
                    return source;
            }
        }
        function createSource(input, activeRange, refetchResourcesOnNavigate, context) {
            if (input) {
                var source = parseResourceSource(input);
                source = fetchSource$1(source, refetchResourcesOnNavigate ? activeRange : null, context);
                return source;
            }
            return null;
        }
        function handleRangeChange(source, activeRange, refetchResourcesOnNavigate, context) {
            if (refetchResourcesOnNavigate &&
                !doesSourceIgnoreRange(source) &&
                (!source.fetchRange || !rangesEqual(source.fetchRange, activeRange))) {
                return fetchSource$1(source, activeRange, context);
            }
    
            return source;
    
        }
        function doesSourceIgnoreRange(source) {
            return Boolean(getResourceSourceDef(source.sourceDefId).ignoreRange);
        }
        function fetchSource$1(source, fetchRange, context) {
            var sourceDef = getResourceSourceDef(source.sourceDefId);
            var fetchId = guid();
            sourceDef.fetch({
                resourceSource: source,
                range: fetchRange,
    
                context: context,
    
            }, function (res) {
                context.dispatch({
                    type: 'RECEIVE_RESOURCES',
                    fetchId: fetchId,
                    fetchRange: fetchRange,
    
                    rawResources: res.rawResources,
    
                });
            }, function (error) {
                context.dispatch({
                    type: 'RECEIVE_RESOURCE_ERROR',
                    fetchId: fetchId,
                    fetchRange: fetchRange,
    
                    error: error,
    
                });
            });
            return __assign(__assign({}, source), { isFetching: true, latestFetchId: fetchId });
        }
        function receiveResponse$1(source, fetchId, fetchRange) {
            if (fetchId === source.latestFetchId) {
                return __assign(__assign({}, source), { isFetching: false, fetchRange: fetchRange });
            }
            return source;
        }
    
        var PRIVATE_ID_PREFIX = '_fc:';
        var RESOURCE_REFINERS = {
            id: String,
            parentId: String,
            children: identity,
            title: String,
            businessHours: identity,
            extendedProps: identity,
            // event-ui
            eventEditable: Boolean,
            eventStartEditable: Boolean,
            eventDurationEditable: Boolean,
            eventConstraint: identity,
            eventOverlap: Boolean,
            eventAllow: identity,
            eventClassNames: parseClassNames,
            eventBackgroundColor: String,
            eventBorderColor: String,
            eventTextColor: String,
    
            eventColor: String,
    
        };
        /*
        needs a full store so that it can populate children too
        */
        function parseResource(raw, parentId, store, context) {
            if (parentId === void 0) { parentId = ''; }
            var _a = refineProps(raw, RESOURCE_REFINERS), refined = _a.refined, extra = _a.extra;
            var resource = {
                id: refined.id || (PRIVATE_ID_PREFIX + guid()),
                parentId: refined.parentId || parentId,
                title: refined.title || '',
                businessHours: refined.businessHours ? parseBusinessHours(refined.businessHours, context) : null,
                ui: createEventUi({
                    editable: refined.eventEditable,
                    startEditable: refined.eventStartEditable,
                    durationEditable: refined.eventDurationEditable,
                    constraint: refined.eventConstraint,
                    overlap: refined.eventOverlap,
                    allow: refined.eventAllow,
                    classNames: refined.eventClassNames,
                    backgroundColor: refined.eventBackgroundColor,
                    borderColor: refined.eventBorderColor,
                    textColor: refined.eventTextColor,
    
                    color: refined.eventColor,
    
                extendedProps: __assign(__assign({}, extra), refined.extendedProps),
    
            };
            // help out ResourceApi from having user modify props
            Object.freeze(resource.ui.classNames);
            Object.freeze(resource.extendedProps);
            if (store[resource.id]) ;
            else {
                store[resource.id] = resource;
                if (refined.children) {
                    for (var _i = 0, _b = refined.children; _i < _b.length; _i++) {
                        var childInput = _b[_i];
                        parseResource(childInput, resource.id, store, context);
                    }
                }
            }
            return resource;
        }
        /*
        TODO: use this in more places
        */
        function getPublicId(id) {
            if (id.indexOf(PRIVATE_ID_PREFIX) === 0) {
                return '';
            }
            return id;
        }
    
        function reduceResourceStore(store, action, source, context) {
            if (!store || !action) {
                return {};
            }
            switch (action.type) {
                case 'RECEIVE_RESOURCES':
                    return receiveRawResources(store, action.rawResources, action.fetchId, source, context);
                case 'ADD_RESOURCE':
                    return addResource(store, action.resourceHash);
                case 'REMOVE_RESOURCE':
                    return removeResource(store, action.resourceId);
                case 'SET_RESOURCE_PROP':
                    return setResourceProp(store, action.resourceId, action.propName, action.propValue);
                case 'SET_RESOURCE_EXTENDED_PROP':
                    return setResourceExtendedProp(store, action.resourceId, action.propName, action.propValue);
                default:
                    return store;
            }
        }
        function receiveRawResources(existingStore, inputs, fetchId, source, context) {
            if (source.latestFetchId === fetchId) {
                var nextStore = {};
                for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) {
                    var input = inputs_1[_i];
                    parseResource(input, '', nextStore, context);
                }
                return nextStore;
            }
    
            return existingStore;
    
        }
        function addResource(existingStore, additions) {
            // TODO: warn about duplicate IDs
            return __assign(__assign({}, existingStore), additions);
        }
        function removeResource(existingStore, resourceId) {
            var newStore = __assign({}, existingStore);
            delete newStore[resourceId];
            // promote children
            for (var childResourceId in newStore) { // a child, *maybe* but probably not
                if (newStore[childResourceId].parentId === resourceId) {
                    newStore[childResourceId] = __assign(__assign({}, newStore[childResourceId]), { parentId: '' });
                }
            }
            return newStore;
        }
        function setResourceProp(existingStore, resourceId, name, value) {
            var _a, _b;
            var existingResource = existingStore[resourceId];
            // TODO: sanitization
            if (existingResource) {
                return __assign(__assign({}, existingStore), (_a = {}, _a[resourceId] = __assign(__assign({}, existingResource), (_b = {}, _b[name] = value, _b)), _a));
            }
    
            return existingStore;
    
        }
        function setResourceExtendedProp(existingStore, resourceId, name, value) {
            var _a, _b;
            var existingResource = existingStore[resourceId];
            if (existingResource) {
                return __assign(__assign({}, existingStore), (_a = {}, _a[resourceId] = __assign(__assign({}, existingResource), { extendedProps: __assign(__assign({}, existingResource.extendedProps), (_b = {}, _b[name] = value, _b)) }), _a));
            }
    
            return existingStore;
    
        }
    
        function reduceResourceEntityExpansions(expansions, action) {
            var _a;
            if (!expansions || !action) {
                return {};
            }
            switch (action.type) {
                case 'SET_RESOURCE_ENTITY_EXPANDED':
                    return __assign(__assign({}, expansions), (_a = {}, _a[action.id] = action.isExpanded, _a));
                default:
                    return expansions;
            }
        }
    
        function reduceResources(state, action, context) {
            var resourceSource = reduceResourceSource(state && state.resourceSource, action, context);
            var resourceStore = reduceResourceStore(state && state.resourceStore, action, resourceSource, context);
            var resourceEntityExpansions = reduceResourceEntityExpansions(state && state.resourceEntityExpansions, action);
            return {
                resourceSource: resourceSource,
                resourceStore: resourceStore,
                resourceEntityExpansions: resourceEntityExpansions,
            };
        }
    
        var EVENT_REFINERS$1 = {
            resourceId: String,
            resourceIds: identity,
    
            resourceEditable: Boolean,
    
        };
        function generateEventDefResourceMembers(refined) {
            return {
                resourceIds: ensureStringArray(refined.resourceIds)
                    .concat(refined.resourceId ? [refined.resourceId] : []),
    
                resourceEditable: refined.resourceEditable,
    
            };
        }
        function ensureStringArray(items) {
    
            return (items || []).map(function (item) { return String(item); });
    
        }
    
        function transformDateSelectionJoin(hit0, hit1) {
            var resourceId0 = hit0.dateSpan.resourceId;
            var resourceId1 = hit1.dateSpan.resourceId;
            if (resourceId0 && resourceId1) {
                if (hit0.component.allowAcrossResources === false &&
                    resourceId0 !== resourceId1) {
                    return false;
                }
    
                return { resourceId: resourceId0 };
    
            return null;
    
        }
    
        var ResourceApi = /** @class */ (function () {
            function ResourceApi(_context, _resource) {
                this._context = _context;
                this._resource = _resource;
            }
            ResourceApi.prototype.setProp = function (name, value) {
                var oldResource = this._resource;
                this._context.dispatch({
                    type: 'SET_RESOURCE_PROP',
                    resourceId: oldResource.id,
                    propName: name,
    
                    propValue: value,
    
                });
                this.sync(oldResource);
            };
            ResourceApi.prototype.setExtendedProp = function (name, value) {
                var oldResource = this._resource;
                this._context.dispatch({
                    type: 'SET_RESOURCE_EXTENDED_PROP',
                    resourceId: oldResource.id,
                    propName: name,
    
                    propValue: value,
    
                });
                this.sync(oldResource);
            };
            ResourceApi.prototype.sync = function (oldResource) {
                var context = this._context;
                var resourceId = oldResource.id;
                // TODO: what if dispatch didn't complete synchronously?
                this._resource = context.getCurrentData().resourceStore[resourceId];
                context.emitter.trigger('resourceChange', {
                    oldResource: new ResourceApi(context, oldResource),
                    resource: this,
                    revert: function () {
                        var _a;
                        context.dispatch({
                            type: 'ADD_RESOURCE',
                            resourceHash: (_a = {},
                                _a[resourceId] = oldResource,
    
                });
            };
            ResourceApi.prototype.remove = function () {
                var context = this._context;
                var internalResource = this._resource;
                var resourceId = internalResource.id;
                context.dispatch({
                    type: 'REMOVE_RESOURCE',
    
                    resourceId: resourceId,
    
                });
                context.emitter.trigger('resourceRemove', {
                    resource: this,
                    revert: function () {
                        var _a;
                        context.dispatch({
                            type: 'ADD_RESOURCE',