@fullcalendar/daygrid 6.1.15 → 7.0.0-beta.1

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.
package/index.global.js CHANGED
@@ -1,133 +1,216 @@
1
1
  /*!
2
- FullCalendar Day Grid Plugin v6.1.15
2
+ FullCalendar Day Grid Plugin v7.0.0-beta.1
3
3
  Docs & License: https://fullcalendar.io/docs/month-view
4
4
  (c) 2024 Adam Shaw
5
5
  */
6
6
  FullCalendar.DayGrid = (function (exports, core, internal$1, preact) {
7
7
  'use strict';
8
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 {
9
+ class DayTableSlicer extends internal$1.Slicer {
14
10
  constructor() {
15
11
  super(...arguments);
16
- this.headerElRef = preact.createRef();
12
+ this.forceDayIfListItem = true;
17
13
  }
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
- });
14
+ sliceRange(dateRange, dayTableModel) {
15
+ return dayTableModel.sliceRange(dateRange);
16
+ }
17
+ }
18
+
19
+ function renderInner(renderProps) {
20
+ return renderProps.text;
21
+ }
22
+ function buildDayTableModel(dateProfile, dateProfileGenerator) {
23
+ let daySeries = new internal$1.DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
24
+ return new internal$1.DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
25
+ }
26
+ function computeColWidth(colCnt, colMinWidth, viewportWidth) {
27
+ if (viewportWidth == null) {
28
+ return [undefined, undefined];
29
+ }
30
+ const colTempWidth = viewportWidth / colCnt;
31
+ if (colTempWidth < colMinWidth) {
32
+ return [colMinWidth * colCnt, colMinWidth];
33
+ }
34
+ return [viewportWidth, undefined];
35
+ }
36
+ function buildHeaderTiers(dates, datesRepDistinctDays) {
37
+ return [
38
+ datesRepDistinctDays
39
+ ? dates.map((date) => ({ colSpan: 1, date }))
40
+ : dates.map((date) => ({ colSpan: 1, dow: date.getUTCDay() }))
41
+ ];
42
+ }
43
+ // Positioning
44
+ // -------------------------------------------------------------------------------------------------
45
+ function computeTopFromDate(date, cellRows, rowHeightMap, adjust = 0) {
46
+ let top = 0;
47
+ for (const cells of cellRows) {
48
+ const start = cells[0].date;
49
+ const end = cells[cells.length - 1].date;
50
+ const key = start.toISOString();
51
+ if (date >= start && date <= end) {
52
+ return top;
33
53
  }
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 })));
54
+ const rowHeight = rowHeightMap.get(key);
55
+ if (rowHeight == null) {
56
+ return; // denote unknown
57
+ }
58
+ top += rowHeight + adjust;
42
59
  }
43
- renderHScrollLayout(headerRowContent, bodyContent, colCnt, dayMinWidth) {
44
- let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
45
- if (!ScrollGrid) {
46
- throw new Error('No ScrollGrid implementation');
60
+ return top;
61
+ }
62
+ function computeHorizontalsFromSeg(seg, colWidth, colCnt, isRtl) {
63
+ let left;
64
+ let right;
65
+ let width;
66
+ if (colWidth != null) {
67
+ width = (seg.lastCol - seg.firstCol + 1) * colWidth;
68
+ if (isRtl) {
69
+ right = seg.firstCol * colWidth;
47
70
  }
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
- });
71
+ else {
72
+ left = seg.firstCol * colWidth;
64
73
  }
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
- });
74
+ }
75
+ else {
76
+ const colWidthFrac = 1 / colCnt;
77
+ width = internal$1.fracToCssDim((seg.lastCol - seg.firstCol + 1) * colWidthFrac);
78
+ if (isRtl) {
79
+ right = internal$1.fracToCssDim(seg.firstCol * colWidthFrac);
80
+ }
81
+ else {
82
+ left = internal$1.fracToCssDim(seg.firstCol * colWidthFrac);
83
+ }
84
+ }
85
+ return { left, right, width };
86
+ }
87
+ function computeColFromPosition(positionLeft, elWidth, colWidth, colCnt, isRtl) {
88
+ const realColWidth = colWidth != null ? colWidth : elWidth / colCnt;
89
+ const colFromLeft = Math.floor(positionLeft / realColWidth);
90
+ const col = isRtl ? (colCnt - colFromLeft - 1) : colFromLeft;
91
+ const left = colFromLeft * realColWidth;
92
+ const right = left + realColWidth;
93
+ return { col, left, right };
94
+ }
95
+ function computeRowFromPosition(positionTop, cellRows, rowHeightMap) {
96
+ let row = 0;
97
+ let top = 0;
98
+ let bottom = 0;
99
+ for (const cells of cellRows) {
100
+ const key = cells[0].key;
101
+ top = bottom;
102
+ bottom = top + rowHeightMap.get(key);
103
+ if (positionTop < bottom) {
104
+ break;
84
105
  }
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 })));
106
+ row++;
87
107
  }
108
+ return { row, top, bottom };
109
+ }
110
+ // Hit Element
111
+ // -------------------------------------------------------------------------------------------------
112
+ function getRowEl(rootEl, row) {
113
+ return rootEl.querySelectorAll(':scope > [role=row]')[row];
114
+ }
115
+ function getCellEl(rowEl, col) {
116
+ return rowEl.querySelectorAll(':scope > [role=gridcell]')[col];
88
117
  }
89
118
 
