📝 Commit Details:

This commit is contained in:
2025-05-31 22:40:29 +02:00
parent 91b1886dde
commit df8fb197c0
14061 changed files with 997277 additions and 103548 deletions

22
backend/node_modules/@fullcalendar/daygrid/LICENSE.md generated vendored Normal file
View File

@@ -0,0 +1,22 @@
MIT License
Copyright (c) 2021 Adam Shaw
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

32
backend/node_modules/@fullcalendar/daygrid/README.md generated vendored Normal file
View File

@@ -0,0 +1,32 @@
# FullCalendar Day Grid Plugin
Display events on a [month view](https://fullcalendar.io/docs/month-view) or ["day grid" view](https://fullcalendar.io/docs/daygrid-view)
## Installation
Install the necessary packages:
```sh
npm install @fullcalendar/core @fullcalendar/daygrid
```
## Usage
Instantiate a Calendar with the necessary plugin:
```js
import { Calendar } from '@fullcalendar/core'
import dayGridPlugin from '@fullcalendar/daygrid'
const calendarEl = document.getElementById('calendar')
const calendar = new Calendar(calendarEl, {
plugins: [dayGridPlugin],
initialView: 'dayGridMonth',
events: [
{ title: 'Meeting', start: new Date() }
]
})
calendar.render()
```

38
backend/node_modules/@fullcalendar/daygrid/index.cjs generated vendored Normal file
View File

@@ -0,0 +1,38 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var index_cjs = require('@fullcalendar/core/index.cjs');
var internalCommon = require('./internal.cjs');
require('@fullcalendar/core/internal.cjs');
require('@fullcalendar/core/preact.cjs');
var index = index_cjs.createPlugin({
name: '@fullcalendar/daygrid',
initialView: 'dayGridMonth',
views: {
dayGrid: {
component: internalCommon.DayGridView,
dateProfileGeneratorClass: internalCommon.TableDateProfileGenerator,
},
dayGridDay: {
type: 'dayGrid',
duration: { days: 1 },
},
dayGridWeek: {
type: 'dayGrid',
duration: { weeks: 1 },
},
dayGridMonth: {
type: 'dayGrid',
duration: { months: 1 },
fixedWeekCount: true,
},
dayGridYear: {
type: 'dayGrid',
duration: { years: 1 },
},
},
});
exports["default"] = index;

View File

@@ -0,0 +1,6 @@
import { PluginDef } from '@fullcalendar/core';
declare const _default: PluginDef;
//# sourceMappingURL=index.d.ts.map
export { _default as default };

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

34
backend/node_modules/@fullcalendar/daygrid/index.js generated vendored Normal file
View File

@@ -0,0 +1,34 @@
import { createPlugin } from '@fullcalendar/core/index.js';
import { DayGridView as DayTableView, TableDateProfileGenerator } from './internal.js';
import '@fullcalendar/core/internal.js';
import '@fullcalendar/core/preact.js';
var index = createPlugin({
name: '@fullcalendar/daygrid',
initialView: 'dayGridMonth',
views: {
dayGrid: {
component: DayTableView,
dateProfileGeneratorClass: TableDateProfileGenerator,
},
dayGridDay: {
type: 'dayGrid',
duration: { days: 1 },
},
dayGridWeek: {
type: 'dayGrid',
duration: { weeks: 1 },
},
dayGridMonth: {
type: 'dayGrid',
duration: { months: 1 },
fixedWeekCount: true,
},
dayGridYear: {
type: 'dayGrid',
duration: { years: 1 },
},
},
});
export { index as default };

997
backend/node_modules/@fullcalendar/daygrid/internal.cjs generated vendored Normal file
View File

@@ -0,0 +1,997 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var internal_cjs = require('@fullcalendar/core/internal.cjs');
var preact_cjs = require('@fullcalendar/core/preact.cjs');
/* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.
----------------------------------------------------------------------------------------------------------------------*/
// It is a manager for a Table subcomponent, which does most of the heavy lifting.
// It is responsible for managing width/height.
class TableView extends internal_cjs.DateComponent {
constructor() {
super(...arguments);
this.headerElRef = preact_cjs.createRef();
}
renderSimpleLayout(headerRowContent, bodyContent) {
let { props, context } = this;
let sections = [];
let stickyHeaderDates = internal_cjs.getStickyHeaderDates(context.options);
if (headerRowContent) {
sections.push({
type: 'header',
key: 'header',
isSticky: stickyHeaderDates,
chunk: {
elRef: this.headerElRef,
tableClassName: 'fc-col-header',
rowContent: headerRowContent,
},
});
}
sections.push({
type: 'body',
key: 'body',
liquid: true,
chunk: { content: bodyContent },
});
return (preact_cjs.createElement(internal_cjs.ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
preact_cjs.createElement(internal_cjs.SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [] /* TODO: make optional? */, sections: sections })));
}
renderHScrollLayout(headerRowContent, bodyContent, colCnt, dayMinWidth) {
let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
if (!ScrollGrid) {
throw new Error('No ScrollGrid implementation');
}
let { props, context } = this;
let stickyHeaderDates = !props.forPrint && internal_cjs.getStickyHeaderDates(context.options);
let stickyFooterScrollbar = !props.forPrint && internal_cjs.getStickyFooterScrollbar(context.options);
let sections = [];
if (headerRowContent) {
sections.push({
type: 'header',
key: 'header',
isSticky: stickyHeaderDates,
chunks: [{
key: 'main',
elRef: this.headerElRef,
tableClassName: 'fc-col-header',
rowContent: headerRowContent,
}],
});
}
sections.push({
type: 'body',
key: 'body',
liquid: true,
chunks: [{
key: 'main',
content: bodyContent,
}],
});
if (stickyFooterScrollbar) {
sections.push({
type: 'footer',
key: 'footer',
isSticky: true,
chunks: [{
key: 'main',
content: internal_cjs.renderScrollShim,
}],
});
}
return (preact_cjs.createElement(internal_cjs.ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
preact_cjs.createElement(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: props.forPrint, colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }], sections: sections })));
}
}
function splitSegsByRow(segs, rowCnt) {
let byRow = [];
for (let i = 0; i < rowCnt; i += 1) {
byRow[i] = [];
}
for (let seg of segs) {
byRow[seg.row].push(seg);
}
return byRow;
}
function splitSegsByFirstCol(segs, colCnt) {
let byCol = [];
for (let i = 0; i < colCnt; i += 1) {
byCol[i] = [];
}
for (let seg of segs) {
byCol[seg.firstCol].push(seg);
}
return byCol;
}
function splitInteractionByRow(ui, rowCnt) {
let byRow = [];
if (!ui) {
for (let i = 0; i < rowCnt; i += 1) {
byRow[i] = null;
}
}
else {
for (let i = 0; i < rowCnt; i += 1) {
byRow[i] = {
affectedInstances: ui.affectedInstances,
isEvent: ui.isEvent,
segs: [],
};
}
for (let seg of ui.segs) {
byRow[seg.row].segs.push(seg);
}
}
return byRow;
}
const DEFAULT_TABLE_EVENT_TIME_FORMAT = internal_cjs.createFormatter({
hour: 'numeric',
minute: '2-digit',
omitZeroMinute: true,
meridiem: 'narrow',
});
function hasListItemDisplay(seg) {
let { display } = seg.eventRange.ui;
return display === 'list-item' || (display === 'auto' &&
!seg.eventRange.def.allDay &&
seg.firstCol === seg.lastCol && // can't be multi-day
seg.isStart && // "
seg.isEnd // "
);
}
class TableBlockEvent extends internal_cjs.BaseComponent {
render() {
let { props } = this;
return (preact_cjs.createElement(internal_cjs.StandardEvent, Object.assign({}, props, { elClasses: ['fc-daygrid-event', 'fc-daygrid-block-event', 'fc-h-event'], defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: props.defaultDisplayEventEnd, disableResizing: !props.seg.eventRange.def.allDay })));
}
}
class TableListItemEvent extends internal_cjs.BaseComponent {
render() {
let { props, context } = this;
let { options } = context;
let { seg } = props;
let timeFormat = options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT;
let timeText = internal_cjs.buildSegTimeText(seg, timeFormat, context, true, props.defaultDisplayEventEnd);
return (preact_cjs.createElement(internal_cjs.EventContainer, Object.assign({}, props, { elTag: "a", elClasses: ['fc-daygrid-event', 'fc-daygrid-dot-event'], elAttrs: internal_cjs.getSegAnchorAttrs(props.seg, context), defaultGenerator: renderInnerContent, timeText: timeText, isResizing: false, isDateSelecting: false })));
}
}
function renderInnerContent(renderProps) {
return (preact_cjs.createElement(preact_cjs.Fragment, null,
preact_cjs.createElement("div", { className: "fc-daygrid-event-dot", style: { borderColor: renderProps.borderColor || renderProps.backgroundColor } }),
renderProps.timeText && (preact_cjs.createElement("div", { className: "fc-event-time" }, renderProps.timeText)),
preact_cjs.createElement("div", { className: "fc-event-title" }, renderProps.event.title || preact_cjs.createElement(preact_cjs.Fragment, null, "\u00A0"))));
}
class TableCellMoreLink extends internal_cjs.BaseComponent {
constructor() {
super(...arguments);
this.compileSegs = internal_cjs.memoize(compileSegs);
}
render() {
let { props } = this;
let { allSegs, invisibleSegs } = this.compileSegs(props.singlePlacements);
return (preact_cjs.createElement(internal_cjs.MoreLinkContainer, { elClasses: ['fc-daygrid-more-link'], dateProfile: props.dateProfile, todayRange: props.todayRange, allDayDate: props.allDayDate, moreCnt: props.moreCnt, allSegs: allSegs, hiddenSegs: invisibleSegs, alignmentElRef: props.alignmentElRef, alignGridTop: props.alignGridTop, extraDateSpan: props.extraDateSpan, popoverContent: () => {
let isForcedInvisible = (props.eventDrag ? props.eventDrag.affectedInstances : null) ||
(props.eventResize ? props.eventResize.affectedInstances : null) ||
{};
return (preact_cjs.createElement(preact_cjs.Fragment, null, allSegs.map((seg) => {
let instanceId = seg.eventRange.instance.instanceId;
return (preact_cjs.createElement("div", { className: "fc-daygrid-event-harness", key: instanceId, style: {
visibility: isForcedInvisible[instanceId] ? 'hidden' : '',
} }, hasListItemDisplay(seg) ? (preact_cjs.createElement(TableListItemEvent, Object.assign({ seg: seg, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, internal_cjs.getSegMeta(seg, props.todayRange)))) : (preact_cjs.createElement(TableBlockEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, internal_cjs.getSegMeta(seg, props.todayRange))))));
})));
} }));
}
}
function compileSegs(singlePlacements) {
let allSegs = [];
let invisibleSegs = [];
for (let placement of singlePlacements) {
allSegs.push(placement.seg);
if (!placement.isVisible) {
invisibleSegs.push(placement.seg);
}
}
return { allSegs, invisibleSegs };
}
const DEFAULT_WEEK_NUM_FORMAT = internal_cjs.createFormatter({ week: 'narrow' });
class TableCell extends internal_cjs.DateComponent {
constructor() {
super(...arguments);
this.rootElRef = preact_cjs.createRef();
this.state = {
dayNumberId: internal_cjs.getUniqueDomId(),
};
this.handleRootEl = (el) => {
internal_cjs.setRef(this.rootElRef, el);
internal_cjs.setRef(this.props.elRef, el);
};
}
render() {
let { context, props, state, rootElRef } = this;
let { options, dateEnv } = context;
let { date, dateProfile } = props;
// TODO: memoize this?
const isMonthStart = props.showDayNumber &&
shouldDisplayMonthStart(date, dateProfile.currentRange, dateEnv);
return (preact_cjs.createElement(internal_cjs.DayCellContainer, { elTag: "td", elRef: this.handleRootEl, elClasses: [
'fc-daygrid-day',
...(props.extraClassNames || []),
], elAttrs: Object.assign(Object.assign(Object.assign({}, props.extraDataAttrs), (props.showDayNumber ? { 'aria-labelledby': state.dayNumberId } : {})), { role: 'gridcell' }), defaultGenerator: renderTopInner, date: date, dateProfile: dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, isMonthStart: isMonthStart, extraRenderProps: props.extraRenderProps }, (InnerContent, renderProps) => (preact_cjs.createElement("div", { ref: props.innerElRef, className: "fc-daygrid-day-frame fc-scrollgrid-sync-inner", style: { minHeight: props.minHeight } },
props.showWeekNumber && (preact_cjs.createElement(internal_cjs.WeekNumberContainer, { elTag: "a", elClasses: ['fc-daygrid-week-number'], elAttrs: internal_cjs.buildNavLinkAttrs(context, date, 'week'), date: date, defaultFormat: DEFAULT_WEEK_NUM_FORMAT })),
!renderProps.isDisabled &&
(props.showDayNumber || internal_cjs.hasCustomDayCellContent(options) || props.forceDayTop) ? (preact_cjs.createElement("div", { className: "fc-daygrid-day-top" },
preact_cjs.createElement(InnerContent, { elTag: "a", elClasses: [
'fc-daygrid-day-number',
isMonthStart && 'fc-daygrid-month-start',
], elAttrs: Object.assign(Object.assign({}, internal_cjs.buildNavLinkAttrs(context, date)), { id: state.dayNumberId }) }))) : props.showDayNumber ? (
// for creating correct amount of space (see issue #7162)
preact_cjs.createElement("div", { className: "fc-daygrid-day-top", style: { visibility: 'hidden' } },
preact_cjs.createElement("a", { className: "fc-daygrid-day-number" }, "\u00A0"))) : undefined,
preact_cjs.createElement("div", { className: "fc-daygrid-day-events", ref: props.fgContentElRef },
props.fgContent,
preact_cjs.createElement("div", { className: "fc-daygrid-day-bottom", style: { marginTop: props.moreMarginTop } },
preact_cjs.createElement(TableCellMoreLink, { allDayDate: date, singlePlacements: props.singlePlacements, moreCnt: props.moreCnt, alignmentElRef: rootElRef, alignGridTop: !props.showDayNumber, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange }))),
preact_cjs.createElement("div", { className: "fc-daygrid-day-bg" }, props.bgContent)))));
}
}
function renderTopInner(props) {
return props.dayNumberText || preact_cjs.createElement(preact_cjs.Fragment, null, "\u00A0");
}
function shouldDisplayMonthStart(date, currentRange, dateEnv) {
const { start: currentStart, end: currentEnd } = currentRange;
const currentEndIncl = internal_cjs.addMs(currentEnd, -1);
const currentFirstYear = dateEnv.getYear(currentStart);
const currentFirstMonth = dateEnv.getMonth(currentStart);
const currentLastYear = dateEnv.getYear(currentEndIncl);
const currentLastMonth = dateEnv.getMonth(currentEndIncl);
// spans more than one month?
return !(currentFirstYear === currentLastYear && currentFirstMonth === currentLastMonth) &&
Boolean(
// first date in current view?
date.valueOf() === currentStart.valueOf() ||
// a month-start that's within the current range?
(dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf()));
}
function generateSegKey(seg) {
return seg.eventRange.instance.instanceId + ':' + seg.firstCol;
}
function generateSegUid(seg) {
return generateSegKey(seg) + ':' + seg.lastCol;
}
function computeFgSegPlacement(segs, // assumed already sorted
dayMaxEvents, dayMaxEventRows, strictOrder, segHeights, maxContentHeight, cells) {
let hierarchy = new DayGridSegHierarchy((segEntry) => {
// TODO: more DRY with generateSegUid
let segUid = segs[segEntry.index].eventRange.instance.instanceId +
':' + segEntry.span.start +
':' + (segEntry.span.end - 1);
// if no thickness known, assume 1 (if 0, so small it always fits)
return segHeights[segUid] || 1;
});
hierarchy.allowReslicing = true;
hierarchy.strictOrder = strictOrder;
if (dayMaxEvents === true || dayMaxEventRows === true) {
hierarchy.maxCoord = maxContentHeight;
hierarchy.hiddenConsumes = true;
}
else if (typeof dayMaxEvents === 'number') {
hierarchy.maxStackCnt = dayMaxEvents;
}
else if (typeof dayMaxEventRows === 'number') {
hierarchy.maxStackCnt = dayMaxEventRows;
hierarchy.hiddenConsumes = true;
}
// create segInputs only for segs with known heights
let segInputs = [];
let unknownHeightSegs = [];
for (let i = 0; i < segs.length; i += 1) {
let seg = segs[i];
let segUid = generateSegUid(seg);
let eventHeight = segHeights[segUid];
if (eventHeight != null) {
segInputs.push({
index: i,
span: {
start: seg.firstCol,
end: seg.lastCol + 1,
},
});
}
else {
unknownHeightSegs.push(seg);
}
}
let hiddenEntries = hierarchy.addSegs(segInputs);
let segRects = hierarchy.toRects();
let { singleColPlacements, multiColPlacements, leftoverMargins } = placeRects(segRects, segs, cells);
let moreCnts = [];
let moreMarginTops = [];
// add segs with unknown heights
for (let seg of unknownHeightSegs) {
multiColPlacements[seg.firstCol].push({
seg,
isVisible: false,
isAbsolute: true,
absoluteTop: 0,
marginTop: 0,
});
for (let col = seg.firstCol; col <= seg.lastCol; col += 1) {
singleColPlacements[col].push({
seg: resliceSeg(seg, col, col + 1, cells),
isVisible: false,
isAbsolute: false,
absoluteTop: 0,
marginTop: 0,
});
}
}
// add the hidden entries
for (let col = 0; col < cells.length; col += 1) {
moreCnts.push(0);
}
for (let hiddenEntry of hiddenEntries) {
let seg = segs[hiddenEntry.index];
let hiddenSpan = hiddenEntry.span;
multiColPlacements[hiddenSpan.start].push({
seg: resliceSeg(seg, hiddenSpan.start, hiddenSpan.end, cells),
isVisible: false,
isAbsolute: true,
absoluteTop: 0,
marginTop: 0,
});
for (let col = hiddenSpan.start; col < hiddenSpan.end; col += 1) {
moreCnts[col] += 1;
singleColPlacements[col].push({
seg: resliceSeg(seg, col, col + 1, cells),
isVisible: false,
isAbsolute: false,
absoluteTop: 0,
marginTop: 0,
});
}
}
// deal with leftover margins
for (let col = 0; col < cells.length; col += 1) {
moreMarginTops.push(leftoverMargins[col]);
}
return { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops };
}
// rects ordered by top coord, then left
function placeRects(allRects, segs, cells) {
let rectsByEachCol = groupRectsByEachCol(allRects, cells.length);
let singleColPlacements = [];
let multiColPlacements = [];
let leftoverMargins = [];
for (let col = 0; col < cells.length; col += 1) {
let rects = rectsByEachCol[col];
// compute all static segs in singlePlacements
let singlePlacements = [];
let currentHeight = 0;
let currentMarginTop = 0;
for (let rect of rects) {
let seg = segs[rect.index];
singlePlacements.push({
seg: resliceSeg(seg, col, col + 1, cells),
isVisible: true,
isAbsolute: false,
absoluteTop: rect.levelCoord,
marginTop: rect.levelCoord - currentHeight,
});
currentHeight = rect.levelCoord + rect.thickness;
}
// compute mixed static/absolute segs in multiPlacements
let multiPlacements = [];
currentHeight = 0;
currentMarginTop = 0;
for (let rect of rects) {
let seg = segs[rect.index];
let isAbsolute = rect.span.end - rect.span.start > 1; // multi-column?
let isFirstCol = rect.span.start === col;
currentMarginTop += rect.levelCoord - currentHeight; // amount of space since bottom of previous seg
currentHeight = rect.levelCoord + rect.thickness; // height will now be bottom of current seg
if (isAbsolute) {
currentMarginTop += rect.thickness;
if (isFirstCol) {
multiPlacements.push({
seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
isVisible: true,
isAbsolute: true,
absoluteTop: rect.levelCoord,
marginTop: 0,
});
}
}
else if (isFirstCol) {
multiPlacements.push({
seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
isVisible: true,
isAbsolute: false,
absoluteTop: rect.levelCoord,
marginTop: currentMarginTop, // claim the margin
});
currentMarginTop = 0;
}
}
singleColPlacements.push(singlePlacements);
multiColPlacements.push(multiPlacements);
leftoverMargins.push(currentMarginTop);
}
return { singleColPlacements, multiColPlacements, leftoverMargins };
}
function groupRectsByEachCol(rects, colCnt) {
let rectsByEachCol = [];
for (let col = 0; col < colCnt; col += 1) {
rectsByEachCol.push([]);
}
for (let rect of rects) {
for (let col = rect.span.start; col < rect.span.end; col += 1) {
rectsByEachCol[col].push(rect);
}
}
return rectsByEachCol;
}
function resliceSeg(seg, spanStart, spanEnd, cells) {
if (seg.firstCol === spanStart && seg.lastCol === spanEnd - 1) {
return seg;
}
let eventRange = seg.eventRange;
let origRange = eventRange.range;
let slicedRange = internal_cjs.intersectRanges(origRange, {
start: cells[spanStart].date,
end: internal_cjs.addDays(cells[spanEnd - 1].date, 1),
});
return Object.assign(Object.assign({}, seg), { firstCol: spanStart, lastCol: spanEnd - 1, eventRange: {
def: eventRange.def,
ui: Object.assign(Object.assign({}, eventRange.ui), { durationEditable: false }),
instance: eventRange.instance,
range: slicedRange,
}, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() });
}
class DayGridSegHierarchy extends internal_cjs.SegHierarchy {
constructor() {
super(...arguments);
// config
this.hiddenConsumes = false;
// allows us to keep hidden entries in the hierarchy so they take up space
this.forceHidden = {};
}
addSegs(segInputs) {
const hiddenSegs = super.addSegs(segInputs);
const { entriesByLevel } = this;
const excludeHidden = (entry) => !this.forceHidden[internal_cjs.buildEntryKey(entry)];
// remove the forced-hidden segs
for (let level = 0; level < entriesByLevel.length; level += 1) {
entriesByLevel[level] = entriesByLevel[level].filter(excludeHidden);
}
return hiddenSegs;
}
handleInvalidInsertion(insertion, entry, hiddenEntries) {
const { entriesByLevel, forceHidden } = this;
const { touchingEntry, touchingLevel, touchingLateral } = insertion;
// the entry that the new insertion is touching must be hidden
if (this.hiddenConsumes && touchingEntry) {
const touchingEntryId = internal_cjs.buildEntryKey(touchingEntry);
if (!forceHidden[touchingEntryId]) {
if (this.allowReslicing) {
// split up the touchingEntry, reinsert it
const hiddenEntry = Object.assign(Object.assign({}, touchingEntry), { span: internal_cjs.intersectSpans(touchingEntry.span, entry.span) });
// reinsert the area that turned into a "more" link (so no other entries try to
// occupy the space) but mark it forced-hidden
const hiddenEntryId = internal_cjs.buildEntryKey(hiddenEntry);
forceHidden[hiddenEntryId] = true;
entriesByLevel[touchingLevel][touchingLateral] = hiddenEntry;
hiddenEntries.push(hiddenEntry);
this.splitEntry(touchingEntry, entry, hiddenEntries);
}
else {
forceHidden[touchingEntryId] = true;
hiddenEntries.push(touchingEntry);
}
}
}
// will try to reslice...
super.handleInvalidInsertion(insertion, entry, hiddenEntries);
}
}
class TableRow extends internal_cjs.DateComponent {
constructor() {
super(...arguments);
this.cellElRefs = new internal_cjs.RefMap(); // the <td>
this.frameElRefs = new internal_cjs.RefMap(); // the fc-daygrid-day-frame
this.fgElRefs = new internal_cjs.RefMap(); // the fc-daygrid-day-events
this.segHarnessRefs = new internal_cjs.RefMap(); // indexed by "instanceId:firstCol"
this.rootElRef = preact_cjs.createRef();
this.state = {
framePositions: null,
maxContentHeight: null,
segHeights: {},
};
this.handleResize = (isForced) => {
if (isForced) {
this.updateSizing(true); // isExternal=true
}
};
}
render() {
let { props, state, context } = this;
let { options } = context;
let colCnt = props.cells.length;
let businessHoursByCol = splitSegsByFirstCol(props.businessHourSegs, colCnt);
let bgEventSegsByCol = splitSegsByFirstCol(props.bgEventSegs, colCnt);
let highlightSegsByCol = splitSegsByFirstCol(this.getHighlightSegs(), colCnt);
let mirrorSegsByCol = splitSegsByFirstCol(this.getMirrorSegs(), colCnt);
let { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops } = computeFgSegPlacement(internal_cjs.sortEventSegs(props.fgEventSegs, options.eventOrder), props.dayMaxEvents, props.dayMaxEventRows, options.eventOrderStrict, state.segHeights, state.maxContentHeight, props.cells);
let isForcedInvisible = // TODO: messy way to compute this
(props.eventDrag && props.eventDrag.affectedInstances) ||
(props.eventResize && props.eventResize.affectedInstances) ||
{};
return (preact_cjs.createElement("tr", { ref: this.rootElRef, role: "row" },
props.renderIntro && props.renderIntro(),
props.cells.map((cell, col) => {
let normalFgNodes = this.renderFgSegs(col, props.forPrint ? singleColPlacements[col] : multiColPlacements[col], props.todayRange, isForcedInvisible);
let mirrorFgNodes = this.renderFgSegs(col, buildMirrorPlacements(mirrorSegsByCol[col], multiColPlacements), props.todayRange, {}, Boolean(props.eventDrag), Boolean(props.eventResize), false);
return (preact_cjs.createElement(TableCell, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), innerElRef: this.frameElRefs.createRef(cell.key) /* FF <td> problem, but okay to use for left/right. TODO: rename prop */, dateProfile: props.dateProfile, date: cell.date, showDayNumber: props.showDayNumbers, showWeekNumber: props.showWeekNumbers && col === 0, forceDayTop: props.showWeekNumbers /* even displaying weeknum for row, not necessarily day */, todayRange: props.todayRange, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, moreCnt: moreCnts[col], moreMarginTop: moreMarginTops[col], singlePlacements: singleColPlacements[col], fgContentElRef: this.fgElRefs.createRef(cell.key), fgContent: ( // Fragment scopes the keys
preact_cjs.createElement(preact_cjs.Fragment, null,
preact_cjs.createElement(preact_cjs.Fragment, null, normalFgNodes),
preact_cjs.createElement(preact_cjs.Fragment, null, mirrorFgNodes))), bgContent: ( // Fragment scopes the keys
preact_cjs.createElement(preact_cjs.Fragment, null,
this.renderFillSegs(highlightSegsByCol[col], 'highlight'),
this.renderFillSegs(businessHoursByCol[col], 'non-business'),
this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))), minHeight: props.cellMinHeight }));
})));
}
componentDidMount() {
this.updateSizing(true);
this.context.addResizeHandler(this.handleResize);
}
componentDidUpdate(prevProps, prevState) {
let currentProps = this.props;
this.updateSizing(!internal_cjs.isPropsEqual(prevProps, currentProps));
}
componentWillUnmount() {
this.context.removeResizeHandler(this.handleResize);
}
getHighlightSegs() {
let { props } = this;
if (props.eventDrag && props.eventDrag.segs.length) { // messy check
return props.eventDrag.segs;
}
if (props.eventResize && props.eventResize.segs.length) { // messy check
return props.eventResize.segs;
}
return props.dateSelectionSegs;
}
getMirrorSegs() {
let { props } = this;
if (props.eventResize && props.eventResize.segs.length) { // messy check
return props.eventResize.segs;
}
return [];
}
renderFgSegs(col, segPlacements, todayRange, isForcedInvisible, isDragging, isResizing, isDateSelecting) {
let { context } = this;
let { eventSelection } = this.props;
let { framePositions } = this.state;
let defaultDisplayEventEnd = this.props.cells.length === 1; // colCnt === 1
let isMirror = isDragging || isResizing || isDateSelecting;
let nodes = [];
if (framePositions) {
for (let placement of segPlacements) {
let { seg } = placement;
let { instanceId } = seg.eventRange.instance;
let isVisible = placement.isVisible && !isForcedInvisible[instanceId];
let isAbsolute = placement.isAbsolute;
let left = '';
let right = '';
if (isAbsolute) {
if (context.isRtl) {
right = 0;
left = framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol];
}
else {
left = 0;
right = framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol];
}
}
/*
known bug: events that are force to be list-item but span multiple days still take up space in later columns
todo: in print view, for multi-day events, don't display title within non-start/end segs
*/
nodes.push(preact_cjs.createElement("div", { className: 'fc-daygrid-event-harness' + (isAbsolute ? ' fc-daygrid-event-harness-abs' : ''), key: generateSegKey(seg), ref: isMirror ? null : this.segHarnessRefs.createRef(generateSegUid(seg)), style: {
visibility: isVisible ? '' : 'hidden',
marginTop: isAbsolute ? '' : placement.marginTop,
top: isAbsolute ? placement.absoluteTop : '',
left,
right,
} }, hasListItemDisplay(seg) ? (preact_cjs.createElement(TableListItemEvent, Object.assign({ seg: seg, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal_cjs.getSegMeta(seg, todayRange)))) : (preact_cjs.createElement(TableBlockEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal_cjs.getSegMeta(seg, todayRange))))));
}
}
return nodes;
}
renderFillSegs(segs, fillType) {
let { isRtl } = this.context;
let { todayRange } = this.props;
let { framePositions } = this.state;
let nodes = [];
if (framePositions) {
for (let seg of segs) {
let leftRightCss = isRtl ? {
right: 0,
left: framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol],
} : {
left: 0,
right: framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol],
};
nodes.push(preact_cjs.createElement("div", { key: internal_cjs.buildEventRangeKey(seg.eventRange), className: "fc-daygrid-bg-harness", style: leftRightCss }, fillType === 'bg-event' ?
preact_cjs.createElement(internal_cjs.BgEvent, Object.assign({ seg: seg }, internal_cjs.getSegMeta(seg, todayRange))) :
internal_cjs.renderFill(fillType)));
}
}
return preact_cjs.createElement(preact_cjs.Fragment, {}, ...nodes);
}
updateSizing(isExternalSizingChange) {
let { props, state, frameElRefs } = this;
if (!props.forPrint &&
props.clientWidth !== null // positioning ready?
) {
if (isExternalSizingChange) {
let frameEls = props.cells.map((cell) => frameElRefs.currentMap[cell.key]);
if (frameEls.length) {
let originEl = this.rootElRef.current;
let newPositionCache = new internal_cjs.PositionCache(originEl, frameEls, true, // isHorizontal
false);
if (!state.framePositions || !state.framePositions.similarTo(newPositionCache)) {
this.setState({
framePositions: new internal_cjs.PositionCache(originEl, frameEls, true, // isHorizontal
false),
});
}
}
}
const oldSegHeights = this.state.segHeights;
const newSegHeights = this.querySegHeights();
const limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
this.safeSetState({
// HACK to prevent oscillations of events being shown/hidden from max-event-rows
// Essentially, once you compute an element's height, never null-out.
// TODO: always display all events, as visibility:hidden?
segHeights: Object.assign(Object.assign({}, oldSegHeights), newSegHeights),
maxContentHeight: limitByContentHeight ? this.computeMaxContentHeight() : null,
});
}
}
querySegHeights() {
let segElMap = this.segHarnessRefs.currentMap;
let segHeights = {};
// get the max height amongst instance segs
for (let segUid in segElMap) {
let height = Math.round(segElMap[segUid].getBoundingClientRect().height);
segHeights[segUid] = Math.max(segHeights[segUid] || 0, height);
}
return segHeights;
}
computeMaxContentHeight() {
let firstKey = this.props.cells[0].key;
let cellEl = this.cellElRefs.currentMap[firstKey];
let fcContainerEl = this.fgElRefs.currentMap[firstKey];
return cellEl.getBoundingClientRect().bottom - fcContainerEl.getBoundingClientRect().top;
}
getCellEls() {
let elMap = this.cellElRefs.currentMap;
return this.props.cells.map((cell) => elMap[cell.key]);
}
}
TableRow.addStateEquality({
segHeights: internal_cjs.isPropsEqual,
});
function buildMirrorPlacements(mirrorSegs, colPlacements) {
if (!mirrorSegs.length) {
return [];
}
let topsByInstanceId = buildAbsoluteTopHash(colPlacements); // TODO: cache this at first render?
return mirrorSegs.map((seg) => ({
seg,
isVisible: true,
isAbsolute: true,
absoluteTop: topsByInstanceId[seg.eventRange.instance.instanceId],
marginTop: 0,
}));
}
function buildAbsoluteTopHash(colPlacements) {
let topsByInstanceId = {};
for (let placements of colPlacements) {
for (let placement of placements) {
topsByInstanceId[placement.seg.eventRange.instance.instanceId] = placement.absoluteTop;
}
}
return topsByInstanceId;
}
class TableRows extends internal_cjs.DateComponent {
constructor() {
super(...arguments);
this.splitBusinessHourSegs = internal_cjs.memoize(splitSegsByRow);
this.splitBgEventSegs = internal_cjs.memoize(splitSegsByRow);
this.splitFgEventSegs = internal_cjs.memoize(splitSegsByRow);
this.splitDateSelectionSegs = internal_cjs.memoize(splitSegsByRow);
this.splitEventDrag = internal_cjs.memoize(splitInteractionByRow);
this.splitEventResize = internal_cjs.memoize(splitInteractionByRow);
this.rowRefs = new internal_cjs.RefMap();
}
render() {
let { props, context } = this;
let rowCnt = props.cells.length;
let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt);
let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);
let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt);
let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt);
let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt);
let eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt);
// for DayGrid view with many rows, force a min-height on cells so doesn't appear squished
// choose 7 because a month view will have max 6 rows
let cellMinHeight = (rowCnt >= 7 && props.clientWidth) ?
props.clientWidth / context.options.aspectRatio / 6 :
null;
return (preact_cjs.createElement(internal_cjs.NowTimer, { unit: "day" }, (nowDate, todayRange) => (preact_cjs.createElement(preact_cjs.Fragment, null, props.cells.map((cells, row) => (preact_cjs.createElement(TableRow, { ref: this.rowRefs.createRef(row), key: cells.length
? cells[0].date.toISOString() /* best? or put key on cell? or use diff formatter? */
: row // in case there are no cells (like when resource view is loading)
, showDayNumbers: rowCnt > 1, showWeekNumbers: props.showWeekNumbers, todayRange: todayRange, dateProfile: props.dateProfile, cells: cells, renderIntro: props.renderRowIntro, businessHourSegs: businessHourSegsByRow[row], eventSelection: props.eventSelection, bgEventSegs: bgEventSegsByRow[row].filter(isSegAllDay) /* hack */, fgEventSegs: fgEventSegsByRow[row], dateSelectionSegs: dateSelectionSegsByRow[row], eventDrag: eventDragByRow[row], eventResize: eventResizeByRow[row], dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, clientWidth: props.clientWidth, clientHeight: props.clientHeight, cellMinHeight: cellMinHeight, forPrint: props.forPrint })))))));
}
componentDidMount() {
this.registerInteractiveComponent();
}
componentDidUpdate() {
// for if started with zero cells
this.registerInteractiveComponent();
}
registerInteractiveComponent() {
if (!this.rootEl) {
// HACK: need a daygrid wrapper parent to do positioning
// NOTE: a daygrid resource view w/o resources can have zero cells
const firstCellEl = this.rowRefs.currentMap[0].getCellEls()[0];
const rootEl = firstCellEl ? firstCellEl.closest('.fc-daygrid-body') : null;
if (rootEl) {
this.rootEl = rootEl;
this.context.registerInteractiveComponent(this, {
el: rootEl,
isHitComboAllowed: this.props.isHitComboAllowed,
});
}
}
}
componentWillUnmount() {
if (this.rootEl) {
this.context.unregisterInteractiveComponent(this);
this.rootEl = null;
}
}
// Hit System
// ----------------------------------------------------------------------------------------------------
prepareHits() {
this.rowPositions = new internal_cjs.PositionCache(this.rootEl, this.rowRefs.collect().map((rowObj) => rowObj.getCellEls()[0]), // first cell el in each row. TODO: not optimal
false, true);
this.colPositions = new internal_cjs.PositionCache(this.rootEl, this.rowRefs.currentMap[0].getCellEls(), // cell els in first row
true, // horizontal
false);
}
queryHit(positionLeft, positionTop) {
let { colPositions, rowPositions } = this;
let col = colPositions.leftToIndex(positionLeft);
let row = rowPositions.topToIndex(positionTop);
if (row != null && col != null) {
let cell = this.props.cells[row][col];
return {
dateProfile: this.props.dateProfile,
dateSpan: Object.assign({ range: this.getCellRange(row, col), allDay: true }, cell.extraDateSpan),
dayEl: this.getCellEl(row, col),
rect: {
left: colPositions.lefts[col],
right: colPositions.rights[col],
top: rowPositions.tops[row],
bottom: rowPositions.bottoms[row],
},
layer: 0,
};
}
return null;
}
getCellEl(row, col) {
return this.rowRefs.currentMap[row].getCellEls()[col]; // TODO: not optimal
}
getCellRange(row, col) {
let start = this.props.cells[row][col].date;
let end = internal_cjs.addDays(start, 1);
return { start, end };
}
}
function isSegAllDay(seg) {
return seg.eventRange.def.allDay;
}
class Table extends internal_cjs.DateComponent {
constructor() {
super(...arguments);
this.elRef = preact_cjs.createRef();
this.needsScrollReset = false;
}
render() {
let { props } = this;
let { dayMaxEventRows, dayMaxEvents, expandRows } = props;
let limitViaBalanced = dayMaxEvents === true || dayMaxEventRows === true;
// if rows can't expand to fill fixed height, can't do balanced-height event limit
// TODO: best place to normalize these options?
if (limitViaBalanced && !expandRows) {
limitViaBalanced = false;
dayMaxEventRows = null;
dayMaxEvents = null;
}
let classNames = [
'fc-daygrid-body',
limitViaBalanced ? 'fc-daygrid-body-balanced' : 'fc-daygrid-body-unbalanced',
expandRows ? '' : 'fc-daygrid-body-natural', // will height of one row depend on the others?
];
return (preact_cjs.createElement("div", { ref: this.elRef, className: classNames.join(' '), 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_cjs.createElement("table", { role: "presentation", className: "fc-scrollgrid-sync-table", style: {
width: props.clientWidth,
minWidth: props.tableMinWidth,
height: expandRows ? props.clientHeight : '',
} },
props.colGroupNode,
preact_cjs.createElement("tbody", { role: "presentation" },
preact_cjs.createElement(TableRows, { dateProfile: props.dateProfile, cells: props.cells, renderRowIntro: props.renderRowIntro, showWeekNumbers: props.showWeekNumbers, clientWidth: props.clientWidth, clientHeight: props.clientHeight, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, dayMaxEvents: dayMaxEvents, dayMaxEventRows: dayMaxEventRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed })))));
}
componentDidMount() {
this.requestScrollReset();
}
componentDidUpdate(prevProps) {
if (prevProps.dateProfile !== this.props.dateProfile) {
this.requestScrollReset();
}
else {
this.flushScrollReset();
}
}
requestScrollReset() {
this.needsScrollReset = true;
this.flushScrollReset();
}
flushScrollReset() {
if (this.needsScrollReset &&
this.props.clientWidth // sizes computed?
) {
const subjectEl = getScrollSubjectEl(this.elRef.current, this.props.dateProfile);
if (subjectEl) {
const originEl = subjectEl.closest('.fc-daygrid-body');
const scrollEl = originEl.closest('.fc-scroller');
const scrollTop = subjectEl.getBoundingClientRect().top -
originEl.getBoundingClientRect().top;
scrollEl.scrollTop = scrollTop ? (scrollTop + 1) : 0; // overcome border
}
this.needsScrollReset = false;
}
}
}
function getScrollSubjectEl(containerEl, dateProfile) {
let el;
if (dateProfile.currentRangeUnit.match(/year|month/)) {
el = containerEl.querySelector(`[data-date="${internal_cjs.formatIsoMonthStr(dateProfile.currentDate)}-01"]`);
// even if view is month-based, first-of-month might be hidden...
}
if (!el) {
el = containerEl.querySelector(`[data-date="${internal_cjs.formatDayString(dateProfile.currentDate)}"]`);
// could still be hidden if an interior-view hidden day
}
return el;
}
class DayTableSlicer extends internal_cjs.Slicer {
constructor() {
super(...arguments);
this.forceDayIfListItem = true;
}
sliceRange(dateRange, dayTableModel) {
return dayTableModel.sliceRange(dateRange);
}
}
class DayTable extends internal_cjs.DateComponent {
constructor() {
super(...arguments);
this.slicer = new DayTableSlicer();
this.tableRef = preact_cjs.createRef();
}
render() {
let { props, context } = this;
return (preact_cjs.createElement(Table, Object.assign({ ref: this.tableRef }, this.slicer.sliceProps(props, props.dateProfile, props.nextDayThreshold, context, props.dayTableModel), { dateProfile: props.dateProfile, cells: props.dayTableModel.cells, colGroupNode: props.colGroupNode, tableMinWidth: props.tableMinWidth, renderRowIntro: props.renderRowIntro, dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, showWeekNumbers: props.showWeekNumbers, expandRows: props.expandRows, headerAlignElRef: props.headerAlignElRef, clientWidth: props.clientWidth, clientHeight: props.clientHeight, forPrint: props.forPrint })));
}
}
class DayTableView extends TableView {
constructor() {
super(...arguments);
this.buildDayTableModel = internal_cjs.memoize(buildDayTableModel);
this.headerRef = preact_cjs.createRef();
this.tableRef = preact_cjs.createRef();
// can't override any lifecycle methods from parent
}
render() {
let { options, dateProfileGenerator } = this.context;
let { props } = this;
let dayTableModel = this.buildDayTableModel(props.dateProfile, dateProfileGenerator);
let headerContent = options.dayHeaders && (preact_cjs.createElement(internal_cjs.DayHeader, { ref: this.headerRef, dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: dayTableModel.rowCnt === 1 }));
let bodyContent = (contentArg) => (preact_cjs.createElement(DayTable, { ref: this.tableRef, dateProfile: props.dateProfile, dayTableModel: dayTableModel, businessHours: props.businessHours, dateSelection: props.dateSelection, eventStore: props.eventStore, eventUiBases: props.eventUiBases, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, nextDayThreshold: options.nextDayThreshold, colGroupNode: contentArg.tableColGroupNode, tableMinWidth: contentArg.tableMinWidth, dayMaxEvents: options.dayMaxEvents, dayMaxEventRows: options.dayMaxEventRows, showWeekNumbers: options.weekNumbers, expandRows: !props.isHeightAuto, headerAlignElRef: this.headerElRef, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, forPrint: props.forPrint }));
return options.dayMinWidth
? this.renderHScrollLayout(headerContent, bodyContent, dayTableModel.colCnt, options.dayMinWidth)
: this.renderSimpleLayout(headerContent, bodyContent);
}
}
function buildDayTableModel(dateProfile, dateProfileGenerator) {
let daySeries = new internal_cjs.DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
return new internal_cjs.DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
}
class TableDateProfileGenerator extends internal_cjs.DateProfileGenerator {
// Computes the date range that will be rendered
buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay);
let { props } = this;
return buildDayTableRenderRange({
currentRange: renderRange,
snapToWeek: /^(year|month)$/.test(currentRangeUnit),
fixedWeekCount: props.fixedWeekCount,
dateEnv: props.dateEnv,
});
}
}
function buildDayTableRenderRange(props) {
let { dateEnv, currentRange } = props;
let { start, end } = currentRange;
let endOfWeek;
// year and month views should be aligned with weeks. this is already done for week
if (props.snapToWeek) {
start = dateEnv.startOfWeek(start);
// make end-of-week if not already
endOfWeek = dateEnv.startOfWeek(end);
if (endOfWeek.valueOf() !== end.valueOf()) {
end = internal_cjs.addWeeks(endOfWeek, 1);
}
}
// ensure 6 weeks
if (props.fixedWeekCount) {
// TODO: instead of these date-math gymnastics (for multimonth view),
// compute dateprofiles of all months, then use start of first and end of last.
let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth(internal_cjs.addDays(currentRange.end, -1)));
let rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
internal_cjs.diffWeeks(lastMonthRenderStart, end));
end = internal_cjs.addWeeks(end, 6 - rowCnt);
}
return { start, end };
}
var css_248z = ":root{--fc-daygrid-event-dot-width:8px}.fc-daygrid-day-events:after,.fc-daygrid-day-events:before,.fc-daygrid-day-frame:after,.fc-daygrid-day-frame:before,.fc-daygrid-event-harness:after,.fc-daygrid-event-harness:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-body{position:relative;z-index:1}.fc .fc-daygrid-day.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-daygrid-day-frame{min-height:100%;position:relative}.fc .fc-daygrid-day-top{display:flex;flex-direction:row-reverse}.fc .fc-day-other .fc-daygrid-day-top{opacity:.3}.fc .fc-daygrid-day-number{padding:4px;position:relative;z-index:4}.fc .fc-daygrid-month-start{font-size:1.1em;font-weight:700}.fc .fc-daygrid-day-events{margin-top:1px}.fc .fc-daygrid-body-balanced .fc-daygrid-day-events{left:0;position:absolute;right:0}.fc .fc-daygrid-body-unbalanced .fc-daygrid-day-events{min-height:2em;position:relative}.fc .fc-daygrid-body-natural .fc-daygrid-day-events{margin-bottom:1em}.fc .fc-daygrid-event-harness{position:relative}.fc .fc-daygrid-event-harness-abs{left:0;position:absolute;right:0;top:0}.fc .fc-daygrid-bg-harness{bottom:0;position:absolute;top:0}.fc .fc-daygrid-day-bg .fc-non-business{z-index:1}.fc .fc-daygrid-day-bg .fc-bg-event{z-index:2}.fc .fc-daygrid-day-bg .fc-highlight{z-index:3}.fc .fc-daygrid-event{margin-top:1px;z-index:6}.fc .fc-daygrid-event.fc-event-mirror{z-index:7}.fc .fc-daygrid-day-bottom{font-size:.85em;margin:0 2px}.fc .fc-daygrid-day-bottom:after,.fc .fc-daygrid-day-bottom:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-more-link{border-radius:3px;cursor:pointer;line-height:1;margin-top:1px;max-width:100%;overflow:hidden;padding:2px;position:relative;white-space:nowrap;z-index:4}.fc .fc-daygrid-more-link:hover{background-color:rgba(0,0,0,.1)}.fc .fc-daygrid-week-number{background-color:var(--fc-neutral-bg-color);color:var(--fc-neutral-text-color);min-width:1.5em;padding:2px;position:absolute;text-align:center;top:0;z-index:5}.fc .fc-more-popover .fc-popover-body{min-width:220px;padding:10px}.fc-direction-ltr .fc-daygrid-event.fc-event-start,.fc-direction-rtl .fc-daygrid-event.fc-event-end{margin-left:2px}.fc-direction-ltr .fc-daygrid-event.fc-event-end,.fc-direction-rtl .fc-daygrid-event.fc-event-start{margin-right:2px}.fc-direction-ltr .fc-daygrid-more-link{float:left}.fc-direction-ltr .fc-daygrid-week-number{border-radius:0 0 3px 0;left:0}.fc-direction-rtl .fc-daygrid-more-link{float:right}.fc-direction-rtl .fc-daygrid-week-number{border-radius:0 0 0 3px;right:0}.fc-liquid-hack .fc-daygrid-day-frame{position:static}.fc-daygrid-event{border-radius:3px;font-size:var(--fc-small-font-size);position:relative;white-space:nowrap}.fc-daygrid-block-event .fc-event-time{font-weight:700}.fc-daygrid-block-event .fc-event-time,.fc-daygrid-block-event .fc-event-title{padding:1px}.fc-daygrid-dot-event{align-items:center;display:flex;padding:2px 0}.fc-daygrid-dot-event .fc-event-title{flex-grow:1;flex-shrink:1;font-weight:700;min-width:0;overflow:hidden}.fc-daygrid-dot-event.fc-event-mirror,.fc-daygrid-dot-event:hover{background:rgba(0,0,0,.1)}.fc-daygrid-dot-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-daygrid-event-dot{border:calc(var(--fc-daygrid-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-daygrid-event-dot-width)/2);box-sizing:content-box;height:0;margin:0 4px;width:0}.fc-direction-ltr .fc-daygrid-event .fc-event-time{margin-right:3px}.fc-direction-rtl .fc-daygrid-event .fc-event-time{margin-left:3px}";
internal_cjs.injectStyles(css_248z);
exports.DayGridView = DayTableView;
exports.DayTable = DayTable;
exports.DayTableSlicer = DayTableSlicer;
exports.Table = Table;
exports.TableDateProfileGenerator = TableDateProfileGenerator;
exports.TableRows = TableRows;
exports.TableView = TableView;
exports.buildDayTableModel = buildDayTableModel;
exports.buildDayTableRenderRange = buildDayTableRenderRange;

