/*!
FullCalendar Time Grid Plugin v6.1.17
Docs & License: https://fullcalendar.io/docs/timegrid-view
(c) 2024 Adam Shaw
*/
FullCalendar.TimeGrid = (function (exports, core, internal$1, preact, internal$2) {
    'use strict';

    class AllDaySplitter extends internal$1.Splitter {
        getKeyInfo() {
            return {
                allDay: {},
                timed: {},
            };
        }
        getKeysForDateSpan(dateSpan) {
            if (dateSpan.allDay) {
                return ['allDay'];
            }
            return ['timed'];
        }
        getKeysForEventDef(eventDef) {
            if (!eventDef.allDay) {
                return ['timed'];
            }
            if (internal$1.hasBgRendering(eventDef)) {
                return ['timed', 'allDay'];
            }
            return ['allDay'];
        }
    }

    const DEFAULT_SLAT_LABEL_FORMAT = internal$1.createFormatter({
        hour: 'numeric',
        minute: '2-digit',
        omitZeroMinute: true,
        meridiem: 'short',
    });
    function TimeColsAxisCell(props) {
        let classNames = [
            'fc-timegrid-slot',
            'fc-timegrid-slot-label',
            props.isLabeled ? 'fc-scrollgrid-shrink' : 'fc-timegrid-slot-minor',
        ];
        return (preact.createElement(internal$1.ViewContextType.Consumer, null, (context) => {
            if (!props.isLabeled) {
                return (preact.createElement("td", { className: classNames.join(' '), "data-time": props.isoTimeStr }));
            }
            let { dateEnv, options, viewApi } = context;
            let labelFormat = // TODO: fully pre-parse
             options.slotLabelFormat == null ? DEFAULT_SLAT_LABEL_FORMAT :
                Array.isArray(options.slotLabelFormat) ? internal$1.createFormatter(options.slotLabelFormat[0]) :
                    internal$1.createFormatter(options.slotLabelFormat);
            let renderProps = {
                level: 0,
                time: props.time,
                date: dateEnv.toDate(props.date),
                view: viewApi,
                text: dateEnv.format(props.date, labelFormat),
            };
            return (preact.createElement(internal$1.ContentContainer, { elTag: "td", elClasses: classNames, elAttrs: {
                    'data-time': props.isoTimeStr,
                }, renderProps: renderProps, generatorName: "slotLabelContent", customGenerator: options.slotLabelContent, defaultGenerator: renderInnerContent, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (preact.createElement("div", { className: "fc-timegrid-slot-label-frame fc-scrollgrid-shrink-frame" },
                preact.createElement(InnerContent, { elTag: "div", elClasses: [
                        'fc-timegrid-slot-label-cushion',
                        'fc-scrollgrid-shrink-cushion',
                    ] })))));
        }));
    }
    function renderInnerContent(props) {
        return props.text;
    }

    class TimeBodyAxis extends internal$1.BaseComponent {
        render() {
            return this.props.slatMetas.map((slatMeta) => (preact.createElement("tr", { key: slatMeta.key },
                preact.createElement(TimeColsAxisCell, Object.assign({}, slatMeta)))));
        }
    }

    const DEFAULT_WEEK_NUM_FORMAT = internal$1.createFormatter({ week: 'short' });
    const AUTO_ALL_DAY_MAX_EVENT_ROWS = 5;
    class TimeColsView extends internal$1.DateComponent {
        constructor() {
            super(...arguments);
            this.allDaySplitter = new AllDaySplitter(); // for use by subclasses
            this.headerElRef = preact.createRef();
            this.rootElRef = preact.createRef();
            this.scrollerElRef = preact.createRef();
            this.state = {
                slatCoords: null,
            };
            this.handleScrollTopRequest = (scrollTop) => {
                let scrollerEl = this.scrollerElRef.current;
                if (scrollerEl) { // TODO: not sure how this could ever be null. weirdness with the reducer
                    scrollerEl.scrollTop = scrollTop;
                }
            };
            /* Header Render Methods
            ------------------------------------------------------------------------------------------------------------------*/
            this.renderHeadAxis = (rowKey, frameHeight = '') => {
                let { options } = this.context;
                let { dateProfile } = this.props;
                let range = dateProfile.renderRange;
                let dayCnt = internal$1.diffDays(range.start, range.end);
                // only do in day views (to avoid doing in week views that dont need it)
                let navLinkAttrs = (dayCnt === 1)
                    ? internal$1.buildNavLinkAttrs(this.context, range.start, 'week')
                    : {};
                if (options.weekNumbers && rowKey === 'day') {
                    return (preact.createElement(internal$1.WeekNumberContainer, { elTag: "th", elClasses: [
                            'fc-timegrid-axis',
                            'fc-scrollgrid-shrink',
                        ], elAttrs: {
                            'aria-hidden': true,
                        }, date: range.start, defaultFormat: DEFAULT_WEEK_NUM_FORMAT }, (InnerContent) => (preact.createElement("div", { className: [
                            'fc-timegrid-axis-frame',
                            'fc-scrollgrid-shrink-frame',
                            'fc-timegrid-axis-frame-liquid',
                        ].join(' '), style: { height: frameHeight } },
                        preact.createElement(InnerContent, { elTag: "a", elClasses: [
                                'fc-timegrid-axis-cushion',
                                'fc-scrollgrid-shrink-cushion',
                                'fc-scrollgrid-sync-inner',
                            ], elAttrs: navLinkAttrs })))));
                }
                return (preact.createElement("th", { "aria-hidden": true, className: "fc-timegrid-axis" },
                    preact.createElement("div", { className: "fc-timegrid-axis-frame", style: { height: frameHeight } })));
            };
            /* Table Component Render Methods
            ------------------------------------------------------------------------------------------------------------------*/
            // only a one-way height sync. we don't send the axis inner-content height to the DayGrid,
            // but DayGrid still needs to have classNames on inner elements in order to measure.
            this.renderTableRowAxis = (rowHeight) => {
                let { options, viewApi } = this.context;
                let renderProps = {
                    text: options.allDayText,
                    view: viewApi,
                };
                return (
                // TODO: make reusable hook. used in list view too
                preact.createElement(internal$1.ContentContainer, { elTag: "td", elClasses: [
                        'fc-timegrid-axis',
                        'fc-scrollgrid-shrink',
                    ], elAttrs: {
                        'aria-hidden': true,
                    }, renderProps: renderProps, generatorName: "allDayContent", customGenerator: options.allDayContent, defaultGenerator: renderAllDayInner, classNameGenerator: options.allDayClassNames, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }, (InnerContent) => (preact.createElement("div", { className: [
                        'fc-timegrid-axis-frame',
                        'fc-scrollgrid-shrink-frame',
                        rowHeight == null ? ' fc-timegrid-axis-frame-liquid' : '',
                    ].join(' '), style: { height: rowHeight } },
                    preact.createElement(InnerContent, { elTag: "span", elClasses: [
                            'fc-timegrid-axis-cushion',
                            'fc-scrollgrid-shrink-cushion',
                            'fc-scrollgrid-sync-inner',
                        ] })))));
            };
            this.handleSlatCoords = (slatCoords) => {
                this.setState({ slatCoords });
            };
        }
        // rendering
        // ----------------------------------------------------------------------------------------------------
        renderSimpleLayout(headerRowContent, allDayContent, timeContent) {
            let { context, props } = this;
            let sections = [];
            let stickyHeaderDates = internal$1.getStickyHeaderDates(context.options);
            if (headerRowContent) {
                sections.push({
                    type: 'header',
                    key: 'header',
                    isSticky: stickyHeaderDates,
                    chunk: {
                        elRef: this.headerElRef,
                        tableClassName: 'fc-col-header',
                        rowContent: headerRowContent,
                    },
                });
            }
            if (allDayContent) {
                sections.push({
                    type: 'body',
                    key: 'all-day',
                    chunk: { content: allDayContent },
                });
                sections.push({
                    type: 'body',
                    key: 'all-day-divider',
                    outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?
                    preact.createElement("tr", { role: "presentation", className: "fc-scrollgrid-section" },
                        preact.createElement("td", { className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),
                });
            }
            sections.push({
                type: 'body',
                key: 'body',
                liquid: true,
                expandRows: Boolean(context.options.expandRows),
                chunk: {
                    scrollerElRef: this.scrollerElRef,
                    content: timeContent,
                },
            });
            return (preact.createElement(internal$1.ViewContainer, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },
                preact.createElement(internal$1.SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [{ width: 'shrink' }], sections: sections })));
        }
        renderHScrollLayout(headerRowContent, allDayContent, timeContent, colCnt, dayMinWidth, slatMetas, slatCoords) {
            let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
            if (!ScrollGrid) {
                throw new Error('No ScrollGrid implementation');
            }
            let { context, props } = this;
            let stickyHeaderDates = !props.forPrint && internal$1.getStickyHeaderDates(context.options);
            let stickyFooterScrollbar = !props.forPrint && internal$1.getStickyFooterScrollbar(context.options);
            let sections = [];
            if (headerRowContent) {
                sections.push({
                    type: 'header',
                    key: 'header',
                    isSticky: stickyHeaderDates,
                    syncRowHeights: true,
                    chunks: [
                        {
                            key: 'axis',
                            rowContent: (arg) => (preact.createElement("tr", { role: "presentation" }, this.renderHeadAxis('day', arg.rowSyncHeights[0]))),
                        },
                        {
                            key: 'cols',
                            elRef: this.headerElRef,
                            tableClassName: 'fc-col-header',
                            rowContent: headerRowContent,
                        },
                    ],
                });
            }
            if (allDayContent) {
                sections.push({
                    type: 'body',
                    key: 'all-day',
                    syncRowHeights: true,
                    chunks: [
                        {
                            key: 'axis',
                            rowContent: (contentArg) => (preact.createElement("tr", { role: "presentation" }, this.renderTableRowAxis(contentArg.rowSyncHeights[0]))),
                        },
                        {
                            key: 'cols',
                            content: allDayContent,
                        },
                    ],
                });
                sections.push({
                    key: 'all-day-divider',
                    type: 'body',
                    outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?
                    preact.createElement("tr", { role: "presentation", className: "fc-scrollgrid-section" },
                        preact.createElement("td", { colSpan: 2, className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),
                });
            }
            let isNowIndicator = context.options.nowIndicator;
            sections.push({
                type: 'body',
                key: 'body',
                liquid: true,
                expandRows: Boolean(context.options.expandRows),
                chunks: [
                    {
                        key: 'axis',
                        content: (arg) => (
                        // TODO: make this now-indicator arrow more DRY with TimeColsContent
                        preact.createElement("div", { className: "fc-timegrid-axis-chunk" },
                            preact.createElement("table", { "aria-hidden": true, style: { height: arg.expandRows ? arg.clientHeight : '' } },
                                arg.tableColGroupNode,
                                preact.createElement("tbody", null,
                                    preact.createElement(TimeBodyAxis, { slatMetas: slatMetas }))),
                            preact.createElement("div", { className: "fc-timegrid-now-indicator-container" },
                                preact.createElement(internal$1.NowTimer, { unit: isNowIndicator ? 'minute' : 'day' /* hacky */ }, (nowDate) => {
                                    let nowIndicatorTop = isNowIndicator &&
                                        slatCoords &&
                                        slatCoords.safeComputeTop(nowDate); // might return void
                                    if (typeof nowIndicatorTop === 'number') {
                                        return (preact.createElement(internal$1.NowIndicatorContainer, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: nowDate }));
                                    }
                                    return null;
                                })))),
                    },
                    {
                        key: 'cols',
                        scrollerElRef: this.scrollerElRef,
                        content: timeContent,
                    },
                ],
            });
            if (stickyFooterScrollbar) {
                sections.push({
                    key: 'footer',
                    type: 'footer',
                    isSticky: true,
                    chunks: [
                        {
                            key: 'axis',
                            content: internal$1.renderScrollShim,
                        },
                        {
                            key: 'cols',
                            content: internal$1.renderScrollShim,
                        },
                    ],
                });
            }
            return (preact.createElement(internal$1.ViewContainer, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },
                preact.createElement(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: false, colGroups: [
                        { width: 'shrink', cols: [{ width: 'shrink' }] },
                        { cols: [{ span: colCnt, minWidth: dayMinWidth }] },
                    ], sections: sections })));
        }
        /* Dimensions
        ------------------------------------------------------------------------------------------------------------------*/
        getAllDayMaxEventProps() {
            let { dayMaxEvents, dayMaxEventRows } = this.context.options;
            if (dayMaxEvents === true || dayMaxEventRows === true) { // is auto?
                dayMaxEvents = undefined;
                dayMaxEventRows = AUTO_ALL_DAY_MAX_EVENT_ROWS; // make sure "auto" goes to a real number
            }
            return { dayMaxEvents, dayMaxEventRows };
        }
    }
    function renderAllDayInner(renderProps) {
        return renderProps.text;
    }

    class TimeColsSlatsCoords {
        constructor(positions, dateProfile, slotDuration) {
            this.positions = positions;
            this.dateProfile = dateProfile;
            this.slotDuration = slotDuration;
        }
        safeComputeTop(date) {
            let { dateProfile } = this;
            if (internal$1.rangeContainsMarker(dateProfile.currentRange, date)) {
                let startOfDayDate = internal$1.startOfDay(date);
                let timeMs = date.valueOf() - startOfDayDate.valueOf();
                if (timeMs >= internal$1.asRoughMs(dateProfile.slotMinTime) &&
                    timeMs < internal$1.asRoughMs(dateProfile.slotMaxTime)) {
                    return this.computeTimeTop(internal$1.createDuration(timeMs));
                }
            }
            return null;
        }
        // Computes the top coordinate, relative to the bounds of the grid, of the given date.
        // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.
        computeDateTop(when, startOfDayDate) {
            if (!startOfDayDate) {
                startOfDayDate = internal$1.startOfDay(when);
            }
            return this.computeTimeTop(internal$1.createDuration(when.valueOf() - startOfDayDate.valueOf()));
        }
        // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).
        // This is a makeshify way to compute the time-top. Assumes all slatMetas dates are uniform.
        // Eventually allow computation with arbirary slat dates.
        computeTimeTop(duration) {
            let { positions, dateProfile } = this;
            let len = positions.els.length;
            // floating-point value of # of slots covered
            let slatCoverage = (duration.milliseconds - internal$1.asRoughMs(dateProfile.slotMinTime)) / internal$1.asRoughMs(this.slotDuration);
            let slatIndex;
            let slatRemainder;
            // compute a floating-point number for how many slats should be progressed through.
            // from 0 to number of slats (inclusive)
            // constrained because slotMinTime/slotMaxTime might be customized.
            slatCoverage = Math.max(0, slatCoverage);
            slatCoverage = Math.min(len, slatCoverage);
            // an integer index of the furthest whole slat
            // from 0 to number slats (*exclusive*, so len-1)
            slatIndex = Math.floor(slatCoverage);
            slatIndex = Math.min(slatIndex, len - 1);
            // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.
            // could be 1.0 if slatCoverage is covering *all* the slots
            slatRemainder = slatCoverage - slatIndex;
            return positions.tops[slatIndex] +
                positions.getHeight(slatIndex) * slatRemainder;
        }
    }

    class TimeColsSlatsBody extends internal$1.BaseComponent {
        render() {
            let { props, context } = this;
            let { options } = context;
            let { slatElRefs } = props;
            return (preact.createElement("tbody", null, props.slatMetas.map((slatMeta, i) => {
                let renderProps = {
                    time: slatMeta.time,
                    date: context.dateEnv.toDate(slatMeta.date),
                    view: context.viewApi,
                };
                return (preact.createElement("tr", { key: slatMeta.key, ref: slatElRefs.createRef(slatMeta.key) },
                    props.axis && (preact.createElement(TimeColsAxisCell, Object.assign({}, slatMeta))),
                    preact.createElement(internal$1.ContentContainer, { elTag: "td", elClasses: [
                            'fc-timegrid-slot',
                            'fc-timegrid-slot-lane',
                            !slatMeta.isLabeled && 'fc-timegrid-slot-minor',
                        ], elAttrs: {
                            'data-time': slatMeta.isoTimeStr,
                        }, renderProps: renderProps, generatorName: "slotLaneContent", customGenerator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount })));
            })));
        }
    }

    /*
    for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL.
    */
    class TimeColsSlats extends internal$1.BaseComponent {
        constructor() {
            super(...arguments);
            this.rootElRef = preact.createRef();
            this.slatElRefs = new internal$1.RefMap();
        }
        render() {
            let { props, context } = this;
            return (preact.createElement("div", { ref: this.rootElRef, className: "fc-timegrid-slots" },
                preact.createElement("table", { "aria-hidden": true, className: context.theme.getClass('table'), style: {
                        minWidth: props.tableMinWidth,
                        width: props.clientWidth,
                        height: props.minHeight,
                    } },
                    props.tableColGroupNode /* relies on there only being a single <col> for the axis */,
                    preact.createElement(TimeColsSlatsBody, { slatElRefs: this.slatElRefs, axis: props.axis, slatMetas: props.slatMetas }))));
        }
        componentDidMount() {
            this.updateSizing();
        }
        componentDidUpdate() {
            this.updateSizing();
        }
        componentWillUnmount() {
            if (this.props.onCoords) {
                this.props.onCoords(null);
            }
        }
        updateSizing() {
            let { context, props } = this;
            if (props.onCoords &&
                props.clientWidth !== null // means sizing has stabilized
            ) {
                let rootEl = this.rootElRef.current;
                if (rootEl.offsetHeight) { // not hidden by css
                    props.onCoords(new TimeColsSlatsCoords(new internal$1.PositionCache(this.rootElRef.current, collectSlatEls(this.slatElRefs.currentMap, props.slatMetas), false, true), this.props.dateProfile, context.options.slotDuration));
                }
            }
        }
    }
    function collectSlatEls(elMap, slatMetas) {
        return slatMetas.map((slatMeta) => elMap[slatMeta.key]);
    }

    function splitSegsByCol(segs, colCnt) {
        let segsByCol = [];
        let i;
        for (i = 0; i < colCnt; i += 1) {
            segsByCol.push([]);
        }
        if (segs) {
            for (i = 0; i < segs.length; i += 1) {
                segsByCol[segs[i].col].push(segs[i]);
            }
        }
        return segsByCol;
    }
    function splitInteractionByCol(ui, colCnt) {
        let byRow = [];
        if (!ui) {
            for (let i = 0; i < colCnt; i += 1) {
                byRow[i] = null;
            }
        }
        else {
            for (let i = 0; i < colCnt; i += 1) {
                byRow[i] = {
                    affectedInstances: ui.affectedInstances,
                    isEvent: ui.isEvent,
                    segs: [],
                };
            }
            for (let seg of ui.segs) {
                byRow[seg.col].segs.push(seg);
            }
        }
        return byRow;
    }

    class TimeColMoreLink extends internal$1.BaseComponent {
        render() {
            let { props } = this;
            return (preact.createElement(internal$1.MoreLinkContainer, { elClasses: ['fc-timegrid-more-link'], elStyle: {
                    top: props.top,
                    bottom: props.bottom,
                }, allDayDate: null, moreCnt: props.hiddenSegs.length, allSegs: props.hiddenSegs, hiddenSegs: props.hiddenSegs, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, todayRange: props.todayRange, popoverContent: () => renderPlainFgSegs(props.hiddenSegs, props), defaultGenerator: renderMoreLinkInner, forceTimed: true }, (InnerContent) => (preact.createElement(InnerContent, { elTag: "div", elClasses: ['fc-timegrid-more-link-inner', 'fc-sticky'] }))));
        }
    }
    function renderMoreLinkInner(props) {
        return props.shortText;
    }

    // segInputs assumed sorted
    function buildPositioning(segInputs, strictOrder, maxStackCnt) {
        let hierarchy = new internal$1.SegHierarchy();
        if (strictOrder != null) {
            hierarchy.strictOrder = strictOrder;
        }
        if (maxStackCnt != null) {
            hierarchy.maxStackCnt = maxStackCnt;
        }
        let hiddenEntries = hierarchy.addSegs(segInputs);
        let hiddenGroups = internal$1.groupIntersectingEntries(hiddenEntries);
        let web = buildWeb(hierarchy);
        web = stretchWeb(web, 1); // all levelCoords/thickness will have 0.0-1.0
        let segRects = webToRects(web);
        return { segRects, hiddenGroups };
    }
    function buildWeb(hierarchy) {
        const { entriesByLevel } = hierarchy;
        const buildNode = cacheable((level, lateral) => level + ':' + lateral, (level, lateral) => {
            let siblingRange = findNextLevelSegs(hierarchy, level, lateral);
            let nextLevelRes = buildNodes(siblingRange, buildNode);
            let entry = entriesByLevel[level][lateral];
            return [
                Object.assign(Object.assign({}, entry), { nextLevelNodes: nextLevelRes[0] }),
                entry.thickness + nextLevelRes[1], // the pressure builds
            ];
        });
        return buildNodes(entriesByLevel.length
            ? { level: 0, lateralStart: 0, lateralEnd: entriesByLevel[0].length }
            : null, buildNode)[0];
    }
    function buildNodes(siblingRange, buildNode) {
        if (!siblingRange) {
            return [[], 0];
        }
        let { level, lateralStart, lateralEnd } = siblingRange;
        let lateral = lateralStart;
        let pairs = [];
        while (lateral < lateralEnd) {
            pairs.push(buildNode(level, lateral));
            lateral += 1;
        }
        pairs.sort(cmpDescPressures);
        return [
            pairs.map(extractNode),
            pairs[0][1], // first item's pressure
        ];
    }
    function cmpDescPressures(a, b) {
        return b[1] - a[1];
    }
    function extractNode(a) {
        return a[0];
    }
    function findNextLevelSegs(hierarchy, subjectLevel, subjectLateral) {
        let { levelCoords, entriesByLevel } = hierarchy;
        let subjectEntry = entriesByLevel[subjectLevel][subjectLateral];
        let afterSubject = levelCoords[subjectLevel] + subjectEntry.thickness;
        let levelCnt = levelCoords.length;
        let level = subjectLevel;
        // skip past levels that are too high up
        for (; level < levelCnt && levelCoords[level] < afterSubject; level += 1)
            ; // do nothing
        for (; level < levelCnt; level += 1) {
            let entries = entriesByLevel[level];
            let entry;
            let searchIndex = internal$1.binarySearch(entries, subjectEntry.span.start, internal$1.getEntrySpanEnd);
            let lateralStart = searchIndex[0] + searchIndex[1]; // if exact match (which doesn't collide), go to next one
            let lateralEnd = lateralStart;
            while ( // loop through entries that horizontally intersect
            (entry = entries[lateralEnd]) && // but not past the whole seg list
                entry.span.start < subjectEntry.span.end) {
                lateralEnd += 1;
            }
            if (lateralStart < lateralEnd) {
                return { level, lateralStart, lateralEnd };
            }
        }
        return null;
    }
    function stretchWeb(topLevelNodes, totalThickness) {
        const stretchNode = cacheable((node, startCoord, prevThickness) => internal$1.buildEntryKey(node), (node, startCoord, prevThickness) => {
            let { nextLevelNodes, thickness } = node;
            let allThickness = thickness + prevThickness;
            let thicknessFraction = thickness / allThickness;
            let endCoord;
            let newChildren = [];
            if (!nextLevelNodes.length) {
                endCoord = totalThickness;
            }
            else {
                for (let childNode of nextLevelNodes) {
                    if (endCoord === undefined) {
                        let res = stretchNode(childNode, startCoord, allThickness);
                        endCoord = res[0];
                        newChildren.push(res[1]);
                    }
                    else {
                        let res = stretchNode(childNode, endCoord, 0);
                        newChildren.push(res[1]);
                    }
                }
            }
            let newThickness = (endCoord - startCoord) * thicknessFraction;
            return [endCoord - newThickness, Object.assign(Object.assign({}, node), { thickness: newThickness, nextLevelNodes: newChildren })];
        });
        return topLevelNodes.map((node) => stretchNode(node, 0, 0)[1]);
    }
    // not sorted in any particular order
    function webToRects(topLevelNodes) {
        let rects = [];
        const processNode = cacheable((node, levelCoord, stackDepth) => internal$1.buildEntryKey(node), (node, levelCoord, stackDepth) => {
            let rect = Object.assign(Object.assign({}, node), { levelCoord,
                stackDepth, stackForward: 0 });
            rects.push(rect);
            return (rect.stackForward = processNodes(node.nextLevelNodes, levelCoord + node.thickness, stackDepth + 1) + 1);
        });
        function processNodes(nodes, levelCoord, stackDepth) {
            let stackForward = 0;
            for (let node of nodes) {
                stackForward = Math.max(processNode(node, levelCoord, stackDepth), stackForward);
            }
            return stackForward;
        }
        processNodes(topLevelNodes, 0, 0);
        return rects; // TODO: sort rects by levelCoord to be consistent with toRects?
    }
    // TODO: move to general util
    function cacheable(keyFunc, workFunc) {
        const cache = {};
        return (...args) => {
            let key = keyFunc(...args);
            return (key in cache)
                ? cache[key]
                : (cache[key] = workFunc(...args));
        };
    }

    function computeSegVCoords(segs, colDate, slatCoords = null, eventMinHeight = 0) {
        let vcoords = [];
        if (slatCoords) {
            for (let i = 0; i < segs.length; i += 1) {
                let seg = segs[i];
                let spanStart = slatCoords.computeDateTop(seg.start, colDate);
                let spanEnd = Math.max(spanStart + (eventMinHeight || 0), // :(
                slatCoords.computeDateTop(seg.end, colDate));
                vcoords.push({
                    start: Math.round(spanStart),
                    end: Math.round(spanEnd), //
                });
            }
        }
        return vcoords;
    }
    function computeFgSegPlacements(segs, segVCoords, // might not have for every seg
    eventOrderStrict, eventMaxStack) {
        let segInputs = [];
        let dumbSegs = []; // segs without coords
        for (let i = 0; i < segs.length; i += 1) {
            let vcoords = segVCoords[i];
            if (vcoords) {
                segInputs.push({
                    index: i,
                    thickness: 1,
                    span: vcoords,
                });
            }
            else {
                dumbSegs.push(segs[i]);
            }
        }
        let { segRects, hiddenGroups } = buildPositioning(segInputs, eventOrderStrict, eventMaxStack);
        let segPlacements = [];
        for (let segRect of segRects) {
            segPlacements.push({
                seg: segs[segRect.index],
                rect: segRect,
            });
        }
        for (let dumbSeg of dumbSegs) {
            segPlacements.push({ seg: dumbSeg, rect: null });
        }
        return { segPlacements, hiddenGroups };
    }

    const DEFAULT_TIME_FORMAT = internal$1.createFormatter({
        hour: 'numeric',
        minute: '2-digit',
        meridiem: false,
    });
    class TimeColEvent extends internal$1.BaseComponent {
        render() {
            return (preact.createElement(internal$1.StandardEvent, Object.assign({}, this.props, { elClasses: [
                    'fc-timegrid-event',
                    'fc-v-event',
                    this.props.isShort && 'fc-timegrid-event-short',
                ], defaultTimeFormat: DEFAULT_TIME_FORMAT })));
        }
    }

    class TimeCol extends internal$1.BaseComponent {
        constructor() {
            super(...arguments);
            this.sortEventSegs = internal$1.memoize(internal$1.sortEventSegs);
        }
        // TODO: memoize event-placement?
        render() {
            let { props, context } = this;
            let { options } = context;
            let isSelectMirror = options.selectMirror;
            let mirrorSegs = // yuck
             (props.eventDrag && props.eventDrag.segs) ||
                (props.eventResize && props.eventResize.segs) ||
                (isSelectMirror && props.dateSelectionSegs) ||
                [];
            let interactionAffectedInstances = // TODO: messy way to compute this
             (props.eventDrag && props.eventDrag.affectedInstances) ||
                (props.eventResize && props.eventResize.affectedInstances) ||
                {};
            let sortedFgSegs = this.sortEventSegs(props.fgEventSegs, options.eventOrder);
            return (preact.createElement(internal$1.DayCellContainer, { elTag: "td", elRef: props.elRef, elClasses: [
                    'fc-timegrid-col',
                    ...(props.extraClassNames || []),
                ], elAttrs: Object.assign({ role: 'gridcell' }, props.extraDataAttrs), date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, extraRenderProps: props.extraRenderProps }, (InnerContent) => (preact.createElement("div", { className: "fc-timegrid-col-frame" },
                preact.createElement("div", { className: "fc-timegrid-col-bg" },
                    this.renderFillSegs(props.businessHourSegs, 'non-business'),
                    this.renderFillSegs(props.bgEventSegs, 'bg-event'),
                    this.renderFillSegs(props.dateSelectionSegs, 'highlight')),
                preact.createElement("div", { className: "fc-timegrid-col-events" }, this.renderFgSegs(sortedFgSegs, interactionAffectedInstances, false, false, false)),
                preact.createElement("div", { className: "fc-timegrid-col-events" }, this.renderFgSegs(mirrorSegs, {}, Boolean(props.eventDrag), Boolean(props.eventResize), Boolean(isSelectMirror), 'mirror')),
                preact.createElement("div", { className: "fc-timegrid-now-indicator-container" }, this.renderNowIndicator(props.nowIndicatorSegs)),
                internal$1.hasCustomDayCellContent(options) && (preact.createElement(InnerContent, { elTag: "div", elClasses: ['fc-timegrid-col-misc'] }))))));
        }
        renderFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey) {
            let { props } = this;
            if (props.forPrint) {
                return renderPlainFgSegs(sortedFgSegs, props);
            }
            return this.renderPositionedFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey);
        }
        renderPositionedFgSegs(segs, // if not mirror, needs to be sorted
        segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey) {
            let { eventMaxStack, eventShortHeight, eventOrderStrict, eventMinHeight } = this.context.options;
            let { date, slatCoords, eventSelection, todayRange, nowDate } = this.props;
            let isMirror = isDragging || isResizing || isDateSelecting;
            let segVCoords = computeSegVCoords(segs, date, slatCoords, eventMinHeight);
            let { segPlacements, hiddenGroups } = computeFgSegPlacements(segs, segVCoords, eventOrderStrict, eventMaxStack);
            return (preact.createElement(preact.Fragment, null,
                this.renderHiddenGroups(hiddenGroups, segs),
                segPlacements.map((segPlacement) => {
                    let { seg, rect } = segPlacement;
                    let instanceId = seg.eventRange.instance.instanceId;
                    let isVisible = isMirror || Boolean(!segIsInvisible[instanceId] && rect);
                    let vStyle = computeSegVStyle(rect && rect.span);
                    let hStyle = (!isMirror && rect) ? this.computeSegHStyle(rect) : { left: 0, right: 0 };
                    let isInset = Boolean(rect) && rect.stackForward > 0;
                    let isShort = Boolean(rect) && (rect.span.end - rect.span.start) < eventShortHeight; // look at other places for this problem
                    return (preact.createElement("div", { className: 'fc-timegrid-event-harness' +
                            (isInset ? ' fc-timegrid-event-harness-inset' : ''), key: forcedKey || instanceId, style: Object.assign(Object.assign({ visibility: isVisible ? '' : 'hidden' }, vStyle), hStyle) },
                        preact.createElement(TimeColEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, isShort: isShort }, internal$1.getSegMeta(seg, todayRange, nowDate)))));
                })));
        }
        // will already have eventMinHeight applied because segInputs already had it
        renderHiddenGroups(hiddenGroups, segs) {
            let { extraDateSpan, dateProfile, todayRange, nowDate, eventSelection, eventDrag, eventResize } = this.props;
            return (preact.createElement(preact.Fragment, null, hiddenGroups.map((hiddenGroup) => {
                let positionCss = computeSegVStyle(hiddenGroup.span);
                let hiddenSegs = compileSegsFromEntries(hiddenGroup.entries, segs);
                return (preact.createElement(TimeColMoreLink, { key: internal$1.buildIsoString(internal$1.computeEarliestSegStart(hiddenSegs)), hiddenSegs: hiddenSegs, top: positionCss.top, bottom: positionCss.bottom, extraDateSpan: extraDateSpan, dateProfile: dateProfile, todayRange: todayRange, nowDate: nowDate, eventSelection: eventSelection, eventDrag: eventDrag, eventResize: eventResize }));
            })));
        }
        renderFillSegs(segs, fillType) {
            let { props, context } = this;
            let segVCoords = computeSegVCoords(segs, props.date, props.slatCoords, context.options.eventMinHeight); // don't assume all populated
            let children = segVCoords.map((vcoords, i) => {
                let seg = segs[i];
                return (preact.createElement("div", { key: internal$1.buildEventRangeKey(seg.eventRange), className: "fc-timegrid-bg-harness", style: computeSegVStyle(vcoords) }, fillType === 'bg-event' ?
                    preact.createElement(internal$1.BgEvent, Object.assign({ seg: seg }, internal$1.getSegMeta(seg, props.todayRange, props.nowDate))) :
                    internal$1.renderFill(fillType)));
            });
            return preact.createElement(preact.Fragment, null, children);
        }
        renderNowIndicator(segs) {
            let { slatCoords, date } = this.props;
            if (!slatCoords) {
                return null;
            }
            return segs.map((seg, i) => (preact.createElement(internal$1.NowIndicatorContainer
            // key doesn't matter. will only ever be one
            , { 
                // key doesn't matter. will only ever be one
                key: i, elClasses: ['fc-timegrid-now-indicator-line'], elStyle: {
                    top: slatCoords.computeDateTop(seg.start, date),
                }, isAxis: false, date: date })));
        }
        computeSegHStyle(segHCoords) {
            let { isRtl, options } = this.context;
            let shouldOverlap = options.slotEventOverlap;
            let nearCoord = segHCoords.levelCoord; // the left side if LTR. the right side if RTL. floating-point
            let farCoord = segHCoords.levelCoord + segHCoords.thickness; // the right side if LTR. the left side if RTL. floating-point
            let left; // amount of space from left edge, a fraction of the total width
            let right; // amount of space from right edge, a fraction of the total width
            if (shouldOverlap) {
                // double the width, but don't go beyond the maximum forward coordinate (1.0)
                farCoord = Math.min(1, nearCoord + (farCoord - nearCoord) * 2);
            }
            if (isRtl) {
                left = 1 - farCoord;
                right = nearCoord;
            }
            else {
                left = nearCoord;
                right = 1 - farCoord;
            }
            let props = {
                zIndex: segHCoords.stackDepth + 1,
                left: left * 100 + '%',
                right: right * 100 + '%',
            };
            if (shouldOverlap && !segHCoords.stackForward) {
                // add padding to the edge so that forward stacked events don't cover the resizer's icon
                props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
            }
            return props;
        }
    }
    function renderPlainFgSegs(sortedFgSegs, { todayRange, nowDate, eventSelection, eventDrag, eventResize }) {
        let hiddenInstances = (eventDrag ? eventDrag.affectedInstances : null) ||
            (eventResize ? eventResize.affectedInstances : null) ||
            {};
        return (preact.createElement(preact.Fragment, null, sortedFgSegs.map((seg) => {
            let instanceId = seg.eventRange.instance.instanceId;
            return (preact.createElement("div", { key: instanceId, style: { visibility: hiddenInstances[instanceId] ? 'hidden' : '' } },
                preact.createElement(TimeColEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === eventSelection, isShort: false }, internal$1.getSegMeta(seg, todayRange, nowDate)))));
        })));
    }
    function computeSegVStyle(segVCoords) {
        if (!segVCoords) {
            return { top: '', bottom: '' };
        }
        return {
            top: segVCoords.start,
            bottom: -segVCoords.end,
        };
    }
    function compileSegsFromEntries(segEntries, allSegs) {
        return segEntries.map((segEntry) => allSegs[segEntry.index]);
    }

    class TimeColsContent extends internal$1.BaseComponent {
        constructor() {
            super(...arguments);
            this.splitFgEventSegs = internal$1.memoize(splitSegsByCol);
            this.splitBgEventSegs = internal$1.memoize(splitSegsByCol);
            this.splitBusinessHourSegs = internal$1.memoize(splitSegsByCol);
            this.splitNowIndicatorSegs = internal$1.memoize(splitSegsByCol);
            this.splitDateSelectionSegs = internal$1.memoize(splitSegsByCol);
            this.splitEventDrag = internal$1.memoize(splitInteractionByCol);
            this.splitEventResize = internal$1.memoize(splitInteractionByCol);
            this.rootElRef = preact.createRef();
            this.cellElRefs = new internal$1.RefMap();
        }
        render() {
            let { props, context } = this;
            let nowIndicatorTop = context.options.nowIndicator &&
                props.slatCoords &&
                props.slatCoords.safeComputeTop(props.nowDate); // might return void
            let colCnt = props.cells.length;
            let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, colCnt);
            let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, colCnt);
            let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, colCnt);
            let nowIndicatorSegsByRow = this.splitNowIndicatorSegs(props.nowIndicatorSegs, colCnt);
            let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, colCnt);
            let eventDragByRow = this.splitEventDrag(props.eventDrag, colCnt);
            let eventResizeByRow = this.splitEventResize(props.eventResize, colCnt);
            return (preact.createElement("div", { className: "fc-timegrid-cols", ref: this.rootElRef },
                preact.createElement("table", { role: "presentation", style: {
                        minWidth: props.tableMinWidth,
                        width: props.clientWidth,
                    } },
                    props.tableColGroupNode,
                    preact.createElement("tbody", { role: "presentation" },
                        preact.createElement("tr", { role: "row" },
                            props.axis && (preact.createElement("td", { "aria-hidden": true, className: "fc-timegrid-col fc-timegrid-axis" },
                                preact.createElement("div", { className: "fc-timegrid-col-frame" },
                                    preact.createElement("div", { className: "fc-timegrid-now-indicator-container" }, typeof nowIndicatorTop === 'number' && (preact.createElement(internal$1.NowIndicatorContainer, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: props.nowDate })))))),
                            props.cells.map((cell, i) => (preact.createElement(TimeCol, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), dateProfile: props.dateProfile, date: cell.date, nowDate: props.nowDate, todayRange: props.todayRange, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, fgEventSegs: fgEventSegsByRow[i], bgEventSegs: bgEventSegsByRow[i], businessHourSegs: businessHourSegsByRow[i], nowIndicatorSegs: nowIndicatorSegsByRow[i], dateSelectionSegs: dateSelectionSegsByRow[i], eventDrag: eventDragByRow[i], eventResize: eventResizeByRow[i], slatCoords: props.slatCoords, eventSelection: props.eventSelection, forPrint: props.forPrint }))))))));
        }
        componentDidMount() {
            this.updateCoords();
        }
        componentDidUpdate() {
            this.updateCoords();
        }
        updateCoords() {
            let { props } = this;
            if (props.onColCoords &&
                props.clientWidth !== null // means sizing has stabilized
            ) {
                props.onColCoords(new internal$1.PositionCache(this.rootElRef.current, collectCellEls(this.cellElRefs.currentMap, props.cells), true, // horizontal
                false));
            }
        }
    }
    function collectCellEls(elMap, cells) {
        return cells.map((cell) => elMap[cell.key]);
    }

    /* A component that renders one or more columns of vertical time slots
    ----------------------------------------------------------------------------------------------------------------------*/
    class TimeCols extends internal$1.DateComponent {
        constructor() {
            super(...arguments);
            this.processSlotOptions = internal$1.memoize(processSlotOptions);
            this.state = {
                slatCoords: null,
            };
            this.handleRootEl = (el) => {
                if (el) {
                    this.context.registerInteractiveComponent(this, {
                        el,
                        isHitComboAllowed: this.props.isHitComboAllowed,
                    });
                }
                else {
                    this.context.unregisterInteractiveComponent(this);
                }
            };
            this.handleScrollRequest = (request) => {
                let { onScrollTopRequest } = this.props;
                let { slatCoords } = this.state;
                if (onScrollTopRequest && slatCoords) {
                    if (request.time) {
                        let top = slatCoords.computeTimeTop(request.time);
                        top = Math.ceil(top); // zoom can give weird floating-point values. rather scroll a little bit further
                        if (top) {
                            top += 1; // to overcome top border that slots beyond the first have. looks better
                        }
                        onScrollTopRequest(top);
                    }
                    return true;
                }
                return false;
            };
            this.handleColCoords = (colCoords) => {
                this.colCoords = colCoords;
            };
            this.handleSlatCoords = (slatCoords) => {
                this.setState({ slatCoords });
                if (this.props.onSlatCoords) {
                    this.props.onSlatCoords(slatCoords);
                }
            };
        }
        render() {
            let { props, state } = this;
            return (preact.createElement("div", { className: "fc-timegrid-body", ref: this.handleRootEl, style: {
                    // these props are important to give this wrapper correct dimensions for interactions
                    // TODO: if we set it here, can we avoid giving to inner tables?
                    width: props.clientWidth,
                    minWidth: props.tableMinWidth,
                } },
                preact.createElement(TimeColsSlats, { axis: props.axis, dateProfile: props.dateProfile, slatMetas: props.slatMetas, clientWidth: props.clientWidth, minHeight: props.expandRows ? props.clientHeight : '', tableMinWidth: props.tableMinWidth, tableColGroupNode: props.axis ? props.tableColGroupNode : null /* axis depends on the colgroup's shrinking */, onCoords: this.handleSlatCoords }),
                preact.createElement(TimeColsContent, { cells: props.cells, axis: props.axis, dateProfile: props.dateProfile, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange, nowDate: props.nowDate, nowIndicatorSegs: props.nowIndicatorSegs, clientWidth: props.clientWidth, tableMinWidth: props.tableMinWidth, tableColGroupNode: props.tableColGroupNode, slatCoords: state.slatCoords, onColCoords: this.handleColCoords, forPrint: props.forPrint })));
        }
        componentDidMount() {
            this.scrollResponder = this.context.createScrollResponder(this.handleScrollRequest);
        }
        componentDidUpdate(prevProps) {
            this.scrollResponder.update(prevProps.dateProfile !== this.props.dateProfile);
        }
        componentWillUnmount() {
            this.scrollResponder.detach();
        }
        queryHit(positionLeft, positionTop) {
            let { dateEnv, options } = this.context;
            let { colCoords } = this;
            let { dateProfile } = this.props;
            let { slatCoords } = this.state;
            let { snapDuration, snapsPerSlot } = this.processSlotOptions(this.props.slotDuration, options.snapDuration);
            let colIndex = colCoords.leftToIndex(positionLeft);
            let slatIndex = slatCoords.positions.topToIndex(positionTop);
            if (colIndex != null && slatIndex != null) {
                let cell = this.props.cells[colIndex];
                let slatTop = slatCoords.positions.tops[slatIndex];
                let slatHeight = slatCoords.positions.getHeight(slatIndex);
                let partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1
                let localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat
                let snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
                let dayDate = this.props.cells[colIndex].date;
                let time = internal$1.addDurations(dateProfile.slotMinTime, internal$1.multiplyDuration(snapDuration, snapIndex));
                let start = dateEnv.add(dayDate, time);
                let end = dateEnv.add(start, snapDuration);
                return {
                    dateProfile,
                    dateSpan: Object.assign({ range: { start, end }, allDay: false }, cell.extraDateSpan),
                    dayEl: colCoords.els[colIndex],
                    rect: {
                        left: colCoords.lefts[colIndex],
                        right: colCoords.rights[colIndex],
                        top: slatTop,
                        bottom: slatTop + slatHeight,
                    },
                    layer: 0,
                };
            }
            return null;
        }
    }
    function processSlotOptions(slotDuration, snapDurationOverride) {
        let snapDuration = snapDurationOverride || slotDuration;
        let snapsPerSlot = internal$1.wholeDivideDurations(slotDuration, snapDuration);
        if (snapsPerSlot === null) {
            snapDuration = slotDuration;
            snapsPerSlot = 1;
            // TODO: say warning?
        }
        return { snapDuration, snapsPerSlot };
    }

    class DayTimeColsSlicer extends internal$1.Slicer {
        sliceRange(range, dayRanges) {
            let segs = [];
            for (let col = 0; col < dayRanges.length; col += 1) {
                let segRange = internal$1.intersectRanges(range, dayRanges[col]);
                if (segRange) {
                    segs.push({
                        start: segRange.start,
                        end: segRange.end,
                        isStart: segRange.start.valueOf() === range.start.valueOf(),
                        isEnd: segRange.end.valueOf() === range.end.valueOf(),
                        col,
                    });
                }
            }
            return segs;
        }
    }

    class DayTimeCols extends internal$1.DateComponent {
        constructor() {
            super(...arguments);
            this.buildDayRanges = internal$1.memoize(buildDayRanges);
            this.slicer = new DayTimeColsSlicer();
            this.timeColsRef = preact.createRef();
        }
        render() {
            let { props, context } = this;
            let { dateProfile, dayTableModel } = props;
            let { nowIndicator, nextDayThreshold } = context.options;
            let dayRanges = this.buildDayRanges(dayTableModel, dateProfile, context.dateEnv);
            // give it the first row of cells
            // TODO: would move this further down hierarchy, but sliceNowDate needs it
            return (preact.createElement(internal$1.NowTimer, { unit: nowIndicator ? 'minute' : 'day' }, (nowDate, todayRange) => (preact.createElement(TimeCols, Object.assign({ ref: this.timeColsRef }, this.slicer.sliceProps(props, dateProfile, null, context, dayRanges), { forPrint: props.forPrint, axis: props.axis, dateProfile: dateProfile, slatMetas: props.slatMetas, slotDuration: props.slotDuration, cells: dayTableModel.cells[0], tableColGroupNode: props.tableColGroupNode, tableMinWidth: props.tableMinWidth, clientWidth: props.clientWidth, clientHeight: props.clientHeight, expandRows: props.expandRows, nowDate: nowDate, nowIndicatorSegs: nowIndicator && this.slicer.sliceNowDate(nowDate, dateProfile, nextDayThreshold, context, dayRanges), todayRange: todayRange, onScrollTopRequest: props.onScrollTopRequest, onSlatCoords: props.onSlatCoords })))));
        }
    }
    function buildDayRanges(dayTableModel, dateProfile, dateEnv) {
        let ranges = [];
        for (let date of dayTableModel.headerDates) {
            ranges.push({
                start: dateEnv.add(date, dateProfile.slotMinTime),
                end: dateEnv.add(date, dateProfile.slotMaxTime),
            });
        }
        return ranges;
    }

    // potential nice values for the slot-duration and interval-duration
    // from largest to smallest
    const STOCK_SUB_DURATIONS = [
        { hours: 1 },
        { minutes: 30 },
        { minutes: 15 },
        { seconds: 30 },
        { seconds: 15 },
    ];
    function buildSlatMetas(slotMinTime, slotMaxTime, explicitLabelInterval, slotDuration, dateEnv) {
        let dayStart = new Date(0);
        let slatTime = slotMinTime;
        let slatIterator = internal$1.createDuration(0);
        let labelInterval = explicitLabelInterval || computeLabelInterval(slotDuration);
        let metas = [];
        while (internal$1.asRoughMs(slatTime) < internal$1.asRoughMs(slotMaxTime)) {
            let date = dateEnv.add(dayStart, slatTime);
            let isLabeled = internal$1.wholeDivideDurations(slatIterator, labelInterval) !== null;
            metas.push({
                date,
                time: slatTime,
                key: date.toISOString(),
                isoTimeStr: internal$1.formatIsoTimeString(date),
                isLabeled,
            });
            slatTime = internal$1.addDurations(slatTime, slotDuration);
            slatIterator = internal$1.addDurations(slatIterator, slotDuration);
        }
        return metas;
    }
    // Computes an automatic value for slotLabelInterval
    function computeLabelInterval(slotDuration) {
        let i;
        let labelInterval;
        let slotsPerLabel;
        // find the smallest stock label interval that results in more than one slots-per-label
        for (i = STOCK_SUB_DURATIONS.length - 1; i >= 0; i -= 1) {
            labelInterval = internal$1.createDuration(STOCK_SUB_DURATIONS[i]);
            slotsPerLabel = internal$1.wholeDivideDurations(labelInterval, slotDuration);
            if (slotsPerLabel !== null && slotsPerLabel > 1) {
                return labelInterval;
            }
        }
        return slotDuration; // fall back
    }

    class DayTimeColsView extends TimeColsView {
        constructor() {
            super(...arguments);
            this.buildTimeColsModel = internal$1.memoize(buildTimeColsModel);
            this.buildSlatMetas = internal$1.memoize(buildSlatMetas);
        }
        render() {
            let { options, dateEnv, dateProfileGenerator } = this.context;
            let { props } = this;
            let { dateProfile } = props;
            let dayTableModel = this.buildTimeColsModel(dateProfile, dateProfileGenerator);
            let splitProps = this.allDaySplitter.splitProps(props);
            let slatMetas = this.buildSlatMetas(dateProfile.slotMinTime, dateProfile.slotMaxTime, options.slotLabelInterval, options.slotDuration, dateEnv);
            let { dayMinWidth } = options;
            let hasAttachedAxis = !dayMinWidth;
            let hasDetachedAxis = dayMinWidth;
            let headerContent = options.dayHeaders && (preact.createElement(internal$1.DayHeader, { dates: dayTableModel.headerDates, dateProfile: dateProfile, datesRepDistinctDays: true, renderIntro: hasAttachedAxis ? this.renderHeadAxis : null }));
            let allDayContent = (options.allDaySlot !== false) && ((contentArg) => (preact.createElement(internal$2.DayTable, Object.assign({}, splitProps.allDay, { dateProfile: dateProfile, dayTableModel: dayTableModel, nextDayThreshold: options.nextDayThreshold, tableMinWidth: contentArg.tableMinWidth, colGroupNode: contentArg.tableColGroupNode, renderRowIntro: hasAttachedAxis ? this.renderTableRowAxis : null, showWeekNumbers: false, expandRows: false, headerAlignElRef: this.headerElRef, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, forPrint: props.forPrint }, this.getAllDayMaxEventProps()))));
            let timeGridContent = (contentArg) => (preact.createElement(DayTimeCols, Object.assign({}, splitProps.timed, { dayTableModel: dayTableModel, dateProfile: dateProfile, axis: hasAttachedAxis, slotDuration: options.slotDuration, slatMetas: slatMetas, forPrint: props.forPrint, tableColGroupNode: contentArg.tableColGroupNode, tableMinWidth: contentArg.tableMinWidth, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, onSlatCoords: this.handleSlatCoords, expandRows: contentArg.expandRows, onScrollTopRequest: this.handleScrollTopRequest })));
            return hasDetachedAxis
                ? this.renderHScrollLayout(headerContent, allDayContent, timeGridContent, dayTableModel.colCnt, dayMinWidth, slatMetas, this.state.slatCoords)
                : this.renderSimpleLayout(headerContent, allDayContent, timeGridContent);
        }
    }
    function buildTimeColsModel(dateProfile, dateProfileGenerator) {
        let daySeries = new internal$1.DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
        return new internal$1.DayTableModel(daySeries, false);
    }

    const OPTION_REFINERS = {
        allDaySlot: Boolean,
    };

    var css_248z = ".fc-v-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-v-event .fc-event-main{color:var(--fc-event-text-color);height:100%}.fc-v-event .fc-event-main-frame{display:flex;flex-direction:column;height:100%}.fc-v-event .fc-event-time{flex-grow:0;flex-shrink:0;max-height:100%;overflow:hidden}.fc-v-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-height:0}.fc-v-event .fc-event-title{bottom:0;max-height:100%;overflow:hidden;top:0}.fc-v-event:not(.fc-event-start){border-top-left-radius:0;border-top-right-radius:0;border-top-width:0}.fc-v-event:not(.fc-event-end){border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-width:0}.fc-v-event.fc-event-selected:before{left:-10px;right:-10px}.fc-v-event .fc-event-resizer-start{cursor:n-resize}.fc-v-event .fc-event-resizer-end{cursor:s-resize}.fc-v-event:not(.fc-event-selected) .fc-event-resizer{height:var(--fc-event-resizer-thickness);left:0;right:0}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-start{top:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer{left:50%;margin-left:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-start{top:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc .fc-timegrid .fc-daygrid-body{z-index:2}.fc .fc-timegrid-divider{padding:0 0 2px}.fc .fc-timegrid-body{min-height:100%;position:relative;z-index:1}.fc .fc-timegrid-axis-chunk{position:relative}.fc .fc-timegrid-axis-chunk>table,.fc .fc-timegrid-slots{position:relative;z-index:1}.fc .fc-timegrid-slot{border-bottom:0;height:1.5em}.fc .fc-timegrid-slot:empty:before{content:\"\\00a0\"}.fc .fc-timegrid-slot-minor{border-top-style:dotted}.fc .fc-timegrid-slot-label-cushion{display:inline-block;white-space:nowrap}.fc .fc-timegrid-slot-label{vertical-align:middle}.fc .fc-timegrid-axis-cushion,.fc .fc-timegrid-slot-label-cushion{padding:0 4px}.fc .fc-timegrid-axis-frame-liquid{height:100%}.fc .fc-timegrid-axis-frame{align-items:center;display:flex;justify-content:flex-end;overflow:hidden}.fc .fc-timegrid-axis-cushion{flex-shrink:0;max-width:60px}.fc-direction-ltr .fc-timegrid-slot-label-frame{text-align:right}.fc-direction-rtl .fc-timegrid-slot-label-frame{text-align:left}.fc-liquid-hack .fc-timegrid-axis-frame-liquid{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-timegrid-col-frame{min-height:100%;position:relative}.fc-media-screen.fc-liquid-hack .fc-timegrid-col-frame{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols{bottom:0;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols>table{height:100%}.fc-media-screen .fc-timegrid-col-bg,.fc-media-screen .fc-timegrid-col-events,.fc-media-screen .fc-timegrid-now-indicator-container{left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col-bg{z-index:2}.fc .fc-timegrid-col-bg .fc-non-business{z-index:1}.fc .fc-timegrid-col-bg .fc-bg-event{z-index:2}.fc .fc-timegrid-col-bg .fc-highlight{z-index:3}.fc .fc-timegrid-bg-harness{left:0;position:absolute;right:0}.fc .fc-timegrid-col-events{z-index:3}.fc .fc-timegrid-now-indicator-container{bottom:0;overflow:hidden}.fc-direction-ltr .fc-timegrid-col-events{margin:0 2.5% 0 2px}.fc-direction-rtl .fc-timegrid-col-events{margin:0 2px 0 2.5%}.fc-timegrid-event-harness{position:absolute}.fc-timegrid-event-harness>.fc-timegrid-event{bottom:0;left:0;position:absolute;right:0;top:0}.fc-timegrid-event-harness-inset .fc-timegrid-event,.fc-timegrid-event.fc-event-mirror,.fc-timegrid-more-link{box-shadow:0 0 0 1px var(--fc-page-bg-color)}.fc-timegrid-event,.fc-timegrid-more-link{border-radius:3px;font-size:var(--fc-small-font-size)}.fc-timegrid-event{margin-bottom:1px}.fc-timegrid-event .fc-event-main{padding:1px 1px 0}.fc-timegrid-event .fc-event-time{font-size:var(--fc-small-font-size);margin-bottom:1px;white-space:nowrap}.fc-timegrid-event-short .fc-event-main-frame{flex-direction:row;overflow:hidden}.fc-timegrid-event-short .fc-event-time:after{content:\"\\00a0-\\00a0\"}.fc-timegrid-event-short .fc-event-title{font-size:var(--fc-small-font-size)}.fc-timegrid-more-link{background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;margin-bottom:1px;position:absolute;z-index:9999}.fc-timegrid-more-link-inner{padding:3px 2px;top:0}.fc-direction-ltr .fc-timegrid-more-link{right:0}.fc-direction-rtl .fc-timegrid-more-link{left:0}.fc .fc-timegrid-now-indicator-arrow,.fc .fc-timegrid-now-indicator-line{pointer-events:none}.fc .fc-timegrid-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;border-width:1px 0 0;left:0;position:absolute;right:0;z-index:4}.fc .fc-timegrid-now-indicator-arrow{border-color:var(--fc-now-indicator-color);border-style:solid;margin-top:-5px;position:absolute;z-index:4}.fc-direction-ltr .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 0 5px 6px;left:0}.fc-direction-rtl .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 6px 5px 0;right:0}";
    internal$1.injectStyles(css_248z);

    var plugin = core.createPlugin({
        name: '@fullcalendar/timegrid',
        initialView: 'timeGridWeek',
        optionRefiners: OPTION_REFINERS,
        views: {
            timeGrid: {
                component: DayTimeColsView,
                usesMinMaxTime: true,
                allDaySlot: true,
                slotDuration: '00:30:00',
                slotEventOverlap: true, // a bad name. confused with overlap/constraint system
            },
            timeGridDay: {
                type: 'timeGrid',
                duration: { days: 1 },
            },
            timeGridWeek: {
                type: 'timeGrid',
                duration: { weeks: 1 },
            },
        },
    });

    var internal = {
        __proto__: null,
        TimeColsView: TimeColsView,
        DayTimeColsView: DayTimeColsView,
        buildTimeColsModel: buildTimeColsModel,
        DayTimeCols: DayTimeCols,
        buildDayRanges: buildDayRanges,
        DayTimeColsSlicer: DayTimeColsSlicer,
        TimeCols: TimeCols,
        buildSlatMetas: buildSlatMetas,
        TimeColsSlatsCoords: TimeColsSlatsCoords
    };

    core.globalPlugins.push(plugin);

    exports.Internal = internal;
    exports["default"] = plugin;

    Object.defineProperty(exports, '__esModule', { value: true });

    return exports;

})({}, FullCalendar, FullCalendar.Internal, FullCalendar.Preact, FullCalendar.DayGrid.Internal);