90
- function splitSegsByRow(segs, rowCnt) {
91
- let byRow = [];
92
- for (let i = 0; i < rowCnt; i += 1) {
93
- byRow[i] = [];
119
+ class DateHeaderCell extends internal$1.BaseComponent {
120
+ constructor() {
121
+ super(...arguments);
122
+ // ref
123
+ this.innerElRef = preact.createRef();
94
124
  }
95
- for (let seg of segs) {
96
- byRow[seg.row].push(seg);
125
+ render() {
126
+ let { props, context } = this;
127
+ let { dateProfile, date, extraRenderProps, extraDataAttrs } = props;
128
+ let { dateEnv, options, theme, viewApi } = context;
129
+ let dayMeta = internal$1.getDateMeta(date, props.todayRange, null, dateProfile);
130
+ let text = dateEnv.format(date, props.dayHeaderFormat);
131
+ let navLinkAttrs = (!dayMeta.isDisabled && props.navLink)
132
+ ? internal$1.buildNavLinkAttrs(context, date)
133
+ : {};
134
+ let renderProps = Object.assign(Object.assign(Object.assign({ date: dateEnv.toDate(date), view: viewApi }, extraRenderProps), { text }), dayMeta);
135
+ return (preact.createElement(internal$1.ContentContainer, { elTag: 'div', elClasses: [
136
+ ...internal$1.getDayClassNames(dayMeta, theme),
137
+ ...(props.extraClassNames || []),
138
+ 'fc-header-cell',
139
+ 'fc-cell',
140
+ props.colWidth != null ? '' : 'fc-liquid',
141
+ 'fc-flex-column',
142
+ 'fc-align-center',
143
+ ], elAttrs: Object.assign({ 'data-date': !dayMeta.isDisabled ? internal$1.formatDayString(date) : undefined }, extraDataAttrs), elStyle: {
144
+ width: props.colWidth != null // TODO: DRY
145
+ ? props.colWidth * (props.colSpan || 1)
146
+ : undefined,
147
+ }, renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContainer) => (preact.createElement("div", { ref: this.innerElRef, className: [
148
+ 'fc-flex-column',
149
+ props.isSticky ? 'fc-sticky-x' : '',
150
+ ].join(' ') }, !dayMeta.isDisabled && (preact.createElement(InnerContainer, { elTag: "a", elAttrs: navLinkAttrs, elClasses: [
151
+ 'fc-cell-inner',
152
+ 'fc-padding-sm',
153
+ ] }))))));
154
+ }
155
+ componentDidMount() {
156
+ const innerEl = this.innerElRef.current; // TODO: make dynamic with useEffect
157
+ // TODO: only attach this if refs props present
158
+ this.disconectInnerHeight = internal$1.watchHeight(innerEl, (height) => {
159
+ internal$1.setRef(this.props.innerHeightRef, height);
160
+ });
161
+ }
162
+ componentWillUnmount() {
163
+ this.disconectInnerHeight();
164
+ internal$1.setRef(this.props.innerHeightRef, null);
97
165
  }
98
- return byRow;
99
166
  }
100
- function splitSegsByFirstCol(segs, colCnt) {
101
- let byCol = [];
102
- for (let i = 0; i < colCnt; i += 1) {
103
- byCol[i] = [];
167
+
168
+ function splitSegsByRow(segs, rowCnt) {
169
+ const byRow = [];
170
+ for (let row = 0; row < rowCnt; row++) {
171
+ byRow[row] = [];
104
172
  }
105
- for (let seg of segs) {
106
- byCol[seg.firstCol].push(seg);
173
+ for (const seg of segs) {
174
+ byRow[seg.row].push(seg);
107
175
  }
108
- return byCol;
176
+ return byRow;
109
177
  }
110
178
  function splitInteractionByRow(ui, rowCnt) {
111
- let byRow = [];
179
+ const byRow = [];
112
180
  if (!ui) {
113
- for (let i = 0; i < rowCnt; i += 1) {
114
- byRow[i] = null;
181
+ for (let row = 0; row < rowCnt; row++) {
182
+ byRow[row] = null;
115
183
  }
116
184
  }
117
185
  else {
118
- for (let i = 0; i < rowCnt; i += 1) {
119
- byRow[i] = {
186
+ for (let row = 0; row < rowCnt; row++) {
187
+ byRow[row] = {
120
188
  affectedInstances: ui.affectedInstances,
121
189
  isEvent: ui.isEvent,
122
190
  segs: [],
123
191
  };
124
192
  }
125
- for (let seg of ui.segs) {
193
+ for (const seg of ui.segs) {
126
194
  byRow[seg.row].segs.push(seg);
127
195
  }
128
196
  }
129
197
  return byRow;
130
198
  }
199
+ function splitSegsByCol(segs, colCnt) {
200
+ let byCol = [];
201
+ for (let col = 0; col < colCnt; col++) {
202
+ byCol.push([]);
203
+ }
204
+ for (let seg of segs) {
205
+ for (let col = seg.firstCol; col <= seg.lastCol; col++) {
206
+ if (seg.firstCol !== col) {
207
+ seg = Object.assign(Object.assign({}, seg), { firstCol: col, lastCol: col, isStart: false, isEnd: seg.isEnd && seg.lastCol === col, isStandin: true });
208
+ }
209
+ byCol[col].push(seg);
210
+ }
211
+ }
212
+ return byCol;
213
+ }
131
214
 
132
215
  const DEFAULT_TABLE_EVENT_TIME_FORMAT = internal$1.createFormatter({
133
216
  hour: 'numeric',
@@ -145,21 +228,21 @@ FullCalendar.DayGrid = (function (exports, core, internal$1, preact) {
145
228
  );
146
229
  }
147
230
 
148
- class TableBlockEvent extends internal$1.BaseComponent {
231
+ class DayGridBlockEvent extends internal$1.BaseComponent {
149
232
  render() {
150
233
  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 })));
234
+ 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.eventRange.def.allDay })));
152
235
  }
153
236
  }
154
237
 
155
- class TableListItemEvent extends internal$1.BaseComponent {
238
+ class DayGridListEvent extends internal$1.BaseComponent {
156
239
  render() {
157
240
  let { props, context } = this;
158
241
  let { options } = context;
159
- let { seg } = props;
242
+ let { eventRange } = props;
160
243
  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 })));
244
+ let timeText = internal$1.buildEventRangeTimeText(eventRange, timeFormat, context, true, props.defaultDisplayEventEnd);
245
+ return (preact.createElement(internal$1.EventContainer, Object.assign({}, props, { elTag: "a", elClasses: ['fc-daygrid-event', 'fc-daygrid-dot-event'], elAttrs: internal$1.getEventRangeAnchorAttrs(eventRange, context), defaultGenerator: renderInnerContent, timeText: timeText, isResizing: false, isDateSelecting: false })));
163
246
  }
164
247
  }
165
248
  function renderInnerContent(renderProps) {
@@ -169,80 +252,84 @@ FullCalendar.DayGrid = (function (exports, core, internal$1, preact) {
169
252
  preact.createElement("div", { className: "fc-event-title" }, renderProps.event.title || preact.createElement(preact.Fragment, null, "\u00A0"))));
170
253
  }
171
254
 
172
- class TableCellMoreLink extends internal$1.BaseComponent {
173
- constructor() {
174
- super(...arguments);
175
- this.compileSegs = internal$1.memoize(compileSegs);
176
- }
255
+ class DayGridMoreLink extends internal$1.BaseComponent {
177
256
  render() {
178
257
  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) ||
258
+ return (preact.createElement(internal$1.MoreLinkContainer, { elClasses: ['fc-daygrid-more-link'], dateProfile: props.dateProfile, todayRange: props.todayRange, allDayDate: props.allDayDate, segs: props.segs, hiddenSegs: props.hiddenSegs, alignmentElRef: props.alignmentElRef, alignGridTop: props.alignGridTop, extraDateSpan: props.extraDateSpan, popoverContent: () => {
259
+ let forcedInvisibleMap = // TODO: more convenient/DRY
260
+ (props.eventDrag ? props.eventDrag.affectedInstances : null) ||
182
261
  (props.eventResize ? props.eventResize.affectedInstances : null) ||
183
262
  {};
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))))));
263
+ return (preact.createElement(preact.Fragment, null, props.segs.map((seg) => {
264
+ let { eventRange } = seg;
265
+ let instanceId = eventRange.instance.instanceId;
266
+ return (preact.createElement("div", { key: instanceId, style: {
267
+ visibility: forcedInvisibleMap[instanceId] ? 'hidden' : '',
268
+ } }, hasListItemDisplay(seg) ? (preact.createElement(DayGridListEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, internal$1.getEventRangeMeta(eventRange, props.todayRange)))) : (preact.createElement(DayGridBlockEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, internal$1.getEventRangeMeta(eventRange, props.todayRange))))));
189
269
  })));
190
270
  } }));
191
271
  }
192
272
  }
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
273
 
205
- const DEFAULT_WEEK_NUM_FORMAT = internal$1.createFormatter({ week: 'narrow' });
206
- class TableCell extends internal$1.DateComponent {
274
+ class DayGridCell extends internal$1.DateComponent {
207
275
  constructor() {
208
276
  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
- };
277
+ // ref
278
+ this.innerElRef = preact.createRef();
279
+ this.headerWrapElRef = preact.createRef();
217
280
  }
218
281
  render() {
219
- let { context, props, state, rootElRef } = this;
282
+ let { props, context } = this;
220
283
  let { options, dateEnv } = context;
221
- let { date, dateProfile } = props;
222
- // TODO: memoize this?
284
+ // TODO: memoize this
223
285
  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',
286
+ shouldDisplayMonthStart(props.date, props.dateProfile.currentRange, dateEnv);
287
+ return (preact.createElement(internal$1.DayCellContainer, { elTag: "div", elClasses: [
288
+ 'fc-daygrid-cell',
289
+ 'fc-cell',
290
+ props.width != null ? '' : 'fc-liquid',
291
+ 'fc-flex-column',
227
292
  ...(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" },
293
+ ], elAttrs: Object.assign(Object.assign({}, props.extraDataAttrs), { role: 'gridcell' }), elStyle: {
294
+ width: props.width
295
+ }, extraRenderProps: props.extraRenderProps, defaultGenerator: renderTopInner, date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, isMonthStart: isMonthStart }, (InnerContent, renderProps) => (preact.createElement("div", { ref: this.innerElRef, className: [
296
+ 'fc-daygrid-cell-inner',
297
+ props.fgLiquidHeight ? 'fc-liquid' : ''
298
+ ].join(' ') },
299
+ preact.createElement("div", { ref: this.headerWrapElRef, className: "fc-flex-column" }, !renderProps.isDisabled && (props.showDayNumber || internal$1.hasCustomDayCellContent(options)) && (preact.createElement("div", { className: "fc-daygrid-cell-header" },
232
300
  preact.createElement(InnerContent, { elTag: "a", elClasses: [
233
- 'fc-daygrid-day-number',
301
+ 'fc-daygrid-cell-number',
234
302
  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)))));
303
+ ], elAttrs: internal$1.buildNavLinkAttrs(context, props.date) })))),
304
+ preact.createElement("div", { className: "fc-daygrid-cell-main", style: {
305
+ height: props.fgLiquidHeight ? '' : props.fgHeight
306
+ } }, props.fg),
307
+ preact.createElement("div", { className: "fc-daygrid-cell-footer", style: props.fgLiquidHeight
308
+ ? { position: 'relative', top: props.fgHeight }
309
+ : {} },
310
+ preact.createElement(DayGridMoreLink, { allDayDate: props.date, segs: props.segs, hiddenSegs: props.hiddenSegs, alignmentElRef: this.innerElRef, alignGridTop: !props.showDayNumber, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange })),
311
+ props.bg))));
312
+ }
313
+ componentDidMount() {
314
+ const innerEl = this.innerElRef.current; // TODO: make dynamic with useEffect
315
+ const headerWrapEl = this.headerWrapElRef.current; // "
316
+ // TODO: only attach this if refs props present
317
+ this.detachInnerHeight = internal$1.watchHeight(innerEl, (height) => {
318
+ internal$1.setRef(this.props.innerHeightRef, height);
319
+ });
320
+ this.detachHeaderHeight = internal$1.watchHeight(headerWrapEl, (height) => {
321
+ internal$1.setRef(this.props.headerHeightRef, height);
322
+ });
323
+ }
324
+ componentWillUnmount() {
325
+ this.detachInnerHeight();
326
+ this.detachHeaderHeight();
327
+ internal$1.setRef(this.props.innerHeightRef, null);
328
+ internal$1.setRef(this.props.headerHeightRef, null);
244
329
  }
