diff options
Diffstat (limited to 'public/js/fullcalendar/packages/daygrid/index.global.js')
-rw-r--r-- | public/js/fullcalendar/packages/daygrid/index.global.js | 1040 |
1 files changed, 1040 insertions, 0 deletions
diff --git a/public/js/fullcalendar/packages/daygrid/index.global.js b/public/js/fullcalendar/packages/daygrid/index.global.js new file mode 100644 index 0000000..dc7eb01 --- /dev/null +++ b/public/js/fullcalendar/packages/daygrid/index.global.js | |||
@@ -0,0 +1,1040 @@ | |||
1 | /*! | ||
2 | FullCalendar Day Grid Plugin v6.1.17 | ||
3 | Docs & License: https://fullcalendar.io/docs/month-view | ||
4 | (c) 2024 Adam Shaw | ||
5 | */ | ||
6 | FullCalendar.DayGrid = (function (exports, core, internal$1, preact) { | ||
7 | 'use strict'; | ||
8 | |||
9 | /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells. | ||
10 | ----------------------------------------------------------------------------------------------------------------------*/ | ||
11 | // It is a manager for a Table subcomponent, which does most of the heavy lifting. | ||
12 | // It is responsible for managing width/height. | ||
13 | class TableView extends internal$1.DateComponent { | ||
14 | constructor() { | ||
15 | super(...arguments); | ||
16 | this.headerElRef = preact.createRef(); | ||
17 | } | ||
18 | renderSimpleLayout(headerRowContent, bodyContent) { | ||
19 | let { props, context } = this; | ||
20 | let sections = []; | ||
21 | let stickyHeaderDates = internal$1.getStickyHeaderDates(context.options); | ||
22 | if (headerRowContent) { | ||
23 | sections.push({ | ||
24 | type: 'header', | ||
25 | key: 'header', | ||
26 | isSticky: stickyHeaderDates, | ||
27 | chunk: { | ||
28 | elRef: this.headerElRef, | ||
29 | tableClassName: 'fc-col-header', | ||
30 | rowContent: headerRowContent, | ||
31 | }, | ||
32 | }); | ||
33 | } | ||
34 | sections.push({ | ||
35 | type: 'body', | ||
36 | key: 'body', | ||
37 | liquid: true, | ||
38 | chunk: { content: bodyContent }, | ||
39 | }); | ||
40 | return (preact.createElement(internal$1.ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec }, | ||
41 | preact.createElement(internal$1.SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [] /* TODO: make optional? */, sections: sections }))); | ||
42 | } | ||
43 | renderHScrollLayout(headerRowContent, bodyContent, colCnt, dayMinWidth) { | ||
44 | let ScrollGrid = this.context.pluginHooks.scrollGridImpl; | ||
45 | if (!ScrollGrid) { | ||
46 | throw new Error('No ScrollGrid implementation'); | ||
47 | } | ||
48 | let { props, context } = this; | ||
49 | let stickyHeaderDates = !props.forPrint && internal$1.getStickyHeaderDates(context.options); | ||
50 | let stickyFooterScrollbar = !props.forPrint && internal$1.getStickyFooterScrollbar(context.options); | ||
51 | let sections = []; | ||
52 | if (headerRowContent) { | ||
53 | sections.push({ | ||
54 | type: 'header', | ||
55 | key: 'header', | ||
56 | isSticky: stickyHeaderDates, | ||
57 | chunks: [{ | ||
58 | key: 'main', | ||
59 | elRef: this.headerElRef, | ||
60 | tableClassName: 'fc-col-header', | ||
61 | rowContent: headerRowContent, | ||
62 | }], | ||
63 | }); | ||
64 | } | ||
65 | sections.push({ | ||
66 | type: 'body', | ||
67 | key: 'body', | ||
68 | liquid: true, | ||
69 | chunks: [{ | ||
70 | key: 'main', | ||
71 | content: bodyContent, | ||
72 | }], | ||
73 | }); | ||
74 | if (stickyFooterScrollbar) { | ||
75 | sections.push({ | ||
76 | type: 'footer', | ||
77 | key: 'footer', | ||
78 | isSticky: true, | ||
79 | chunks: [{ | ||
80 | key: 'main', | ||
81 | content: internal$1.renderScrollShim, | ||
82 | }], | ||
83 | }); | ||
84 | } | ||
85 | return (preact.createElement(internal$1.ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec }, | ||
86 | preact.createElement(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: props.forPrint, colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }], sections: sections }))); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | function splitSegsByRow(segs, rowCnt) { | ||
91 | let byRow = []; | ||
92 | for (let i = 0; i < rowCnt; i += 1) { | ||
93 | byRow[i] = []; | ||
94 | } | ||
95 | for (let seg of segs) { | ||
96 | byRow[seg.row].push(seg); | ||
97 | } | ||
98 | return byRow; | ||
99 | } | ||
100 | function splitSegsByFirstCol(segs, colCnt) { | ||
101 | let byCol = []; | ||
102 | for (let i = 0; i < colCnt; i += 1) { | ||
103 | byCol[i] = []; | ||
104 | } | ||
105 | for (let seg of segs) { | ||
106 | byCol[seg.firstCol].push(seg); | ||
107 | } | ||
108 | return byCol; | ||
109 | } | ||
110 | function splitInteractionByRow(ui, rowCnt) { | ||
111 | let byRow = []; | ||
112 | if (!ui) { | ||
113 | for (let i = 0; i < rowCnt; i += 1) { | ||
114 | byRow[i] = null; | ||
115 | } | ||
116 | } | ||
117 | else { | ||
118 | for (let i = 0; i < rowCnt; i += 1) { | ||
119 | byRow[i] = { | ||
120 | affectedInstances: ui.affectedInstances, | ||
121 | isEvent: ui.isEvent, | ||
122 | segs: [], | ||
123 | }; | ||
124 | } | ||
125 | for (let seg of ui.segs) { | ||
126 | byRow[seg.row].segs.push(seg); | ||
127 | } | ||
128 | } | ||
129 | return byRow; | ||
130 | } | ||
131 | |||
132 | const DEFAULT_TABLE_EVENT_TIME_FORMAT = internal$1.createFormatter({ | ||
133 | hour: 'numeric', | ||
134 | minute: '2-digit', | ||
135 | omitZeroMinute: true, | ||
136 | meridiem: 'narrow', | ||
137 | }); | ||
138 | function hasListItemDisplay(seg) { | ||
139 | let { display } = seg.eventRange.ui; | ||
140 | return display === 'list-item' || (display === 'auto' && | ||
141 | !seg.eventRange.def.allDay && | ||
142 | seg.firstCol === seg.lastCol && // can't be multi-day | ||
143 | seg.isStart && // " | ||
144 | seg.isEnd // " | ||
145 | ); | ||
146 | } | ||
147 | |||
148 | class TableBlockEvent extends internal$1.BaseComponent { | ||
149 | render() { | ||
150 | let { props } = this; | ||
151 | return (preact.createElement(internal$1.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 }))); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | class TableListItemEvent extends internal$1.BaseComponent { | ||
156 | render() { | ||
157 | let { props, context } = this; | ||
158 | let { options } = context; | ||
159 | let { seg } = props; | ||
160 | let timeFormat = options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT; | ||
161 | let timeText = internal$1.buildSegTimeText(seg, timeFormat, context, true, props.defaultDisplayEventEnd); | ||
162 | return (preact.createElement(internal$1.EventContainer, Object.assign({}, props, { elTag: "a", elClasses: ['fc-daygrid-event', 'fc-daygrid-dot-event'], elAttrs: internal$1.getSegAnchorAttrs(props.seg, context), defaultGenerator: renderInnerContent, timeText: timeText, isResizing: false, isDateSelecting: false }))); | ||
163 | } | ||
164 | } | ||
165 | function renderInnerContent(renderProps) { | ||
166 | return (preact.createElement(preact.Fragment, null, | ||
167 | preact.createElement("div", { className: "fc-daygrid-event-dot", style: { borderColor: renderProps.borderColor || renderProps.backgroundColor } }), | ||
168 | renderProps.timeText && (preact.createElement("div", { className: "fc-event-time" }, renderProps.timeText)), | ||
169 | preact.createElement("div", { className: "fc-event-title" }, renderProps.event.title || preact.createElement(preact.Fragment, null, "\u00A0")))); | ||
170 | } | ||
171 | |||
172 | class TableCellMoreLink extends internal$1.BaseComponent { | ||
173 | constructor() { | ||
174 | super(...arguments); | ||
175 | this.compileSegs = internal$1.memoize(compileSegs); | ||
176 | } | ||
177 | render() { | ||
178 | let { props } = this; | ||
179 | let { allSegs, invisibleSegs } = this.compileSegs(props.singlePlacements); | ||
180 | return (preact.createElement(internal$1.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: () => { | ||
181 | let isForcedInvisible = (props.eventDrag ? props.eventDrag.affectedInstances : null) || | ||
182 | (props.eventResize ? props.eventResize.affectedInstances : null) || | ||
183 | {}; | ||
184 | return (preact.createElement(preact.Fragment, null, allSegs.map((seg) => { | ||
185 | let instanceId = seg.eventRange.instance.instanceId; | ||
186 | return (preact.createElement("div", { className: "fc-daygrid-event-harness", key: instanceId, style: { | ||
187 | visibility: isForcedInvisible[instanceId] ? 'hidden' : '', | ||
188 | } }, hasListItemDisplay(seg) ? (preact.createElement(TableListItemEvent, Object.assign({ seg: seg, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, internal$1.getSegMeta(seg, props.todayRange)))) : (preact.createElement(TableBlockEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, internal$1.getSegMeta(seg, props.todayRange)))))); | ||
189 | }))); | ||
190 | } })); | ||
191 | } | ||
192 | } | ||
193 | function compileSegs(singlePlacements) { | ||
194 | let allSegs = []; | ||
195 | let invisibleSegs = []; | ||
196 | for (let placement of singlePlacements) { | ||
197 | allSegs.push(placement.seg); | ||
198 | if (!placement.isVisible) { | ||
199 | invisibleSegs.push(placement.seg); | ||
200 | } | ||
201 | } | ||
202 | return { allSegs, invisibleSegs }; | ||
203 | } | ||
204 | |||
205 | const DEFAULT_WEEK_NUM_FORMAT = internal$1.createFormatter({ week: 'narrow' }); | ||
206 | class TableCell extends internal$1.DateComponent { | ||
207 | constructor() { | ||
208 | super(...arguments); | ||
209 | this.rootElRef = preact.createRef(); | ||
210 | this.state = { | ||
211 | dayNumberId: internal$1.getUniqueDomId(), | ||
212 | }; | ||
213 | this.handleRootEl = (el) => { | ||
214 | internal$1.setRef(this.rootElRef, el); | ||
215 | internal$1.setRef(this.props.elRef, el); | ||
216 | }; | ||
217 | } | ||
218 | render() { | ||
219 | let { context, props, state, rootElRef } = this; | ||
220 | let { options, dateEnv } = context; | ||
221 | let { date, dateProfile } = props; | ||
222 | // TODO: memoize this? | ||
223 | const isMonthStart = props.showDayNumber && | ||
224 | shouldDisplayMonthStart(date, dateProfile.currentRange, dateEnv); | ||
225 | return (preact.createElement(internal$1.DayCellContainer, { elTag: "td", elRef: this.handleRootEl, elClasses: [ | ||
226 | 'fc-daygrid-day', | ||
227 | ...(props.extraClassNames || []), | ||
228 | ], 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.createElement("div", { ref: props.innerElRef, className: "fc-daygrid-day-frame fc-scrollgrid-sync-inner", style: { minHeight: props.minHeight } }, | ||
229 | props.showWeekNumber && (preact.createElement(internal$1.WeekNumberContainer, { elTag: "a", elClasses: ['fc-daygrid-week-number'], elAttrs: internal$1.buildNavLinkAttrs(context, date, 'week'), date: date, defaultFormat: DEFAULT_WEEK_NUM_FORMAT })), | ||
230 | !renderProps.isDisabled && | ||
231 | (props.showDayNumber || internal$1.hasCustomDayCellContent(options) || props.forceDayTop) ? (preact.createElement("div", { className: "fc-daygrid-day-top" }, | ||
232 | preact.createElement(InnerContent, { elTag: "a", elClasses: [ | ||
233 | 'fc-daygrid-day-number', | ||
234 | isMonthStart && 'fc-daygrid-month-start', | ||
235 | ], elAttrs: Object.assign(Object.assign({}, internal$1.buildNavLinkAttrs(context, date)), { id: state.dayNumberId }) }))) : props.showDayNumber ? ( | ||
236 | // for creating correct amount of space (see issue #7162) | ||
237 | preact.createElement("div", { className: "fc-daygrid-day-top", style: { visibility: 'hidden' } }, | ||
238 | preact.createElement("a", { className: "fc-daygrid-day-number" }, "\u00A0"))) : undefined, | ||
239 | preact.createElement("div", { className: "fc-daygrid-day-events", ref: props.fgContentElRef }, | ||
240 | props.fgContent, | ||
241 | preact.createElement("div", { className: "fc-daygrid-day-bottom", style: { marginTop: props.moreMarginTop } }, | ||
242 | preact.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 }))), | ||
243 | preact.createElement("div", { className: "fc-daygrid-day-bg" }, props.bgContent))))); | ||
244 | } | ||
245 | } | ||
246 | function renderTopInner(props) { | ||
247 | return props.dayNumberText || preact.createElement(preact.Fragment, null, "\u00A0"); | ||
248 | } | ||
249 | function shouldDisplayMonthStart(date, currentRange, dateEnv) { | ||
250 | const { start: currentStart, end: currentEnd } = currentRange; | ||
251 | const currentEndIncl = internal$1.addMs(currentEnd, -1); | ||
252 | const currentFirstYear = dateEnv.getYear(currentStart); | ||
253 | const currentFirstMonth = dateEnv.getMonth(currentStart); | ||
254 | const currentLastYear = dateEnv.getYear(currentEndIncl); | ||
255 | const currentLastMonth = dateEnv.getMonth(currentEndIncl); | ||
256 | // spans more than one month? | ||
257 | return !(currentFirstYear === currentLastYear && currentFirstMonth === currentLastMonth) && | ||
258 | Boolean( | ||
259 | // first date in current view? | ||
260 | date.valueOf() === currentStart.valueOf() || | ||
261 | // a month-start that's within the current range? | ||
262 | (dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf())); | ||
263 | } | ||
264 | |||
265 | function generateSegKey(seg) { | ||
266 | return seg.eventRange.instance.instanceId + ':' + seg.firstCol; | ||
267 | } | ||
268 | function generateSegUid(seg) { | ||
269 | return generateSegKey(seg) + ':' + seg.lastCol; | ||
270 | } | ||
271 | function computeFgSegPlacement(segs, // assumed already sorted | ||
272 | dayMaxEvents, dayMaxEventRows, strictOrder, segHeights, maxContentHeight, cells) { | ||
273 | let hierarchy = new DayGridSegHierarchy((segEntry) => { | ||
274 | // TODO: more DRY with generateSegUid | ||
275 | let segUid = segs[segEntry.index].eventRange.instance.instanceId + | ||
276 | ':' + segEntry.span.start + | ||
277 | ':' + (segEntry.span.end - 1); | ||
278 | // if no thickness known, assume 1 (if 0, so small it always fits) | ||
279 | return segHeights[segUid] || 1; | ||
280 | }); | ||
281 | hierarchy.allowReslicing = true; | ||
282 | hierarchy.strictOrder = strictOrder; | ||
283 | if (dayMaxEvents === true || dayMaxEventRows === true) { | ||
284 | hierarchy.maxCoord = maxContentHeight; | ||
285 | hierarchy.hiddenConsumes = true; | ||
286 | } | ||
287 | else if (typeof dayMaxEvents === 'number') { | ||
288 | hierarchy.maxStackCnt = dayMaxEvents; | ||
289 | } | ||
290 | else if (typeof dayMaxEventRows === 'number') { | ||
291 | hierarchy.maxStackCnt = dayMaxEventRows; | ||
292 | hierarchy.hiddenConsumes = true; | ||
293 | } | ||
294 | // create segInputs only for segs with known heights | ||
295 | let segInputs = []; | ||
296 | let unknownHeightSegs = []; | ||
297 | for (let i = 0; i < segs.length; i += 1) { | ||
298 | let seg = segs[i]; | ||
299 | let segUid = generateSegUid(seg); | ||
300 | let eventHeight = segHeights[segUid]; | ||
301 | if (eventHeight != null) { | ||
302 | segInputs.push({ | ||
303 | index: i, | ||
304 | span: { | ||
305 | start: seg.firstCol, | ||
306 | end: seg.lastCol + 1, | ||
307 | }, | ||
308 | }); | ||
309 | } | ||
310 | else { | ||
311 | unknownHeightSegs.push(seg); | ||
312 | } | ||
313 | } | ||
314 | let hiddenEntries = hierarchy.addSegs(segInputs); | ||
315 | let segRects = hierarchy.toRects(); | ||
316 | let { singleColPlacements, multiColPlacements, leftoverMargins } = placeRects(segRects, segs, cells); | ||
317 | let moreCnts = []; | ||
318 | let moreMarginTops = []; | ||
319 | // add segs with unknown heights | ||
320 | for (let seg of unknownHeightSegs) { | ||
321 | multiColPlacements[seg.firstCol].push({ | ||
322 | seg, | ||
323 | isVisible: false, | ||
324 | isAbsolute: true, | ||
325 | absoluteTop: 0, | ||
326 | marginTop: 0, | ||
327 | }); | ||
328 | for (let col = seg.firstCol; col <= seg.lastCol; col += 1) { | ||
329 | singleColPlacements[col].push({ | ||
330 | seg: resliceSeg(seg, col, col + 1, cells), | ||
331 | isVisible: false, | ||
332 | isAbsolute: false, | ||
333 | absoluteTop: 0, | ||
334 | marginTop: 0, | ||
335 | }); | ||
336 | } | ||
337 | } | ||
338 | // add the hidden entries | ||
339 | for (let col = 0; col < cells.length; col += 1) { | ||
340 | moreCnts.push(0); | ||
341 | } | ||
342 | for (let hiddenEntry of hiddenEntries) { | ||
343 | let seg = segs[hiddenEntry.index]; | ||
344 | let hiddenSpan = hiddenEntry.span; | ||
345 | multiColPlacements[hiddenSpan.start].push({ | ||
346 | seg: resliceSeg(seg, hiddenSpan.start, hiddenSpan.end, cells), | ||
347 | isVisible: false, | ||
348 | isAbsolute: true, | ||
349 | absoluteTop: 0, | ||
350 | marginTop: 0, | ||
351 | }); | ||
352 | for (let col = hiddenSpan.start; col < hiddenSpan.end; col += 1) { | ||
353 | moreCnts[col] += 1; | ||
354 | singleColPlacements[col].push({ | ||
355 | seg: resliceSeg(seg, col, col + 1, cells), | ||
356 | isVisible: false, | ||
357 | isAbsolute: false, | ||
358 | absoluteTop: 0, | ||
359 | marginTop: 0, | ||
360 | }); | ||
361 | } | ||
362 | } | ||
363 | // deal with leftover margins | ||
364 | for (let col = 0; col < cells.length; col += 1) { | ||
365 | moreMarginTops.push(leftoverMargins[col]); | ||
366 | } | ||
367 | return { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops }; | ||
368 | } | ||
369 | // rects ordered by top coord, then left | ||
370 | function placeRects(allRects, segs, cells) { | ||
371 | let rectsByEachCol = groupRectsByEachCol(allRects, cells.length); | ||
372 | let singleColPlacements = []; | ||
373 | let multiColPlacements = []; | ||
374 | let leftoverMargins = []; | ||
375 | for (let col = 0; col < cells.length; col += 1) { | ||
376 | let rects = rectsByEachCol[col]; | ||
377 | // compute all static segs in singlePlacements | ||
378 | let singlePlacements = []; | ||
379 | let currentHeight = 0; | ||
380 | let currentMarginTop = 0; | ||
381 | for (let rect of rects) { | ||
382 | let seg = segs[rect.index]; | ||
383 | singlePlacements.push({ | ||
384 | seg: resliceSeg(seg, col, col + 1, cells), | ||
385 | isVisible: true, | ||
386 | isAbsolute: false, | ||
387 | absoluteTop: rect.levelCoord, | ||
388 | marginTop: rect.levelCoord - currentHeight, | ||
389 | }); | ||
390 | currentHeight = rect.levelCoord + rect.thickness; | ||
391 | } | ||
392 | // compute mixed static/absolute segs in multiPlacements | ||
393 | let multiPlacements = []; | ||
394 | currentHeight = 0; | ||
395 | currentMarginTop = 0; | ||
396 | for (let rect of rects) { | ||
397 | let seg = segs[rect.index]; | ||
398 | let isAbsolute = rect.span.end - rect.span.start > 1; // multi-column? | ||
399 | let isFirstCol = rect.span.start === col; | ||
400 | currentMarginTop += rect.levelCoord - currentHeight; // amount of space since bottom of previous seg | ||
401 | currentHeight = rect.levelCoord + rect.thickness; // height will now be bottom of current seg | ||
402 | if (isAbsolute) { | ||
403 | currentMarginTop += rect.thickness; | ||
404 | if (isFirstCol) { | ||
405 | multiPlacements.push({ | ||
406 | seg: resliceSeg(seg, rect.span.start, rect.span.end, cells), | ||
407 | isVisible: true, | ||
408 | isAbsolute: true, | ||
409 | absoluteTop: rect.levelCoord, | ||
410 | marginTop: 0, | ||
411 | }); | ||
412 | } | ||
413 | } | ||
414 | else if (isFirstCol) { | ||
415 | multiPlacements.push({ | ||
416 | seg: resliceSeg(seg, rect.span.start, rect.span.end, cells), | ||
417 | isVisible: true, | ||
418 | isAbsolute: false, | ||
419 | absoluteTop: rect.levelCoord, | ||
420 | marginTop: currentMarginTop, // claim the margin | ||
421 | }); | ||
422 | currentMarginTop = 0; | ||
423 | } | ||
424 | } | ||
425 | singleColPlacements.push(singlePlacements); | ||
426 | multiColPlacements.push(multiPlacements); | ||
427 | leftoverMargins.push(currentMarginTop); | ||
428 | } | ||
429 | return { singleColPlacements, multiColPlacements, leftoverMargins }; | ||
430 | } | ||
431 | function groupRectsByEachCol(rects, colCnt) { | ||
432 | let rectsByEachCol = []; | ||
433 | for (let col = 0; col < colCnt; col += 1) { | ||
434 | rectsByEachCol.push([]); | ||
435 | } | ||
436 | for (let rect of rects) { | ||
437 | for (let col = rect.span.start; col < rect.span.end; col += 1) { | ||
438 | rectsByEachCol[col].push(rect); | ||
439 | } | ||
440 | } | ||
441 | return rectsByEachCol; | ||
442 | } | ||
443 | function resliceSeg(seg, spanStart, spanEnd, cells) { | ||
444 | if (seg.firstCol === spanStart && seg.lastCol === spanEnd - 1) { | ||
445 | return seg; | ||
446 | } | ||
447 | let eventRange = seg.eventRange; | ||
448 | let origRange = eventRange.range; | ||
449 | let slicedRange = internal$1.intersectRanges(origRange, { | ||
450 | start: cells[spanStart].date, | ||
451 | end: internal$1.addDays(cells[spanEnd - 1].date, 1), | ||
452 | }); | ||
453 | return Object.assign(Object.assign({}, seg), { firstCol: spanStart, lastCol: spanEnd - 1, eventRange: { | ||
454 | def: eventRange.def, | ||
455 | ui: Object.assign(Object.assign({}, eventRange.ui), { durationEditable: false }), | ||
456 | instance: eventRange.instance, | ||
457 | range: slicedRange, | ||
458 | }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() }); | ||
459 | } | ||
460 | class DayGridSegHierarchy extends internal$1.SegHierarchy { | ||
461 | constructor() { | ||
462 | super(...arguments); | ||
463 | // config | ||
464 | this.hiddenConsumes = false; | ||
465 | // allows us to keep hidden entries in the hierarchy so they take up space | ||
466 | this.forceHidden = {}; | ||
467 | } | ||
468 | addSegs(segInputs) { | ||
469 | const hiddenSegs = super.addSegs(segInputs); | ||
470 | const { entriesByLevel } = this; | ||
471 | const excludeHidden = (entry) => !this.forceHidden[internal$1.buildEntryKey(entry)]; | ||
472 | // remove the forced-hidden segs | ||
473 | for (let level = 0; level < entriesByLevel.length; level += 1) { | ||
474 | entriesByLevel[level] = entriesByLevel[level].filter(excludeHidden); | ||
475 | } | ||
476 | return hiddenSegs; | ||
477 | } | ||
478 | handleInvalidInsertion(insertion, entry, hiddenEntries) { | ||
479 | const { entriesByLevel, forceHidden } = this; | ||
480 | const { touchingEntry, touchingLevel, touchingLateral } = insertion; | ||
481 | // the entry that the new insertion is touching must be hidden | ||
482 | if (this.hiddenConsumes && touchingEntry) { | ||
483 | const touchingEntryId = internal$1.buildEntryKey(touchingEntry); | ||
484 | if (!forceHidden[touchingEntryId]) { | ||
485 | if (this.allowReslicing) { | ||
486 | // split up the touchingEntry, reinsert it | ||
487 | const hiddenEntry = Object.assign(Object.assign({}, touchingEntry), { span: internal$1.intersectSpans(touchingEntry.span, entry.span) }); | ||
488 | // reinsert the area that turned into a "more" link (so no other entries try to | ||
489 | // occupy the space) but mark it forced-hidden | ||
490 | const hiddenEntryId = internal$1.buildEntryKey(hiddenEntry); | ||
491 | forceHidden[hiddenEntryId] = true; | ||
492 | entriesByLevel[touchingLevel][touchingLateral] = hiddenEntry; | ||
493 | hiddenEntries.push(hiddenEntry); | ||
494 | this.splitEntry(touchingEntry, entry, hiddenEntries); | ||
495 | } | ||
496 | else { | ||
497 | forceHidden[touchingEntryId] = true; | ||
498 | hiddenEntries.push(touchingEntry); | ||
499 | } | ||
500 | } | ||
501 | } | ||
502 | // will try to reslice... | ||
503 | super.handleInvalidInsertion(insertion, entry, hiddenEntries); | ||
504 | } | ||
505 | } | ||
506 | |||
507 | class TableRow extends internal$1.DateComponent { | ||
508 | constructor() { | ||
509 | super(...arguments); | ||
510 | this.cellElRefs = new internal$1.RefMap(); // the <td> | ||
511 | this.frameElRefs = new internal$1.RefMap(); // the fc-daygrid-day-frame | ||
512 | this.fgElRefs = new internal$1.RefMap(); // the fc-daygrid-day-events | ||
513 | this.segHarnessRefs = new internal$1.RefMap(); // indexed by "instanceId:firstCol" | ||
514 | this.rootElRef = preact.createRef(); | ||
515 | this.state = { | ||
516 | framePositions: null, | ||
517 | maxContentHeight: null, | ||
518 | segHeights: {}, | ||
519 | }; | ||
520 | this.handleResize = (isForced) => { | ||
521 | if (isForced) { | ||
522 | this.updateSizing(true); // isExternal=true | ||
523 | } | ||
524 | }; | ||
525 | } | ||
526 | render() { | ||
527 | let { props, state, context } = this; | ||
528 | let { options } = context; | ||
529 | let colCnt = props.cells.length; | ||
530 | let businessHoursByCol = splitSegsByFirstCol(props.businessHourSegs, colCnt); | ||
531 | let bgEventSegsByCol = splitSegsByFirstCol(props.bgEventSegs, colCnt); | ||
532 | let highlightSegsByCol = splitSegsByFirstCol(this.getHighlightSegs(), colCnt); | ||
533 | let mirrorSegsByCol = splitSegsByFirstCol(this.getMirrorSegs(), colCnt); | ||
534 | let { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops } = computeFgSegPlacement(internal$1.sortEventSegs(props.fgEventSegs, options.eventOrder), props.dayMaxEvents, props.dayMaxEventRows, options.eventOrderStrict, state.segHeights, state.maxContentHeight, props.cells); | ||
535 | let isForcedInvisible = // TODO: messy way to compute this | ||
536 | (props.eventDrag && props.eventDrag.affectedInstances) || | ||
537 | (props.eventResize && props.eventResize.affectedInstances) || | ||
538 | {}; | ||
539 | return (preact.createElement("tr", { ref: this.rootElRef, role: "row" }, | ||
540 | props.renderIntro && props.renderIntro(), | ||
541 | props.cells.map((cell, col) => { | ||
542 | let normalFgNodes = this.renderFgSegs(col, props.forPrint ? singleColPlacements[col] : multiColPlacements[col], props.todayRange, isForcedInvisible); | ||
543 | let mirrorFgNodes = this.renderFgSegs(col, buildMirrorPlacements(mirrorSegsByCol[col], multiColPlacements), props.todayRange, {}, Boolean(props.eventDrag), Boolean(props.eventResize), false); | ||
544 | return (preact.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 | ||
545 | preact.createElement(preact.Fragment, null, | ||
546 | preact.createElement(preact.Fragment, null, normalFgNodes), | ||
547 | preact.createElement(preact.Fragment, null, mirrorFgNodes))), bgContent: ( // Fragment scopes the keys | ||
548 | preact.createElement(preact.Fragment, null, | ||
549 | this.renderFillSegs(highlightSegsByCol[col], 'highlight'), | ||
550 | this.renderFillSegs(businessHoursByCol[col], 'non-business'), | ||
551 | this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))), minHeight: props.cellMinHeight })); | ||
552 | }))); | ||
553 | } | ||
554 | componentDidMount() { | ||
555 | this.updateSizing(true); | ||
556 | this.context.addResizeHandler(this.handleResize); | ||
557 | } | ||
558 | componentDidUpdate(prevProps, prevState) { | ||
559 | let currentProps = this.props; | ||
560 | this.updateSizing(!internal$1.isPropsEqual(prevProps, currentProps)); | ||
561 | } | ||
562 | componentWillUnmount() { | ||
563 | this.context.removeResizeHandler(this.handleResize); | ||
564 | } | ||
565 | getHighlightSegs() { | ||
566 | let { props } = this; | ||
567 | if (props.eventDrag && props.eventDrag.segs.length) { // messy check | ||
568 | return props.eventDrag.segs; | ||
569 | } | ||
570 | if (props.eventResize && props.eventResize.segs.length) { // messy check | ||
571 | return props.eventResize.segs; | ||
572 | } | ||
573 | return props.dateSelectionSegs; | ||
574 | } | ||
575 | getMirrorSegs() { | ||
576 | let { props } = this; | ||
577 | if (props.eventResize && props.eventResize.segs.length) { // messy check | ||
578 | return props.eventResize.segs; | ||
579 | } | ||
580 | return []; | ||
581 | } | ||
582 | renderFgSegs(col, segPlacements, todayRange, isForcedInvisible, isDragging, isResizing, isDateSelecting) { | ||
583 | let { context } = this; | ||
584 | let { eventSelection } = this.props; | ||
585 | let { framePositions } = this.state; | ||
586 | let defaultDisplayEventEnd = this.props.cells.length === 1; // colCnt === 1 | ||
587 | let isMirror = isDragging || isResizing || isDateSelecting; | ||
588 | let nodes = []; | ||
589 | if (framePositions) { | ||
590 | for (let placement of segPlacements) { | ||
591 | let { seg } = placement; | ||
592 | let { instanceId } = seg.eventRange.instance; | ||
593 | let isVisible = placement.isVisible && !isForcedInvisible[instanceId]; | ||
594 | let isAbsolute = placement.isAbsolute; | ||
595 | let left = ''; | ||
596 | let right = ''; | ||
597 | if (isAbsolute) { | ||
598 | if (context.isRtl) { | ||
599 | right = 0; | ||
600 | left = framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol]; | ||
601 | } | ||
602 | else { | ||
603 | left = 0; | ||
604 | right = framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol]; | ||
605 | } | ||
606 | } | ||
607 | /* | ||
608 | known bug: events that are force to be list-item but span multiple days still take up space in later columns | ||
609 | todo: in print view, for multi-day events, don't display title within non-start/end segs | ||
610 | */ | ||
611 | nodes.push(preact.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: { | ||
612 | visibility: isVisible ? '' : 'hidden', | ||
613 | marginTop: isAbsolute ? '' : placement.marginTop, | ||
614 | top: isAbsolute ? placement.absoluteTop : '', | ||
615 | left, | ||
616 | right, | ||
617 | } }, hasListItemDisplay(seg) ? (preact.createElement(TableListItemEvent, Object.assign({ seg: seg, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal$1.getSegMeta(seg, todayRange)))) : (preact.createElement(TableBlockEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal$1.getSegMeta(seg, todayRange)))))); | ||
618 | } | ||
619 | } | ||
620 | return nodes; | ||
621 | } | ||
622 | renderFillSegs(segs, fillType) { | ||
623 | let { isRtl } = this.context; | ||
624 | let { todayRange } = this.props; | ||
625 | let { framePositions } = this.state; | ||
626 | let nodes = []; | ||
627 | if (framePositions) { | ||
628 | for (let seg of segs) { | ||
629 | let leftRightCss = isRtl ? { | ||
630 | right: 0, | ||
631 | left: framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol], | ||
632 | } : { | ||
633 | left: 0, | ||
634 | right: framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol], | ||
635 | }; | ||
636 | nodes.push(preact.createElement("div", { key: internal$1.buildEventRangeKey(seg.eventRange), className: "fc-daygrid-bg-harness", style: leftRightCss }, fillType === 'bg-event' ? | ||
637 | preact.createElement(internal$1.BgEvent, Object.assign({ seg: seg }, internal$1.getSegMeta(seg, todayRange))) : | ||
638 | internal$1.renderFill(fillType))); | ||
639 | } | ||
640 | } | ||
641 | return preact.createElement(preact.Fragment, {}, ...nodes); | ||
642 | } | ||
643 | updateSizing(isExternalSizingChange) { | ||
644 | let { props, state, frameElRefs } = this; | ||
645 | if (!props.forPrint && | ||
646 | props.clientWidth !== null // positioning ready? | ||
647 | ) { | ||
648 | if (isExternalSizingChange) { | ||
649 | let frameEls = props.cells.map((cell) => frameElRefs.currentMap[cell.key]); | ||
650 | if (frameEls.length) { | ||
651 | let originEl = this.rootElRef.current; | ||
652 | let newPositionCache = new internal$1.PositionCache(originEl, frameEls, true, // isHorizontal | ||
653 | false); | ||
654 | if (!state.framePositions || !state.framePositions.similarTo(newPositionCache)) { | ||
655 | this.setState({ | ||
656 | framePositions: new internal$1.PositionCache(originEl, frameEls, true, // isHorizontal | ||
657 | false), | ||
658 | }); | ||
659 | } | ||
660 | } | ||
661 | } | ||
662 | const oldSegHeights = this.state.segHeights; | ||
663 | const newSegHeights = this.querySegHeights(); | ||
664 | const limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true; | ||
665 | this.safeSetState({ | ||
666 | // HACK to prevent oscillations of events being shown/hidden from max-event-rows | ||
667 | // Essentially, once you compute an element's height, never null-out. | ||
668 | // TODO: always display all events, as visibility:hidden? | ||
669 | segHeights: Object.assign(Object.assign({}, oldSegHeights), newSegHeights), | ||
670 | maxContentHeight: limitByContentHeight ? this.computeMaxContentHeight() : null, | ||
671 | }); | ||
672 | } | ||
673 | } | ||
674 | querySegHeights() { | ||
675 | let segElMap = this.segHarnessRefs.currentMap; | ||
676 | let segHeights = {}; | ||
677 | // get the max height amongst instance segs | ||
678 | for (let segUid in segElMap) { | ||
679 | let height = Math.round(segElMap[segUid].getBoundingClientRect().height); | ||
680 | segHeights[segUid] = Math.max(segHeights[segUid] || 0, height); | ||
681 | } | ||
682 | return segHeights; | ||
683 | } | ||
684 | computeMaxContentHeight() { | ||
685 | let firstKey = this.props.cells[0].key; | ||
686 | let cellEl = this.cellElRefs.currentMap[firstKey]; | ||
687 | let fcContainerEl = this.fgElRefs.currentMap[firstKey]; | ||
688 | return cellEl.getBoundingClientRect().bottom - fcContainerEl.getBoundingClientRect().top; | ||
689 | } | ||
690 | getCellEls() { | ||
691 | let elMap = this.cellElRefs.currentMap; | ||
692 | return this.props.cells.map((cell) => elMap[cell.key]); | ||
693 | } | ||
694 | } | ||
695 | TableRow.addStateEquality({ | ||
696 | segHeights: internal$1.isPropsEqual, | ||
697 | }); | ||
698 | function buildMirrorPlacements(mirrorSegs, colPlacements) { | ||
699 | if (!mirrorSegs.length) { | ||
700 | return []; | ||
701 | } | ||
702 | let topsByInstanceId = buildAbsoluteTopHash(colPlacements); // TODO: cache this at first render? | ||
703 | return mirrorSegs.map((seg) => ({ | ||
704 | seg, | ||
705 | isVisible: true, | ||
706 | isAbsolute: true, | ||
707 | absoluteTop: topsByInstanceId[seg.eventRange.instance.instanceId], | ||
708 | marginTop: 0, | ||
709 | })); | ||
710 | } | ||
711 | function buildAbsoluteTopHash(colPlacements) { | ||
712 | let topsByInstanceId = {}; | ||
713 | for (let placements of colPlacements) { | ||
714 | for (let placement of placements) { | ||
715 | topsByInstanceId[placement.seg.eventRange.instance.instanceId] = placement.absoluteTop; | ||
716 | } | ||
717 | } | ||
718 | return topsByInstanceId; | ||
719 | } | ||
720 | |||
721 | class TableRows extends internal$1.DateComponent { | ||
722 | constructor() { | ||
723 | super(...arguments); | ||
724 | this.splitBusinessHourSegs = internal$1.memoize(splitSegsByRow); | ||
725 | this.splitBgEventSegs = internal$1.memoize(splitSegsByRow); | ||
726 | this.splitFgEventSegs = internal$1.memoize(splitSegsByRow); | ||
727 | this.splitDateSelectionSegs = internal$1.memoize(splitSegsByRow); | ||
728 | this.splitEventDrag = internal$1.memoize(splitInteractionByRow); | ||
729 | this.splitEventResize = internal$1.memoize(splitInteractionByRow); | ||
730 | this.rowRefs = new internal$1.RefMap(); | ||
731 | } | ||
732 | render() { | ||
733 | let { props, context } = this; | ||
734 | let rowCnt = props.cells.length; | ||
735 | let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt); | ||
736 | let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt); | ||
737 | let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt); | ||
738 | let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt); | ||
739 | let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt); | ||
740 | let eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt); | ||
741 | // for DayGrid view with many rows, force a min-height on cells so doesn't appear squished | ||
742 | // choose 7 because a month view will have max 6 rows | ||
743 | let cellMinHeight = (rowCnt >= 7 && props.clientWidth) ? | ||
744 | props.clientWidth / context.options.aspectRatio / 6 : | ||
745 | null; | ||
746 | return (preact.createElement(internal$1.NowTimer, { unit: "day" }, (nowDate, todayRange) => (preact.createElement(preact.Fragment, null, props.cells.map((cells, row) => (preact.createElement(TableRow, { ref: this.rowRefs.createRef(row), key: cells.length | ||
747 | ? cells[0].date.toISOString() /* best? or put key on cell? or use diff formatter? */ | ||
748 | : row // in case there are no cells (like when resource view is loading) | ||
749 | , 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 }))))))); | ||
750 | } | ||
751 | componentDidMount() { | ||
752 | this.registerInteractiveComponent(); | ||
753 | } | ||
754 | componentDidUpdate() { | ||
755 | // for if started with zero cells | ||
756 | this.registerInteractiveComponent(); | ||
757 | } | ||
758 | registerInteractiveComponent() { | ||
759 | if (!this.rootEl) { | ||
760 | // HACK: need a daygrid wrapper parent to do positioning | ||
761 | // NOTE: a daygrid resource view w/o resources can have zero cells | ||
762 | const firstCellEl = this.rowRefs.currentMap[0].getCellEls()[0]; | ||
763 | const rootEl = firstCellEl ? firstCellEl.closest('.fc-daygrid-body') : null; | ||
764 | if (rootEl) { | ||
765 | this.rootEl = rootEl; | ||
766 | this.context.registerInteractiveComponent(this, { | ||
767 | el: rootEl, | ||
768 | isHitComboAllowed: this.props.isHitComboAllowed, | ||
769 | }); | ||
770 | } | ||
771 | } | ||
772 | } | ||
773 | componentWillUnmount() { | ||
774 | if (this.rootEl) { | ||
775 | this.context.unregisterInteractiveComponent(this); | ||
776 | this.rootEl = null; | ||
777 | } | ||
778 | } | ||
779 | // Hit System | ||
780 | // ---------------------------------------------------------------------------------------------------- | ||
781 | prepareHits() { | ||
782 | this.rowPositions = new internal$1.PositionCache(this.rootEl, this.rowRefs.collect().map((rowObj) => rowObj.getCellEls()[0]), // first cell el in each row. TODO: not optimal | ||
783 | false, true); | ||
784 | this.colPositions = new internal$1.PositionCache(this.rootEl, this.rowRefs.currentMap[0].getCellEls(), // cell els in first row | ||
785 | true, // horizontal | ||
786 | false); | ||
787 | } | ||
788 | queryHit(positionLeft, positionTop) { | ||
789 | let { colPositions, rowPositions } = this; | ||
790 | let col = colPositions.leftToIndex(positionLeft); | ||
791 | let row = rowPositions.topToIndex(positionTop); | ||
792 | if (row != null && col != null) { | ||
793 | let cell = this.props.cells[row][col]; | ||
794 | return { | ||
795 | dateProfile: this.props.dateProfile, | ||
796 | dateSpan: Object.assign({ range: this.getCellRange(row, col), allDay: true }, cell.extraDateSpan), | ||
797 | dayEl: this.getCellEl(row, col), | ||
798 | rect: { | ||
799 | left: colPositions.lefts[col], | ||
800 | right: colPositions.rights[col], | ||
801 | top: rowPositions.tops[row], | ||
802 | bottom: rowPositions.bottoms[row], | ||
803 | }, | ||
804 | layer: 0, | ||
805 | }; | ||
806 | } | ||
807 | return null; | ||
808 | } | ||
809 | getCellEl(row, col) { | ||
810 | return this.rowRefs.currentMap[row].getCellEls()[col]; // TODO: not optimal | ||
811 | } | ||
812 | getCellRange(row, col) { | ||
813 | let start = this.props.cells[row][col].date; | ||
814 | let end = internal$1.addDays(start, 1); | ||
815 | return { start, end }; | ||
816 | } | ||
817 | } | ||
818 | function isSegAllDay(seg) { | ||
819 | return seg.eventRange.def.allDay; | ||
820 | } | ||
821 | |||
822 | class Table extends internal$1.DateComponent { | ||
823 | constructor() { | ||
824 | super(...arguments); | ||
825 | this.elRef = preact.createRef(); | ||
826 | this.needsScrollReset = false; | ||
827 | } | ||
828 | render() { | ||
829 | let { props } = this; | ||
830 | let { dayMaxEventRows, dayMaxEvents, expandRows } = props; | ||
831 | let limitViaBalanced = dayMaxEvents === true || dayMaxEventRows === true; | ||
832 | // if rows can't expand to fill fixed height, can't do balanced-height event limit | ||
833 | // TODO: best place to normalize these options? | ||
834 | if (limitViaBalanced && !expandRows) { | ||
835 | limitViaBalanced = false; | ||
836 | dayMaxEventRows = null; | ||
837 | dayMaxEvents = null; | ||
838 | } | ||
839 | let classNames = [ | ||
840 | 'fc-daygrid-body', | ||
841 | limitViaBalanced ? 'fc-daygrid-body-balanced' : 'fc-daygrid-body-unbalanced', | ||
842 | expandRows ? '' : 'fc-daygrid-body-natural', // will height of one row depend on the others? | ||
843 | ]; | ||
844 | return (preact.createElement("div", { ref: this.elRef, className: classNames.join(' '), style: { | ||
845 | // these props are important to give this wrapper correct dimensions for interactions | ||
846 | // TODO: if we set it here, can we avoid giving to inner tables? | ||
847 | width: props.clientWidth, | ||
848 | minWidth: props.tableMinWidth, | ||
849 | } }, | ||
850 | preact.createElement("table", { role: "presentation", className: "fc-scrollgrid-sync-table", style: { | ||
851 | width: props.clientWidth, | ||
852 | minWidth: props.tableMinWidth, | ||
853 | height: expandRows ? props.clientHeight : '', | ||
854 | } }, | ||
855 | props.colGroupNode, | ||
856 | preact.createElement("tbody", { role: "presentation" }, | ||
857 | preact.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 }))))); | ||
858 | } | ||
859 | componentDidMount() { | ||
860 | this.requestScrollReset(); | ||
861 | } | ||
862 | componentDidUpdate(prevProps) { | ||
863 | if (prevProps.dateProfile !== this.props.dateProfile) { | ||
864 | this.requestScrollReset(); | ||
865 | } | ||
866 | else { | ||
867 | this.flushScrollReset(); | ||
868 | } | ||
869 | } | ||
870 | requestScrollReset() { | ||
871 | this.needsScrollReset = true; | ||
872 | this.flushScrollReset(); | ||
873 | } | ||
874 | flushScrollReset() { | ||
875 | if (this.needsScrollReset && | ||
876 | this.props.clientWidth // sizes computed? | ||
877 | ) { | ||
878 | const subjectEl = getScrollSubjectEl(this.elRef.current, this.props.dateProfile); | ||
879 | if (subjectEl) { | ||
880 | const originEl = subjectEl.closest('.fc-daygrid-body'); | ||
881 | const scrollEl = originEl.closest('.fc-scroller'); | ||
882 | const scrollTop = subjectEl.getBoundingClientRect().top - | ||
883 | originEl.getBoundingClientRect().top; | ||
884 | scrollEl.scrollTop = scrollTop ? (scrollTop + 1) : 0; // overcome border | ||
885 | } | ||
886 | this.needsScrollReset = false; | ||
887 | } | ||
888 | } | ||
889 | } | ||
890 | function getScrollSubjectEl(containerEl, dateProfile) { | ||
891 | let el; | ||
892 | if (dateProfile.currentRangeUnit.match(/year|month/)) { | ||
893 | el = containerEl.querySelector(`[data-date="${internal$1.formatIsoMonthStr(dateProfile.currentDate)}-01"]`); | ||
894 | // even if view is month-based, first-of-month might be hidden... | ||
895 | } | ||
896 | if (!el) { | ||
897 | el = containerEl.querySelector(`[data-date="${internal$1.formatDayString(dateProfile.currentDate)}"]`); | ||
898 | // could still be hidden if an interior-view hidden day | ||
899 | } | ||
900 | return el; | ||
901 | } | ||
902 | |||
903 | class DayTableSlicer extends internal$1.Slicer { | ||
904 | constructor() { | ||
905 | super(...arguments); | ||
906 | this.forceDayIfListItem = true; | ||
907 | } | ||
908 | sliceRange(dateRange, dayTableModel) { | ||
909 | return dayTableModel.sliceRange(dateRange); | ||
910 | } | ||
911 | } | ||
912 | |||
913 | class DayTable extends internal$1.DateComponent { | ||
914 | constructor() { | ||
915 | super(...arguments); | ||
916 | this.slicer = new DayTableSlicer(); | ||
917 | this.tableRef = preact.createRef(); | ||
918 | } | ||
919 | render() { | ||
920 | let { props, context } = this; | ||
921 | return (preact.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 }))); | ||
922 | } | ||
923 | } | ||
924 | |||
925 | class DayTableView extends TableView { | ||
926 | constructor() { | ||
927 | super(...arguments); | ||
928 | this.buildDayTableModel = internal$1.memoize(buildDayTableModel); | ||
929 | this.headerRef = preact.createRef(); | ||
930 | this.tableRef = preact.createRef(); | ||
931 | // can't override any lifecycle methods from parent | ||
932 | } | ||
933 | render() { | ||
934 | let { options, dateProfileGenerator } = this.context; | ||
935 | let { props } = this; | ||
936 | let dayTableModel = this.buildDayTableModel(props.dateProfile, dateProfileGenerator); | ||
937 | let headerContent = options.dayHeaders && (preact.createElement(internal$1.DayHeader, { ref: this.headerRef, dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: dayTableModel.rowCnt === 1 })); | ||
938 | let bodyContent = (contentArg) => (preact.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 })); | ||
939 | return options.dayMinWidth | ||
940 | ? this.renderHScrollLayout(headerContent, bodyContent, dayTableModel.colCnt, options.dayMinWidth) | ||
941 | : this.renderSimpleLayout(headerContent, bodyContent); | ||
942 | } | ||
943 | } | ||
944 | function buildDayTableModel(dateProfile, dateProfileGenerator) { | ||
945 | let daySeries = new internal$1.DaySeriesModel(dateProfile.renderRange, dateProfileGenerator); | ||
946 | return new internal$1.DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit)); | ||
947 | } | ||
948 | |||
949 | class TableDateProfileGenerator extends internal$1.DateProfileGenerator { | ||
950 | // Computes the date range that will be rendered | ||
951 | buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) { | ||
952 | let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay); | ||
953 | let { props } = this; | ||
954 | return buildDayTableRenderRange({ | ||
955 | currentRange: renderRange, | ||
956 | snapToWeek: /^(year|month)$/.test(currentRangeUnit), | ||
957 | fixedWeekCount: props.fixedWeekCount, | ||
958 | dateEnv: props.dateEnv, | ||
959 | }); | ||
960 | } | ||
961 | } | ||
962 | function buildDayTableRenderRange(props) { | ||
963 | let { dateEnv, currentRange } = props; | ||
964 | let { start, end } = currentRange; | ||
965 | let endOfWeek; | ||
966 | // year and month views should be aligned with weeks. this is already done for week | ||
967 | if (props.snapToWeek) { | ||
968 | start = dateEnv.startOfWeek(start); | ||
969 | // make end-of-week if not already | ||
970 | endOfWeek = dateEnv.startOfWeek(end); | ||
971 | if (endOfWeek.valueOf() !== end.valueOf()) { | ||
972 | end = internal$1.addWeeks(endOfWeek, 1); | ||
973 | } | ||
974 | } | ||
975 | // ensure 6 weeks | ||
976 | if (props.fixedWeekCount) { | ||
977 | // TODO: instead of these date-math gymnastics (for multimonth view), | ||
978 | // compute dateprofiles of all months, then use start of first and end of last. | ||
979 | let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth(internal$1.addDays(currentRange.end, -1))); | ||
980 | let rowCnt = Math.ceil(// could be partial weeks due to hiddenDays | ||
981 | internal$1.diffWeeks(lastMonthRenderStart, end)); | ||
982 | end = internal$1.addWeeks(end, 6 - rowCnt); | ||
983 | } | ||
984 | return { start, end }; | ||
985 | } | ||
986 | |||
987 | 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}"; | ||
988 | internal$1.injectStyles(css_248z); | ||
989 | |||
990 | var plugin = core.createPlugin({ | ||
991 | name: '@fullcalendar/daygrid', | ||
992 | initialView: 'dayGridMonth', | ||
993 | views: { | ||
994 | dayGrid: { | ||
995 | component: DayTableView, | ||
996 | dateProfileGeneratorClass: TableDateProfileGenerator, | ||
997 | }, | ||
998 | dayGridDay: { | ||
999 | type: 'dayGrid', | ||
1000 | duration: { days: 1 }, | ||
1001 | }, | ||
1002 | dayGridWeek: { | ||
1003 | type: 'dayGrid', | ||
1004 | duration: { weeks: 1 }, | ||
1005 | }, | ||
1006 | dayGridMonth: { | ||
1007 | type: 'dayGrid', | ||
1008 | duration: { months: 1 }, | ||
1009 | fixedWeekCount: true, | ||
1010 | }, | ||
1011 | dayGridYear: { | ||
1012 | type: 'dayGrid', | ||
1013 | duration: { years: 1 }, | ||
1014 | }, | ||
1015 | }, | ||
1016 | }); | ||
1017 | |||
1018 | var internal = { | ||
1019 | __proto__: null, | ||
1020 | DayTable: DayTable, | ||
1021 | DayTableSlicer: DayTableSlicer, | ||
1022 | TableDateProfileGenerator: TableDateProfileGenerator, | ||
1023 | buildDayTableRenderRange: buildDayTableRenderRange, | ||
1024 | Table: Table, | ||
1025 | TableRows: TableRows, | ||
1026 | TableView: TableView, | ||
1027 | buildDayTableModel: buildDayTableModel, | ||
1028 | DayGridView: DayTableView | ||
1029 | }; | ||
1030 | |||
1031 | core.globalPlugins.push(plugin); | ||
1032 | |||
1033 | exports.Internal = internal; | ||
1034 | exports["default"] = plugin; | ||
1035 | |||
1036 | Object.defineProperty(exports, '__esModule', { value: true }); | ||
1037 | |||
1038 | return exports; | ||
1039 | |||
1040 | })({}, FullCalendar, FullCalendar.Internal, FullCalendar.Preact); | ||