View File

@@ -0,0 +1,126 @@
import { Duration, CssDimValue } from '@fullcalendar/core';
import { DateComponent, ViewContext, DateProfile, DayTableModel, EventStore, EventUiHash, DateSpan, EventInteractionState, Seg, Slicer, DateRange, DateProfileGenerator, DateEnv, Hit, DayTableCell, EventSegUiInteractionState, Dictionary, ViewProps, ChunkConfigRowContent, ChunkContentCallbackArgs } from '@fullcalendar/core/internal';
import { createElement, VNode, RefObject } from '@fullcalendar/core/preact';
interface DayTableProps {
dateProfile: DateProfile;
dayTableModel: DayTableModel;
nextDayThreshold: Duration;
businessHours: EventStore;
eventStore: EventStore;
eventUiBases: EventUiHash;
dateSelection: DateSpan | null;
eventSelection: string;
eventDrag: EventInteractionState | null;
eventResize: EventInteractionState | null;
colGroupNode: VNode;
tableMinWidth: CssDimValue;
renderRowIntro?: () => VNode;
dayMaxEvents: boolean | number;
dayMaxEventRows: boolean | number;
expandRows: boolean;
showWeekNumbers: boolean;
headerAlignElRef?: RefObject<HTMLElement>;
clientWidth: number | null;
clientHeight: number | null;
forPrint: boolean;
}
declare class DayTable extends DateComponent<DayTableProps, ViewContext> {
private slicer;
private tableRef;
render(): createElement.JSX.Element;
}
interface TableSeg extends Seg {
row: number;
firstCol: number;
lastCol: number;
}
declare class DayTableSlicer extends Slicer<TableSeg, [DayTableModel]> {
forceDayIfListItem: boolean;
sliceRange(dateRange: DateRange, dayTableModel: DayTableModel): TableSeg[];
}
declare class TableDateProfileGenerator extends DateProfileGenerator {
buildRenderRange(currentRange: any, currentRangeUnit: any, isRangeAllDay: any): DateRange;
}
declare function buildDayTableRenderRange(props: {
currentRange: DateRange;
snapToWeek: boolean;
fixedWeekCount: boolean;
dateEnv: DateEnv;
}): DateRange;
interface TableRowsProps {
dateProfile: DateProfile;
cells: DayTableCell[][];
renderRowIntro?: () => VNode;
showWeekNumbers: boolean;
clientWidth: number | null;
clientHeight: number | null;
businessHourSegs: TableSeg[];
bgEventSegs: TableSeg[];
fgEventSegs: TableSeg[];
dateSelectionSegs: TableSeg[];
eventSelection: string;
eventDrag: EventSegUiInteractionState | null;
eventResize: EventSegUiInteractionState | null;
dayMaxEvents: boolean | number;
dayMaxEventRows: boolean | number;
forPrint: boolean;
isHitComboAllowed?: (hit0: Hit, hit1: Hit) => boolean;
}
declare class TableRows extends DateComponent<TableRowsProps> {
private splitBusinessHourSegs;
private splitBgEventSegs;
private splitFgEventSegs;
private splitDateSelectionSegs;
private splitEventDrag;
private splitEventResize;
private rootEl;
private rowRefs;
private rowPositions;
private colPositions;
render(): createElement.JSX.Element;
componentDidMount(): void;
componentDidUpdate(): void;
registerInteractiveComponent(): void;
componentWillUnmount(): void;
prepareHits(): void;
queryHit(positionLeft: number, positionTop: number): Hit;
private getCellEl;
private getCellRange;
}
interface TableProps extends TableRowsProps {
colGroupNode: VNode;
tableMinWidth: CssDimValue;
expandRows: boolean;
headerAlignElRef?: RefObject<HTMLElement>;
}
declare class Table extends DateComponent<TableProps> {
private elRef;
private needsScrollReset;
render(): createElement.JSX.Element;
componentDidMount(): void;
componentDidUpdate(prevProps: TableProps): void;
requestScrollReset(): void;
flushScrollReset(): void;
}
declare abstract class TableView<State = Dictionary> extends DateComponent<ViewProps, State> {
protected headerElRef: RefObject<HTMLTableCellElement>;
renderSimpleLayout(headerRowContent: ChunkConfigRowContent, bodyContent: (contentArg: ChunkContentCallbackArgs) => VNode): createElement.JSX.Element;
renderHScrollLayout(headerRowContent: ChunkConfigRowContent, bodyContent: (contentArg: ChunkContentCallbackArgs) => VNode, colCnt: number, dayMinWidth: number): createElement.JSX.Element;
}
declare class DayTableView extends TableView {
private buildDayTableModel;
private headerRef;
private tableRef;
render(): createElement.JSX.Element;
}
declare function buildDayTableModel(dateProfile: DateProfile, dateProfileGenerator: DateProfileGenerator): DayTableModel;
export { DayTableView as DayGridView, DayTable, DayTableSlicer, Table, TableDateProfileGenerator, TableRows, TableSeg, TableView, buildDayTableModel, buildDayTableRenderRange };