245
330
  }
331
+ // Utils
332
+ // -------------------------------------------------------------------------------------------------
246
333
  function renderTopInner(props) {
247
334
  return props.dayNumberText || preact.createElement(preact.Fragment, null, "\u00A0");
248
335
  }
@@ -262,26 +349,43 @@ FullCalendar.DayGrid = (function (exports, core, internal$1, preact) {
262
349
  (dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf()));
263
350
  }
264
351
 
265
- function generateSegKey(seg) {
352
+ /*
353
+ Unique per-START-column, good for cataloging by top
354
+ */
355
+ function getSegStartId(seg) {
266
356
  return seg.eventRange.instance.instanceId + ':' + seg.firstCol;
267
357
  }
268
- function generateSegUid(seg) {
269
- return generateSegKey(seg) + ':' + seg.lastCol;
358
+ /*
359
+ Unique per-START-and-END-column, good for cataloging by width/height
360
+ */
361
+ function getSegSpanId(seg) {
362
+ return getSegStartId(seg) + ':' + seg.lastCol;
270
363
  }
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;
364
+ function computeFgSegVerticals(segs, segHeightMap, // keyed by segSpanId
365
+ cells, topOrigin, maxHeight, strictOrder, dayMaxEvents, dayMaxEventRows) {
366
+ // initialize column-based arrays
367
+ const colCnt = cells.length;
368
+ const hiddenSegsByCol = [];
369
+ const heightsByCol = [];
370
+ for (let col = 0; col < colCnt; col++) {
371
+ hiddenSegsByCol.push([]);
372
+ heightsByCol.push(0);
373
+ }
374
+ // create entries to be given to DayGridSegHierarchy
375
+ const segEntries = segs.map((seg, index) => ({
376
+ index: index,
377
+ seg,
378
+ span: {
379
+ start: seg.firstCol,
380
+ end: seg.lastCol + 1,
381
+ },
382
+ }));
383
+ // configure hierarchy position-generator
384
+ let hierarchy = new DayGridSegHierarchy((segEntry) => (segHeightMap.get(getSegSpanId(segs[segEntry.index]))));
385
+ hierarchy.allowReslicing = false;
282
386
  hierarchy.strictOrder = strictOrder;
283
387
  if (dayMaxEvents === true || dayMaxEventRows === true) {
284
- hierarchy.maxCoord = maxContentHeight;
388
+ hierarchy.maxCoord = maxHeight;
285
389
  hierarchy.hiddenConsumes = true;
286
390
  }
287
391
  else if (typeof dayMaxEvents === 'number') {
@@ -291,172 +395,30 @@ FullCalendar.DayGrid = (function (exports, core, internal$1, preact) {
291
395
  hierarchy.maxStackCnt = dayMaxEventRows;
292
396
  hierarchy.hiddenConsumes = true;
293
397
  }
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);
398
+ // compile segTops & heightsByCol
399
+ const hiddenSegEntries = hierarchy.addSegs(segEntries);
400
+ const segRects = hierarchy.toRects();
401
+ const segTops = {};
402
+ for (const segRect of segRects) {
403
+ const seg = segs[segRect.index];
404
+ segTops[getSegStartId(seg)] = topOrigin + segRect.levelCoord;
405
+ let { start: col, end: endCol } = segRect.span;
406
+ for (; col < endCol; col++) {
407
+ heightsByCol[col] = Math.max(heightsByCol[col], segRect.levelCoord + segRect.thickness);
312
408
  }
313
409
  }
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
- });
410
+ // compile # of invisible segs per-column
411
+ for (const hiddenSegEntry of hiddenSegEntries) {
412
+ const { span } = hiddenSegEntry;
413
+ const hiddenSeg = segs[hiddenSegEntry.index];
414
+ for (let col = span.start; col < span.end; col++) {
415
+ hiddenSegsByCol[col].push(hiddenSeg);
336
416
  }
337
417
  }
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() });
418
+ return [segTops, heightsByCol, hiddenSegsByCol];
459
419
  }
