@fullcalendar/daygrid 7.0.0-beta.4 → 7.0.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1339 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var internal = require('@fullcalendar/core/internal');
6
+ var preact = require('@fullcalendar/core/preact');
7
+ var core = require('@fullcalendar/core');
8
+ var classNames = require('@fullcalendar/core/internal-classnames');
9
+
10
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
11
+
12
+ var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
13
+
14
+ class DayTableSlicer extends internal.Slicer {
15
+ constructor() {
16
+ super(...arguments);
17
+ this.forceDayIfListItem = true;
18
+ }
19
+ sliceRange(dateRange, dayTableModel) {
20
+ return dayTableModel.sliceRange(dateRange);
21
+ }
22
+ }
23
+
24
+ // TODO: converge types with DayTableCell and DayCellContainer (the component) and refineRenderProps
25
+ // the generation of DayTableCell will be distinct (for the BODY cells)
26
+ // but can share some of the same types/utils
27
+ // Date Cells
28
+ // -------------------------------------------------------------------------------------------------
29
+ const firstSunday = new Date(259200000);
30
+ function buildDateRowConfigs(dates, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, // TODO: rename to dateHeaderFormat?
31
+ context) {
32
+ const rowConfig = buildDateRowConfig(dates, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, context);
33
+ const majorUnit = internal.computeMajorUnit(dateProfile, context.dateEnv);
34
+ // HACK mutate isMajor
35
+ if (datesRepDistinctDays) {
36
+ for (const dataConfig of rowConfig.dataConfigs) {
37
+ if (internal.isMajorUnit(dataConfig.dateMarker, majorUnit, context.dateEnv)) {
38
+ dataConfig.renderProps.isMajor = true;
39
+ }
40
+ }
41
+ }
42
+ return [rowConfig];
43
+ }
44
+ /*
45
+ Should this receive resource data attributes?
46
+ Or ResourceApi object itself?
47
+ */
48
+ function buildDateRowConfig(dateMarkers, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, // TODO: rename to dateHeaderFormat?
49
+ context, colSpan, isMajorMod) {
50
+ return {
51
+ isDateRow: true,
52
+ renderConfig: buildDateRenderConfig(context),
53
+ dataConfigs: buildDateDataConfigs(dateMarkers, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, context, colSpan, undefined, undefined, undefined, undefined, isMajorMod)
54
+ };
55
+ }
56
+ /*
57
+ For header cells: how to connect w/ custom rendering
58
+ Applies to all cells in a row
59
+ */
60
+ function buildDateRenderConfig(context) {
61
+ const { options } = context;
62
+ return {
63
+ generatorName: 'dayHeaderContent',
64
+ customGenerator: options.dayHeaderContent,
65
+ classNameGenerator: options.dayHeaderClass,
66
+ innerClassNameGenerator: options.dayHeaderInnerClass,
67
+ didMount: options.dayHeaderDidMount,
68
+ willUnmount: options.dayHeaderWillUnmount,
69
+ align: options.dayHeaderAlign,
70
+ sticky: options.dayHeaderSticky,
71
+ };
72
+ }
73
+ const dowDates = [];
74
+ for (let dow = 0; dow < 7; dow++) {
75
+ dowDates.push(internal.addDays(new Date(259200000), dow)); // start with Sun, 04 Jan 1970 00:00:00 GMT)
76
+ }
77
+ /*
78
+ For header cells: data
79
+ */
80
+ function buildDateDataConfigs(dateMarkers, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, // TODO: rename to dateHeaderFormat?
81
+ context, colSpan = 1, keyPrefix = '', extraRenderProps = {}, // TODO
82
+ extraAttrs = {}, // TODO
83
+ className = '', isMajorMod) {
84
+ const { dateEnv, viewApi, options } = context;
85
+ return datesRepDistinctDays
86
+ ? dateMarkers.map((dateMarker, i) => {
87
+ const dateMeta = internal.getDateMeta(dateMarker, dateEnv, dateProfile, todayRange);
88
+ const isMajor = isMajorMod != null && !(i % isMajorMod);
89
+ const [text, textParts] = dateEnv.format(dateMarker, dayHeaderFormat);
90
+ const hasNavLink = options.navLinks && !dateMeta.isDisabled &&
91
+ dateMarkers.length > 1; // don't show navlink to day if only one day
92
+ const renderProps = Object.assign(Object.assign(Object.assign({}, dateMeta), extraRenderProps), { text,
93
+ textParts,
94
+ get weekdayText() { return internal.findWeekdayText(textParts); },
95
+ get dayNumberText() { return datesRepDistinctDays ? internal.findDayNumberText(textParts) : ''; },
96
+ isMajor, isNarrow: false, isSticky: false, inPopover: false, level: 0, // HACK. gets overridden
97
+ hasNavLink, view: viewApi });
98
+ const fullDateStr = internal.buildDateStr(context, dateMarker);
99
+ // for DayGridHeaderCell
100
+ return {
101
+ key: keyPrefix + dateMarker.toUTCString(),
102
+ dateMarker,
103
+ renderProps,
104
+ attrs: Object.assign(Object.assign(Object.assign({ 'aria-label': fullDateStr }, (dateMeta.isToday ? { 'aria-current': 'date' } : {})), { 'data-date': internal.formatDayString(dateMarker) }), extraAttrs),
105
+ // for navlink
106
+ innerAttrs: hasNavLink
107
+ ? internal.buildNavLinkAttrs(context, dateMarker, undefined, fullDateStr)
108
+ : { 'aria-hidden': true },
109
+ colSpan,
110
+ hasNavLink,
111
+ className,
112
+ };
113
+ })
114
+ : dateMarkers.map((dateMarker, i) => {
115
+ const dow = dateMarker.getUTCDay();
116
+ const normDate = internal.addDays(firstSunday, dow);
117
+ const dateMeta = {
118
+ date: dateEnv.toDate(dateMarker),
119
+ dow,
120
+ isDisabled: false,
121
+ isFuture: false,
122
+ isPast: false,
123
+ isToday: false,
124
+ isOther: false,
125
+ };
126
+ const isMajor = isMajorMod != null && !(i % isMajorMod);
127
+ const [text, textParts] = dateEnv.format(normDate, dayHeaderFormat);
128
+ const renderProps = Object.assign(Object.assign(Object.assign({}, dateMeta), { date: dowDates[dow], isMajor, isNarrow: false, isSticky: false, inPopover: false, hasNavLink: false, level: 0, view: viewApi, text,
129
+ textParts,
130
+ get weekdayText() { return internal.findWeekdayText(textParts); },
131
+ get dayNumberText() { return datesRepDistinctDays ? internal.findDayNumberText(textParts) : ''; } }), extraRenderProps);
132
+ const fullWeekDayStr = dateEnv.format(normDate, internal.WEEKDAY_ONLY_FORMAT)[0];
133
+ // for DayGridHeaderCell
134
+ return {
135
+ key: keyPrefix + String(dow),
136
+ dateMarker,
137
+ renderProps,
138
+ attrs: Object.assign({ 'aria-label': fullWeekDayStr }, extraAttrs),
139
+ // NOT a navlink
140
+ innerAttrs: {
141
+ 'aria-hidden': true, // label already on cell
142
+ },
143
+ colSpan,
144
+ className,
145
+ };
146
+ });
147
+ }
148
+
149
+ /*
150
+ We need really specific keys because RefMap::createRef() which is then given to heightRef
151
+ unable to change key! As a result, we cannot reuse elements between normal/slice/standin types,
152
+ but that's okay since they render quite differently
153
+ */
154
+ function getEventPartKey(seg) {
155
+ return internal.getEventKey(seg) + ':' + seg.start +
156
+ (seg.standinFor ? ':standin' : seg.isSlice ? ':slice' : '');
157
+ }
158
+ // DayGridRange utils (TODO: move)
159
+ // -------------------------------------------------------------------------------------------------
160
+ function splitSegsByRow(segs, rowCount) {
161
+ const byRow = [];
162
+ for (let row = 0; row < rowCount; row++) {
163
+ byRow[row] = [];
164
+ }
165
+ for (const seg of segs) {
166
+ byRow[seg.row].push(seg);
167
+ }
168
+ return byRow;
169
+ }
170
+ function splitInteractionByRow(ui, rowCount) {
171
+ const byRow = [];
172
+ if (!ui) {
173
+ for (let row = 0; row < rowCount; row++) {
174
+ byRow[row] = null;
175
+ }
176
+ }
177
+ else {
178
+ for (let row = 0; row < rowCount; row++) {
179
+ byRow[row] = {
180
+ affectedInstances: ui.affectedInstances,
181
+ isEvent: ui.isEvent,
182
+ segs: [],
183
+ };
184
+ }
185
+ for (const seg of ui.segs) {
186
+ byRow[seg.row].segs.push(seg);
187
+ }
188
+ }
189
+ return byRow;
190
+ }
191
+ function sliceSegForCol(seg, col) {
192
+ return Object.assign(Object.assign({}, seg), { start: col, end: col + 1, isStart: seg.isStart && seg.start === col, isEnd: seg.isEnd && seg.end - 1 === col, standinFor: seg });
193
+ }
194
+
195
+ const DEFAULT_TABLE_EVENT_TIME_FORMAT = internal.createFormatter({
196
+ hour: 'numeric',
197
+ minute: '2-digit',
198
+ omitZeroMinute: true,
199
+ meridiem: 'narrow',
200
+ });
201
+ function hasListItemDisplay(seg) {
202
+ let { display } = seg.eventRange.ui;
203
+ return display === 'list-item' || (display === 'auto' &&
204
+ !seg.eventRange.def.allDay &&
205
+ (seg.end - seg.start) === 1 && // single-day
206
+ seg.isStart && // "
207
+ seg.isEnd // "
208
+ );
209
+ }
210
+
211
+ class DayGridMoreLink extends internal.BaseComponent {
212
+ render() {
213
+ let { props } = this;
214
+ return (preact.createElement(internal.MoreLinkContainer, { display: 'row', className: props.className, isNarrow: props.isNarrow, isMicro: props.isMicro, dateProfile: props.dateProfile, todayRange: props.todayRange, allDayDate: props.allDayDate, segs: props.segs, hiddenSegs: props.hiddenSegs, alignElRef: props.alignElRef, alignParentTop: props.alignParentTop, dateSpanProps: props.dateSpanProps, popoverContent: () => (preact.createElement(preact.Fragment, null, props.segs.map((seg) => {
215
+ let { eventRange } = seg;
216
+ let { instanceId } = eventRange.instance;
217
+ let isDragging = Boolean(props.eventDrag && props.eventDrag.affectedInstances[instanceId]);
218
+ let isResizing = Boolean(props.eventResize && props.eventResize.affectedInstances[instanceId]);
219
+ let isInvisible = isDragging || isResizing;
220
+ return (preact.createElement("div", { key: instanceId, style: {
221
+ visibility: isInvisible ? 'hidden' : undefined,
222
+ } },
223
+ preact.createElement(internal.StandardEvent, Object.assign({ display: hasListItemDisplay(seg) ? 'list-item' : 'row', eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isResizing: isResizing, isMirror: false, isSelected: instanceId === props.eventSelection, defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: false }, internal.getEventRangeMeta(eventRange, props.todayRange)))));
224
+ }))) }));
225
+ }
226
+ }
227
+
228
+ class DayGridCell extends internal.DateComponent {
229
+ constructor() {
230
+ super(...arguments);
231
+ // memo
232
+ this.getDateMeta = internal.memoize(internal.getDateMeta);
233
+ this.refineRenderProps = internal.memoizeObjArg(refineRenderProps);
234
+ // ref
235
+ this.rootElRef = preact.createRef();
236
+ this.handleBodyEl = (bodyEl) => {
237
+ if (this.disconnectBodyHeight) {
238
+ this.disconnectBodyHeight();
239
+ this.disconnectBodyHeight = undefined;
240
+ internal.setRef(this.props.headerHeightRef, null);
241
+ internal.setRef(this.props.mainHeightRef, null);
242
+ }
243
+ if (bodyEl) {
244
+ // we want to fire on ANY size change, because we do more advanced stuff
245
+ this.disconnectBodyHeight = internal.watchSize(bodyEl, (_bodyWidth, bodyHeight) => {
246
+ const { props } = this;
247
+ const mainRect = bodyEl.getBoundingClientRect();
248
+ const rootRect = this.rootElRef.current.getBoundingClientRect();
249
+ const headerHeight = mainRect.top - rootRect.top;
250
+ if (!internal.isDimsEqual(this.headerHeight, headerHeight)) {
251
+ this.headerHeight = headerHeight;
252
+ internal.setRef(props.headerHeightRef, headerHeight);
253
+ }
254
+ if (props.fgLiquidHeight) {
255
+ internal.setRef(props.mainHeightRef, bodyHeight);
256
+ }
257
+ });
258
+ }
259
+ };
260
+ }
261
+ render() {
262
+ let { props, context } = this;
263
+ let { options, dateEnv } = context;
264
+ // TODO: memoize this
265
+ const isMonthStart = props.showDayNumber &&
266
+ shouldDisplayMonthStart(props.date, props.dateProfile.currentRange, dateEnv);
267
+ const dateMeta = this.getDateMeta(props.date, dateEnv, props.dateProfile, props.todayRange);
268
+ const baseClassName = core.joinClassNames(props.borderStart ? classNames__default["default"].borderOnlyS : classNames__default["default"].borderNone, props.width != null ? '' : classNames__default["default"].liquid, classNames__default["default"].flexCol);
269
+ const hasNavLink = options.navLinks;
270
+ const renderProps = this.refineRenderProps({
271
+ date: props.date,
272
+ isMajor: props.isMajor,
273
+ isNarrow: props.isNarrow,
274
+ dateMeta: dateMeta,
275
+ hasLabel: props.showDayNumber,
276
+ hasMonthLabel: isMonthStart,
277
+ hasNavLink,
278
+ renderProps: props.renderProps,
279
+ viewApi: context.viewApi,
280
+ dateEnv: context.dateEnv,
281
+ monthStartFormat: options.monthStartFormat,
282
+ dayCellFormat: options.dayCellFormat,
283
+ businessHours: Boolean(options.businessHours),
284
+ });
285
+ if (dateMeta.isDisabled) {
286
+ return (preact.createElement("div", { role: 'gridcell', "aria-disabled": true, className: internal.joinArrayishClassNames(internal.generateClassName(options.dayCellClass, renderProps), props.className, baseClassName), style: {
287
+ width: props.width
288
+ } }));
289
+ }
290
+ const fullDateStr = internal.buildDateStr(context, props.date);
291
+ return (preact.createElement(internal.ContentContainer, { tag: "div", elRef: this.rootElRef, className: core.joinClassNames(props.className, baseClassName), attrs: Object.assign(Object.assign(Object.assign(Object.assign({}, props.attrs), { role: 'gridcell', 'aria-label': fullDateStr }), (renderProps.isToday ? { 'aria-current': 'date' } : {})), { 'data-date': internal.formatDayString(props.date) }), style: {
292
+ width: props.width,
293
+ }, renderProps: renderProps, generatorName: "dayCellTopContent" // !!! for top
294
+ , customGenerator: options.dayCellTopContent /* !!! for top */, defaultGenerator: renderTopInner, classNameGenerator: options.dayCellClass, didMount: options.dayCellDidMount, willUnmount: options.dayCellWillUnmount }, (InnerContent) => (preact.createElement(preact.Fragment, null,
295
+ preact.createElement("div", { className: core.joinClassNames(classNames__default["default"].rel, // puts it above bg-fills, which are positioned on TOP of this component :|
296
+ internal.generateClassName(options.dayCellTopClass, renderProps)) }, props.showDayNumber && (preact.createElement(InnerContent // the dayCellTopContent
297
+ , { tag: 'div', attrs: hasNavLink
298
+ ? internal.buildNavLinkAttrs(context, props.date, undefined, fullDateStr)
299
+ : { 'aria-hidden': true } // label already on cell
300
+ , className: internal.generateClassName(options.dayCellTopInnerClass, renderProps) }))),
301
+ preact.createElement("div", { className: core.joinClassNames(classNames__default["default"].flexCol, props.fgLiquidHeight ? classNames__default["default"].liquid : classNames__default["default"].grow), ref: this.handleBodyEl },
302
+ preact.createElement("div", { className: internal.generateClassName(options.dayCellInnerClass, renderProps), style: { minHeight: props.fgHeight } }, props.fg),
303
+ preact.createElement(DayGridMoreLink, { className: classNames__default["default"].rel, allDayDate: props.date, segs: props.segs, hiddenSegs: props.hiddenSegs, alignElRef: this.rootElRef, alignParentTop: props.showDayNumber
304
+ ? '[role=row]'
305
+ : `.${classNames__default["default"].internalView}`, dateSpanProps: props.dateSpanProps, dateProfile: props.dateProfile, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange, isNarrow: props.isNarrow, isMicro: props.isMicro })),
306
+ preact.createElement("div", { className: core.joinClassNames(classNames__default["default"].rel, // puts it above bg-fills
307
+ internal.generateClassName(options.dayCellBottomClass, renderProps)) })))));
308
+ }
309
+ }
310
+ // Utils
311
+ // -------------------------------------------------------------------------------------------------
312
+ function renderTopInner(props) {
313
+ return props.text || preact.createElement(preact.Fragment, null, "\u00A0"); // TODO: DRY?
314
+ }
315
+ function shouldDisplayMonthStart(date, currentRange, dateEnv) {
316
+ const { start: currentStart, end: currentEnd } = currentRange;
317
+ const currentEndIncl = internal.addMs(currentEnd, -1);
318
+ const currentFirstYear = dateEnv.getYear(currentStart);
319
+ const currentFirstMonth = dateEnv.getMonth(currentStart);
320
+ const currentLastYear = dateEnv.getYear(currentEndIncl);
321
+ const currentLastMonth = dateEnv.getMonth(currentEndIncl);
322
+ // spans more than one month?
323
+ return !(currentFirstYear === currentLastYear && currentFirstMonth === currentLastMonth) &&
324
+ Boolean(
325
+ // first date in current view?
326
+ date.valueOf() === currentStart.valueOf() ||
327
+ // a month-start that's within the current range?
328
+ (dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf()));
329
+ }
330
+ function refineRenderProps(raw) {
331
+ let { date, dateEnv, hasLabel, hasMonthLabel, hasNavLink, businessHours } = raw;
332
+ let [text, textParts] = hasLabel
333
+ ? dateEnv.format(date, hasMonthLabel ? raw.monthStartFormat : raw.dayCellFormat)
334
+ : ['', []];
335
+ return Object.assign(Object.assign(Object.assign({}, raw.dateMeta), raw.renderProps), { text,
336
+ textParts, isMajor: raw.isMajor, isNarrow: raw.isNarrow, inPopover: false, hasNavLink,
337
+ get dayNumberText() { return internal.findDayNumberText(textParts); },
338
+ get monthText() { return internal.findMonthText(textParts); }, options: { businessHours }, view: raw.viewApi });
339
+ }
340
+
341
+ function computeFgSegVerticals(segs, segHeightMap, cells, maxHeight, strictOrder, allowSlicing = true, dayMaxEvents, dayMaxEventRows) {
342
+ let maxCoord;
343
+ let maxDepth;
344
+ let hiddenConsumes;
345
+ if (dayMaxEvents === true || dayMaxEventRows === true) {
346
+ maxCoord = maxHeight;
347
+ hiddenConsumes = true;
348
+ }
349
+ else if (typeof dayMaxEvents === 'number') {
350
+ maxDepth = dayMaxEvents;
351
+ hiddenConsumes = false;
352
+ }
353
+ else if (typeof dayMaxEventRows === 'number') {
354
+ maxDepth = dayMaxEventRows;
355
+ hiddenConsumes = true;
356
+ }
357
+ // NOTE: visibleSegsMap and hiddenSegMap map NEVER overlap for a given event
358
+ // once a seg has a height, the combined potentially-sliced segs will comprise the entire span of the seg
359
+ // if a seg does not have a height yet, it won't be inserted into either visibleSegsMap/hiddenSegMap
360
+ const visibleSegMap = new Map();
361
+ const hiddenSegMap = new Map();
362
+ const segTops = new Map();
363
+ const isSlicedMap = new Map();
364
+ let hierarchy = new internal.SegHierarchy(segs, (seg) => segHeightMap.get(getEventPartKey(seg)), strictOrder, maxCoord, maxDepth, hiddenConsumes, allowSlicing);
365
+ hierarchy.traverseSegs((seg, segTop) => {
366
+ addToSegMap(visibleSegMap, seg);
367
+ segTops.set(getEventPartKey(seg), segTop);
368
+ if (seg.isSlice) {
369
+ isSlicedMap.set(seg.eventRange, true);
370
+ }
371
+ });
372
+ for (const hiddenSeg of hierarchy.hiddenSegs) {
373
+ addToSegMap(hiddenSegMap, hiddenSeg); // hidden main segs
374
+ }
375
+ // recompute tops while considering slices
376
+ // portions of these slices might be added to hiddenSegMap
377
+ if (isSlicedMap.size) {
378
+ segTops.clear();
379
+ hierarchy = new internal.SegHierarchy(compileSegMap(segs, visibleSegMap), (seg) => segHeightMap.get(getEventPartKey(seg)), strictOrder, maxCoord, maxDepth, hiddenConsumes);
380
+ hierarchy.traverseSegs((seg, segTop) => {
381
+ segTops.set(getEventPartKey(seg), segTop); // newly-hidden main segs and slices
382
+ });
383
+ for (const hiddenSeg of hierarchy.hiddenSegs) {
384
+ addToSegMap(hiddenSegMap, hiddenSeg);
385
+ }
386
+ }
387
+ const segsByCol = [];
388
+ const hiddenSegsByCol = [];
389
+ const renderableSegsByCol = [];
390
+ const heightsByCol = [];
391
+ for (let col = 0; col < cells.length; col++) {
392
+ segsByCol.push([]);
393
+ hiddenSegsByCol.push([]);
394
+ renderableSegsByCol.push([]);
395
+ heightsByCol.push(0);
396
+ }
397
+ for (const seg of segs) {
398
+ const { eventRange } = seg;
399
+ const visibleSegs = visibleSegMap.get(eventRange) || [];
400
+ const hiddenSegs = hiddenSegMap.get(eventRange) || [];
401
+ const isSliced = isSlicedMap.get(eventRange) || false;
402
+ // add orig to renderable
403
+ renderableSegsByCol[seg.start].push(seg);
404
+ // add slices to renderable
405
+ if (isSliced) {
406
+ for (const visibleSeg of visibleSegs) {
407
+ renderableSegsByCol[visibleSeg.start].push(visibleSeg);
408
+ }
409
+ }
410
+ // accumulate segsByCol/heightsByCol for visible segs
411
+ for (const visibleSeg of visibleSegs) {
412
+ for (let col = visibleSeg.start; col < visibleSeg.end; col++) {
413
+ const slice = sliceSegForCol(visibleSeg, col);
414
+ segsByCol[col].push(slice);
415
+ }
416
+ const segKey = getEventPartKey(visibleSeg);
417
+ const segTop = segTops.get(segKey);
418
+ if (segTop != null) { // positioned?
419
+ const segHeight = segHeightMap.get(segKey);
420
+ for (let col = visibleSeg.start; col < visibleSeg.end; col++) {
421
+ heightsByCol[col] = Math.max(heightsByCol[col], segTop + segHeight);
422
+ }
423
+ }
424
+ }
425
+ // accumulate segsByCol/hiddenSegsByCol for hidden segs
426
+ for (const hiddenSeg of hiddenSegs) {
427
+ for (let col = hiddenSeg.start; col < hiddenSeg.end; col++) {
428
+ const slice = sliceSegForCol(hiddenSeg, col);
429
+ segsByCol[col].push(slice);
430
+ hiddenSegsByCol[col].push(slice);
431
+ }
432
+ }
433
+ }
434
+ return [
435
+ segsByCol,
436
+ hiddenSegsByCol,
437
+ renderableSegsByCol,
438
+ segTops,
439
+ heightsByCol,
440
+ ];
441
+ }
442
+ // Utils
443
+ // -------------------------------------------------------------------------------------------------
444
+ function addToSegMap(map, seg) {
445
+ let list = map.get(seg.eventRange);
446
+ if (!list) {
447
+ map.set(seg.eventRange, list = []);
448
+ }
449
+ list.push(seg);
450
+ }
451
+ /*
452
+ Ensures relative order of DayRowEventRange stays consistent with segs
453
+ */
454
+ function compileSegMap(segs, segMap) {
455
+ const res = [];
456
+ for (const seg of segs) {
457
+ res.push(...(segMap.get(seg.eventRange) || []));
458
+ }
459
+ return res;
460
+ }
461
+
462
+ function buildDayTableModel(dateProfile, dateProfileGenerator, dateEnv) {
463
+ const daySeries = new internal.DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
464
+ const breakOnWeeks = /year|month|week/.test(dateProfile.currentRangeUnit);
465
+ const majorUnit = !breakOnWeeks && internal.computeMajorUnit(dateProfile, dateEnv);
466
+ return new internal.DayTableModel(daySeries, breakOnWeeks, dateEnv, majorUnit);
467
+ }
468
+ function computeColWidth(colCount, colMinWidth, viewportWidth) {
469
+ if (viewportWidth == null) {
470
+ return [undefined, undefined];
471
+ }
472
+ const colTempWidth = viewportWidth / colCount;
473
+ if (colTempWidth < colMinWidth) {
474
+ return [colMinWidth * colCount, colMinWidth];
475
+ }
476
+ return [viewportWidth, undefined];
477
+ }
478
+ // Positioning
479
+ // -------------------------------------------------------------------------------------------------
480
+ function computeTopFromDate(date, cellRows, rowHeightMap, adjust = 0) {
481
+ let top = 0;
482
+ for (const cells of cellRows) {
483
+ const start = cells[0].date;
484
+ const end = cells[cells.length - 1].date;
485
+ const key = start.toISOString();
486
+ if (date >= start && date <= end) {
487
+ return top;
488
+ }
489
+ const rowHeight = rowHeightMap.get(key);
490
+ if (rowHeight == null) {
491
+ return; // denote unknown
492
+ }
493
+ top += rowHeight + adjust;
494
+ }
495
+ return top;
496
+ }
497
+ /*
498
+ FYI, `width` is not dependable for aligning completely to farside
499
+ */
500
+ function computeHorizontalsFromSeg(seg, colWidth, colCount) {
501
+ let fromStart;
502
+ let fromEnd;
503
+ if (colWidth != null) {
504
+ fromStart = seg.start * colWidth;
505
+ fromEnd = (colCount - seg.end) * colWidth;
506
+ }
507
+ else {
508
+ const colWidthFrac = 1 / colCount;
509
+ fromStart = internal.fracToCssDim(seg.start * colWidthFrac);
510
+ fromEnd = internal.fracToCssDim(1 - seg.end * colWidthFrac);
511
+ }
512
+ return { insetInlineStart: fromStart, insetInlineEnd: fromEnd };
513
+ }
514
+ function computeColFromPosition(positionLeft, elWidth, colWidth, colCount, isRtl) {
515
+ const realColWidth = colWidth != null ? colWidth : elWidth / colCount;
516
+ const colFromLeft = Math.floor(positionLeft / realColWidth);
517
+ const col = isRtl ? (colCount - colFromLeft - 1) : colFromLeft;
518
+ const left = colFromLeft * realColWidth;
519
+ const right = left + realColWidth;
520
+ return { col, left, right };
521
+ }
522
+ function computeRowFromPosition(positionTop, cellRows, rowHeightMap) {
523
+ let row = 0;
524
+ let top = 0;
525
+ let bottom = 0;
526
+ for (const cells of cellRows) {
527
+ const key = cells[0].key;
528
+ top = bottom;
529
+ bottom = top + rowHeightMap.get(key);
530
+ if (positionTop < bottom) {
531
+ break;
532
+ }
533
+ row++;
534
+ }
535
+ return { row, top, bottom };
536
+ }
537
+ // Hit Element
538
+ // -------------------------------------------------------------------------------------------------
539
+ function getRowEl(rootEl, row) {
540
+ return rootEl.querySelectorAll('[role=row]')[row];
541
+ }
542
+ function getCellEl(rowEl, col) {
543
+ return rowEl.querySelectorAll('[role=gridcell]')[col];
544
+ }
545
+ // Header Formatting
546
+ // -------------------------------------------------------------------------------------------------
547
+ const dayMicroWidth = 50;
548
+ const dayHeaderMicroFormat = internal.createFormatter({
549
+ weekday: 'narrow'
550
+ });
551
+ function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) {
552
+ return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt);
553
+ }
554
+ // Computes a default column header formatting string if `colFormat` is not explicitly defined
555
+ function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
556
+ // if more than one week row, or if there are a lot of columns with not much space,
557
+ // put just the day numbers will be in each cell
558
+ if (!datesRepDistinctDays) {
559
+ return internal.createFormatter({ weekday: 'short' }); // "Sat"
560
+ }
561
+ if (dayCnt > 1) {
562
+ return internal.createFormatter({
563
+ weekday: 'short',
564
+ weekdayJustify: 'start',
565
+ day: 'numeric',
566
+ omitCommas: true,
567
+ });
568
+ }
569
+ return internal.createFormatter({
570
+ weekday: 'long',
571
+ weekdayJustify: 'start',
572
+ day: 'numeric',
573
+ omitCommas: true,
574
+ });
575
+ }
576
+
577
+ class DayGridEventHarness extends preact.Component {
578
+ constructor() {
579
+ super(...arguments);
580
+ // ref
581
+ this.rootElRef = preact.createRef();
582
+ }
583
+ render() {
584
+ const { props } = this;
585
+ return (preact.createElement("div", { className: core.joinClassNames(props.className, classNames__default["default"].abs), style: props.style, ref: this.rootElRef }, props.children));
586
+ }
587
+ componentDidMount() {
588
+ const rootEl = this.rootElRef.current; // TODO: make dynamic with useEffect
589
+ this.disconnectHeight = internal.watchHeight(rootEl, (height) => {
590
+ internal.setRef(this.props.heightRef, height);
591
+ });
592
+ }
593
+ componentWillUnmount() {
594
+ this.disconnectHeight();
595
+ internal.setRef(this.props.heightRef, null);
596
+ }
597
+ }
598
+
599
+ const DEFAULT_WEEK_NUM_FORMAT = internal.createFormatter({ week: 'narrow' });
600
+ class DayGridRow extends internal.BaseComponent {
601
+ constructor() {
602
+ super(...arguments);
603
+ this.headerHeightRefMap = new internal.RefMap(() => {
604
+ internal.afterSize(this.handleSegPositioning);
605
+ });
606
+ this.mainHeightRefMap = new internal.RefMap(() => {
607
+ const fgLiquidHeight = this.props.dayMaxEvents === true || this.props.dayMaxEventRows === true;
608
+ if (fgLiquidHeight) {
609
+ internal.afterSize(this.handleSegPositioning);
610
+ }
611
+ });
612
+ this.segHeightRefMap = new internal.RefMap(() => {
613
+ internal.afterSize(this.handleSegPositioning);
614
+ });
615
+ // memo
616
+ this.buildWeekNumberRenderProps = internal.memoize(buildWeekNumberRenderProps);
617
+ this.handleRootEl = (rootEl) => {
618
+ this.rootEl = rootEl;
619
+ internal.setRef(this.props.rootElRef, rootEl);
620
+ };
621
+ this.handleSegPositioning = () => {
622
+ this.forceUpdate();
623
+ };
624
+ }
625
+ render() {
626
+ const { props, context, headerHeightRefMap, mainHeightRefMap } = this;
627
+ const { cells } = props;
628
+ const { options } = context;
629
+ const weekDateMarker = props.cells[0].date;
630
+ const fgLiquidHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
631
+ // TODO: memoize? sort all types of segs?
632
+ const fgEventSegs = internal.sortEventSegs(props.fgEventSegs, options.eventOrder);
633
+ // TODO: memoize?
634
+ const [maxMainTop, minMainHeight] = this.computeFgDims(); // uses headerHeightRefMap/mainHeightRefMap
635
+ const [segsByCol, hiddenSegsByCol, renderableSegsByCol, segTops, simpleHeightsByCol] = computeFgSegVerticals(fgEventSegs, this.segHeightRefMap.current, cells, fgLiquidHeight ? minMainHeight : undefined, // if not defined in first run, will unlimited!?
636
+ options.eventOrderStrict, options.eventSlicing, props.dayMaxEvents, props.dayMaxEventRows);
637
+ const heightsByCol = [];
638
+ if (maxMainTop != null) {
639
+ let col = 0;
640
+ for (const cell of cells) { // uses headerHeightRefMap/maxMainTop/simpleHeightsByCol
641
+ const cellHeaderHeight = headerHeightRefMap.current.get(cell.key);
642
+ const extraFgHeight = maxMainTop - cellHeaderHeight;
643
+ heightsByCol.push(simpleHeightsByCol[col++] + extraFgHeight);
644
+ }
645
+ }
646
+ const highlightSegs = this.getHighlightSegs();
647
+ const mirrorSegs = this.getMirrorSegs();
648
+ const hasNavLink = options.navLinks;
649
+ const fullWeekStr = internal.buildDateStr(context, weekDateMarker, 'week');
650
+ const weekNumberRenderProps = this.buildWeekNumberRenderProps(weekDateMarker, context, props.cellIsNarrow, hasNavLink);
651
+ return (preact.createElement("div", { role: props.role /* !!! */, "aria-label": props.role === 'row' // HACK
652
+ ? fullWeekStr
653
+ : undefined // can't have label on non-role div
654
+ , className: internal.joinArrayishClassNames(options.dayRowClass, props.className, classNames__default["default"].flexRow, classNames__default["default"].rel, // origin for inlineWeekNumber?
655
+ classNames__default["default"].isolate, (props.forPrint && props.basis !== undefined) && // basis implies siblings (must share height)
656
+ classNames__default["default"].printSiblingRow), style: {
657
+ 'flex-basis': props.basis,
658
+ }, ref: this.handleRootEl },
659
+ (props.showWeekNumbers && !props.cellIsMicro) && (preact.createElement(internal.ContentContainer, { tag: 'div', attrs: Object.assign(Object.assign({}, (hasNavLink
660
+ ? internal.buildNavLinkAttrs(context, weekDateMarker, 'week', fullWeekStr, /* isTabbable = */ false)
661
+ : {})), { 'role': undefined, 'aria-hidden': true }),
662
+ // put above all cells (TODO: put explicit z0 on each cell?)
663
+ className: classNames__default["default"].z1, renderProps: weekNumberRenderProps, generatorName: "inlineWeekNumberContent", customGenerator: options.inlineWeekNumberContent, defaultGenerator: internal.renderText, classNameGenerator: options.inlineWeekNumberClass, didMount: options.inlineWeekNumberDidMount, willUnmount: options.inlineWeekNumberWillUnmount })),
664
+ this.renderFillSegs(props.businessHourSegs, 'non-business'),
665
+ this.renderFillSegs(props.bgEventSegs, 'bg-event'),
666
+ this.renderFillSegs(highlightSegs, 'highlight'),
667
+ props.cells.map((cell, col) => {
668
+ const normalFgNodes = this.renderFgSegs(maxMainTop, renderableSegsByCol[col], segTops, props.todayRange,
669
+ /* isMirror = */ false);
670
+ return (preact.createElement(DayGridCell, { key: cell.key, dateProfile: props.dateProfile, todayRange: props.todayRange, date: cell.date, isMajor: cell.isMajor, showDayNumber: props.showDayNumbers, isNarrow: props.cellIsNarrow, isMicro: props.cellIsMicro, borderStart: Boolean(col),
671
+ // content
672
+ segs: segsByCol[col], hiddenSegs: hiddenSegsByCol[col], fgLiquidHeight: fgLiquidHeight, fg: (preact.createElement(preact.Fragment, null, normalFgNodes)), eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
673
+ // render hooks
674
+ renderProps: cell.renderProps, dateSpanProps: cell.dateSpanProps, attrs: cell.attrs, className: cell.className,
675
+ // dimensions
676
+ fgHeight: heightsByCol[col], width: props.colWidth,
677
+ // refs
678
+ headerHeightRef: headerHeightRefMap.createRef(cell.key), mainHeightRef: mainHeightRefMap.createRef(cell.key) }));
679
+ }),
680
+ this.renderFgSegs(maxMainTop, mirrorSegs, segTops, props.todayRange,
681
+ /* isMirror = */ true)));
682
+ }
683
+ renderFgSegs(headerHeight, segs, segTops, todayRange, isMirror) {
684
+ var _a;
685
+ const { props, segHeightRefMap } = this;
686
+ const { colWidth, eventSelection, cellIsMicro } = props;
687
+ const colCount = props.cells.length;
688
+ const defaultDisplayEventEnd = props.cells.length === 1;
689
+ const nodes = [];
690
+ for (const seg of segs) {
691
+ const key = getEventPartKey(seg);
692
+ const { standinFor, eventRange } = seg;
693
+ const { instanceId } = eventRange.instance;
694
+ if (standinFor) {
695
+ continue;
696
+ }
697
+ const { insetInlineStart, insetInlineEnd } = computeHorizontalsFromSeg(seg, colWidth, colCount);
698
+ const localTop = (_a = segTops.get(standinFor ? getEventPartKey(standinFor) : key)) !== null && _a !== void 0 ? _a : (isMirror ? 0 : undefined);
699
+ const top = headerHeight != null && localTop != null
700
+ ? headerHeight + localTop
701
+ : undefined;
702
+ const isDragging = Boolean(props.eventDrag && props.eventDrag.affectedInstances[instanceId]);
703
+ const isResizing = Boolean(props.eventResize && props.eventResize.affectedInstances[instanceId]);
704
+ const isInvisible = !isMirror && (isDragging || isResizing || standinFor || top == null);
705
+ const isListItem = hasListItemDisplay(seg);
706
+ nodes.push(preact.createElement(DayGridEventHarness, { key: key, className: seg.start ? classNames__default["default"].fakeBorderS : '', style: {
707
+ visibility: isInvisible ? 'hidden' : undefined,
708
+ top,
709
+ insetInlineStart,
710
+ insetInlineEnd,
711
+ zIndex: 0, // container inner z-indexes
712
+ }, heightRef: (!standinFor && !isMirror)
713
+ ? segHeightRefMap.createRef(key)
714
+ : null },
715
+ preact.createElement(internal.StandardEvent, Object.assign({ display: isListItem ? 'list-item' : 'row', eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isResizing: isResizing, isMirror: isMirror, isSelected: instanceId === eventSelection, isNarrow: props.cellIsNarrow, defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: defaultDisplayEventEnd, disableResizing: isListItem, forcedTimeText: cellIsMicro ? '' : undefined }, internal.getEventRangeMeta(eventRange, todayRange)))));
716
+ }
717
+ return nodes;
718
+ }
719
+ renderFillSegs(segs, fillType) {
720
+ const { props, context } = this;
721
+ const { todayRange, colWidth } = props;
722
+ const colCount = props.cells.length;
723
+ const nodes = [];
724
+ for (const seg of segs) {
725
+ const key = internal.buildEventRangeKey(seg.eventRange); // TODO: use different type of key than fg!?
726
+ const { insetInlineStart, insetInlineEnd } = computeHorizontalsFromSeg(seg, colWidth, colCount);
727
+ const isVisible = !seg.standinFor;
728
+ nodes.push(preact.createElement("div", { key: key, className: classNames__default["default"].fillY, style: {
729
+ visibility: isVisible ? '' : 'hidden',
730
+ insetInlineStart,
731
+ insetInlineEnd,
732
+ } }, fillType === 'bg-event' ?
733
+ preact.createElement(internal.BgEvent, Object.assign({ eventRange: seg.eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isNarrow: props.cellIsNarrow, isVertical: false }, internal.getEventRangeMeta(seg.eventRange, todayRange))) : (internal.renderFill(fillType, context.options))));
734
+ }
735
+ return preact.createElement(preact.Fragment, {}, ...nodes); // TODO: shouldn't this be an array, so keyed?
736
+ }
737
+ // Sizing
738
+ // -----------------------------------------------------------------------------------------------
739
+ componentDidMount() {
740
+ const { rootEl } = this; // TODO: make dynamic with useEffect
741
+ this.disconnectHeight = internal.watchHeight(rootEl, (contentHeight) => {
742
+ internal.setRef(this.props.heightRef, contentHeight);
743
+ });
744
+ }
745
+ componentWillUnmount() {
746
+ this.disconnectHeight();
747
+ internal.setRef(this.props.heightRef, null);
748
+ }
749
+ computeFgDims() {
750
+ const { cells } = this.props;
751
+ const headerHeightMap = this.headerHeightRefMap.current;
752
+ const mainHeightMap = this.mainHeightRefMap.current;
753
+ let maxMainTop;
754
+ let minMainBottom;
755
+ for (const cell of cells) {
756
+ const mainTop = headerHeightMap.get(cell.key);
757
+ const mainHeight = mainHeightMap.get(cell.key);
758
+ if (mainTop != null) {
759
+ if (maxMainTop === undefined || mainTop > maxMainTop) {
760
+ maxMainTop = mainTop;
761
+ }
762
+ if (mainHeight != null) {
763
+ const mainBottom = mainTop + mainHeight;
764
+ if (minMainBottom === undefined || mainBottom < minMainBottom) {
765
+ minMainBottom = mainBottom;
766
+ }
767
+ }
768
+ }
769
+ }
770
+ return [
771
+ maxMainTop,
772
+ minMainBottom != null && maxMainTop != null
773
+ ? minMainBottom - maxMainTop
774
+ : undefined,
775
+ ];
776
+ }
777
+ // Internal Utils
778
+ // -----------------------------------------------------------------------------------------------
779
+ getMirrorSegs() {
780
+ let { props } = this;
781
+ if (props.eventResize && props.eventResize.segs.length) { // messy check
782
+ return props.eventResize.segs;
783
+ }
784
+ return [];
785
+ }
786
+ getHighlightSegs() {
787
+ let { props } = this;
788
+ if (props.eventDrag && props.eventDrag.segs.length) { // messy check
789
+ return props.eventDrag.segs;
790
+ }
791
+ if (props.eventResize && props.eventResize.segs.length) { // messy check
792
+ return props.eventResize.segs;
793
+ }
794
+ return props.dateSelectionSegs;
795
+ }
796
+ }
797
+ // Utils
798
+ // -------------------------------------------------------------------------------------------------
799
+ function buildWeekNumberRenderProps(weekDateMarker, context, isNarrow, hasNavLink) {
800
+ const { dateEnv, options } = context;
801
+ const weekNum = dateEnv.computeWeekNumber(weekDateMarker);
802
+ const [weekNumText, weekNumTextParts] = dateEnv.format(weekDateMarker, options.weekNumberFormat || DEFAULT_WEEK_NUM_FORMAT);
803
+ const weekDateZoned = dateEnv.toDate(weekDateMarker);
804
+ return {
805
+ num: weekNum,
806
+ text: weekNumText,
807
+ textParts: weekNumTextParts,
808
+ date: weekDateZoned,
809
+ isNarrow,
810
+ hasNavLink,
811
+ };
812
+ }
813
+
814
+ class DayGridRows extends internal.DateComponent {
815
+ constructor() {
816
+ super(...arguments);
817
+ // memo
818
+ this.splitBusinessHourSegs = internal.memoize(splitSegsByRow);
819
+ this.splitBgEventSegs = internal.memoize(splitSegsByRow);
820
+ this.splitFgEventSegs = internal.memoize(splitSegsByRow);
821
+ this.splitDateSelectionSegs = internal.memoize(splitSegsByRow);
822
+ this.splitEventDrag = internal.memoize(splitInteractionByRow);
823
+ this.splitEventResize = internal.memoize(splitInteractionByRow);
824
+ // internal
825
+ this.rowHeightRefMap = new internal.RefMap((height, key) => {
826
+ // HACKy way of syncing RefMap results with prop
827
+ const { rowHeightRefMap } = this.props;
828
+ if (rowHeightRefMap) {
829
+ rowHeightRefMap.handleValue(height, key);
830
+ }
831
+ });
832
+ this.handleRootEl = (rootEl) => {
833
+ this.rootEl = rootEl;
834
+ if (rootEl) {
835
+ this.context.registerInteractiveComponent(this, {
836
+ el: rootEl,
837
+ isHitComboAllowed: this.props.isHitComboAllowed,
838
+ });
839
+ }
840
+ else {
841
+ this.context.unregisterInteractiveComponent(this);
842
+ }
843
+ };
844
+ }
845
+ render() {
846
+ let { props, context, rowHeightRefMap } = this;
847
+ let { options } = context;
848
+ let rowCount = props.cellRows.length;
849
+ let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCount);
850
+ let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCount);
851
+ let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCount);
852
+ let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCount);
853
+ let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCount);
854
+ let eventResizeByRow = this.splitEventResize(props.eventResize, rowCount);
855
+ let isHeightAuto = internal.getIsHeightAuto(options);
856
+ let rowHeightsRedistribute = !props.forPrint && !isHeightAuto;
857
+ let rowBasis = computeRowBasis(props.visibleWidth, rowCount, isHeightAuto, options);
858
+ return (preact.createElement("div", { role: 'rowgroup', className: core.joinClassNames(props.className,
859
+ // HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
860
+ // https://stackoverflow.com/a/60256345
861
+ !props.forPrint && classNames__default["default"].flexCol), style: { width: props.width }, ref: this.handleRootEl }, props.cellRows.map((cells, row) => (preact.createElement(DayGridRow, { key: cells[0].key, role: 'row', dateProfile: props.dateProfile, todayRange: props.todayRange, cells: cells, cellIsNarrow: props.cellIsNarrow, cellIsMicro: props.cellIsMicro, showDayNumbers: rowCount > 1, showWeekNumbers: rowCount > 1 && options.weekNumbers, forPrint: props.forPrint,
862
+ // if not auto-height, distribute height of container somewhat evently to rows
863
+ className: core.joinClassNames(rowHeightsRedistribute && classNames__default["default"].grow, rowCount > 1 && classNames__default["default"].breakInsideAvoid, // don't avoid breaks for single tall row
864
+ row < rowCount - 1 ? classNames__default["default"].borderOnlyB : classNames__default["default"].borderNone),
865
+ // content
866
+ fgEventSegs: fgEventSegsByRow[row], bgEventSegs: bgEventSegsByRow[row].filter(isSegAllDay) /* HACK */, businessHourSegs: businessHourSegsByRow[row], dateSelectionSegs: dateSelectionSegsByRow[row], eventSelection: props.eventSelection, eventDrag: eventDragByRow[row], eventResize: eventResizeByRow[row], dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows,
867
+ // dimensions
868
+ colWidth: props.colWidth, basis: rowBasis,
869
+ // refs
870
+ heightRef: rowHeightRefMap.createRef(cells[0].key) })))));
871
+ }
872
+ // Hit System
873
+ // -----------------------------------------------------------------------------------------------
874
+ queryHit(isRtl, positionLeft, positionTop, elWidth) {
875
+ const { props } = this;
876
+ const colCount = props.cellRows[0].length;
877
+ const { col, left, right } = computeColFromPosition(positionLeft, elWidth, props.colWidth, colCount, isRtl);
878
+ const { row, top, bottom } = computeRowFromPosition(positionTop, props.cellRows, this.rowHeightRefMap.current);
879
+ const cell = props.cellRows[row][col];
880
+ const cellStartDate = cell.date;
881
+ const cellEndDate = internal.addDays(cellStartDate, 1);
882
+ return {
883
+ dateProfile: props.dateProfile,
884
+ dateSpan: Object.assign({ range: {
885
+ start: cellStartDate,
886
+ end: cellEndDate,
887
+ }, allDay: true }, cell.dateSpanProps),
888
+ getDayEl: () => getCellEl(getRowEl(this.rootEl, row), col),
889
+ rect: {
890
+ left,
891
+ right,
892
+ top,
893
+ bottom,
894
+ },
895
+ layer: 0,
896
+ };
897
+ }
898
+ }
899
+ // Utils
900
+ // -------------------------------------------------------------------------------------------------
901
+ function isSegAllDay(seg) {
902
+ return seg.eventRange.def.allDay;
903
+ }
904
+ /*
905
+ Amount of height a row should consume prior to expanding
906
+ We don't want to use min-height with flexbox because we leverage min-height:auto,
907
+ which yields value based on natural height of events
908
+ */
909
+ function computeRowBasis(visibleWidth, // should INCLUDE any scrollbar width to avoid oscillation
910
+ rowCount, isHeightAuto, options) {
911
+ if (visibleWidth != null) {
912
+ // ensure a consistent row min-height modelled after a month with 6 rows respecting aspectRatio
913
+ // will result in same minHeight regardless of weekends, dayMinWidth, height:auto
914
+ const rowBasis = visibleWidth / options.aspectRatio / 6;
915
+ // don't give minHeight when single-month non-auto-height
916
+ // TODO: better way to detect this with DateProfile?
917
+ return (rowCount > 6 || isHeightAuto) ? rowBasis : 0;
918
+ }
919
+ return 0;
920
+ }
921
+
922
+ class DayGridHeaderCell extends internal.BaseComponent {
923
+ constructor() {
924
+ super(...arguments);
925
+ this.handleInnerEl = (innerEl) => {
926
+ if (this.disconnectSize) {
927
+ this.disconnectSize();
928
+ this.disconnectSize = undefined;
929
+ }
930
+ if (innerEl) {
931
+ this.disconnectSize = internal.watchSize(innerEl, (width, height) => {
932
+ internal.setRef(this.props.innerHeightRef, height);
933
+ /*
934
+ TODO: DRY with TimelineHeaderCell
935
+ */
936
+ if (this.align === 'center' && this.isSticky) {
937
+ this.setState({ innerWidth: width });
938
+ }
939
+ });
940
+ }
941
+ else {
942
+ internal.setRef(this.props.innerHeightRef, null);
943
+ }
944
+ };
945
+ }
946
+ render() {
947
+ const { props, state, context } = this;
948
+ const { renderConfig, dataConfig } = props;
949
+ // HACK
950
+ const isDisabled = dataConfig.renderProps.isDisabled;
951
+ const finalRenderProps = Object.assign(Object.assign({}, dataConfig.renderProps), { isNarrow: props.cellIsNarrow, level: props.rowLevel });
952
+ if (props.cellIsMicro) {
953
+ // TODO: only if not distinct dates
954
+ const [microText, microTextParts] = context.dateEnv.format(dataConfig.dateMarker, dayHeaderMicroFormat);
955
+ finalRenderProps.text = finalRenderProps.weekdayText = microText;
956
+ finalRenderProps.textParts = microTextParts;
957
+ }
958
+ /*
959
+ TODO: DRY with TimelineHeaderCell
960
+ */
961
+ const alignInput = renderConfig.align;
962
+ const align = this.align =
963
+ typeof alignInput === 'function'
964
+ ? alignInput({ level: props.rowLevel, inPopover: dataConfig.renderProps.inPopover, isNarrow: props.cellIsNarrow })
965
+ : alignInput;
966
+ const stickyInput = renderConfig.sticky;
967
+ const isSticky = this.isSticky =
968
+ props.rowLevel && stickyInput !== false;
969
+ let edgeCoord;
970
+ if (isSticky) {
971
+ if (align === 'center') {
972
+ if (state.innerWidth != null) {
973
+ edgeCoord = `calc(50% - ${state.innerWidth / 2}px)`;
974
+ }
975
+ }
976
+ else {
977
+ edgeCoord = (typeof stickyInput === 'number' ||
978
+ typeof stickyInput === 'string') ? stickyInput : 0;
979
+ }
980
+ }
981
+ return (preact.createElement(internal.ContentContainer, { tag: 'div', attrs: Object.assign({ role: 'columnheader', 'aria-colspan': dataConfig.colSpan }, dataConfig.attrs), className: core.joinClassNames(dataConfig.className, classNames__default["default"].tight, classNames__default["default"].flexCol, props.borderStart ? classNames__default["default"].borderOnlyS : classNames__default["default"].borderNone, align === 'center' ? classNames__default["default"].alignCenter :
982
+ align === 'end' ? classNames__default["default"].alignEnd :
983
+ classNames__default["default"].alignStart, props.colWidth == null && classNames__default["default"].liquid, !isSticky && classNames__default["default"].crop), style: {
984
+ width: props.colWidth != null
985
+ ? props.colWidth * (dataConfig.colSpan || 1)
986
+ : undefined,
987
+ }, renderProps: finalRenderProps, generatorName: renderConfig.generatorName, customGenerator: renderConfig.customGenerator, defaultGenerator: internal.renderText, classNameGenerator:
988
+ // don't use custom classNames if disabled
989
+ // TODO: make DRY with DayCellContainer
990
+ isDisabled ? undefined : renderConfig.classNameGenerator, didMount: renderConfig.didMount, willUnmount: renderConfig.willUnmount }, (InnerContainer) => (preact.createElement("div", { ref: this.handleInnerEl, className: core.joinClassNames(classNames__default["default"].flexCol, classNames__default["default"].rigid, isSticky && classNames__default["default"].sticky), style: {
991
+ left: edgeCoord,
992
+ right: edgeCoord,
993
+ } },
994
+ preact.createElement(InnerContainer, { tag: 'div', attrs: dataConfig.innerAttrs, className: internal.generateClassName(renderConfig.innerClassNameGenerator, finalRenderProps) })))));
995
+ }
996
+ }
997
+
998
+ class DayGridHeaderRow extends internal.BaseComponent {
999
+ constructor() {
1000
+ super(...arguments);
1001
+ // ref
1002
+ this.innerHeightRefMap = new internal.RefMap(() => {
1003
+ internal.afterSize(this.handleInnerHeights);
1004
+ });
1005
+ this.handleInnerHeights = () => {
1006
+ const innerHeightMap = this.innerHeightRefMap.current;
1007
+ let max = 0;
1008
+ for (const innerHeight of innerHeightMap.values()) {
1009
+ max = Math.max(max, innerHeight);
1010
+ }
1011
+ if (this.currentInnerHeight !== max) {
1012
+ this.currentInnerHeight = max;
1013
+ internal.setRef(this.props.innerHeightRef, max);
1014
+ }
1015
+ };
1016
+ }
1017
+ render() {
1018
+ const { props, context } = this;
1019
+ const { options } = context;
1020
+ return (preact.createElement("div", { role: props.role /* !!! */, "aria-rowindex": props.rowIndex != null ? 1 + props.rowIndex : undefined, className: internal.joinArrayishClassNames(options.dayHeaderRowClass, props.className, classNames__default["default"].flexRow, classNames__default["default"].contentBox, props.borderBottom ? classNames__default["default"].borderOnlyB : classNames__default["default"].borderNone), style: {
1021
+ height: props.height,
1022
+ } }, props.dataConfigs.map((dataConfig, cellI) => (preact.createElement(DayGridHeaderCell, { key: dataConfig.key, renderConfig: props.renderConfig, dataConfig: dataConfig, borderStart: Boolean(cellI), colWidth: props.colWidth, innerHeightRef: this.innerHeightRefMap.createRef(dataConfig.key), cellIsNarrow: props.cellIsNarrow, cellIsMicro: props.cellIsMicro, rowLevel: props.rowLevel })))));
1023
+ }
1024
+ componentWillUnmount() {
1025
+ internal.setRef(this.props.innerHeightRef, null);
1026
+ }
1027
+ }
1028
+
1029
+ /*
1030
+ TODO: kill this class in favor of DayGridHeaderRows?
1031
+ */
1032
+ class DayGridHeader extends internal.BaseComponent {
1033
+ render() {
1034
+ const { props } = this;
1035
+ const { headerTiers } = props;
1036
+ return (preact.createElement("div", { role: 'rowgroup', className: core.joinClassNames(props.className, classNames__default["default"].flexCol, props.width == null && classNames__default["default"].liquid), style: {
1037
+ width: props.width,
1038
+ } }, headerTiers.map((rowConfig, i) => (preact.createElement(DayGridHeaderRow, Object.assign({}, rowConfig, { key: i, role: 'row', borderBottom: i < headerTiers.length - 1, colWidth: props.colWidth, cellIsNarrow: props.cellIsNarrow, cellIsMicro: props.cellIsMicro, rowLevel: headerTiers.length - i - 1 }))))));
1039
+ }
1040
+ }
1041
+
1042
+ class DayGridLayoutNormal extends internal.BaseComponent {
1043
+ constructor() {
1044
+ super(...arguments);
1045
+ this.handleScroller = (scroller) => {
1046
+ internal.setRef(this.props.scrollerRef, scroller);
1047
+ };
1048
+ this.handleTotalWidth = (totalWidth) => {
1049
+ this.setState({ totalWidth });
1050
+ };
1051
+ this.handleClientWidth = (clientWidth) => {
1052
+ this.setState({ clientWidth });
1053
+ };
1054
+ }
1055
+ render() {
1056
+ const { props, state, context } = this;
1057
+ const { options } = context;
1058
+ const { totalWidth, clientWidth } = state;
1059
+ let endScrollbarWidth = (totalWidth != null && clientWidth != null)
1060
+ ? totalWidth - clientWidth
1061
+ : undefined;
1062
+ // HACK when clientWidth does NOT include body-border, compared to totalWidth
1063
+ if (endScrollbarWidth < 3) {
1064
+ endScrollbarWidth = 0;
1065
+ }
1066
+ const verticalScrollbars = !props.forPrint && !internal.getIsHeightAuto(options);
1067
+ const stickyHeaderDates = !props.forPrint && internal.getStickyHeaderDates(options);
1068
+ const colCount = props.cellRows[0].length;
1069
+ const cellWidth = clientWidth != null ? clientWidth / colCount : undefined;
1070
+ const cellIsMicro = cellWidth != null && cellWidth <= dayMicroWidth;
1071
+ const cellIsNarrow = cellIsMicro || (cellWidth != null && cellWidth <= options.dayNarrowWidth);
1072
+ return (preact.createElement(preact.Fragment, null,
1073
+ options.dayHeaders && (preact.createElement("div", { className: core.joinClassNames(internal.generateClassName(options.tableHeaderClass, {
1074
+ isSticky: stickyHeaderDates,
1075
+ }), props.borderlessX && classNames__default["default"].borderlessX, classNames__default["default"].printHeader, // either flexCol or table-header-group
1076
+ stickyHeaderDates && classNames__default["default"].tableHeaderSticky) },
1077
+ preact.createElement("div", { className: classNames__default["default"].flexRow },
1078
+ preact.createElement(DayGridHeader, { headerTiers: props.headerTiers, cellIsNarrow: cellIsNarrow, cellIsMicro: cellIsMicro }),
1079
+ Boolean(endScrollbarWidth) && (preact.createElement("div", { className: internal.joinArrayishClassNames(internal.generateClassName(options.fillerClass, { isHeader: true }), classNames__default["default"].borderOnlyS), style: { minWidth: endScrollbarWidth } }))),
1080
+ preact.createElement("div", { className: internal.generateClassName(options.dayHeaderDividerClass, {
1081
+ isSticky: stickyHeaderDates,
1082
+ options: { allDaySlot: Boolean(options.allDaySlot) },
1083
+ }) }))),
1084
+ preact.createElement(internal.Scroller, { vertical: verticalScrollbars, className: internal.joinArrayishClassNames(options.tableBodyClass, props.borderlessX && classNames__default["default"].borderlessX, stickyHeaderDates && classNames__default["default"].borderlessTop, (stickyHeaderDates || props.noEdgeEffects) && classNames__default["default"].noEdgeEffects,
1085
+ // HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
1086
+ // https://stackoverflow.com/a/60256345
1087
+ !props.forPrint && classNames__default["default"].flexCol, verticalScrollbars && classNames__default["default"].liquid), ref: this.handleScroller, clientWidthRef: this.handleClientWidth },
1088
+ preact.createElement(DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed, className: classNames__default["default"].grow, dayMaxEvents: props.forPrint ? undefined : options.dayMaxEvents, dayMaxEventRows: options.dayMaxEventRows,
1089
+ // content
1090
+ fgEventSegs: props.fgEventSegs, bgEventSegs: props.bgEventSegs, businessHourSegs: props.businessHourSegs, dateSelectionSegs: props.dateSelectionSegs, eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
1091
+ // dimensions
1092
+ visibleWidth: totalWidth, cellIsNarrow: cellIsNarrow, cellIsMicro: cellIsMicro,
1093
+ // refs
1094
+ rowHeightRefMap: props.rowHeightRefMap })),
1095
+ preact.createElement(internal.Ruler, { widthRef: this.handleTotalWidth })));
1096
+ }
1097
+ }
1098
+
1099
+ class DayGridLayoutPannable extends internal.BaseComponent {
1100
+ constructor() {
1101
+ super(...arguments);
1102
+ this.headerScrollerRef = preact.createRef();
1103
+ this.bodyScrollerRef = preact.createRef();
1104
+ this.footerScrollerRef = preact.createRef();
1105
+ // Sizing
1106
+ // -----------------------------------------------------------------------------------------------
1107
+ this.handleTotalWidth = (totalWidth) => {
1108
+ this.setState({ totalWidth });
1109
+ };
1110
+ this.handleClientWidth = (clientWidth) => {
1111
+ this.setState({ clientWidth });
1112
+ };
1113
+ }
1114
+ render() {
1115
+ const { props, state, context } = this;
1116
+ const { options } = context;
1117
+ const { totalWidth, clientWidth } = state;
1118
+ const endScrollbarWidth = (totalWidth != null && clientWidth != null)
1119
+ ? totalWidth - clientWidth
1120
+ : undefined;
1121
+ const verticalScrollbars = !props.forPrint && !internal.getIsHeightAuto(options);
1122
+ const stickyHeaderDates = !props.forPrint && internal.getStickyHeaderDates(options);
1123
+ const stickyFooterScrollbar = !props.forPrint && internal.getStickyFooterScrollbar(options);
1124
+ const colCount = props.cellRows[0].length;
1125
+ const [canvasWidth, colWidth] = computeColWidth(colCount, props.dayMinWidth, clientWidth);
1126
+ const cellIsMicro = colWidth != null && colWidth <= dayMicroWidth;
1127
+ const cellIsNarrow = cellIsMicro || (colWidth != null && colWidth <= options.dayNarrowWidth);
1128
+ return (preact.createElement(preact.Fragment, null,
1129
+ options.dayHeaders && (preact.createElement("div", { className: core.joinClassNames(internal.generateClassName(options.tableHeaderClass, {
1130
+ isSticky: stickyHeaderDates,
1131
+ }), props.borderlessX && classNames__default["default"].borderlessX, classNames__default["default"].printHeader, // either flexCol or table-header-group
1132
+ stickyHeaderDates && classNames__default["default"].tableHeaderSticky) },
1133
+ preact.createElement(internal.Scroller, { horizontal: true, hideScrollbars: true, className: classNames__default["default"].flexRow, ref: this.headerScrollerRef },
1134
+ preact.createElement(DayGridHeader, { headerTiers: props.headerTiers, colWidth: colWidth, width: canvasWidth, cellIsNarrow: cellIsNarrow, cellIsMicro: cellIsMicro }),
1135
+ Boolean(endScrollbarWidth) && (preact.createElement("div", { className: internal.joinArrayishClassNames(internal.generateClassName(options.fillerClass, { isHeader: true }), classNames__default["default"].borderOnlyS), style: { minWidth: endScrollbarWidth } }))),
1136
+ preact.createElement("div", { className: internal.generateClassName(options.dayHeaderDividerClass, {
1137
+ isSticky: stickyHeaderDates,
1138
+ options: { allDaySlot: Boolean(options.allDaySlot) },
1139
+ }) }))),
1140
+ preact.createElement(internal.Scroller, { vertical: verticalScrollbars, horizontal: true, hideScrollbars: stickyFooterScrollbar ||
1141
+ props.forPrint // prevents blank space in print-view on Safari
1142
+ , className: internal.joinArrayishClassNames(options.tableBodyClass, props.borderlessX && classNames__default["default"].borderlessX, stickyHeaderDates && classNames__default["default"].borderlessTop, (stickyHeaderDates || props.noEdgeEffects) && classNames__default["default"].noEdgeEffects,
1143
+ // HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
1144
+ // https://stackoverflow.com/a/60256345
1145
+ !props.forPrint && classNames__default["default"].flexCol, verticalScrollbars && classNames__default["default"].liquid), ref: this.bodyScrollerRef, clientWidthRef: this.handleClientWidth },
1146
+ preact.createElement(DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed, className: classNames__default["default"].grow, dayMaxEvents: props.forPrint ? undefined : options.dayMaxEvents, dayMaxEventRows: options.dayMaxEventRows,
1147
+ // content
1148
+ fgEventSegs: props.fgEventSegs, bgEventSegs: props.bgEventSegs, businessHourSegs: props.businessHourSegs, dateSelectionSegs: props.dateSelectionSegs, eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
1149
+ // dimensions
1150
+ colWidth: colWidth, width: canvasWidth, visibleWidth: totalWidth, cellIsNarrow: cellIsNarrow, cellIsMicro: cellIsMicro,
1151
+ // refs
1152
+ rowHeightRefMap: props.rowHeightRefMap })),
1153
+ Boolean(stickyFooterScrollbar) && (preact.createElement(internal.FooterScrollbar, { isSticky: true, canvasWidth: canvasWidth, scrollerRef: this.footerScrollerRef })),
1154
+ preact.createElement(internal.Ruler, { widthRef: this.handleTotalWidth })));
1155
+ }
1156
+ // Lifecycle
1157
+ // -----------------------------------------------------------------------------------------------
1158
+ componentDidMount() {
1159
+ // scroller
1160
+ const ScrollerSyncer = internal.getScrollerSyncerClass(this.context.pluginHooks);
1161
+ this.syncedScroller = new ScrollerSyncer(true); // horizontal=true
1162
+ internal.setRef(this.props.scrollerRef, this.syncedScroller);
1163
+ this.updateSyncedScroller();
1164
+ }
1165
+ componentDidUpdate() {
1166
+ // scroller
1167
+ this.updateSyncedScroller();
1168
+ }
1169
+ componentWillUnmount() {
1170
+ // scroller
1171
+ this.syncedScroller.destroy();
1172
+ }
1173
+ // Scrolling
1174
+ // -----------------------------------------------------------------------------------------------
1175
+ updateSyncedScroller() {
1176
+ this.syncedScroller.handleChildren([
1177
+ this.headerScrollerRef.current,
1178
+ this.bodyScrollerRef.current,
1179
+ this.footerScrollerRef.current,
1180
+ ]);
1181
+ }
1182
+ }
1183
+
1184
+ class DayGridLayout extends internal.BaseComponent {
1185
+ constructor() {
1186
+ super(...arguments);
1187
+ // ref
1188
+ this.scrollerRef = preact.createRef();
1189
+ this.rowHeightRefMap = new internal.RefMap(() => {
1190
+ internal.afterSize(this.updateScrollY);
1191
+ });
1192
+ // internal
1193
+ this.scrollDate = null;
1194
+ this.updateScrollY = () => {
1195
+ const rowHeightMap = this.rowHeightRefMap.current;
1196
+ const scroller = this.scrollerRef.current;
1197
+ // Since updateScrollY is called by rowHeightRefMap, could be called with null during cleanup,
1198
+ // and the scroller might not exist
1199
+ if (scroller && this.scrollDate) {
1200
+ let scrollTop = computeTopFromDate(this.scrollDate, this.props.cellRows, rowHeightMap, 1);
1201
+ if (scrollTop != null) {
1202
+ if (scrollTop) {
1203
+ scrollTop++; // clear top border
1204
+ }
1205
+ scroller.scrollTo({ y: scrollTop });
1206
+ }
1207
+ }
1208
+ };
1209
+ this.handleScrollEnd = (isUser) => {
1210
+ if (isUser) {
1211
+ this.scrollDate = null;
1212
+ }
1213
+ };
1214
+ }
1215
+ render() {
1216
+ const { props, context } = this;
1217
+ const { options } = context;
1218
+ const commonLayoutProps = Object.assign(Object.assign({}, props), { scrollerRef: this.scrollerRef, rowHeightRefMap: this.rowHeightRefMap });
1219
+ return (preact.createElement(internal.ViewContainer, { viewSpec: context.viewSpec, attrs: {
1220
+ role: 'grid',
1221
+ 'aria-rowcount': props.headerTiers.length + props.cellRows.length,
1222
+ 'aria-colcount': props.cellRows[0].length,
1223
+ 'aria-labelledby': props.labelId,
1224
+ 'aria-label': props.labelStr,
1225
+ }, className: internal.joinArrayishClassNames(props.className, classNames__default["default"].printRoot, // either flexCol or table
1226
+ options.tableClass), borderlessX: props.borderlessX, borderlessTop: props.borderlessTop, borderlessBottom: props.borderlessBottom, noEdgeEffects: props.noEdgeEffects }, options.dayMinWidth ? (preact.createElement(DayGridLayoutPannable, Object.assign({}, commonLayoutProps, { dayMinWidth: options.dayMinWidth }))) : (preact.createElement(DayGridLayoutNormal, Object.assign({}, commonLayoutProps)))));
1227
+ }
1228
+ // Lifecycle
1229
+ // -----------------------------------------------------------------------------------------------
1230
+ componentDidMount() {
1231
+ this.resetScroll();
1232
+ this.scrollerRef.current.addScrollEndListener(this.handleScrollEnd);
1233
+ }
1234
+ componentDidUpdate(prevProps) {
1235
+ if (prevProps.dateProfile !== this.props.dateProfile && this.context.options.scrollTimeReset) {
1236
+ this.resetScroll();
1237
+ }
1238
+ }
1239
+ componentWillUnmount() {
1240
+ this.scrollerRef.current.removeScrollEndListener(this.handleScrollEnd);
1241
+ }
1242
+ // Scrolling
1243
+ // -----------------------------------------------------------------------------------------------
1244
+ resetScroll() {
1245
+ this.scrollDate = this.props.dateProfile.currentDate;
1246
+ this.updateScrollY();
1247
+ const scroller = this.scrollerRef.current;
1248
+ scroller.scrollTo({ x: 0 });
1249
+ }
1250
+ }
1251
+
1252
+ class DayGridView extends internal.BaseComponent {
1253
+ constructor() {
1254
+ super(...arguments);
1255
+ // memo
1256
+ this.buildDayTableModel = internal.memoize(buildDayTableModel);
1257
+ this.buildDateRowConfigs = internal.memoize(buildDateRowConfigs);
1258
+ this.createDayHeaderFormatter = internal.memoize(createDayHeaderFormatter);
1259
+ // internal
1260
+ this.slicer = new DayTableSlicer();
1261
+ }
1262
+ render() {
1263
+ const { props, context } = this;
1264
+ const { dateProfile } = props;
1265
+ const { options, dateEnv } = context;
1266
+ const dayTableModel = this.buildDayTableModel(dateProfile, context.dateProfileGenerator, dateEnv);
1267
+ const datesRepDistinctDays = dayTableModel.rowCount === 1;
1268
+ const dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dayTableModel.colCount);
1269
+ const slicedProps = this.slicer.sliceProps(props, dateProfile, options.nextDayThreshold, context, dayTableModel);
1270
+ return (preact.createElement(internal.NowTimer, { unit: "day" }, (nowDate, todayRange) => {
1271
+ const headerTiers = this.buildDateRowConfigs(dayTableModel.headerDates, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, context);
1272
+ return (preact.createElement(DayGridLayout, { labelId: props.labelId, labelStr: props.labelStr, dateProfile: dateProfile, todayRange: todayRange, cellRows: dayTableModel.cellRows, forPrint: props.forPrint, className: props.className,
1273
+ // header content
1274
+ headerTiers: headerTiers,
1275
+ // body content
1276
+ fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection, borderlessX: props.borderlessX, borderlessTop: props.borderlessTop, borderlessBottom: props.borderlessBottom, noEdgeEffects: props.noEdgeEffects }));
1277
+ }));
1278
+ }
1279
+ }
1280
+
1281
+ class TableDateProfileGenerator extends internal.DateProfileGenerator {
1282
+ // Computes the date range that will be rendered
1283
+ buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
1284
+ let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay);
1285
+ let { props } = this;
1286
+ return buildDayTableRenderRange({
1287
+ currentRange: renderRange,
1288
+ snapToWeek: /^(year|month)$/.test(currentRangeUnit),
1289
+ fixedWeekCount: props.fixedWeekCount,
1290
+ dateEnv: props.dateEnv,
1291
+ });
1292
+ }
1293
+ }
1294
+ function buildDayTableRenderRange(props) {
1295
+ let { dateEnv, currentRange } = props;
1296
+ let { start, end } = currentRange;
1297
+ let endOfWeek;
1298
+ // year and month views should be aligned with weeks. this is already done for week
1299
+ if (props.snapToWeek) {
1300
+ start = dateEnv.startOfWeek(start);
1301
+ // make end-of-week if not already
1302
+ endOfWeek = dateEnv.startOfWeek(end);
1303
+ if (endOfWeek.valueOf() !== end.valueOf()) {
1304
+ end = internal.addWeeks(endOfWeek, 1);
1305
+ }
1306
+ }
1307
+ // ensure 6 weeks
1308
+ if (props.fixedWeekCount) {
1309
+ // TODO: instead of these date-math gymnastics (for multimonth view),
1310
+ // compute dateprofiles of all months, then use start of first and end of last.
1311
+ let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth(internal.addDays(currentRange.end, -1)));
1312
+ let rowCount = Math.ceil(// could be partial weeks due to hiddenDays
1313
+ internal.diffWeeks(lastMonthRenderStart, end));
1314
+ end = internal.addWeeks(end, 6 - rowCount);
1315
+ }
1316
+ return { start, end };
1317
+ }
1318
+
1319
+ exports.DayGridHeaderRow = DayGridHeaderRow;
1320
+ exports.DayGridLayout = DayGridLayout;
1321
+ exports.DayGridRow = DayGridRow;
1322
+ exports.DayGridRows = DayGridRows;
1323
+ exports.DayGridView = DayGridView;
1324
+ exports.DayTableSlicer = DayTableSlicer;
1325
+ exports.TableDateProfileGenerator = TableDateProfileGenerator;
1326
+ exports.buildDateDataConfigs = buildDateDataConfigs;
1327
+ exports.buildDateRenderConfig = buildDateRenderConfig;
1328
+ exports.buildDateRowConfig = buildDateRowConfig;
1329
+ exports.buildDateRowConfigs = buildDateRowConfigs;
1330
+ exports.buildDayTableModel = buildDayTableModel;
1331
+ exports.buildDayTableRenderRange = buildDayTableRenderRange;
1332
+ exports.computeColFromPosition = computeColFromPosition;
1333
+ exports.computeColWidth = computeColWidth;
1334
+ exports.computeRowBasis = computeRowBasis;
1335
+ exports.createDayHeaderFormatter = createDayHeaderFormatter;
1336
+ exports.dayHeaderMicroFormat = dayHeaderMicroFormat;
1337
+ exports.dayMicroWidth = dayMicroWidth;
1338
+ exports.getCellEl = getCellEl;
1339
+ exports.getRowEl = getRowEl;