diff options
author | Mario <mario@mariovavti.com> | 2023-01-25 13:09:00 +0000 |
---|---|---|
committer | Mario <mario@mariovavti.com> | 2023-01-25 13:09:00 +0000 |
commit | a9ae17036d30a676c833a6ddb98409f19cbbd963 (patch) | |
tree | 66d29806350386a585dcbf4aa20f51cda4da6c49 /library/fullcalendar/packages/timegrid/index.global.js | |
parent | 08e925758e920b898ac2d08710eab2f9638fe276 (diff) | |
download | volse-hubzilla-a9ae17036d30a676c833a6ddb98409f19cbbd963.tar.gz volse-hubzilla-a9ae17036d30a676c833a6ddb98409f19cbbd963.tar.bz2 volse-hubzilla-a9ae17036d30a676c833a6ddb98409f19cbbd963.zip |
update fullcalendar
Diffstat (limited to 'library/fullcalendar/packages/timegrid/index.global.js')
-rw-r--r-- | library/fullcalendar/packages/timegrid/index.global.js | 1198 |
1 files changed, 1198 insertions, 0 deletions
diff --git a/library/fullcalendar/packages/timegrid/index.global.js b/library/fullcalendar/packages/timegrid/index.global.js new file mode 100644 index 000000000..830c7ee2c --- /dev/null +++ b/library/fullcalendar/packages/timegrid/index.global.js @@ -0,0 +1,1198 @@ +/*! +FullCalendar Time Grid Plugin v6.0.3 +Docs & License: https://fullcalendar.io/docs/timegrid-view +(c) 2022 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", generator: options.slotLabelContent || 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", generator: options.allDayContent || 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, 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", generator: 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 }, (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))), + 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) { + let { props } = this; + if (props.forPrint) { + return renderPlainFgSegs(sortedFgSegs, props); + } + return this.renderPositionedFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting); + } + renderPositionedFgSegs(segs, // if not mirror, needs to be sorted + segIsInvisible, isDragging, isResizing, isDateSelecting) { + 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: 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 isNowIndicator = context.options.nowIndicator; + 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: isNowIndicator ? '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: isNowIndicator && this.slicer.sliceNowDate(nowDate, 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-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); |