420
+ // DayGridSegHierarchy
421
+ // -------------------------------------------------------------------------------------------------
460
422
  class DayGridSegHierarchy extends internal$1.SegHierarchy {
461
423
  constructor() {
462
424
  super(...arguments);
@@ -504,74 +466,206 @@ FullCalendar.DayGrid = (function (exports, core, internal$1, preact) {
504
466
  }
505
467
  }
506
468
 
507
- class TableRow extends internal$1.DateComponent {
469
+ class DayGridEventHarness extends preact.Component {
508
470
  constructor() {
509
471
  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"
472
+ // ref
514
473
  this.rootElRef = preact.createRef();
515
- this.state = {
516
- framePositions: null,
517
- maxContentHeight: null,
518
- segHeights: {},
474
+ }
475
+ render() {
476
+ const { props } = this;
477
+ return (preact.createElement("div", { className: "fc-abs", style: props.style, ref: this.rootElRef }, props.children));
478
+ }
479
+ componentDidMount() {
480
+ const rootEl = this.rootElRef.current; // TODO: make dynamic with useEffect
481
+ this.detachHeight = internal$1.watchHeight(rootEl, (height) => {
482
+ internal$1.setRef(this.props.heightRef, height);
483
+ });
484
+ }
485
+ componentWillUnmount() {
486
+ this.detachHeight();
487
+ internal$1.setRef(this.props.heightRef, null);
488
+ }
489
+ }
490
+
491
+ const DEFAULT_WEEK_NUM_FORMAT = internal$1.createFormatter({ week: 'narrow' });
492
+ const COMPACT_CELL_WIDTH = 80;
493
+ class DayGridRow extends internal$1.BaseComponent {
494
+ constructor() {
495
+ super(...arguments);
496
+ this.cellInnerHeightRefMap = new internal$1.RefMap(() => {
497
+ internal$1.afterSize(this.handleInnerHeights);
498
+ });
499
+ this.cellHeaderHeightRefMap = new internal$1.RefMap(() => {
500
+ internal$1.afterSize(this.handleHeaderHeights);
501
+ });
502
+ this.segHeightRefMap = new internal$1.RefMap(() => {
503
+ internal$1.afterSize(this.handleSegHeights);
504
+ });
505
+ this.handleRootEl = (rootEl) => {
506
+ this.rootEl = rootEl;
507
+ internal$1.setRef(this.props.rootElRef, rootEl);
508
+ };
509
+ // Sizing
510
+ // -----------------------------------------------------------------------------------------------
511
+ this.handleHeaderHeights = () => {
512
+ const cellHeaderHeightMap = this.cellHeaderHeightRefMap.current;
513
+ let max = 0;
514
+ for (const height of cellHeaderHeightMap.values()) {
515
+ max = Math.max(max, height);
516
+ }
517
+ if (this.state.headerHeight !== max) {
518
+ this.setState({ headerHeight: max });
519
+ }
519
520
  };
520
- this.handleResize = (isForced) => {
521
- if (isForced) {
522
- this.updateSizing(true); // isExternal=true
521
+ this.handleInnerHeights = () => {
522
+ const { props } = this;
523
+ const fgLiquidHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
524
+ const cellInnerHeightMap = this.cellInnerHeightRefMap.current;
525
+ let max = 0;
526
+ for (const height of cellInnerHeightMap.values()) {
527
+ max = Math.max(max, height);
528
+ }
529
+ if (fgLiquidHeight) {
530
+ if (this.state.innerHeight !== max) {
531
+ this.setState({ innerHeight: max }); // will trigger event rerender
532
+ }
533
+ }
534
+ else {
535
+ internal$1.setRef(props.innerHeightRef, max);
523
536
  }
524
537
  };
538
+ this.handleSegHeights = () => {
539
+ this.setState({ segHeightRev: this.segHeightRefMap.rev }); // will trigger event rerender
540
+ };
525
541
  }
526
542
  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
543
+ const { props, state, context, cellInnerHeightRefMap, cellHeaderHeightRefMap } = this;
544
+ const { cells } = props;
545
+ const { options } = context;
546
+ const weekDate = props.cells[0].date;
547
+ const colCnt = props.cells.length;
548
+ const fgLiquidHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
549
+ // TODO: memoize? sort all types of segs?
550
+ const fgEventSegs = internal$1.sortEventSegs(props.fgEventSegs, options.eventOrder);
551
+ // TODO: memoize?
552
+ const fgEventSegsByCol = splitSegsByCol(fgEventSegs, colCnt);
553
+ const bgEventSegsByCol = splitSegsByCol(props.bgEventSegs, colCnt);
554
+ const businessHoursByCol = splitSegsByCol(props.businessHourSegs, colCnt);
555
+ const highlightSegsByCol = splitSegsByCol(this.getHighlightSegs(), colCnt); // TODO: doesn't need standins
556
+ const mirrorSegsByCol = splitSegsByCol(this.getMirrorSegs(), colCnt); // TODO: doesn't need standins
557
+ // TODO: memoize?
558
+ const [segTops, heightsByCol, hiddenSegsByCol] = computeFgSegVerticals(fgEventSegs, this.segHeightRefMap.current, cells, state.headerHeight, (fgLiquidHeight && state.innerHeight != null && state.headerHeight != null)
559
+ ? state.innerHeight - state.headerHeight
560
+ : undefined, options.eventOrderStrict, props.dayMaxEvents, props.dayMaxEventRows);
561
+ const forcedInvisibleMap = // TODO: more convenient/DRY
536
562
  (props.eventDrag && props.eventDrag.affectedInstances) ||
537
563
  (props.eventResize && props.eventResize.affectedInstances) ||
538
564
  {};
539
- return (preact.createElement("tr", { ref: this.rootElRef, role: "row" },
540
- props.renderIntro && props.renderIntro(),
565
+ return (preact.createElement("div", { role: props.cellGroup ? undefined : 'row', className: [
566
+ 'fc-daygrid-row',
567
+ props.forceVSpacing
568
+ ? 'fc-daygrid-row-spacious'
569
+ : props.compact
570
+ ? 'fc-daygrid-row-compact'
571
+ : '',
572
+ props.cellGroup ? 'fc-flex-row' : 'fc-row',
573
+ 'fc-rel',
574
+ props.className || '',
575
+ ].join(' '), style: {
576
+ minHeight: props.minHeight,
577
+ }, ref: this.handleRootEl },
541
578
  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,
579
+ const normalFgNodes = this.renderFgSegs(fgEventSegsByCol[col], segTops, props.todayRange, forcedInvisibleMap);
580
+ const mirrorFgNodes = this.renderFgSegs(mirrorSegsByCol[col], segTops, props.todayRange, {}, // forcedInvisibleMap
581
+ Boolean(props.eventDrag), Boolean(props.eventResize), false);
582
+ return (preact.createElement(DayGridCell, { key: cell.key, dateProfile: props.dateProfile, todayRange: props.todayRange, date: cell.date, showDayNumber: props.showDayNumbers,
583
+ // content
584
+ segs: fgEventSegsByCol[col], hiddenSegs: hiddenSegsByCol[col], fgLiquidHeight: fgLiquidHeight, fg: (preact.createElement(preact.Fragment, null,
546
585
  preact.createElement(preact.Fragment, null, normalFgNodes),
547
- preact.createElement(preact.Fragment, null, mirrorFgNodes))), bgContent: ( // Fragment scopes the keys
548
- preact.createElement(preact.Fragment, null,
586
+ preact.createElement(preact.Fragment, null, mirrorFgNodes))), bg: (preact.createElement(preact.Fragment, null,
549
587
  this.renderFillSegs(highlightSegsByCol[col], 'highlight'),
550
588
  this.renderFillSegs(businessHoursByCol[col], 'non-business'),
551
- this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))), minHeight: props.cellMinHeight }));
552
- })));
589
+ this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))), eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
590
+ // render hooks
591
+ extraRenderProps: cell.extraRenderProps, extraDateSpan: cell.extraDateSpan, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames,
592
+ // dimensions
593
+ fgHeight: heightsByCol[col], width: props.colWidth,
594
+ // refs
595
+ innerHeightRef: cellInnerHeightRefMap.createRef(cell.key), headerHeightRef: cellHeaderHeightRefMap.createRef(cell.key) }));
596
+ }),
597
+ props.showWeekNumbers && (preact.createElement(internal$1.WeekNumberContainer, { elTag: "a", elClasses: ['fc-daygrid-week-number'], elAttrs: internal$1.buildNavLinkAttrs(context, weekDate, 'week'), date: weekDate, defaultFormat: DEFAULT_WEEK_NUM_FORMAT }))));
598
+ }
599
+ renderFgSegs(segs, segTops, todayRange, forcedInvisibleMap, isDragging, isResizing, isDateSelecting) {
600
+ const { props, context, segHeightRefMap } = this;
601
+ const { isRtl } = context;
602
+ const { colWidth, eventSelection } = props;
603
+ const colCnt = props.cells.length;
604
+ const defaultDisplayEventEnd = props.cells.length === 1;
605
+ const isMirror = isDragging || isResizing || isDateSelecting;
606
+ const nodes = [];
607
+ for (const seg of segs) {
608
+ const { left, right, width } = computeHorizontalsFromSeg(seg, colWidth, colCnt, isRtl);
609
+ // TODO: optimize ID creation? all related
610
+ const { eventRange } = seg;
611
+ const { instanceId } = eventRange.instance;
612
+ const segSpanId = getSegSpanId(seg);
613
+ const segStartId = getSegStartId(seg);
614
+ const top = segTops[segStartId];
615
+ const isVisible = !seg.isStandin &&
616
+ top != null &&
617
+ !forcedInvisibleMap[instanceId];
618
+ /*
619
+ TODO: is this comment still relevant? vvvvvvvv
620
+ known bug: events that are force to be list-item but span multiple days still take up space in later columns
621
+ todo: in print view, for multi-day events, don't display title within non-start/end segs
622
+ */
623
+ nodes.push(preact.createElement(DayGridEventHarness, { key: segSpanId, style: {
624
+ visibility: isVisible ? '' : 'hidden',
625
+ top,
626
+ left,
627
+ right,
628
+ width,
629
+ }, heightRef: (isMirror || seg.isStandin)
630
+ ? null
631
+ : segHeightRefMap.createRef(segSpanId) }, hasListItemDisplay(seg) ? (preact.createElement(DayGridListEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal$1.getEventRangeMeta(eventRange, todayRange)))) : (preact.createElement(DayGridBlockEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal$1.getEventRangeMeta(eventRange, todayRange))))));
632
+ }
633
+ return nodes;
553
634
  }