985
backend/node_modules/@fullcalendar/daygrid/internal.js generated vendored Normal file
View File

@@ -0,0 +1,985 @@
import { DateComponent, getStickyHeaderDates, ViewContainer, SimpleScrollGrid, getStickyFooterScrollbar, renderScrollShim, createFormatter, BaseComponent, StandardEvent, buildSegTimeText, EventContainer, getSegAnchorAttrs, memoize, MoreLinkContainer, getSegMeta, getUniqueDomId, setRef, DayCellContainer, WeekNumberContainer, buildNavLinkAttrs, hasCustomDayCellContent, addMs, intersectRanges, addDays, SegHierarchy, buildEntryKey, intersectSpans, RefMap, sortEventSegs, isPropsEqual, buildEventRangeKey, BgEvent, renderFill, PositionCache, NowTimer, formatIsoMonthStr, formatDayString, Slicer, DayHeader, DaySeriesModel, DayTableModel, DateProfileGenerator, addWeeks, diffWeeks, injectStyles } from '@fullcalendar/core/internal.js';
import { createRef, createElement, Fragment } from '@fullcalendar/core/preact.js';
/* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.
----------------------------------------------------------------------------------------------------------------------*/
// It is a manager for a Table subcomponent, which does most of the heavy lifting.
// It is responsible for managing width/height.
class TableView extends DateComponent {
constructor() {
super(...arguments);
this.headerElRef = createRef();
}
renderSimpleLayout(headerRowContent, bodyContent) {
let { props, context } = this;
let sections = [];
let stickyHeaderDates = getStickyHeaderDates(context.options);
if (headerRowContent) {
sections.push({
type: 'header',
key: 'header',
isSticky: stickyHeaderDates,
chunk: {
elRef: this.headerElRef,
tableClassName: 'fc-col-header',
rowContent: headerRowContent,
},
});
}
sections.push({
type: 'body',
key: 'body',
liquid: true,
chunk: { content: bodyContent },
});
return (createElement(ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
createElement(SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [] /* TODO: make optional? */, sections: sections })));
}
renderHScrollLayout(headerRowContent, bodyContent, colCnt, dayMinWidth) {
let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
if (!ScrollGrid) {
throw new Error('No ScrollGrid implementation');
}
let { props, context } = this;
let stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options);
let stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options);
let sections = [];
if (headerRowContent) {
sections.push({
type: 'header',
key: 'header',
isSticky: stickyHeaderDates,
chunks: [{
key: 'main',
elRef: this.headerElRef,
tableClassName: 'fc-col-header',
rowContent: headerRowContent,
}],
});
}
sections.push({
type: 'body',
key: 'body',
liquid: true,
chunks: [{
key: 'main',
content: bodyContent,
}],
});
if (stickyFooterScrollbar) {
sections.push({
type: 'footer',
key: 'footer',
isSticky: true,
chunks: [{
key: 'main',
content: renderScrollShim,
}],
});
}
return (createElement(ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
createElement(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: props.forPrint, colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }], sections: sections })));
}
}
function splitSegsByRow(segs, rowCnt) {
let byRow = [];
for (let i = 0; i < rowCnt; i += 1) {
byRow[i] = [];
}
for (let seg of segs) {
byRow[seg.row].push(seg);
}
return byRow;
}
function splitSegsByFirstCol(segs, colCnt) {
let byCol = [];
for (let i = 0; i < colCnt; i += 1) {
byCol[i] = [];
}
for (let seg of segs) {
byCol[seg.firstCol].push(seg);
}
return byCol;
}
function splitInteractionByRow(ui, rowCnt) {
let byRow = [];
if (!ui) {
for (let i = 0; i < rowCnt; i += 1) {
byRow[i] = null;
}
}
else {
for (let i = 0; i < rowCnt; i += 1) {
byRow[i] = {
affectedInstances: ui.affectedInstances,
isEvent: ui.isEvent,
segs: [],
};
}
for (let seg of ui.segs) {
byRow[seg.row].segs.push(seg);
}
}
return byRow;
}
const DEFAULT_TABLE_EVENT_TIME_FORMAT = createFormatter({
hour: 'numeric',
minute: '2-digit',
omitZeroMinute: true,
meridiem: 'narrow',
});
function hasListItemDisplay(seg) {
let { display } = seg.eventRange.ui;
return display === 'list-item' || (display === 'auto' &&
!seg.eventRange.def.allDay &&
seg.firstCol === seg.lastCol && // can't be multi-day
seg.isStart && // "
seg.isEnd // "
);
}
class TableBlockEvent extends BaseComponent {
render() {
let { props } = this;
return (createElement(StandardEvent, Object.assign({}, props, { elClasses: ['fc-daygrid-event', 'fc-daygrid-block-event', 'fc-h-event'], defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: props.defaultDisplayEventEnd, disableResizing: !props.seg.eventRange.def.allDay })));
}
}
class TableListItemEvent extends BaseComponent {
render() {
let { props, context } = this;
let { options } = context;
let { seg } = props;
let timeFormat = options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT;
let timeText = buildSegTimeText(seg, timeFormat, context, true, props.defaultDisplayEventEnd);
return (createElement(EventContainer, Object.assign({}, props, { elTag: "a", elClasses: ['fc-daygrid-event', 'fc-daygrid-dot-event'], elAttrs: getSegAnchorAttrs(props.seg, context), defaultGenerator: renderInnerContent, timeText: timeText, isResizing: false, isDateSelecting: false })));
}
}
function renderInnerContent(renderProps) {
return (createElement(Fragment, null,
createElement("div", { className: "fc-daygrid-event-dot", style: { borderColor: renderProps.borderColor || renderProps.backgroundColor } }),
renderProps.timeText && (createElement("div", { className: "fc-event-time" }, renderProps.timeText)),
createElement("div", { className: "fc-event-title" }, renderProps.event.title || createElement(Fragment, null, "\u00A0"))));
}
class TableCellMoreLink extends BaseComponent {
constructor() {
super(...arguments);
this.compileSegs = memoize(compileSegs);
}
render() {
let { props } = this;
let { allSegs, invisibleSegs } = this.compileSegs(props.singlePlacements);
return (createElement(MoreLinkContainer, { elClasses: ['fc-daygrid-more-link'], dateProfile: props.dateProfile, todayRange: props.todayRange, allDayDate: props.allDayDate, moreCnt: props.moreCnt, allSegs: allSegs, hiddenSegs: invisibleSegs, alignmentElRef: props.alignmentElRef, alignGridTop: props.alignGridTop, extraDateSpan: props.extraDateSpan, popoverContent: () => {
let isForcedInvisible = (props.eventDrag ? props.eventDrag.affectedInstances : null) ||
(props.eventResize ? props.eventResize.affectedInstances : null) ||
{};
return (createElement(Fragment, null, allSegs.map((seg) => {
let instanceId = seg.eventRange.instance.instanceId;
return (createElement("div", { className: "fc-daygrid-event-harness", key: instanceId, style: {
visibility: isForcedInvisible[instanceId] ? 'hidden' : '',
} }, hasListItemDisplay(seg) ? (createElement(TableListItemEvent, Object.assign({ seg: seg, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, getSegMeta(seg, props.todayRange)))) : (createElement(TableBlockEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, getSegMeta(seg, props.todayRange))))));
})));
} }));
}
}
function compileSegs(singlePlacements) {
let allSegs = [];
let invisibleSegs = [];
for (let placement of singlePlacements) {
allSegs.push(placement.seg);
if (!placement.isVisible) {
invisibleSegs.push(placement.seg);
}
}
return { allSegs, invisibleSegs };
}
const DEFAULT_WEEK_NUM_FORMAT = createFormatter({ week: 'narrow' });
class TableCell extends DateComponent {
constructor() {
super(...arguments);
this.rootElRef = createRef();
this.state = {
dayNumberId: getUniqueDomId(),
};
this.handleRootEl = (el) => {
setRef(this.rootElRef, el);
setRef(this.props.elRef, el);
};
}
render() {
let { context, props, state, rootElRef } = this;
let { options, dateEnv } = context;
let { date, dateProfile } = props;
// TODO: memoize this?
const isMonthStart = props.showDayNumber &&
shouldDisplayMonthStart(date, dateProfile.currentRange, dateEnv);
return (createElement(DayCellContainer, { elTag: "td", elRef: this.handleRootEl, elClasses: [
'fc-daygrid-day',
...(props.extraClassNames || []),
], elAttrs: Object.assign(Object.assign(Object.assign({}, props.extraDataAttrs), (props.showDayNumber ? { 'aria-labelledby': state.dayNumberId } : {})), { role: 'gridcell' }), defaultGenerator: renderTopInner, date: date, dateProfile: dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, isMonthStart: isMonthStart, extraRenderProps: props.extraRenderProps }, (InnerContent, renderProps) => (createElement("div", { ref: props.innerElRef, className: "fc-daygrid-day-frame fc-scrollgrid-sync-inner", style: { minHeight: props.minHeight } },
props.showWeekNumber && (createElement(WeekNumberContainer, { elTag: "a", elClasses: ['fc-daygrid-week-number'], elAttrs: buildNavLinkAttrs(context, date, 'week'), date: date, defaultFormat: DEFAULT_WEEK_NUM_FORMAT })),
!renderProps.isDisabled &&
(props.showDayNumber || hasCustomDayCellContent(options) || props.forceDayTop) ? (createElement("div", { className: "fc-daygrid-day-top" },
createElement(InnerContent, { elTag: "a", elClasses: [
'fc-daygrid-day-number',
isMonthStart && 'fc-daygrid-month-start',
], elAttrs: Object.assign(Object.assign({}, buildNavLinkAttrs(context, date)), { id: state.dayNumberId }) }))) : props.showDayNumber ? (
// for creating correct amount of space (see issue #7162)
createElement("div", { className: "fc-daygrid-day-top", style: { visibility: 'hidden' } },
createElement("a", { className: "fc-daygrid-day-number" }, "\u00A0"))) : undefined,
createElement("div", { className: "fc-daygrid-day-events", ref: props.fgContentElRef },
props.fgContent,
createElement("div", { className: "fc-daygrid-day-bottom", style: { marginTop: props.moreMarginTop } },
createElement(TableCellMoreLink, { allDayDate: date, singlePlacements: props.singlePlacements, moreCnt: props.moreCnt, alignmentElRef: rootElRef, alignGridTop: !props.showDayNumber, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange }))),
createElement("div", { className: "fc-daygrid-day-bg" }, props.bgContent)))));
}
}
function renderTopInner(props) {
return props.dayNumberText || createElement(Fragment, null, "\u00A0");
}
function shouldDisplayMonthStart(date, currentRange, dateEnv) {
const { start: currentStart, end: currentEnd } = currentRange;
const currentEndIncl = addMs(currentEnd, -1);
const currentFirstYear = dateEnv.getYear(currentStart);
const currentFirstMonth = dateEnv.getMonth(currentStart);
const currentLastYear = dateEnv.getYear(currentEndIncl);
const currentLastMonth = dateEnv.getMonth(currentEndIncl);
// spans more than one month?
return !(currentFirstYear === currentLastYear && currentFirstMonth === currentLastMonth) &&
Boolean(
// first date in current view?
date.valueOf() === currentStart.valueOf() ||
// a month-start that's within the current range?
(dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf()));
}
function generateSegKey(seg) {
return seg.eventRange.instance.instanceId + ':' + seg.firstCol;
}
function generateSegUid(seg) {
return generateSegKey(seg) + ':' + seg.lastCol;
}
function computeFgSegPlacement(segs, // assumed already sorted
dayMaxEvents, dayMaxEventRows, strictOrder, segHeights, maxContentHeight, cells) {
let hierarchy = new DayGridSegHierarchy((segEntry) => {
// TODO: more DRY with generateSegUid
let segUid = segs[segEntry.index].eventRange.instance.instanceId +
':' + segEntry.span.start +
':' + (segEntry.span.end - 1);
// if no thickness known, assume 1 (if 0, so small it always fits)
return segHeights[segUid] || 1;
});
hierarchy.allowReslicing = true;
hierarchy.strictOrder = strictOrder;
if (dayMaxEvents === true || dayMaxEventRows === true) {
hierarchy.maxCoord = maxContentHeight;
hierarchy.hiddenConsumes = true;
}
else if (typeof dayMaxEvents === 'number') {
hierarchy.maxStackCnt = dayMaxEvents;
}
else if (typeof dayMaxEventRows === 'number') {
hierarchy.maxStackCnt = dayMaxEventRows;
hierarchy.hiddenConsumes = true;
}
// create segInputs only for segs with known heights
let segInputs = [];
let unknownHeightSegs = [];
for (let i = 0; i < segs.length; i += 1) {
let seg = segs[i];
let segUid = generateSegUid(seg);
let eventHeight = segHeights[segUid];
if (eventHeight != null) {
segInputs.push({
index: i,
span: {
start: seg.firstCol,
end: seg.lastCol + 1,
},
});
}
else {
unknownHeightSegs.push(seg);
}
}
let hiddenEntries = hierarchy.addSegs(segInputs);
let segRects = hierarchy.toRects();
let { singleColPlacements, multiColPlacements, leftoverMargins } = placeRects(segRects, segs, cells);
let moreCnts = [];
let moreMarginTops = [];
// add segs with unknown heights
for (let seg of unknownHeightSegs) {
multiColPlacements[seg.firstCol].push({
seg,
isVisible: false,
isAbsolute: true,
absoluteTop: 0,
marginTop: 0,
});
for (let col = seg.firstCol; col <= seg.lastCol; col += 1) {
singleColPlacements[col].push({
seg: resliceSeg(seg, col, col + 1, cells),
isVisible: false,
isAbsolute: false,
absoluteTop: 0,
marginTop: 0,
});
}
}
// add the hidden entries
for (let col = 0; col < cells.length; col += 1) {
moreCnts.push(0);
}
for (let hiddenEntry of hiddenEntries) {
let seg = segs[hiddenEntry.index];
let hiddenSpan = hiddenEntry.span;
multiColPlacements[hiddenSpan.start].push({
seg: resliceSeg(seg, hiddenSpan.start, hiddenSpan.end, cells),
isVisible: false,
isAbsolute: true,
absoluteTop: 0,
marginTop: 0,
});
for (let col = hiddenSpan.start; col < hiddenSpan.end; col += 1) {
moreCnts[col] += 1;
singleColPlacements[col].push({
seg: resliceSeg(seg, col, col + 1, cells),
isVisible: false,
isAbsolute: false,
absoluteTop: 0,
marginTop: 0,
});
}
}
// deal with leftover margins
for (let col = 0; col < cells.length; col += 1) {
moreMarginTops.push(leftoverMargins[col]);
}
return { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops };
}
// rects ordered by top coord, then left
function placeRects(allRects, segs, cells) {
let rectsByEachCol = groupRectsByEachCol(allRects, cells.length);
let singleColPlacements = [];
let multiColPlacements = [];
let leftoverMargins = [];
for (let col = 0; col < cells.length; col += 1) {
let rects = rectsByEachCol[col];
// compute all static segs in singlePlacements
let singlePlacements = [];
let currentHeight = 0;
let currentMarginTop = 0;
for (let rect of rects) {
let seg = segs[rect.index];
singlePlacements.push({
seg: resliceSeg(seg, col, col + 1, cells),
isVisible: true,
isAbsolute: false,
absoluteTop: rect.levelCoord,
marginTop: rect.levelCoord - currentHeight,
});
currentHeight = rect.levelCoord + rect.thickness;
}
// compute mixed static/absolute segs in multiPlacements
let multiPlacements = [];
currentHeight = 0;
currentMarginTop = 0;
for (let rect of rects) {
let seg = segs[rect.index];
let isAbsolute = rect.span.end - rect.span.start > 1; // multi-column?
let isFirstCol = rect.span.start === col;
currentMarginTop += rect.levelCoord - currentHeight; // amount of space since bottom of previous seg
currentHeight = rect.levelCoord + rect.thickness; // height will now be bottom of current seg
if (isAbsolute) {
currentMarginTop += rect.thickness;
if (isFirstCol) {
multiPlacements.push({
seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
isVisible: true,
isAbsolute: true,
absoluteTop: rect.levelCoord,
marginTop: 0,
});
}
}
else if (isFirstCol) {
multiPlacements.push({
seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
isVisible: true,
isAbsolute: false,
absoluteTop: rect.levelCoord,
marginTop: currentMarginTop, // claim the margin
});
currentMarginTop = 0;
}
}
singleColPlacements.push(singlePlacements);
multiColPlacements.push(multiPlacements);
leftoverMargins.push(currentMarginTop);
}
return { singleColPlacements, multiColPlacements, leftoverMargins };
}
function groupRectsByEachCol(rects, colCnt) {
let rectsByEachCol = [];
for (let col = 0; col < colCnt; col += 1) {
rectsByEachCol.push([]);
}
for (let rect of rects) {
for (let col = rect.span.start; col < rect.span.end; col += 1) {
rectsByEachCol[col].push(rect);
}
}
return rectsByEachCol;
}
function resliceSeg(seg, spanStart, spanEnd, cells) {
if (seg.firstCol === spanStart && seg.lastCol === spanEnd - 1) {
return seg;
}
let eventRange = seg.eventRange;
let origRange = eventRange.range;
let slicedRange = intersectRanges(origRange, {
start: cells[spanStart].date,
end: addDays(cells[spanEnd - 1].date, 1),
});
return Object.assign(Object.assign({}, seg), { firstCol: spanStart, lastCol: spanEnd - 1, eventRange: {
def: eventRange.def,
ui: Object.assign(Object.assign({}, eventRange.ui), { durationEditable: false }),
instance: eventRange.instance,
range: slicedRange,
}, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() });
}
class DayGridSegHierarchy extends SegHierarchy {
constructor() {
super(...arguments);
// config
this.hiddenConsumes = false;
// allows us to keep hidden entries in the hierarchy so they take up space
this.forceHidden = {};
}
addSegs(segInputs) {
const hiddenSegs = super.addSegs(segInputs);
const { entriesByLevel } = this;
const excludeHidden = (entry) => !this.forceHidden[buildEntryKey(entry)];
// remove the forced-hidden segs
for (let level = 0; level < entriesByLevel.length; level += 1) {
entriesByLevel[level] = entriesByLevel[level].filter(excludeHidden);
}
return hiddenSegs;
}
handleInvalidInsertion(insertion, entry, hiddenEntries) {
const { entriesByLevel, forceHidden } = this;
const { touchingEntry, touchingLevel, touchingLateral } = insertion;
// the entry that the new insertion is touching must be hidden
if (this.hiddenConsumes && touchingEntry) {
const touchingEntryId = buildEntryKey(touchingEntry);
if (!forceHidden[touchingEntryId]) {
if (this.allowReslicing) {
// split up the touchingEntry, reinsert it
const hiddenEntry = Object.assign(Object.assign({}, touchingEntry), { span: intersectSpans(touchingEntry.span, entry.span) });
// reinsert the area that turned into a "more" link (so no other entries try to
// occupy the space) but mark it forced-hidden
const hiddenEntryId = buildEntryKey(hiddenEntry);
forceHidden[hiddenEntryId] = true;
entriesByLevel[touchingLevel][touchingLateral] = hiddenEntry;
hiddenEntries.push(hiddenEntry);
this.splitEntry(touchingEntry, entry, hiddenEntries);
}
else {
forceHidden[touchingEntryId] = true;
hiddenEntries.push(touchingEntry);
}
}
}
// will try to reslice...
super.handleInvalidInsertion(insertion, entry, hiddenEntries);
}
}
class TableRow extends DateComponent {
constructor() {
super(...arguments);
this.cellElRefs = new RefMap(); // the <td>
this.frameElRefs = new RefMap(); // the fc-daygrid-day-frame
this.fgElRefs = new RefMap(); // the fc-daygrid-day-events
this.segHarnessRefs = new RefMap(); // indexed by "instanceId:firstCol"
this.rootElRef = createRef();
this.state = {
framePositions: null,
maxContentHeight: null,
segHeights: {},
};
this.handleResize = (isForced) => {
if (isForced) {
this.updateSizing(true); // isExternal=true
}
};
}
render() {
let { props, state, context } = this;
let { options } = context;
let colCnt = props.cells.length;
let businessHoursByCol = splitSegsByFirstCol(props.businessHourSegs, colCnt);
let bgEventSegsByCol = splitSegsByFirstCol(props.bgEventSegs, colCnt);
let highlightSegsByCol = splitSegsByFirstCol(this.getHighlightSegs(), colCnt);
let mirrorSegsByCol = splitSegsByFirstCol(this.getMirrorSegs(), colCnt);
let { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops } = computeFgSegPlacement(sortEventSegs(props.fgEventSegs, options.eventOrder), props.dayMaxEvents, props.dayMaxEventRows, options.eventOrderStrict, state.segHeights, state.maxContentHeight, props.cells);
let isForcedInvisible = // TODO: messy way to compute this
(props.eventDrag && props.eventDrag.affectedInstances) ||
(props.eventResize && props.eventResize.affectedInstances) ||
{};
return (createElement("tr", { ref: this.rootElRef, role: "row" },
props.renderIntro && props.renderIntro(),
props.cells.map((cell, col) => {
let normalFgNodes = this.renderFgSegs(col, props.forPrint ? singleColPlacements[col] : multiColPlacements[col], props.todayRange, isForcedInvisible);
let mirrorFgNodes = this.renderFgSegs(col, buildMirrorPlacements(mirrorSegsByCol[col], multiColPlacements), props.todayRange, {}, Boolean(props.eventDrag), Boolean(props.eventResize), false);
return (createElement(TableCell, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), innerElRef: this.frameElRefs.createRef(cell.key) /* FF <td> problem, but okay to use for left/right. TODO: rename prop */, dateProfile: props.dateProfile, date: cell.date, showDayNumber: props.showDayNumbers, showWeekNumber: props.showWeekNumbers && col === 0, forceDayTop: props.showWeekNumbers /* even displaying weeknum for row, not necessarily day */, todayRange: props.todayRange, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, moreCnt: moreCnts[col], moreMarginTop: moreMarginTops[col], singlePlacements: singleColPlacements[col], fgContentElRef: this.fgElRefs.createRef(cell.key), fgContent: ( // Fragment scopes the keys
createElement(Fragment, null,
createElement(Fragment, null, normalFgNodes),
createElement(Fragment, null, mirrorFgNodes))), bgContent: ( // Fragment scopes the keys
createElement(Fragment, null,
this.renderFillSegs(highlightSegsByCol[col], 'highlight'),
this.renderFillSegs(businessHoursByCol[col], 'non-business'),
this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))), minHeight: props.cellMinHeight }));
})));
}
componentDidMount() {
this.updateSizing(true);
this.context.addResizeHandler(this.handleResize);
}
componentDidUpdate(prevProps, prevState) {
let currentProps = this.props;
this.updateSizing(!isPropsEqual(prevProps, currentProps));
}
componentWillUnmount() {
this.context.removeResizeHandler(this.handleResize);
}
getHighlightSegs() {
let { props } = this;
if (props.eventDrag && props.eventDrag.segs.length) { // messy check
return props.eventDrag.segs;
}
if (props.eventResize && props.eventResize.segs.length) { // messy check
return props.eventResize.segs;
}
return props.dateSelectionSegs;
}
getMirrorSegs() {
let { props } = this;
if (props.eventResize && props.eventResize.segs.length) { // messy check
return props.eventResize.segs;
}
return [];
}
renderFgSegs(col, segPlacements, todayRange, isForcedInvisible, isDragging, isResizing, isDateSelecting) {
let { context } = this;
let { eventSelection } = this.props;
let { framePositions } = this.state;
let defaultDisplayEventEnd = this.props.cells.length === 1; // colCnt === 1
let isMirror = isDragging || isResizing || isDateSelecting;
let nodes = [];
if (framePositions) {
for (let placement of segPlacements) {
let { seg } = placement;
let { instanceId } = seg.eventRange.instance;
let isVisible = placement.isVisible && !isForcedInvisible[instanceId];
let isAbsolute = placement.isAbsolute;
let left = '';
let right = '';
if (isAbsolute) {
if (context.isRtl) {
right = 0;
left = framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol];
}
else {
left = 0;
right = framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol];
}
}
/*
known bug: events that are force to be list-item but span multiple days still take up space in later columns
todo: in print view, for multi-day events, don't display title within non-start/end segs
*/
nodes.push(createElement("div", { className: 'fc-daygrid-event-harness' + (isAbsolute ? ' fc-daygrid-event-harness-abs' : ''), key: generateSegKey(seg), ref: isMirror ? null : this.segHarnessRefs.createRef(generateSegUid(seg)), style: {
visibility: isVisible ? '' : 'hidden',
marginTop: isAbsolute ? '' : placement.marginTop,
top: isAbsolute ? placement.absoluteTop : '',
left,
right,
} }, hasListItemDisplay(seg) ? (createElement(TableListItemEvent, Object.assign({ seg: seg, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getSegMeta(seg, todayRange)))) : (createElement(TableBlockEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getSegMeta(seg, todayRange))))));
}
}
return nodes;
}
renderFillSegs(segs, fillType) {
let { isRtl } = this.context;
let { todayRange } = this.props;
let { framePositions } = this.state;
let nodes = [];
if (framePositions) {
for (let seg of segs) {
let leftRightCss = isRtl ? {
right: 0,
left: framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol],
} : {
left: 0,
right: framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol],
};
nodes.push(createElement("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-daygrid-bg-harness", style: leftRightCss }, fillType === 'bg-event' ?
createElement(BgEvent, Object.assign({ seg: seg }, getSegMeta(seg, todayRange))) :
renderFill(fillType)));
}
}
return createElement(Fragment, {}, ...nodes);
}
updateSizing(isExternalSizingChange) {
let { props, state, frameElRefs } = this;
if (!props.forPrint &&
props.clientWidth !== null // positioning ready?
) {
if (isExternalSizingChange) {
let frameEls = props.cells.map((cell) => frameElRefs.currentMap[cell.key]);
if (frameEls.length) {
let originEl = this.rootElRef.current;
let newPositionCache = new PositionCache(originEl, frameEls, true, // isHorizontal
false);
if (!state.framePositions || !state.framePositions.similarTo(newPositionCache)) {
this.setState({
framePositions: new PositionCache(originEl, frameEls, true, // isHorizontal
false),
});
}
}
}
const oldSegHeights = this.state.segHeights;
const newSegHeights = this.querySegHeights();
const limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
this.safeSetState({
// HACK to prevent oscillations of events being shown/hidden from max-event-rows
// Essentially, once you compute an element's height, never null-out.
// TODO: always display all events, as visibility:hidden?
segHeights: Object.assign(Object.assign({}, oldSegHeights), newSegHeights),
maxContentHeight: limitByContentHeight ? this.computeMaxContentHeight() : null,
});
}
}
querySegHeights() {
let segElMap = this.segHarnessRefs.currentMap;
let segHeights = {};
// get the max height amongst instance segs
for (let segUid in segElMap) {
let height = Math.round(segElMap[segUid].getBoundingClientRect().height);
segHeights[segUid] = Math.max(segHeights[segUid] || 0, height);
}
return segHeights;
}
computeMaxContentHeight() {
let firstKey = this.props.cells[0].key;
let cellEl = this.cellElRefs.currentMap[firstKey];
let fcContainerEl = this.fgElRefs.currentMap[firstKey];
return cellEl.getBoundingClientRect().bottom - fcContainerEl.getBoundingClientRect().top;
}
getCellEls() {
let elMap = this.cellElRefs.currentMap;
return this.props.cells.map((cell) => elMap[cell.key]);
}
}
TableRow.addStateEquality({
segHeights: isPropsEqual,
});
function buildMirrorPlacements(mirrorSegs, colPlacements) {
if (!mirrorSegs.length) {
return [];
}
let topsByInstanceId = buildAbsoluteTopHash(colPlacements); // TODO: cache this at first render?
return mirrorSegs.map((seg) => ({
seg,
isVisible: true,
isAbsolute: true,
absoluteTop: topsByInstanceId[seg.eventRange.instance.instanceId],
marginTop: 0,
}));
}
function buildAbsoluteTopHash(colPlacements) {
let topsByInstanceId = {};
for (let placements of colPlacements) {
for (let placement of placements) {
topsByInstanceId[placement.seg.eventRange.instance.instanceId] = placement.absoluteTop;
}
}
return topsByInstanceId;
}
class TableRows extends DateComponent {
constructor() {
super(...arguments);
this.splitBusinessHourSegs = memoize(splitSegsByRow);
this.splitBgEventSegs = memoize(splitSegsByRow);
this.splitFgEventSegs = memoize(splitSegsByRow);
this.splitDateSelectionSegs = memoize(splitSegsByRow);
this.splitEventDrag = memoize(splitInteractionByRow);
this.splitEventResize = memoize(splitInteractionByRow);
this.rowRefs = new RefMap();
}
render() {
let { props, context } = this;
let rowCnt = props.cells.length;
let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt);
let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);
let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt);
let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt);
let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt);
let eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt);
// for DayGrid view with many rows, force a min-height on cells so doesn't appear squished
// choose 7 because a month view will have max 6 rows
let cellMinHeight = (rowCnt >= 7 && props.clientWidth) ?
props.clientWidth / context.options.aspectRatio / 6 :
null;
return (createElement(NowTimer, { unit: "day" }, (nowDate, todayRange) => (createElement(Fragment, null, props.cells.map((cells, row) => (createElement(TableRow, { ref: this.rowRefs.createRef(row), key: cells.length
? cells[0].date.toISOString() /* best? or put key on cell? or use diff formatter? */
: row // in case there are no cells (like when resource view is loading)
, showDayNumbers: rowCnt > 1, showWeekNumbers: props.showWeekNumbers, todayRange: todayRange, dateProfile: props.dateProfile, cells: cells, renderIntro: props.renderRowIntro, businessHourSegs: businessHourSegsByRow[row], eventSelection: props.eventSelection, bgEventSegs: bgEventSegsByRow[row].filter(isSegAllDay) /* hack */, fgEventSegs: fgEventSegsByRow[row], dateSelectionSegs: dateSelectionSegsByRow[row], eventDrag: eventDragByRow[row], eventResize: eventResizeByRow[row], dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, clientWidth: props.clientWidth, clientHeight: props.clientHeight, cellMinHeight: cellMinHeight, forPrint: props.forPrint })))))));
}
componentDidMount() {
this.registerInteractiveComponent();
}
componentDidUpdate() {
// for if started with zero cells
this.registerInteractiveComponent();
}
registerInteractiveComponent() {
if (!this.rootEl) {
// HACK: need a daygrid wrapper parent to do positioning
// NOTE: a daygrid resource view w/o resources can have zero cells
const firstCellEl = this.rowRefs.currentMap[0].getCellEls()[0];
const rootEl = firstCellEl ? firstCellEl.closest('.fc-daygrid-body') : null;
if (rootEl) {
this.rootEl = rootEl;
this.context.registerInteractiveComponent(this, {
el: rootEl,
isHitComboAllowed: this.props.isHitComboAllowed,
});
}
}
}
componentWillUnmount() {
if (this.rootEl) {
this.context.unregisterInteractiveComponent(this);
this.rootEl = null;
}
}
// Hit System
// ----------------------------------------------------------------------------------------------------
prepareHits() {
this.rowPositions = new PositionCache(this.rootEl, this.rowRefs.collect().map((rowObj) => rowObj.getCellEls()[0]), // first cell el in each row. TODO: not optimal
false, true);
this.colPositions = new PositionCache(this.rootEl, this.rowRefs.currentMap[0].getCellEls(), // cell els in first row
true, // horizontal
false);
}
queryHit(positionLeft, positionTop) {
let { colPositions, rowPositions } = this;
let col = colPositions.leftToIndex(positionLeft);
let row = rowPositions.topToIndex(positionTop);
if (row != null && col != null) {
let cell = this.props.cells[row][col];
return {
dateProfile: this.props.dateProfile,
dateSpan: Object.assign({ range: this.getCellRange(row, col), allDay: true }, cell.extraDateSpan),
dayEl: this.getCellEl(row, col),
rect: {
left: colPositions.lefts[col],
right: colPositions.rights[col],
top: rowPositions.tops[row],
bottom: rowPositions.bottoms[row],
},
layer: 0,
};
}
return null;
}
getCellEl(row, col) {
return this.rowRefs.currentMap[row].getCellEls()[col]; // TODO: not optimal
}
getCellRange(row, col) {
let start = this.props.cells[row][col].date;
let end = addDays(start, 1);
return { start, end };
}
}
function isSegAllDay(seg) {
return seg.eventRange.def.allDay;
}
class Table extends DateComponent {
constructor() {
super(...arguments);
this.elRef = createRef();
this.needsScrollReset = false;
}
render() {
let { props } = this;
let { dayMaxEventRows, dayMaxEvents, expandRows } = props;
let limitViaBalanced = dayMaxEvents === true || dayMaxEventRows === true;
// if rows can't expand to fill fixed height, can't do balanced-height event limit
// TODO: best place to normalize these options?
if (limitViaBalanced && !expandRows) {
limitViaBalanced = false;
dayMaxEventRows = null;
dayMaxEvents = null;
}
let classNames = [
'fc-daygrid-body',
limitViaBalanced ? 'fc-daygrid-body-balanced' : 'fc-daygrid-body-unbalanced',
expandRows ? '' : 'fc-daygrid-body-natural', // will height of one row depend on the others?
];
return (createElement("div", { ref: this.elRef, className: classNames.join(' '), 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,
} },
createElement("table", { role: "presentation", className: "fc-scrollgrid-sync-table", style: {
width: props.clientWidth,
minWidth: props.tableMinWidth,
height: expandRows ? props.clientHeight : '',
} },
props.colGroupNode,
createElement("tbody", { role: "presentation" },
createElement(TableRows, { dateProfile: props.dateProfile, cells: props.cells, renderRowIntro: props.renderRowIntro, showWeekNumbers: props.showWeekNumbers, clientWidth: props.clientWidth, clientHeight: props.clientHeight, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, dayMaxEvents: dayMaxEvents, dayMaxEventRows: dayMaxEventRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed })))));
}
componentDidMount() {
this.requestScrollReset();
}
componentDidUpdate(prevProps) {
if (prevProps.dateProfile !== this.props.dateProfile) {
this.requestScrollReset();
}
else {
this.flushScrollReset();
}
}
requestScrollReset() {
this.needsScrollReset = true;
this.flushScrollReset();
}
flushScrollReset() {
if (this.needsScrollReset &&
this.props.clientWidth // sizes computed?
) {
const subjectEl = getScrollSubjectEl(this.elRef.current, this.props.dateProfile);
if (subjectEl) {
const originEl = subjectEl.closest('.fc-daygrid-body');
const scrollEl = originEl.closest('.fc-scroller');
const scrollTop = subjectEl.getBoundingClientRect().top -
originEl.getBoundingClientRect().top;
scrollEl.scrollTop = scrollTop ? (scrollTop + 1) : 0; // overcome border
}
this.needsScrollReset = false;
}
}
}
function getScrollSubjectEl(containerEl, dateProfile) {
let el;
if (dateProfile.currentRangeUnit.match(/year|month/)) {
el = containerEl.querySelector(`[data-date="${formatIsoMonthStr(dateProfile.currentDate)}-01"]`);
// even if view is month-based, first-of-month might be hidden...
}
if (!el) {
el = containerEl.querySelector(`[data-date="${formatDayString(dateProfile.currentDate)}"]`);
// could still be hidden if an interior-view hidden day
}
return el;
}
class DayTableSlicer extends Slicer {
constructor() {
super(...arguments);
this.forceDayIfListItem = true;
}
sliceRange(dateRange, dayTableModel) {
return dayTableModel.sliceRange(dateRange);
}
}
class DayTable extends DateComponent {
constructor() {
super(...arguments);
this.slicer = new DayTableSlicer();
this.tableRef = createRef();
}
render() {
let { props, context } = this;
return (createElement(Table, Object.assign({ ref: this.tableRef }, this.slicer.sliceProps(props, props.dateProfile, props.nextDayThreshold, context, props.dayTableModel), { dateProfile: props.dateProfile, cells: props.dayTableModel.cells, colGroupNode: props.colGroupNode, tableMinWidth: props.tableMinWidth, renderRowIntro: props.renderRowIntro, dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, showWeekNumbers: props.showWeekNumbers, expandRows: props.expandRows, headerAlignElRef: props.headerAlignElRef, clientWidth: props.clientWidth, clientHeight: props.clientHeight, forPrint: props.forPrint })));
}
}
class DayTableView extends TableView {
constructor() {
super(...arguments);
this.buildDayTableModel = memoize(buildDayTableModel);
this.headerRef = createRef();
this.tableRef = createRef();
// can't override any lifecycle methods from parent
}
render() {
let { options, dateProfileGenerator } = this.context;
let { props } = this;
let dayTableModel = this.buildDayTableModel(props.dateProfile, dateProfileGenerator);
let headerContent = options.dayHeaders && (createElement(DayHeader, { ref: this.headerRef, dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: dayTableModel.rowCnt === 1 }));
let bodyContent = (contentArg) => (createElement(DayTable, { ref: this.tableRef, dateProfile: props.dateProfile, dayTableModel: dayTableModel, businessHours: props.businessHours, dateSelection: props.dateSelection, eventStore: props.eventStore, eventUiBases: props.eventUiBases, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, nextDayThreshold: options.nextDayThreshold, colGroupNode: contentArg.tableColGroupNode, tableMinWidth: contentArg.tableMinWidth, dayMaxEvents: options.dayMaxEvents, dayMaxEventRows: options.dayMaxEventRows, showWeekNumbers: options.weekNumbers, expandRows: !props.isHeightAuto, headerAlignElRef: this.headerElRef, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, forPrint: props.forPrint }));
return options.dayMinWidth
? this.renderHScrollLayout(headerContent, bodyContent, dayTableModel.colCnt, options.dayMinWidth)
: this.renderSimpleLayout(headerContent, bodyContent);
}
}
function buildDayTableModel(dateProfile, dateProfileGenerator) {
let daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
return new DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
}
class TableDateProfileGenerator extends DateProfileGenerator {
// Computes the date range that will be rendered
buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay);
let { props } = this;
return buildDayTableRenderRange({
currentRange: renderRange,
snapToWeek: /^(year|month)$/.test(currentRangeUnit),
fixedWeekCount: props.fixedWeekCount,
dateEnv: props.dateEnv,
});
}
}
function buildDayTableRenderRange(props) {
let { dateEnv, currentRange } = props;
let { start, end } = currentRange;
let endOfWeek;
// year and month views should be aligned with weeks. this is already done for week
if (props.snapToWeek) {
start = dateEnv.startOfWeek(start);
// make end-of-week if not already
endOfWeek = dateEnv.startOfWeek(end);
if (endOfWeek.valueOf() !== end.valueOf()) {
end = addWeeks(endOfWeek, 1);
}
}
// ensure 6 weeks
if (props.fixedWeekCount) {
// TODO: instead of these date-math gymnastics (for multimonth view),
// compute dateprofiles of all months, then use start of first and end of last.
let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth(addDays(currentRange.end, -1)));
let rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
diffWeeks(lastMonthRenderStart, end));
end = addWeeks(end, 6 - rowCnt);
}
return { start, end };
}
var css_248z = ":root{--fc-daygrid-event-dot-width:8px}.fc-daygrid-day-events:after,.fc-daygrid-day-events:before,.fc-daygrid-day-frame:after,.fc-daygrid-day-frame:before,.fc-daygrid-event-harness:after,.fc-daygrid-event-harness:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-body{position:relative;z-index:1}.fc .fc-daygrid-day.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-daygrid-day-frame{min-height:100%;position:relative}.fc .fc-daygrid-day-top{display:flex;flex-direction:row-reverse}.fc .fc-day-other .fc-daygrid-day-top{opacity:.3}.fc .fc-daygrid-day-number{padding:4px;position:relative;z-index:4}.fc .fc-daygrid-month-start{font-size:1.1em;font-weight:700}.fc .fc-daygrid-day-events{margin-top:1px}.fc .fc-daygrid-body-balanced .fc-daygrid-day-events{left:0;position:absolute;right:0}.fc .fc-daygrid-body-unbalanced .fc-daygrid-day-events{min-height:2em;position:relative}.fc .fc-daygrid-body-natural .fc-daygrid-day-events{margin-bottom:1em}.fc .fc-daygrid-event-harness{position:relative}.fc .fc-daygrid-event-harness-abs{left:0;position:absolute;right:0;top:0}.fc .fc-daygrid-bg-harness{bottom:0;position:absolute;top:0}.fc .fc-daygrid-day-bg .fc-non-business{z-index:1}.fc .fc-daygrid-day-bg .fc-bg-event{z-index:2}.fc .fc-daygrid-day-bg .fc-highlight{z-index:3}.fc .fc-daygrid-event{margin-top:1px;z-index:6}.fc .fc-daygrid-event.fc-event-mirror{z-index:7}.fc .fc-daygrid-day-bottom{font-size:.85em;margin:0 2px}.fc .fc-daygrid-day-bottom:after,.fc .fc-daygrid-day-bottom:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-more-link{border-radius:3px;cursor:pointer;line-height:1;margin-top:1px;max-width:100%;overflow:hidden;padding:2px;position:relative;white-space:nowrap;z-index:4}.fc .fc-daygrid-more-link:hover{background-color:rgba(0,0,0,.1)}.fc .fc-daygrid-week-number{background-color:var(--fc-neutral-bg-color);color:var(--fc-neutral-text-color);min-width:1.5em;padding:2px;position:absolute;text-align:center;top:0;z-index:5}.fc .fc-more-popover .fc-popover-body{min-width:220px;padding:10px}.fc-direction-ltr .fc-daygrid-event.fc-event-start,.fc-direction-rtl .fc-daygrid-event.fc-event-end{margin-left:2px}.fc-direction-ltr .fc-daygrid-event.fc-event-end,.fc-direction-rtl .fc-daygrid-event.fc-event-start{margin-right:2px}.fc-direction-ltr .fc-daygrid-more-link{float:left}.fc-direction-ltr .fc-daygrid-week-number{border-radius:0 0 3px 0;left:0}.fc-direction-rtl .fc-daygrid-more-link{float:right}.fc-direction-rtl .fc-daygrid-week-number{border-radius:0 0 0 3px;right:0}.fc-liquid-hack .fc-daygrid-day-frame{position:static}.fc-daygrid-event{border-radius:3px;font-size:var(--fc-small-font-size);position:relative;white-space:nowrap}.fc-daygrid-block-event .fc-event-time{font-weight:700}.fc-daygrid-block-event .fc-event-time,.fc-daygrid-block-event .fc-event-title{padding:1px}.fc-daygrid-dot-event{align-items:center;display:flex;padding:2px 0}.fc-daygrid-dot-event .fc-event-title{flex-grow:1;flex-shrink:1;font-weight:700;min-width:0;overflow:hidden}.fc-daygrid-dot-event.fc-event-mirror,.fc-daygrid-dot-event:hover{background:rgba(0,0,0,.1)}.fc-daygrid-dot-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-daygrid-event-dot{border:calc(var(--fc-daygrid-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-daygrid-event-dot-width)/2);box-sizing:content-box;height:0;margin:0 4px;width:0}.fc-direction-ltr .fc-daygrid-event .fc-event-time{margin-right:3px}.fc-direction-rtl .fc-daygrid-event .fc-event-time{margin-left:3px}";
injectStyles(css_248z);
export { DayTableView as DayGridView, DayTable, DayTableSlicer, Table, TableDateProfileGenerator, TableRows, TableView, buildDayTableModel, buildDayTableRenderRange };