554
- componentDidMount() {
555
- this.updateSizing(true);
556
- this.context.addResizeHandler(this.handleResize);
635
+ renderFillSegs(segs, fillType) {
636
+ const { props, context } = this;
637
+ const { isRtl } = context;
638
+ const { todayRange, colWidth } = props;
639
+ const colCnt = props.cells.length;
640
+ const nodes = [];
641
+ for (const seg of segs) {
642
+ const { left, right, width } = computeHorizontalsFromSeg(seg, colWidth, colCnt, isRtl);
643
+ const isVisible = !seg.isStandin;
644
+ nodes.push(preact.createElement("div", { key: internal$1.buildEventRangeKey(seg.eventRange), className: "fc-fill-y", style: {
645
+ visibility: isVisible ? '' : 'hidden',
646
+ left,
647
+ right,
648
+ width,
649
+ } }, fillType === 'bg-event' ?
650
+ preact.createElement(internal$1.BgEvent, Object.assign({ eventRange: seg.eventRange, isStart: seg.isStart, isEnd: seg.isEnd }, internal$1.getEventRangeMeta(seg.eventRange, todayRange))) : (internal$1.renderFill(fillType))));
651
+ }
652
+ return preact.createElement(preact.Fragment, {}, ...nodes);
557
653
  }
558
- componentDidUpdate(prevProps, prevState) {
559
- let currentProps = this.props;
560
- this.updateSizing(!internal$1.isPropsEqual(prevProps, currentProps));
654
+ // Sizing
655
+ // -----------------------------------------------------------------------------------------------
656
+ componentDidMount() {
657
+ const { rootEl } = this; // TODO: make dynamic with useEffect
658
+ this.disconnectHeight = internal$1.watchHeight(rootEl, (contentHeight) => {
659
+ internal$1.setRef(this.props.heightRef, contentHeight);
660
+ });
561
661
  }
562
662
  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;
663
+ this.disconnectHeight();
664
+ internal$1.setRef(this.props.heightRef, null);
665
+ internal$1.setRef(this.props.innerHeightRef, null);
574
666
  }
667
+ // Utils
668
+ // -----------------------------------------------------------------------------------------------
575
669
  getMirrorSegs() {
576
670
  let { props } = this;
577
671
  if (props.eventResize && props.eventResize.segs.length) { // messy check
@@ -579,372 +673,440 @@ FullCalendar.DayGrid = (function (exports, core, internal$1, preact) {
579
673
  }
580
674
  return [];
581
675
  }
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);
676
+ getHighlightSegs() {
677
+ let { props } = this;
678
+ if (props.eventDrag && props.eventDrag.segs.length) { // messy check
679
+ return props.eventDrag.segs;
681
680
  }
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;
681
+ if (props.eventResize && props.eventResize.segs.length) { // messy check
682
+ return props.eventResize.segs;
716
683
  }
684
+ return props.dateSelectionSegs;
717
685
  }
718
- return topsByInstanceId;
719
686
  }
720
687
 
721
- class TableRows extends internal$1.DateComponent {
688
+ class DayGridRows extends internal$1.DateComponent {
722
689
  constructor() {
723
690
  super(...arguments);
691
+ // memo
724
692
  this.splitBusinessHourSegs = internal$1.memoize(splitSegsByRow);
725
693
  this.splitBgEventSegs = internal$1.memoize(splitSegsByRow);
726
694
  this.splitFgEventSegs = internal$1.memoize(splitSegsByRow);
727
695
  this.splitDateSelectionSegs = internal$1.memoize(splitSegsByRow);
728
696
  this.splitEventDrag = internal$1.memoize(splitInteractionByRow);
729
697
  this.splitEventResize = internal$1.memoize(splitInteractionByRow);
730
- this.rowRefs = new internal$1.RefMap();
698
+ // internal
699
+ this.rowHeightRefMap = new internal$1.RefMap((height, key) => {
700
+ // HACKy way of syncing RefMap results with prop
701
+ const { rowHeightRefMap } = this.props;
702
+ if (rowHeightRefMap) {
703
+ rowHeightRefMap.handleValue(height, key);
704
+ }
705
+ });
706
+ this.handleRootEl = (rootEl) => {
707
+ this.rootEl = rootEl;
708
+ if (rootEl) {
709
+ this.context.registerInteractiveComponent(this, {
710
+ el: rootEl,
711
+ isHitComboAllowed: this.props.isHitComboAllowed,
712
+ });
713
+ }
714
+ else {
715
+ this.context.unregisterInteractiveComponent(this);
716
+ }
717
+ };
731
718
  }
732
719
  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);
720
+ let { props, state, context, rowHeightRefMap } = this;
721
+ let { options } = context;
722
+ let rowCnt = props.cellRows.length;
737
723
  let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt);
724
+ let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);
725
+ let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt);
738
726
  let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt);
739
727
  let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt);
740
728
  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 })))))));
729
+ // whether the ROW should expand in height
730
+ // (not to be confused with whether the fg events within the row should be molded by height of row)
731
+ let isHeightAuto = internal$1.getIsHeightAuto(options);
732
+ // maintain at least aspectRatio for cells?
733
+ let rowMinHeight = (state.width != null && (rowCnt >= 7 || // TODO: better way to infer if across single-month boundary
734
+ isHeightAuto)) ? state.width / context.options.aspectRatio / 6 // okay to hardcode 6 (weeks) ?
735
+ : null;
736
+ return (preact.createElement("div", { className: 'fc-grow fc-flex-column', style: { width: props.width }, ref: this.handleRootEl }, props.cellRows.map((cells, row) => (preact.createElement(DayGridRow, { key: cells[0].key, dateProfile: props.dateProfile, todayRange: props.todayRange, cells: cells, showDayNumbers: rowCnt > 1, showWeekNumbers: options.weekNumbers, forPrint: props.forPrint, compact: state.width != null && (state.width / cells.length) < COMPACT_CELL_WIDTH,
737
+ // if not auto-height, distribute height of container somewhat evently to rows
738
+ // (treat all as zero, distribute height, then ensure min-heights -- the inner content height)
739
+ className: isHeightAuto ? '' : 'fc-grow fc-basis0',
740
+ // content
741
+ 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: options.dayMaxEvents, dayMaxEventRows: options.dayMaxEventRows,
742
+ // dimensions
743
+ colWidth: props.colWidth, minHeight: rowMinHeight,
744
+ // refs
745
+ heightRef: rowHeightRefMap.createRef(cells[0].key) })))));
750
746
  }
751
747
  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
- }
748
+ this.detachWidth = internal$1.watchWidth(this.rootEl, (width) => {
749
+ this.setState({ width });
750
+ });
772
751
  }
773
752
  componentWillUnmount() {
774
- if (this.rootEl) {
775
- this.context.unregisterInteractiveComponent(this);
776
- this.rootEl = null;
777
- }
753
+ this.detachWidth();
778
754
  }
779
755
  // 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 };
756
+ // -----------------------------------------------------------------------------------------------
757
+ queryHit(positionLeft, positionTop, elWidth) {
758
+ const { props, context } = this;
759
+ const colCnt = props.cellRows[0].length;
760
+ const { col, left, right } = computeColFromPosition(positionLeft, elWidth, props.colWidth, colCnt, context.isRtl);
761
+ const { row, top, bottom } = computeRowFromPosition(positionTop, props.cellRows, this.rowHeightRefMap.current);
762
+ const cell = props.cellRows[row][col];
763
+ const cellStartDate = cell.date;
764
+ const cellEndDate = internal$1.addDays(cellStartDate, 1);
765
+ return {
766
+ dateProfile: props.dateProfile,
767
+ dateSpan: Object.assign({ range: {
768
+ start: cellStartDate,
769
+ end: cellEndDate,
770
+ }, allDay: true }, cell.extraDateSpan),
771
+ // HACK. TODO: This is expensive to do every hit-query
772
+ dayEl: getCellEl(getRowEl(this.rootEl, row), col),
773
+ rect: {
774
+ left,
775
+ right,
776
+ top,
777
+ bottom,
778
+ },
779
+ layer: 0,
780
+ };
816
781
  }
817
782
  }
783
+ // Utils
784
+ // -------------------------------------------------------------------------------------------------
818
785
  function isSegAllDay(seg) {
819
786
  return seg.eventRange.def.allDay;
820
787
  }
821
788
 
822
- class Table extends internal$1.DateComponent {
789
+ class HeaderRow extends internal$1.BaseComponent {
790
+ render() {
791
+ const { props } = this;
792
+ return (preact.createElement("div", { role: props.cellGroup ? undefined : 'row', className: [
793
+ props.cellGroup ? 'fc-flex-row' : 'fc-row',
794
+ props.className || '',
795
+ ].join(' ') }, props.cells.map((cell) => (preact.createElement(preact.Fragment, { key: props.getHeaderModelKey(cell) }, props.renderHeaderContent(cell, props.tierNum, undefined, // innerHeightRef
796
+ props.colWidth))))));
797
+ }
798
+ }
799
+
800
+ function DayGridHeader(props) {
801
+ return (preact.createElement("div", { className: [
802
+ 'fc-rowgroup',
803
+ 'fc-content-box',
804
+ ...(props.extraClassNames || []),
805
+ ].join(' '), style: {
806
+ width: props.width,
807
+ paddingLeft: props.paddingLeft,
808
+ paddingRight: props.paddingRight,
809
+ } }, props.headerTiers.map((cells, tierNum) => (preact.createElement(HeaderRow, { key: tierNum, tierNum: tierNum, cells: cells, renderHeaderContent: props.renderHeaderContent, getHeaderModelKey: props.getHeaderModelKey, colWidth: props.colWidth })))));
810
+ }
811
+
812
+ class DayGridLayoutNormal extends internal$1.BaseComponent {
823
813
  constructor() {
824
814
  super(...arguments);
825
- this.elRef = preact.createRef();
826
- this.needsScrollReset = false;
815
+ this.handleScroller = (scroller) => {
816
+ internal$1.setRef(this.props.scrollerRef, scroller);
817
+ };
818
+ this.handleLeftScrollbarWidth = (leftScrollbarWidth) => {
819
+ this.setState({ leftScrollbarWidth });
820
+ };
821
+ this.handleRightScrollbarWidth = (rightScrollbarWidth) => {
822
+ this.setState({ rightScrollbarWidth });
823
+ };
827
824
  }
828
825
  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 })))));
826
+ const { props, state, context } = this;
827
+ const { options } = context;
828
+ const verticalScrollbars = !props.forPrint && !internal$1.getIsHeightAuto(options);
829
+ const stickyHeaderDates = !props.forPrint && internal$1.getStickyHeaderDates(options);
830
+ return (preact.createElement(preact.Fragment, null,
831
+ options.dayHeaders && (preact.createElement(DayGridHeader, { headerTiers: props.headerTiers, renderHeaderContent: props.renderHeaderContent, getHeaderModelKey: props.getHeaderModelKey,
832
+ // render hooks
833
+ extraClassNames: [
834
+ 'fc-daygrid-header',
835
+ stickyHeaderDates ? 'fc-sticky-header' : '',
836
+ ],
837
+ // dimensions
838
+ paddingLeft: state.leftScrollbarWidth, paddingRight: state.rightScrollbarWidth })),
839
+ preact.createElement(internal$1.Scroller, { vertical: verticalScrollbars, leftScrollbarWidthRef: this.handleLeftScrollbarWidth, rightScrollbarWidthRef: this.handleRightScrollbarWidth, elClassNames: [
840
+ 'fc-daygrid-body',
841
+ 'fc-rowgroup',
842
+ 'fc-flex-column',
843
+ verticalScrollbars ? 'fc-liquid' : '',
844
+ ], ref: this.handleScroller },
845
+ preact.createElement(DayGridRows // .fc-grow
846
+ , { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed,
847
+ // content
848
+ fgEventSegs: props.fgEventSegs, bgEventSegs: props.bgEventSegs, businessHourSegs: props.businessHourSegs, dateSelectionSegs: props.dateSelectionSegs, eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
849
+ // refs
850
+ rowHeightRefMap: props.rowHeightRefMap }))));
858
851
  }
859
- componentDidMount() {
860
- this.requestScrollReset();
852
+ }
853
+
854
+ class DayGridLayoutPannable extends internal$1.BaseComponent {
855
+ constructor() {
856
+ super(...arguments);
857
+ this.headerScrollerRef = preact.createRef();
858
+ this.bodyScrollerRef = preact.createRef();
859
+ this.footerScrollerRef = preact.createRef();
860
+ // Sizing
861
+ // -----------------------------------------------------------------------------------------------
862
+ this.handleWidth = (width) => {
863
+ this.setState({ width });
864
+ };
865
+ this.handleLeftScrollbarWidth = (leftScrollbarWidth) => {
866
+ this.setState({ leftScrollbarWidth });
867
+ };
868
+ this.handleRightScrollbarWidth = (rightScrollbarWidth) => {
869
+ this.setState({ rightScrollbarWidth });
870
+ };
861
871
  }
862
- componentDidUpdate(prevProps) {
863
- if (prevProps.dateProfile !== this.props.dateProfile) {
864
- this.requestScrollReset();
865
- }
866
- else {
867
- this.flushScrollReset();
868
- }
872
+ render() {
873
+ const { props, state, context } = this;
874
+ const { options } = context;
875
+ const verticalScrollbars = !props.forPrint && !internal$1.getIsHeightAuto(options);
876
+ const stickyHeaderDates = !props.forPrint && internal$1.getStickyHeaderDates(options);
877
+ const stickyFooterScrollbar = !props.forPrint && internal$1.getStickyFooterScrollbar(options);
878
+ const colCnt = props.cellRows[0].length;
879
+ const [canvasWidth, colWidth] = computeColWidth(colCnt, props.dayMinWidth, state.width);
880
+ return (preact.createElement(preact.Fragment, null,
881
+ options.dayHeaders && (preact.createElement(internal$1.Scroller, { horizontal: true, hideScrollbars: true, elClassNames: [
882
+ 'fc-daygrid-header',
883
+ 'fc-rowgroup',
884
+ stickyHeaderDates ? 'fc-sticky-header' : ''
885
+ ], ref: this.headerScrollerRef },
886
+ preact.createElement(DayGridHeader, { headerTiers: props.headerTiers, renderHeaderContent: props.renderHeaderContent, getHeaderModelKey: props.getHeaderModelKey,
887
+ // dimensions
888
+ colWidth: colWidth, width: canvasWidth, paddingLeft: state.leftScrollbarWidth, paddingRight: state.rightScrollbarWidth }))),
889
+ preact.createElement(internal$1.Scroller, { vertical: verticalScrollbars, horizontal: true, hideScrollbars: stickyFooterScrollbar, widthRef: this.handleWidth, leftScrollbarWidthRef: this.handleLeftScrollbarWidth, rightScrollbarWidthRef: this.handleRightScrollbarWidth, elClassNames: [
890
+ 'fc-daygrid-body',
891
+ 'fc-rowgroup',
892
+ 'fc-flex-column',
893
+ verticalScrollbars ? 'fc-liquid' : '',
894
+ ], ref: this.bodyScrollerRef },
895
+ preact.createElement(DayGridRows // .fc-grow
896
+ , { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed,
897
+ // content
898
+ fgEventSegs: props.fgEventSegs, bgEventSegs: props.bgEventSegs, businessHourSegs: props.businessHourSegs, dateSelectionSegs: props.dateSelectionSegs, eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
899
+ // dimensions
900
+ colWidth: colWidth, width: canvasWidth,
901
+ // refs
902
+ rowHeightRefMap: props.rowHeightRefMap })),
903
+ Boolean(stickyFooterScrollbar) && (preact.createElement(internal$1.Scroller, { ref: this.footerScrollerRef, horizontal: true, elClassNames: ['fc-sticky-footer'], elStyle: {
904
+ marginTop: '-1px', // HACK
905
+ } },
906
+ preact.createElement("div", { style: {
907
+ width: canvasWidth,
908
+ height: '1px', // HACK
909
+ } })))));
869
910
  }
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
- }
911
+ // Lifecycle
912
+ // -----------------------------------------------------------------------------------------------
913
+ componentDidMount() {
914
+ // scroller
915
+ const ScrollerSyncer = internal$1.getScrollerSyncerClass(this.context.pluginHooks);
916
+ this.syncedScroller = new ScrollerSyncer(true); // horizontal=true
917
+ internal$1.setRef(this.props.scrollerRef, this.syncedScroller);
918
+ this.updateSyncedScroller();
888
919
  }
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...
920
+ componentDidUpdate() {
921
+ // scroller
922
+ this.updateSyncedScroller();
895
923
  }
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
924
+ componentWillUnmount() {
925
+ // scroller
926
+ this.syncedScroller.destroy();
927
+ }
928
+ // Scrolling
929
+ // -----------------------------------------------------------------------------------------------
930
+ updateSyncedScroller() {
931
+ this.syncedScroller.handleChildren([
932
+ this.headerScrollerRef.current,
933
+ this.bodyScrollerRef.current,
934
+ this.footerScrollerRef.current,
935
+ ]);
899
936
  }
900
- return el;
901
937
  }