View File

@@ -0,0 +1,55 @@
{
"name": "@fullcalendar/daygrid",
"version": "6.1.17",
"title": "FullCalendar Day Grid Plugin",
"description": "Display events on a month view or \"day grid\" view",
"homepage": "https://fullcalendar.io/docs/month-view",
"keywords": [
"calendar",
"event",
"full-sized",
"fullcalendar",
"month",
"month-view"
],
"peerDependencies": {
"@fullcalendar/core": "~6.1.17"
},
"type": "module",
"bugs": "https://fullcalendar.io/reporting-bugs",
"repository": {
"type": "git",
"url": "https://github.com/fullcalendar/fullcalendar.git",
"directory": "packages/daygrid"
},
"license": "MIT",
"author": {
"name": "Adam Shaw",
"email": "arshaw@arshaw.com",
"url": "http://arshaw.com/"
},
"copyright": "2024 Adam Shaw",
"types": "./index.d.ts",
"main": "./index.cjs",
"module": "./index.js",
"unpkg": "./index.global.min.js",
"jsdelivr": "./index.global.min.js",
"exports": {
"./package.json": "./package.json",
"./index.cjs": "./index.cjs",
"./index.js": "./index.js",
".": {
"types": "./index.d.ts",
"require": "./index.cjs",
"import": "./index.js"
},
"./internal.cjs": "./internal.cjs",
"./internal.js": "./internal.js",
"./internal": {
"types": "./internal.d.ts",
"require": "./internal.cjs",
"import": "./internal.js"
}
},
"sideEffects": false
}