902
938
 
903
- class DayTableSlicer extends internal$1.Slicer {
939
+ class DayGridLayout extends internal$1.BaseComponent {
904
940
  constructor() {
905
941
  super(...arguments);
906
- this.forceDayIfListItem = true;
942
+ // ref
943
+ this.scrollerRef = preact.createRef();
944
+ this.rowHeightRefMap = new internal$1.RefMap(() => {
945
+ internal$1.afterSize(this.updateScrollY);
946
+ });
947
+ // internal
948
+ this.scrollDate = null;
949
+ this.updateScrollY = () => {
950
+ const rowHeightMap = this.rowHeightRefMap.current;
951
+ const scroller = this.scrollerRef.current;
952
+ // Since updateScrollY is called by rowHeightRefMap, could be called with null during cleanup,
953
+ // and the scroller might not exist
954
+ if (scroller && this.scrollDate) {
955
+ let scrollTop = computeTopFromDate(this.scrollDate, this.props.cellRows, rowHeightMap, 1);
956
+ if (scrollTop != null) {
957
+ if (scrollTop) {
958
+ scrollTop++; // clear top border
959
+ }
960
+ scroller.scrollTo({ y: scrollTop });
961
+ }
962
+ }
963
+ };
964
+ this.clearScroll = () => {
965
+ this.scrollDate = null;
966
+ };
907
967
  }
908
- sliceRange(dateRange, dayTableModel) {
909
- return dayTableModel.sliceRange(dateRange);
968
+ render() {
969
+ const { props, context } = this;
970
+ const { options } = context;
971
+ const commonLayoutProps = Object.assign(Object.assign({}, props), { scrollerRef: this.scrollerRef, rowHeightRefMap: this.rowHeightRefMap });
972
+ return (preact.createElement(internal$1.ViewContainer, { viewSpec: context.viewSpec, elClasses: [props.className, 'fc-flex-column', 'fc-border'] }, options.dayMinWidth ? (preact.createElement(DayGridLayoutPannable, Object.assign({}, commonLayoutProps, { dayMinWidth: options.dayMinWidth }))) : (preact.createElement(DayGridLayoutNormal, Object.assign({}, commonLayoutProps)))));
973
+ }
974
+ // Lifecycle
975
+ // -----------------------------------------------------------------------------------------------
976
+ componentDidMount() {
977
+ this.resetScroll();
978
+ this.scrollerRef.current.addScrollEndListener(this.clearScroll);
979
+ }
980
+ componentDidUpdate(prevProps) {
981
+ if (prevProps.dateProfile !== this.props.dateProfile && this.context.options.scrollTimeReset) {
982
+ this.resetScroll();
983
+ }
984
+ }
985
+ componentWillUnmount() {
986
+ this.scrollerRef.current.removeScrollEndListener(this.clearScroll);
987
+ }
988
+ // Scrolling
989
+ // -----------------------------------------------------------------------------------------------
990
+ resetScroll() {
991
+ this.scrollDate = this.props.dateProfile.currentDate;
992
+ this.updateScrollY();
993
+ // updateScrollX
994
+ const scroller = this.scrollerRef.current;
995
+ scroller.scrollTo({ x: 0 });
910
996
  }
911
997
  }
912
998
 
913
- class DayTable extends internal$1.DateComponent {
999
+ const WEEKDAY_FORMAT = internal$1.createFormatter({ weekday: 'long' });
1000
+ class DayOfWeekHeaderCell extends internal$1.BaseComponent {
914
1001
  constructor() {
915
1002
  super(...arguments);
916
- this.slicer = new DayTableSlicer();
917
- this.tableRef = preact.createRef();
1003
+ // ref
1004
+ this.innerElRef = preact.createRef();
918
1005
  }
919
1006
  render() {
920
1007
  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 })));
1008
+ let { dateEnv, theme, viewApi, options } = context;
1009
+ let date = internal$1.addDays(new Date(259200000), props.dow); // start with Sun, 04 Jan 1970 00:00:00 GMT
1010
+ let dateMeta = {
1011
+ dow: props.dow,
1012
+ isDisabled: false,
1013
+ isFuture: false,
1014
+ isPast: false,
1015
+ isToday: false,
1016
+ isOther: false,
1017
+ };
1018
+ let text = dateEnv.format(date, props.dayHeaderFormat);
1019
+ let renderProps = Object.assign(Object.assign(Object.assign(Object.assign({ date }, dateMeta), { view: viewApi }), props.extraRenderProps), { text });
1020
+ return (preact.createElement(internal$1.ContentContainer, { elTag: 'div', elClasses: [
1021
+ ...internal$1.getDayClassNames(dateMeta, theme),
1022
+ ...(props.extraClassNames || []),
1023
+ 'fc-header-cell',
1024
+ 'fc-cell',
1025
+ props.colWidth != null ? '' : 'fc-liquid',
1026
+ 'fc-flex-column',
1027
+ 'fc-align-center',
1028
+ ], elAttrs: props.extraDataAttrs, elStyle: {
1029
+ width: props.colWidth != null // TODO: DRY
1030
+ ? props.colWidth * (props.colSpan || 1)
1031
+ : undefined,
1032
+ }, renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => (preact.createElement("div", { ref: this.innerElRef, className: [
1033
+ 'fc-flex-column',
1034
+ props.isSticky ? 'fc-sticky-x' : '',
1035
+ ].join(' ') },
1036
+ preact.createElement(InnerContent, { elTag: "a", elClasses: [
1037
+ 'fc-cell-inner',
1038
+ 'fc-padding-sm',
1039
+ ], elAttrs: {
1040
+ 'aria-label': dateEnv.format(date, WEEKDAY_FORMAT),
1041
+ } })))));
1042
+ }
1043
+ componentDidMount() {
1044
+ const innerEl = this.innerElRef.current; // TODO: make dynamic with useEffect
1045
+ // TODO: only attach this if refs props present
1046
+ this.disconectInnerHeight = internal$1.watchHeight(innerEl, (height) => {
1047
+ internal$1.setRef(this.props.innerHeightRef, height);
1048
+ });
1049
+ }
1050
+ componentWillUnmount() {
1051
+ this.disconectInnerHeight();
1052
+ internal$1.setRef(this.props.innerHeightRef, null);
922
1053
  }
923
1054
  }
924
1055
 
925
- class DayTableView extends TableView {
1056
+ function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) {
1057
+ return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt);
1058
+ }
1059
+ // Computes a default column header formatting string if `colFormat` is not explicitly defined
1060
+ function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
1061
+ // if more than one week row, or if there are a lot of columns with not much space,
1062
+ // put just the day numbers will be in each cell
1063
+ if (!datesRepDistinctDays || dayCnt > 10) {
1064
+ return internal$1.createFormatter({ weekday: 'short' }); // "Sat"
1065
+ }
1066
+ if (dayCnt > 1) {
1067
+ return internal$1.createFormatter({ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }); // "Sat 11/12"
1068
+ }
1069
+ return internal$1.createFormatter({ weekday: 'long' }); // "Saturday"
1070
+ }
1071
+
1072
+ class DayGridView extends internal$1.BaseComponent {
926
1073
  constructor() {
927
1074
  super(...arguments);
1075
+ // memo
928
1076
  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
1077
+ this.buildHeaderTiers = internal$1.memoize(buildHeaderTiers);
1078
+ this.createDayHeaderFormatter = internal$1.memoize(createDayHeaderFormatter);
1079
+ // internal
1080
+ this.slicer = new DayTableSlicer();
932
1081
  }
933
1082
  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);
1083
+ const { props, context } = this;
1084
+ const { options } = context;
1085
+ const dayTableModel = this.buildDayTableModel(props.dateProfile, context.dateProfileGenerator);
1086
+ const datesRepDistinctDays = dayTableModel.rowCnt === 1;
1087
+ const headerTiers = this.buildHeaderTiers(dayTableModel.headerDates, datesRepDistinctDays);
1088
+ const slicedProps = this.slicer.sliceProps(props, props.dateProfile, options.nextDayThreshold, context, dayTableModel);
1089
+ const dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dayTableModel.colCnt);
1090
+ return (preact.createElement(internal$1.NowTimer, { unit: "day" }, (nowDate, todayRange) => (preact.createElement(DayGridLayout, { dateProfile: props.dateProfile, todayRange: todayRange, cellRows: dayTableModel.cellRows, forPrint: props.forPrint, className: 'fc-daygrid-view',
1091
+ // header content
1092
+ headerTiers: headerTiers, renderHeaderContent: (model, tier, innerHeightRef, colWidth) => {
1093
+ if (model.date) {
1094
+ return (preact.createElement(DateHeaderCell, Object.assign({}, model, { dateProfile: props.dateProfile, todayRange: todayRange, navLink: dayTableModel.colCnt > 1, dayHeaderFormat: dayHeaderFormat, colSpan: model.colSpan, colWidth: colWidth })));
1095
+ }
1096
+ else {
1097
+ return (preact.createElement(DayOfWeekHeaderCell, Object.assign({}, model, { dayHeaderFormat: dayHeaderFormat, colSpan: model.colSpan, colWidth: colWidth })));
1098
+ }
1099
+ }, getHeaderModelKey: (model) => {
1100
+ // can use model.key???
1101
+ if (model.date) {
1102
+ return model.date.toUTCString();
1103
+ }
1104
+ return model.dow;
1105
+ },
1106
+ // body content
1107
+ fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection }))));
942
1108
  }
943
1109
  }
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
1110
 
949
1111
  class TableDateProfileGenerator extends internal$1.DateProfileGenerator {
950
1112
  // Computes the date range that will be rendered
@@ -984,7 +1146,7 @@ FullCalendar.DayGrid = (function (exports, core, internal$1, preact) {
984
1146
  return { start, end };
985
1147
  }
986
1148
 
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}";
1149
+ var css_248z = ":root{--fc-daygrid-event-dot-width:8px}.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-daygrid-cell.fc-day-today{background-color:var(--fc-today-bg-color)}.fc-daygrid-row-spacious .fc-daygrid-cell-inner{min-height:3em}.fc-daygrid-cell-header{display:flex;flex-direction:row-reverse}.fc-day-other .fc-daygrid-cell-header{opacity:.3}.fc-daygrid-cell-number{padding:4px;position:relative;z-index:4}.fc-daygrid-month-start{font-size:1.1em;font-weight:700}.fc-daygrid-cell-footer{align-items:flex-start;display:flex;flex-direction:column;font-size:.85em;margin:0 2px}.fc-daygrid-row-spacious .fc-daygrid-cell-footer{margin-bottom:1em!important}.fc-daygrid-row-compact .fc-daygrid-cell-footer{align-items:stretch}.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-daygrid-more-link:hover{background-color:rgba(0,0,0,.1)}.fc-daygrid-row-compact .fc-daygrid-more-link{border:1px solid var(--fc-event-border-color);padding:1px}.fc-daygrid-cell .fc-non-business{z-index:1}.fc-daygrid-cell .fc-bg-event{z-index:2}.fc-daygrid-cell .fc-highlight{z-index:3}.fc-more-popover .fc-popover-body{min-width:220px;padding:10px}.fc-daygrid-event{border-radius:3px;font-size:var(--fc-small-font-size);margin-top:1px;z-index:6}.fc-daygrid-event.fc-event-mirror{z-index:7}.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-event .fc-event-time{margin-right:3px}.fc-direction-rtl .fc-daygrid-event .fc-event-time{margin-left:3px}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-start),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-end){border-bottom-left-radius:0;border-left-width:0;border-top-left-radius:0}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-end),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-start){border-bottom-right-radius:0;border-right-width:0;border-top-right-radius:0}.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;direction:row;display:flex;padding:2px 0;position:relative}.fc-daygrid-dot-event.fc-event-mirror,.fc-daygrid-dot-event:hover{background:rgba(0,0,0,.1)}.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-daygrid-dot-event .fc-event-time,.fc-daygrid-dot-event .fc-event-title{overflow:hidden;white-space:nowrap}.fc-daygrid-dot-event .fc-event-title{flex-basis:0;flex-grow:1;font-weight:700;min-width:0}";
988
1150
  internal$1.injectStyles(css_248z);
989
1151
 
990
1152
  var plugin = core.createPlugin({
@@ -992,7 +1154,7 @@ FullCalendar.DayGrid = (function (exports, core, internal$1, preact) {
992
1154
  initialView: 'dayGridMonth',
993
1155
  views: {
994
1156
  dayGrid: {
995
- component: DayTableView,
1157
+ component: DayGridView,
996
1158
  dateProfileGeneratorClass: TableDateProfileGenerator,
997
1159
  },
998
1160
  dayGridDay: {
@@ -1015,17 +1177,58 @@ FullCalendar.DayGrid = (function (exports, core, internal$1, preact) {
1015
1177
  },
1016
1178
  });
1017
1179
 
1180
+ /*
1181
+ TODO: is it even worth doing this "advanced" version?
1182
+ */
1183
+ class HeaderRowAdvanced extends internal$1.BaseComponent {
1184
+ constructor() {
1185
+ super(...arguments);
1186
+ // ref
1187
+ this.innerHeightRefMap = new internal$1.RefMap(() => {
1188
+ internal$1.afterSize(this.handleInnerHeights);
1189
+ });
1190
+ this.handleInnerHeights = () => {
1191
+ const innerHeightMap = this.innerHeightRefMap.current;
1192
+ let max = 0;
1193
+ for (const innerHeight of innerHeightMap.values()) {
1194
+ max = Math.max(max, innerHeight);
1195
+ }
1196
+ if (this.currentInnerHeight !== max) {
1197
+ this.currentInnerHeight = max;
1198
+ internal$1.setRef(this.props.innerHeightRef, max);
1199
+ }
1200
+ };
1201
+ }
1202
+ render() {
1203
+ const { props } = this;
1204
+ return (preact.createElement("div", { role: 'row', className: 'fc-row', style: { height: props.height } }, props.cells.map((cell) => {
1205
+ const key = props.getHeaderModelKey(cell);
1206
+ return (preact.createElement(preact.Fragment, { key: props.getHeaderModelKey(cell) }, props.renderHeaderContent(cell, props.tierNum, this.innerHeightRefMap.createRef(key), // innerHeightRef
1207
+ props.colWidth)));
1208
+ })));
1209
+ }
1210
+ }
1211
+
1018
1212
  var internal = {
1019
1213
  __proto__: null,
1020
- DayTable: DayTable,
1021
1214
  DayTableSlicer: DayTableSlicer,
1022
1215
  TableDateProfileGenerator: TableDateProfileGenerator,
1023
1216
  buildDayTableRenderRange: buildDayTableRenderRange,
1024
- Table: Table,
1025
- TableRows: TableRows,
1026
- TableView: TableView,
1217
+ DayGridView: DayGridView,
1218
+ DateHeaderCell: DateHeaderCell,
1219
+ DayOfWeekHeaderCell: DayOfWeekHeaderCell,
1220
+ HeaderRow: HeaderRow,
1221
+ HeaderRowAdvanced: HeaderRowAdvanced,
1222
+ createDayHeaderFormatter: createDayHeaderFormatter,
1223
+ DayGridLayout: DayGridLayout,
1224
+ DayGridRow: DayGridRow,
1225
+ COMPACT_CELL_WIDTH: COMPACT_CELL_WIDTH,
1226
+ DayGridRows: DayGridRows,
1027
1227
  buildDayTableModel: buildDayTableModel,
1028
- DayGridView: DayTableView
1228
+ computeColWidth: computeColWidth,
1229
+ computeColFromPosition: computeColFromPosition,
1230
+ getRowEl: getRowEl,
1231
+ getCellEl: getCellEl
1029
1232
  };
1030
1233
 
1031
1234
  core.globalPlugins.push(plugin);