@fullcalendar/daygrid 7.0.0-beta.1 → 7.0.0-beta.3

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/internal.js CHANGED
@@ -1,8 +1,5 @@
1
- import { injectStyles, Slicer, DateProfileGenerator, addWeeks, addDays, diffWeeks, DaySeriesModel, DayTableModel, fracToCssDim, BaseComponent, getDateMeta, buildNavLinkAttrs, ContentContainer, getDayClassNames, formatDayString, watchHeight, setRef, createFormatter, StandardEvent, buildEventRangeTimeText, EventContainer, getEventRangeAnchorAttrs, MoreLinkContainer, getEventRangeMeta, DateComponent, DayCellContainer, hasCustomDayCellContent, addMs, SegHierarchy, buildEntryKey, intersectSpans, RefMap, afterSize, sortEventSegs, WeekNumberContainer, buildEventRangeKey, BgEvent, renderFill, memoize, getIsHeightAuto, watchWidth, getStickyHeaderDates, Scroller, getStickyFooterScrollbar, getScrollerSyncerClass, ViewContainer, NowTimer } from '@fullcalendar/core/internal.js';
2
- import { createRef, createElement, Fragment, Component } from '@fullcalendar/core/preact.js';
3
-
4
- 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}";
5
- injectStyles(css_248z);
1
+ import { Slicer, createFormatter, getDateMeta, formatDayString, buildNavLinkAttrs, getDayClassName, addDays, getEventKey, BaseComponent, StandardEvent, buildEventRangeTimeText, getEventRangeAnchorAttrs, EventContainer, MoreLinkContainer, joinClassNames, getEventRangeMeta, DateComponent, DayCellContainer, hasCustomDayCellContent, watchSize, isDimsEqual, setRef, addMs, SegHierarchy, DaySeriesModel, DayTableModel, fracToCssDim, watchHeight, RefMap, afterSize, sortEventSegs, WeekNumberContainer, buildEventRangeKey, BgEvent, renderFill, memoize, getIsHeightAuto, watchWidth, ContentContainer, renderText, getStickyHeaderDates, Scroller, getStickyFooterScrollbar, StickyFooterScrollbar, getScrollerSyncerClass, ViewContainer, NowTimer, DateProfileGenerator, addWeeks, diffWeeks, injectStyles } from '@fullcalendar/core/internal.js';
2
+ import { createElement, Fragment, createRef, Component } from '@fullcalendar/core/preact.js';
6
3
 
7
4
  class DayTableSlicer extends Slicer {
8
5
  constructor() {
@@ -14,193 +11,90 @@ class DayTableSlicer extends Slicer {
14
11
  }
15
12
  }
16
13
 
17
- class TableDateProfileGenerator extends DateProfileGenerator {
18
- // Computes the date range that will be rendered
19
- buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
20
- let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay);
21
- let { props } = this;
22
- return buildDayTableRenderRange({
23
- currentRange: renderRange,
24
- snapToWeek: /^(year|month)$/.test(currentRangeUnit),
25
- fixedWeekCount: props.fixedWeekCount,
26
- dateEnv: props.dateEnv,
27
- });
28
- }
29
- }
30
- function buildDayTableRenderRange(props) {
31
- let { dateEnv, currentRange } = props;
32
- let { start, end } = currentRange;
33
- let endOfWeek;
34
- // year and month views should be aligned with weeks. this is already done for week
35
- if (props.snapToWeek) {
36
- start = dateEnv.startOfWeek(start);
37
- // make end-of-week if not already
38
- endOfWeek = dateEnv.startOfWeek(end);
39
- if (endOfWeek.valueOf() !== end.valueOf()) {
40
- end = addWeeks(endOfWeek, 1);
41
- }
42
- }
43
- // ensure 6 weeks
44
- if (props.fixedWeekCount) {
45
- // TODO: instead of these date-math gymnastics (for multimonth view),
46
- // compute dateprofiles of all months, then use start of first and end of last.
47
- let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth(addDays(currentRange.end, -1)));
48
- let rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
49
- diffWeeks(lastMonthRenderStart, end));
50
- end = addWeeks(end, 6 - rowCnt);
51
- }
52
- return { start, end };
53
- }
54
-
55
- function renderInner(renderProps) {
56
- return renderProps.text;
57
- }
58
- function buildDayTableModel(dateProfile, dateProfileGenerator) {
59
- let daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
60
- return new DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
61
- }
62
- function computeColWidth(colCnt, colMinWidth, viewportWidth) {
63
- if (viewportWidth == null) {
64
- return [undefined, undefined];
65
- }
66
- const colTempWidth = viewportWidth / colCnt;
67
- if (colTempWidth < colMinWidth) {
68
- return [colMinWidth * colCnt, colMinWidth];
69
- }
70
- return [viewportWidth, undefined];
71
- }
72
- function buildHeaderTiers(dates, datesRepDistinctDays) {
73
- return [
74
- datesRepDistinctDays
75
- ? dates.map((date) => ({ colSpan: 1, date }))
76
- : dates.map((date) => ({ colSpan: 1, dow: date.getUTCDay() }))
77
- ];
78
- }
79
- // Positioning
14
+ // TODO: converge types with DayTableCell and DayCellContainer (the component) and refineRenderProps
15
+ // the generation of DayTableCell will be distinct (for the BODY cells)
16
+ // but can share some of the same types/utils
17
+ // Date Cells
80
18
  // -------------------------------------------------------------------------------------------------
81
- function computeTopFromDate(date, cellRows, rowHeightMap, adjust = 0) {
82
- let top = 0;
83
- for (const cells of cellRows) {
84
- const start = cells[0].date;
85
- const end = cells[cells.length - 1].date;
86
- const key = start.toISOString();
87
- if (date >= start && date <= end) {
88
- return top;
89
- }
90
- const rowHeight = rowHeightMap.get(key);
91
- if (rowHeight == null) {
92
- return; // denote unknown
93
- }
94
- top += rowHeight + adjust;
95
- }
96
- return top;
97
- }
98
- function computeHorizontalsFromSeg(seg, colWidth, colCnt, isRtl) {
99
- let left;
100
- let right;
101
- let width;
102
- if (colWidth != null) {
103
- width = (seg.lastCol - seg.firstCol + 1) * colWidth;
104
- if (isRtl) {
105
- right = seg.firstCol * colWidth;
106
- }
107
- else {
108
- left = seg.firstCol * colWidth;
109
- }
110
- }
111
- else {
112
- const colWidthFrac = 1 / colCnt;
113
- width = fracToCssDim((seg.lastCol - seg.firstCol + 1) * colWidthFrac);
114
- if (isRtl) {
115
- right = fracToCssDim(seg.firstCol * colWidthFrac);
116
- }
117
- else {
118
- left = fracToCssDim(seg.firstCol * colWidthFrac);
119
- }
120
- }
121
- return { left, right, width };
122
- }
123
- function computeColFromPosition(positionLeft, elWidth, colWidth, colCnt, isRtl) {
124
- const realColWidth = colWidth != null ? colWidth : elWidth / colCnt;
125
- const colFromLeft = Math.floor(positionLeft / realColWidth);
126
- const col = isRtl ? (colCnt - colFromLeft - 1) : colFromLeft;
127
- const left = colFromLeft * realColWidth;
128
- const right = left + realColWidth;
129
- return { col, left, right };
130
- }
131
- function computeRowFromPosition(positionTop, cellRows, rowHeightMap) {
132
- let row = 0;
133
- let top = 0;
134
- let bottom = 0;
135
- for (const cells of cellRows) {
136
- const key = cells[0].key;
137
- top = bottom;
138
- bottom = top + rowHeightMap.get(key);
139
- if (positionTop < bottom) {
140
- break;
141
- }
142
- row++;
143
- }
144
- return { row, top, bottom };
19
+ const WEEKDAY_FORMAT = createFormatter({ weekday: 'long' });
20
+ const firstSunday = new Date(259200000);
21
+ function buildDateRowConfigs(...args) {
22
+ return [buildDateRowConfig(...args)];
145
23
  }
146
- // Hit Element
147
- // -------------------------------------------------------------------------------------------------
148
- function getRowEl(rootEl, row) {
149
- return rootEl.querySelectorAll(':scope > [role=row]')[row];
24
+ /*
25
+ Should this receive resource data attributes?
26
+ Or ResourceApi object itself?
27
+ */
28
+ function buildDateRowConfig(dates, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, // TODO: rename to dateHeaderFormat?
29
+ context, colSpan) {
30
+ return {
31
+ renderConfig: buildDateRenderConfig(context),
32
+ dataConfigs: buildDateDataConfigs(dates, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, context, colSpan)
33
+ };
150
34
  }
151
- function getCellEl(rowEl, col) {
152
- return rowEl.querySelectorAll(':scope > [role=gridcell]')[col];
35
+ function buildDateRenderConfig(context) {
36
+ const { options } = context;
37
+ return {
38
+ generatorName: 'dayHeaderContent',
39
+ customGenerator: options.dayHeaderContent,
40
+ classNameGenerator: options.dayHeaderClassNames,
41
+ didMount: options.dayHeaderDidMount,
42
+ willUnmount: options.dayHeaderWillUnmount,
43
+ };
153
44
  }
154
-
155
- class DateHeaderCell extends BaseComponent {
156
- constructor() {
157
- super(...arguments);
158
- // ref
159
- this.innerElRef = createRef();
160
- }
161
- render() {
162
- let { props, context } = this;
163
- let { dateProfile, date, extraRenderProps, extraDataAttrs } = props;
164
- let { dateEnv, options, theme, viewApi } = context;
165
- let dayMeta = getDateMeta(date, props.todayRange, null, dateProfile);
166
- let text = dateEnv.format(date, props.dayHeaderFormat);
167
- let navLinkAttrs = (!dayMeta.isDisabled && props.navLink)
168
- ? buildNavLinkAttrs(context, date)
169
- : {};
170
- let renderProps = Object.assign(Object.assign(Object.assign({ date: dateEnv.toDate(date), view: viewApi }, extraRenderProps), { text }), dayMeta);
171
- return (createElement(ContentContainer, { elTag: 'div', elClasses: [
172
- ...getDayClassNames(dayMeta, theme),
173
- ...(props.extraClassNames || []),
174
- 'fc-header-cell',
175
- 'fc-cell',
176
- props.colWidth != null ? '' : 'fc-liquid',
177
- 'fc-flex-column',
178
- 'fc-align-center',
179
- ], elAttrs: Object.assign({ 'data-date': !dayMeta.isDisabled ? formatDayString(date) : undefined }, extraDataAttrs), elStyle: {
180
- width: props.colWidth != null // TODO: DRY
181
- ? props.colWidth * (props.colSpan || 1)
182
- : undefined,
183
- }, renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContainer) => (createElement("div", { ref: this.innerElRef, className: [
184
- 'fc-flex-column',
185
- props.isSticky ? 'fc-sticky-x' : '',
186
- ].join(' ') }, !dayMeta.isDisabled && (createElement(InnerContainer, { elTag: "a", elAttrs: navLinkAttrs, elClasses: [
187
- 'fc-cell-inner',
188
- 'fc-padding-sm',
189
- ] }))))));
190
- }
191
- componentDidMount() {
192
- const innerEl = this.innerElRef.current; // TODO: make dynamic with useEffect
193
- // TODO: only attach this if refs props present
194
- this.disconectInnerHeight = watchHeight(innerEl, (height) => {
195
- setRef(this.props.innerHeightRef, height);
45
+ function buildDateDataConfigs(dates, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, // TODO: rename to dateHeaderFormat?
46
+ context, colSpan = 1, keyPrefix = '') {
47
+ const { dateEnv, viewApi, options } = context;
48
+ return datesRepDistinctDays
49
+ ? dates.map((date) => {
50
+ const dateMeta = getDateMeta(date, todayRange, null, dateProfile);
51
+ const text = dateEnv.format(date, dayHeaderFormat);
52
+ const renderProps = Object.assign(Object.assign({}, dateMeta), { date: dateEnv.toDate(date), view: viewApi, text });
53
+ const isNavLink = options.navLinks && !dateMeta.isDisabled;
54
+ return {
55
+ key: keyPrefix + date.toUTCString(),
56
+ renderProps,
57
+ attrs: { 'data-date': !dateMeta.isDisabled ? formatDayString(date) : undefined },
58
+ innerAttrs: isNavLink ? buildNavLinkAttrs(context, date) : {},
59
+ colSpan,
60
+ isNavLink,
61
+ className: getDayClassName(dateMeta),
62
+ };
63
+ })
64
+ : dates.map((date) => {
65
+ const dow = date.getUTCDay();
66
+ const normDate = addDays(firstSunday, dow);
67
+ const dayMeta = {
68
+ dow,
69
+ isDisabled: false,
70
+ isFuture: false,
71
+ isPast: false,
72
+ isToday: false,
73
+ isOther: false,
74
+ };
75
+ const text = dateEnv.format(normDate, dayHeaderFormat);
76
+ const renderProps = Object.assign(Object.assign({}, dayMeta), { date, view: viewApi, text });
77
+ return {
78
+ key: keyPrefix + String(dow),
79
+ renderProps,
80
+ innerAttrs: { 'aria-label': dateEnv.format(normDate, WEEKDAY_FORMAT) },
81
+ colSpan,
82
+ className: getDayClassName(dayMeta),
83
+ };
196
84
  });
197
- }
198
- componentWillUnmount() {
199
- this.disconectInnerHeight();
200
- setRef(this.props.innerHeightRef, null);
201
- }
202
85
  }
203
86
 
87
+ /*
88
+ We need really specific keys because RefMap::createRef() which is then given to heightRef
89
+ unable to change key! As a result, we cannot reuse elements between normal/slice/standin types,
90
+ but that's okay since they render quite differently
91
+ */
92
+ function getEventPartKey(seg) {
93
+ return getEventKey(seg) + ':' + seg.start +
94
+ (seg.standinFor ? ':standin' : seg.isSlice ? ':slice' : '');
95
+ }
96
+ // DayGridRange utils (TODO: move)
97
+ // -------------------------------------------------------------------------------------------------
204
98
  function splitSegsByRow(segs, rowCnt) {
205
99
  const byRow = [];
206
100
  for (let row = 0; row < rowCnt; row++) {
@@ -232,20 +126,8 @@ function splitInteractionByRow(ui, rowCnt) {
232
126
  }
233
127
  return byRow;
234
128
  }
235
- function splitSegsByCol(segs, colCnt) {
236
- let byCol = [];
237
- for (let col = 0; col < colCnt; col++) {
238
- byCol.push([]);
239
- }
240
- for (let seg of segs) {
241
- for (let col = seg.firstCol; col <= seg.lastCol; col++) {
242
- if (seg.firstCol !== col) {
243
- seg = Object.assign(Object.assign({}, seg), { firstCol: col, lastCol: col, isStart: false, isEnd: seg.isEnd && seg.lastCol === col, isStandin: true });
244
- }
245
- byCol[col].push(seg);
246
- }
247
- }
248
- return byCol;
129
+ function sliceSegForCol(seg, col) {
130
+ return Object.assign(Object.assign({}, seg), { start: col, end: col + 1, isStart: seg.isStart && seg.start === col, isEnd: seg.isEnd && seg.end - 1 === col, standinFor: seg });
249
131
  }
250
132
 
251
133
  const DEFAULT_TABLE_EVENT_TIME_FORMAT = createFormatter({
@@ -258,7 +140,7 @@ function hasListItemDisplay(seg) {
258
140
  let { display } = seg.eventRange.ui;
259
141
  return display === 'list-item' || (display === 'auto' &&
260
142
  !seg.eventRange.def.allDay &&
261
- seg.firstCol === seg.lastCol && // can't be multi-day
143
+ (seg.end - seg.start) === 1 && // single-day
262
144
  seg.isStart && // "
263
145
  seg.isEnd // "
264
146
  );
@@ -267,7 +149,7 @@ function hasListItemDisplay(seg) {
267
149
  class DayGridBlockEvent extends BaseComponent {
268
150
  render() {
269
151
  let { props } = this;
270
- return (createElement(StandardEvent, Object.assign({}, props, { elClasses: ['fc-daygrid-event', 'fc-daygrid-block-event', 'fc-h-event'], defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: props.defaultDisplayEventEnd, disableResizing: !props.eventRange.def.allDay })));
152
+ return (createElement(StandardEvent, Object.assign({}, props, { className: 'fc-daygrid-block-event fc-daygrid-event fc-h-event', defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: props.defaultDisplayEventEnd, disableResizing: !props.eventRange.def.allDay })));
271
153
  }
272
154
  }
273
155
 
@@ -277,8 +159,12 @@ class DayGridListEvent extends BaseComponent {
277
159
  let { options } = context;
278
160
  let { eventRange } = props;
279
161
  let timeFormat = options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT;
280
- let timeText = buildEventRangeTimeText(eventRange, timeFormat, context, true, props.defaultDisplayEventEnd);
281
- return (createElement(EventContainer, Object.assign({}, props, { elTag: "a", elClasses: ['fc-daygrid-event', 'fc-daygrid-dot-event'], elAttrs: getEventRangeAnchorAttrs(eventRange, context), defaultGenerator: renderInnerContent, timeText: timeText, isResizing: false, isDateSelecting: false })));
162
+ let timeText = buildEventRangeTimeText(timeFormat, eventRange,
163
+ /* slicedStart = */ undefined,
164
+ /* slicedEnd = */ undefined, props.isStart, props.isEnd, context,
165
+ /* defaultDisplayEventTime = */ true, props.defaultDisplayEventEnd);
166
+ let anchorAttrs = getEventRangeAnchorAttrs(eventRange, context);
167
+ return (createElement(EventContainer, Object.assign({}, props, { tag: anchorAttrs ? 'a' : 'div', attrs: anchorAttrs, className: 'fc-daygrid-dot-event fc-daygrid-event', defaultGenerator: renderInnerContent, timeText: timeText, isResizing: false, isDateSelecting: false })));
282
168
  }
283
169
  }
284
170
  function renderInnerContent(renderProps) {
@@ -291,14 +177,16 @@ function renderInnerContent(renderProps) {
291
177
  class DayGridMoreLink extends BaseComponent {
292
178
  render() {
293
179
  let { props } = this;
294
- return (createElement(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: () => {
180
+ return (createElement(MoreLinkContainer, { className: joinClassNames('fc-daygrid-more-link', props.isBlock
181
+ ? 'fc-daygrid-more-link-block'
182
+ : 'fc-daygrid-more-link-button'), dateProfile: props.dateProfile, todayRange: props.todayRange, allDayDate: props.allDayDate, segs: props.segs, hiddenSegs: props.hiddenSegs, alignElRef: props.alignElRef, alignParentTop: props.alignParentTop, dateSpanProps: props.dateSpanProps, popoverContent: () => {
295
183
  let forcedInvisibleMap = // TODO: more convenient/DRY
296
184
  (props.eventDrag ? props.eventDrag.affectedInstances : null) ||
297
185
  (props.eventResize ? props.eventResize.affectedInstances : null) ||
298
186
  {};
299
187
  return (createElement(Fragment, null, props.segs.map((seg) => {
300
188
  let { eventRange } = seg;
301
- let instanceId = eventRange.instance.instanceId;
189
+ let { instanceId } = eventRange.instance;
302
190
  return (createElement("div", { key: instanceId, style: {
303
191
  visibility: forcedInvisibleMap[instanceId] ? 'hidden' : '',
304
192
  } }, hasListItemDisplay(seg) ? (createElement(DayGridListEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, getEventRangeMeta(eventRange, props.todayRange)))) : (createElement(DayGridBlockEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, getEventRangeMeta(eventRange, props.todayRange))))));
@@ -311,8 +199,8 @@ class DayGridCell extends DateComponent {
311
199
  constructor() {
312
200
  super(...arguments);
313
201
  // ref
314
- this.innerElRef = createRef();
315
- this.headerWrapElRef = createRef();
202
+ this.rootElRef = createRef();
203
+ this.bodyElRef = createRef();
316
204
  }
317
205
  render() {
318
206
  let { props, context } = this;
@@ -320,48 +208,37 @@ class DayGridCell extends DateComponent {
320
208
  // TODO: memoize this
321
209
  const isMonthStart = props.showDayNumber &&
322
210
  shouldDisplayMonthStart(props.date, props.dateProfile.currentRange, dateEnv);
323
- return (createElement(DayCellContainer, { elTag: "div", elClasses: [
324
- 'fc-daygrid-cell',
325
- 'fc-cell',
326
- props.width != null ? '' : 'fc-liquid',
327
- 'fc-flex-column',
328
- ...(props.extraClassNames || []),
329
- ], elAttrs: Object.assign(Object.assign({}, props.extraDataAttrs), { role: 'gridcell' }), elStyle: {
211
+ return (createElement(DayCellContainer, { tag: "div", className: joinClassNames(props.className, 'fc-daygrid-day fc-flex-col', props.borderStart && 'fc-border-s', props.width != null ? '' : 'fc-liquid'), attrs: Object.assign(Object.assign({}, props.attrs), { role: 'gridcell' }), style: {
330
212
  width: props.width
331
- }, extraRenderProps: props.extraRenderProps, defaultGenerator: renderTopInner, date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, isMonthStart: isMonthStart }, (InnerContent, renderProps) => (createElement("div", { ref: this.innerElRef, className: [
332
- 'fc-daygrid-cell-inner',
333
- props.fgLiquidHeight ? 'fc-liquid' : ''
334
- ].join(' ') },
335
- createElement("div", { ref: this.headerWrapElRef, className: "fc-flex-column" }, !renderProps.isDisabled && (props.showDayNumber || hasCustomDayCellContent(options)) && (createElement("div", { className: "fc-daygrid-cell-header" },
336
- createElement(InnerContent, { elTag: "a", elClasses: [
337
- 'fc-daygrid-cell-number',
338
- isMonthStart && 'fc-daygrid-month-start',
339
- ], elAttrs: buildNavLinkAttrs(context, props.date) })))),
340
- createElement("div", { className: "fc-daygrid-cell-main", style: {
341
- height: props.fgLiquidHeight ? '' : props.fgHeight
342
- } }, props.fg),
343
- createElement("div", { className: "fc-daygrid-cell-footer", style: props.fgLiquidHeight
344
- ? { position: 'relative', top: props.fgHeight }
345
- : {} },
346
- 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 })),
347
- props.bg))));
213
+ }, elRef: this.rootElRef, renderProps: props.renderProps, defaultGenerator: renderTopInner, date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, isMonthStart: isMonthStart }, (InnerContent, renderProps) => (createElement(Fragment, null,
214
+ !renderProps.isDisabled && (props.showDayNumber || hasCustomDayCellContent(options)) && (createElement("div", { className: "fc-daygrid-day-header" },
215
+ createElement(InnerContent, { tag: "a", attrs: buildNavLinkAttrs(context, props.date), className: joinClassNames('fc-daygrid-day-number', isMonthStart && 'fc-daygrid-month-start') }))),
216
+ createElement("div", { className: joinClassNames('fc-daygrid-day-body', props.isTall && 'fc-daygrid-day-body-tall', props.fgLiquidHeight ? 'fc-liquid' : 'fc-grow'), ref: this.bodyElRef },
217
+ createElement("div", { className: 'fc-daygrid-day-events', style: { height: props.fgHeight } }, props.fg),
218
+ createElement(DayGridMoreLink, { isBlock: props.isCompact, allDayDate: props.date, segs: props.segs, hiddenSegs: props.hiddenSegs, alignElRef: this.rootElRef, alignParentTop: props.showDayNumber ? '[role=row]' : '.fc-view', dateSpanProps: props.dateSpanProps, dateProfile: props.dateProfile, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange }))))));
348
219
  }
349
220
  componentDidMount() {
350
- const innerEl = this.innerElRef.current; // TODO: make dynamic with useEffect
351
- const headerWrapEl = this.headerWrapElRef.current; // "
352
- // TODO: only attach this if refs props present
353
- this.detachInnerHeight = watchHeight(innerEl, (height) => {
354
- setRef(this.props.innerHeightRef, height);
355
- });
356
- this.detachHeaderHeight = watchHeight(headerWrapEl, (height) => {
357
- setRef(this.props.headerHeightRef, height);
221
+ const bodyEl = this.bodyElRef.current;
222
+ // we want to fire on ANY size change, because we do more advanced stuff
223
+ this.disconnectBodyHeight = watchSize(bodyEl, (_bodyWidth, bodyHeight) => {
224
+ const { props } = this;
225
+ const mainRect = bodyEl.getBoundingClientRect();
226
+ const rootRect = this.rootElRef.current.getBoundingClientRect();
227
+ const headerHeight = mainRect.top - rootRect.top;
228
+ if (!isDimsEqual(this.headerHeight, headerHeight)) {
229
+ this.headerHeight = headerHeight;
230
+ setRef(props.headerHeightRef, headerHeight);
231
+ }
232
+ if (props.fgLiquidHeight) {
233
+ setRef(props.mainHeightRef, bodyHeight);
234
+ }
358
235
  });
359
236
  }
360
237
  componentWillUnmount() {
361
- this.detachInnerHeight();
362
- this.detachHeaderHeight();
363
- setRef(this.props.innerHeightRef, null);
364
- setRef(this.props.headerHeightRef, null);
238
+ this.disconnectBodyHeight();
239
+ const { props } = this;
240
+ setRef(props.headerHeightRef, null);
241
+ setRef(props.mainHeightRef, null);
365
242
  }
366
243
  }
367
244
  // Utils
@@ -385,121 +262,232 @@ function shouldDisplayMonthStart(date, currentRange, dateEnv) {
385
262
  (dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf()));
386
263
  }
387
264
 
265
+ function computeFgSegVerticals(segs, segHeightMap, cells, maxHeight, strictOrder, allowSlicing = true, dayMaxEvents, dayMaxEventRows) {
266
+ let maxCoord;
267
+ let maxDepth;
268
+ let hiddenConsumes;
269
+ if (dayMaxEvents === true || dayMaxEventRows === true) {
270
+ maxCoord = maxHeight;
271
+ hiddenConsumes = true;
272
+ }
273
+ else if (typeof dayMaxEvents === 'number') {
274
+ maxDepth = dayMaxEvents;
275
+ hiddenConsumes = false;
276
+ }
277
+ else if (typeof dayMaxEventRows === 'number') {
278
+ maxDepth = dayMaxEventRows;
279
+ hiddenConsumes = true;
280
+ }
281
+ // NOTE: visibleSegsMap and hiddenSegMap map NEVER overlap for a given event
282
+ // once a seg has a height, the combined potentially-sliced segs will comprise the entire span of the seg
283
+ // if a seg does not have a height yet, it won't be inserted into either visibleSegsMap/hiddenSegMap
284
+ const visibleSegMap = new Map();
285
+ const hiddenSegMap = new Map();
286
+ const segTops = new Map();
287
+ const isSlicedMap = new Map();
288
+ let hierarchy = new SegHierarchy(segs, (seg) => segHeightMap.get(getEventPartKey(seg)), strictOrder, maxCoord, maxDepth, hiddenConsumes, allowSlicing);
289
+ hierarchy.traverseSegs((seg, segTop) => {
290
+ addToSegMap(visibleSegMap, seg);
291
+ segTops.set(getEventPartKey(seg), segTop);
292
+ if (seg.isSlice) {
293
+ isSlicedMap.set(seg.eventRange, true);
294
+ }
295
+ });
296
+ for (const hiddenSeg of hierarchy.hiddenSegs) {
297
+ addToSegMap(hiddenSegMap, hiddenSeg); // hidden main segs
298
+ }
299
+ // recompute tops while considering slices
300
+ // portions of these slices might be added to hiddenSegMap
301
+ if (isSlicedMap.size) {
302
+ segTops.clear();
303
+ hierarchy = new SegHierarchy(compileSegMap(segs, visibleSegMap), (seg) => segHeightMap.get(getEventPartKey(seg)), strictOrder, maxCoord, maxDepth, hiddenConsumes);
304
+ hierarchy.traverseSegs((seg, segTop) => {
305
+ segTops.set(getEventPartKey(seg), segTop); // newly-hidden main segs and slices
306
+ });
307
+ for (const hiddenSeg of hierarchy.hiddenSegs) {
308
+ addToSegMap(hiddenSegMap, hiddenSeg);
309
+ }
310
+ }
311
+ const segsByCol = [];
312
+ const hiddenSegsByCol = [];
313
+ const renderableSegsByCol = [];
314
+ const heightsByCol = [];
315
+ for (let col = 0; col < cells.length; col++) {
316
+ segsByCol.push([]);
317
+ hiddenSegsByCol.push([]);
318
+ renderableSegsByCol.push([]);
319
+ heightsByCol.push(0);
320
+ }
321
+ for (const seg of segs) {
322
+ const { eventRange } = seg;
323
+ const visibleSegs = visibleSegMap.get(eventRange) || [];
324
+ const hiddenSegs = hiddenSegMap.get(eventRange) || [];
325
+ const isSliced = isSlicedMap.get(eventRange) || false;
326
+ // add orig to renderable
327
+ renderableSegsByCol[seg.start].push(seg);
328
+ // add slices to renderable
329
+ if (isSliced) {
330
+ for (const visibleSeg of visibleSegs) {
331
+ renderableSegsByCol[visibleSeg.start].push(visibleSeg);
332
+ }
333
+ }
334
+ // accumulate segsByCol/heightsByCol for visible segs
335
+ for (const visibleSeg of visibleSegs) {
336
+ for (let col = visibleSeg.start; col < visibleSeg.end; col++) {
337
+ const slice = sliceSegForCol(visibleSeg, col);
338
+ segsByCol[col].push(slice);
339
+ }
340
+ const segKey = getEventPartKey(visibleSeg);
341
+ const segTop = segTops.get(segKey);
342
+ if (segTop != null) { // positioned?
343
+ const segHeight = segHeightMap.get(segKey);
344
+ for (let col = visibleSeg.start; col < visibleSeg.end; col++) {
345
+ heightsByCol[col] = Math.max(heightsByCol[col], segTop + segHeight);
346
+ }
347
+ }
348
+ }
349
+ // accumulate segsByCol/hiddenSegsByCol for hidden segs
350
+ for (const hiddenSeg of hiddenSegs) {
351
+ for (let col = hiddenSeg.start; col < hiddenSeg.end; col++) {
352
+ const slice = sliceSegForCol(hiddenSeg, col);
353
+ segsByCol[col].push(slice);
354
+ hiddenSegsByCol[col].push(slice);
355
+ }
356
+ }
357
+ }
358
+ return [
359
+ segsByCol,
360
+ hiddenSegsByCol,
361
+ renderableSegsByCol,
362
+ segTops,
363
+ heightsByCol,
364
+ ];
365
+ }
366
+ // Utils
367
+ // -------------------------------------------------------------------------------------------------
368
+ function addToSegMap(map, seg) {
369
+ let list = map.get(seg.eventRange);
370
+ if (!list) {
371
+ map.set(seg.eventRange, list = []);
372
+ }
373
+ list.push(seg);
374
+ }
388
375
  /*
389
- Unique per-START-column, good for cataloging by top
376
+ Ensures relative order of DayRowEventRange stays consistent with segs
390
377
  */
391
- function getSegStartId(seg) {
392
- return seg.eventRange.instance.instanceId + ':' + seg.firstCol;
378
+ function compileSegMap(segs, segMap) {
379
+ const res = [];
380
+ for (const seg of segs) {
381
+ res.push(...(segMap.get(seg.eventRange) || []));
382
+ }
383
+ return res;
393
384
  }
385
+
394
386
  /*
395
- Unique per-START-and-END-column, good for cataloging by width/height
387
+ TODO: move this so @fullcalendar/daygrid
396
388
  */
397
- function getSegSpanId(seg) {
398
- return getSegStartId(seg) + ':' + seg.lastCol;
389
+ function buildDayTableModel(dateProfile, dateProfileGenerator) {
390
+ let daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
391
+ return new DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
399
392
  }
400
- function computeFgSegVerticals(segs, segHeightMap, // keyed by segSpanId
401
- cells, topOrigin, maxHeight, strictOrder, dayMaxEvents, dayMaxEventRows) {
402
- // initialize column-based arrays
403
- const colCnt = cells.length;
404
- const hiddenSegsByCol = [];
405
- const heightsByCol = [];
406
- for (let col = 0; col < colCnt; col++) {
407
- hiddenSegsByCol.push([]);
408
- heightsByCol.push(0);
409
- }
410
- // create entries to be given to DayGridSegHierarchy
411
- const segEntries = segs.map((seg, index) => ({
412
- index: index,
413
- seg,
414
- span: {
415
- start: seg.firstCol,
416
- end: seg.lastCol + 1,
417
- },
418
- }));
419
- // configure hierarchy position-generator
420
- let hierarchy = new DayGridSegHierarchy((segEntry) => (segHeightMap.get(getSegSpanId(segs[segEntry.index]))));
421
- hierarchy.allowReslicing = false;
422
- hierarchy.strictOrder = strictOrder;
423
- if (dayMaxEvents === true || dayMaxEventRows === true) {
424
- hierarchy.maxCoord = maxHeight;
425
- hierarchy.hiddenConsumes = true;
393
+ function computeColWidth(colCnt, colMinWidth, viewportWidth) {
394
+ if (viewportWidth == null) {
395
+ return [undefined, undefined];
426
396
  }
427
- else if (typeof dayMaxEvents === 'number') {
428
- hierarchy.maxStackCnt = dayMaxEvents;
397
+ const colTempWidth = viewportWidth / colCnt;
398
+ if (colTempWidth < colMinWidth) {
399
+ return [colMinWidth * colCnt, colMinWidth];
429
400
  }
430
- else if (typeof dayMaxEventRows === 'number') {
431
- hierarchy.maxStackCnt = dayMaxEventRows;
432
- hierarchy.hiddenConsumes = true;
433
- }
434
- // compile segTops & heightsByCol
435
- const hiddenSegEntries = hierarchy.addSegs(segEntries);
436
- const segRects = hierarchy.toRects();
437
- const segTops = {};
438
- for (const segRect of segRects) {
439
- const seg = segs[segRect.index];
440
- segTops[getSegStartId(seg)] = topOrigin + segRect.levelCoord;
441
- let { start: col, end: endCol } = segRect.span;
442
- for (; col < endCol; col++) {
443
- heightsByCol[col] = Math.max(heightsByCol[col], segRect.levelCoord + segRect.thickness);
401
+ return [viewportWidth, undefined];
402
+ }
403
+ // Positioning
404
+ // -------------------------------------------------------------------------------------------------
405
+ function computeTopFromDate(date, cellRows, rowHeightMap, adjust = 0) {
406
+ let top = 0;
407
+ for (const cells of cellRows) {
408
+ const start = cells[0].date;
409
+ const end = cells[cells.length - 1].date;
410
+ const key = start.toISOString();
411
+ if (date >= start && date <= end) {
412
+ return top;
444
413
  }
414
+ const rowHeight = rowHeightMap.get(key);
415
+ if (rowHeight == null) {
416
+ return; // denote unknown
417
+ }
418
+ top += rowHeight + adjust;
419
+ }
420
+ return top;
421
+ }
422
+ /*
423
+ FYI, `width` is not dependable for aligning completely to farside
424
+ */
425
+ function computeHorizontalsFromSeg(seg, colWidth, colCnt, isRtl) {
426
+ let fromStart;
427
+ let fromEnd;
428
+ if (colWidth != null) {
429
+ fromStart = seg.start * colWidth;
430
+ fromEnd = (colCnt - seg.end) * colWidth;
431
+ }
432
+ else {
433
+ const colWidthFrac = 1 / colCnt;
434
+ fromStart = fracToCssDim(seg.start * colWidthFrac);
435
+ fromEnd = fracToCssDim(1 - seg.end * colWidthFrac);
436
+ }
437
+ if (isRtl) {
438
+ return { right: fromStart, left: fromEnd };
439
+ }
440
+ else {
441
+ return { left: fromStart, right: fromEnd };
445
442
  }
446
- // compile # of invisible segs per-column
447
- for (const hiddenSegEntry of hiddenSegEntries) {
448
- const { span } = hiddenSegEntry;
449
- const hiddenSeg = segs[hiddenSegEntry.index];
450
- for (let col = span.start; col < span.end; col++) {
451
- hiddenSegsByCol[col].push(hiddenSeg);
443
+ }
444
+ function computeColFromPosition(positionLeft, elWidth, colWidth, colCnt, isRtl) {
445
+ const realColWidth = colWidth != null ? colWidth : elWidth / colCnt;
446
+ const colFromLeft = Math.floor(positionLeft / realColWidth);
447
+ const col = isRtl ? (colCnt - colFromLeft - 1) : colFromLeft;
448
+ const left = colFromLeft * realColWidth;
449
+ const right = left + realColWidth;
450
+ return { col, left, right };
451
+ }
452
+ function computeRowFromPosition(positionTop, cellRows, rowHeightMap) {
453
+ let row = 0;
454
+ let top = 0;
455
+ let bottom = 0;
456
+ for (const cells of cellRows) {
457
+ const key = cells[0].key;
458
+ top = bottom;
459
+ bottom = top + rowHeightMap.get(key);
460
+ if (positionTop < bottom) {
461
+ break;
452
462
  }
463
+ row++;
453
464
  }
454
- return [segTops, heightsByCol, hiddenSegsByCol];
465
+ return { row, top, bottom };
455
466
  }
456
- // DayGridSegHierarchy
467
+ // Hit Element
457
468
  // -------------------------------------------------------------------------------------------------
458
- class DayGridSegHierarchy extends SegHierarchy {
459
- constructor() {
460
- super(...arguments);
461
- // config
462
- this.hiddenConsumes = false;
463
- // allows us to keep hidden entries in the hierarchy so they take up space
464
- this.forceHidden = {};
465
- }
466
- addSegs(segInputs) {
467
- const hiddenSegs = super.addSegs(segInputs);
468
- const { entriesByLevel } = this;
469
- const excludeHidden = (entry) => !this.forceHidden[buildEntryKey(entry)];
470
- // remove the forced-hidden segs
471
- for (let level = 0; level < entriesByLevel.length; level += 1) {
472
- entriesByLevel[level] = entriesByLevel[level].filter(excludeHidden);
473
- }
474
- return hiddenSegs;
475
- }
476
- handleInvalidInsertion(insertion, entry, hiddenEntries) {
477
- const { entriesByLevel, forceHidden } = this;
478
- const { touchingEntry, touchingLevel, touchingLateral } = insertion;
479
- // the entry that the new insertion is touching must be hidden
480
- if (this.hiddenConsumes && touchingEntry) {
481
- const touchingEntryId = buildEntryKey(touchingEntry);
482
- if (!forceHidden[touchingEntryId]) {
483
- if (this.allowReslicing) {
484
- // split up the touchingEntry, reinsert it
485
- const hiddenEntry = Object.assign(Object.assign({}, touchingEntry), { span: intersectSpans(touchingEntry.span, entry.span) });
486
- // reinsert the area that turned into a "more" link (so no other entries try to
487
- // occupy the space) but mark it forced-hidden
488
- const hiddenEntryId = buildEntryKey(hiddenEntry);
489
- forceHidden[hiddenEntryId] = true;
490
- entriesByLevel[touchingLevel][touchingLateral] = hiddenEntry;
491
- hiddenEntries.push(hiddenEntry);
492
- this.splitEntry(touchingEntry, entry, hiddenEntries);
493
- }
494
- else {
495
- forceHidden[touchingEntryId] = true;
496
- hiddenEntries.push(touchingEntry);
497
- }
498
- }
499
- }
500
- // will try to reslice...
501
- super.handleInvalidInsertion(insertion, entry, hiddenEntries);
469
+ function getRowEl(rootEl, row) {
470
+ return rootEl.querySelectorAll(':scope > [role=row]')[row];
471
+ }
472
+ function getCellEl(rowEl, col) {
473
+ return rowEl.querySelectorAll(':scope > [role=gridcell]')[col];
474
+ }
475
+ // Header Formatting
476
+ // -------------------------------------------------------------------------------------------------
477
+ function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) {
478
+ return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt);
479
+ }
480
+ // Computes a default column header formatting string if `colFormat` is not explicitly defined
481
+ function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
482
+ // if more than one week row, or if there are a lot of columns with not much space,
483
+ // put just the day numbers will be in each cell
484
+ if (!datesRepDistinctDays || dayCnt > 10) {
485
+ return createFormatter({ weekday: 'short' }); // "Sat"
502
486
  }
487
+ if (dayCnt > 1) {
488
+ return createFormatter({ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }); // "Sat 11/12"
489
+ }
490
+ return createFormatter({ weekday: 'long' }); // "Saturday"
503
491
  }
504
492
 
505
493
  class DayGridEventHarness extends Component {
@@ -510,129 +498,96 @@ class DayGridEventHarness extends Component {
510
498
  }
511
499
  render() {
512
500
  const { props } = this;
513
- return (createElement("div", { className: "fc-abs", style: props.style, ref: this.rootElRef }, props.children));
501
+ return (createElement("div", { className: joinClassNames(props.className, 'fc-abs'), style: props.style, ref: this.rootElRef }, props.children));
514
502
  }
515
503
  componentDidMount() {
516
504
  const rootEl = this.rootElRef.current; // TODO: make dynamic with useEffect
517
- this.detachHeight = watchHeight(rootEl, (height) => {
505
+ this.disconnectHeight = watchHeight(rootEl, (height) => {
518
506
  setRef(this.props.heightRef, height);
519
507
  });
520
508
  }
521
509
  componentWillUnmount() {
522
- this.detachHeight();
510
+ this.disconnectHeight();
523
511
  setRef(this.props.heightRef, null);
524
512
  }
525
513
  }
526
514
 
527
515
  const DEFAULT_WEEK_NUM_FORMAT = createFormatter({ week: 'narrow' });
528
- const COMPACT_CELL_WIDTH = 80;
529
516
  class DayGridRow extends BaseComponent {
530
517
  constructor() {
531
518
  super(...arguments);
532
- this.cellInnerHeightRefMap = new RefMap(() => {
533
- afterSize(this.handleInnerHeights);
519
+ this.headerHeightRefMap = new RefMap(() => {
520
+ afterSize(this.handleSegPositioning);
534
521
  });
535
- this.cellHeaderHeightRefMap = new RefMap(() => {
536
- afterSize(this.handleHeaderHeights);
522
+ this.mainHeightRefMap = new RefMap(() => {
523
+ const fgLiquidHeight = this.props.dayMaxEvents === true || this.props.dayMaxEventRows === true;
524
+ if (fgLiquidHeight) {
525
+ afterSize(this.handleSegPositioning);
526
+ }
537
527
  });
538
528
  this.segHeightRefMap = new RefMap(() => {
539
- afterSize(this.handleSegHeights);
529
+ afterSize(this.handleSegPositioning);
540
530
  });
541
531
  this.handleRootEl = (rootEl) => {
542
532
  this.rootEl = rootEl;
543
533
  setRef(this.props.rootElRef, rootEl);
544
534
  };
545
- // Sizing
546
- // -----------------------------------------------------------------------------------------------
547
- this.handleHeaderHeights = () => {
548
- const cellHeaderHeightMap = this.cellHeaderHeightRefMap.current;
549
- let max = 0;
550
- for (const height of cellHeaderHeightMap.values()) {
551
- max = Math.max(max, height);
552
- }
553
- if (this.state.headerHeight !== max) {
554
- this.setState({ headerHeight: max });
555
- }
556
- };
557
- this.handleInnerHeights = () => {
558
- const { props } = this;
559
- const fgLiquidHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
560
- const cellInnerHeightMap = this.cellInnerHeightRefMap.current;
561
- let max = 0;
562
- for (const height of cellInnerHeightMap.values()) {
563
- max = Math.max(max, height);
564
- }
565
- if (fgLiquidHeight) {
566
- if (this.state.innerHeight !== max) {
567
- this.setState({ innerHeight: max }); // will trigger event rerender
568
- }
569
- }
570
- else {
571
- setRef(props.innerHeightRef, max);
572
- }
573
- };
574
- this.handleSegHeights = () => {
575
- this.setState({ segHeightRev: this.segHeightRefMap.rev }); // will trigger event rerender
535
+ this.handleSegPositioning = () => {
536
+ this.forceUpdate();
576
537
  };
577
538
  }
578
539
  render() {
579
- const { props, state, context, cellInnerHeightRefMap, cellHeaderHeightRefMap } = this;
540
+ const { props, context, headerHeightRefMap, mainHeightRefMap } = this;
580
541
  const { cells } = props;
581
542
  const { options } = context;
582
543
  const weekDate = props.cells[0].date;
583
- const colCnt = props.cells.length;
584
544
  const fgLiquidHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
585
545
  // TODO: memoize? sort all types of segs?
586
546
  const fgEventSegs = sortEventSegs(props.fgEventSegs, options.eventOrder);
587
547
  // TODO: memoize?
588
- const fgEventSegsByCol = splitSegsByCol(fgEventSegs, colCnt);
589
- const bgEventSegsByCol = splitSegsByCol(props.bgEventSegs, colCnt);
590
- const businessHoursByCol = splitSegsByCol(props.businessHourSegs, colCnt);
591
- const highlightSegsByCol = splitSegsByCol(this.getHighlightSegs(), colCnt); // TODO: doesn't need standins
592
- const mirrorSegsByCol = splitSegsByCol(this.getMirrorSegs(), colCnt); // TODO: doesn't need standins
593
- // TODO: memoize?
594
- const [segTops, heightsByCol, hiddenSegsByCol] = computeFgSegVerticals(fgEventSegs, this.segHeightRefMap.current, cells, state.headerHeight, (fgLiquidHeight && state.innerHeight != null && state.headerHeight != null)
595
- ? state.innerHeight - state.headerHeight
596
- : undefined, options.eventOrderStrict, props.dayMaxEvents, props.dayMaxEventRows);
548
+ const [maxMainTop, minMainHeight] = this.computeFgDims(); // uses headerHeightRefMap/mainHeightRefMap
549
+ const [segsByCol, hiddenSegsByCol, renderableSegsByCol, segTops, simpleHeightsByCol] = computeFgSegVerticals(fgEventSegs, this.segHeightRefMap.current, cells, fgLiquidHeight ? minMainHeight : undefined, // if not defined in first run, will unlimited!?
550
+ options.eventOrderStrict, options.eventSlicing, props.dayMaxEvents, props.dayMaxEventRows);
551
+ const heightsByCol = [];
552
+ if (maxMainTop != null) {
553
+ let col = 0;
554
+ for (const cell of cells) { // uses headerHeightRefMap/maxMainTop/simpleHeightsByCol
555
+ const cellHeaderHeight = headerHeightRefMap.current.get(cell.key);
556
+ const extraFgHeight = maxMainTop - cellHeaderHeight;
557
+ heightsByCol.push(simpleHeightsByCol[col++] + extraFgHeight);
558
+ }
559
+ }
560
+ const highlightSegs = this.getHighlightSegs();
561
+ const mirrorSegs = this.getMirrorSegs();
597
562
  const forcedInvisibleMap = // TODO: more convenient/DRY
598
563
  (props.eventDrag && props.eventDrag.affectedInstances) ||
599
564
  (props.eventResize && props.eventResize.affectedInstances) ||
600
565
  {};
601
- return (createElement("div", { role: props.cellGroup ? undefined : 'row', className: [
602
- 'fc-daygrid-row',
603
- props.forceVSpacing
604
- ? 'fc-daygrid-row-spacious'
605
- : props.compact
606
- ? 'fc-daygrid-row-compact'
607
- : '',
608
- props.cellGroup ? 'fc-flex-row' : 'fc-row',
609
- 'fc-rel',
610
- props.className || '',
611
- ].join(' '), style: {
566
+ return (createElement("div", { role: 'row' // TODO: audit this for all scenarios
567
+ , className: joinClassNames('fc-flex-row fc-rel', props.className), style: {
612
568
  minHeight: props.minHeight,
613
569
  }, ref: this.handleRootEl },
614
- props.cells.map((cell, col) => {
615
- const normalFgNodes = this.renderFgSegs(fgEventSegsByCol[col], segTops, props.todayRange, forcedInvisibleMap);
616
- const mirrorFgNodes = this.renderFgSegs(mirrorSegsByCol[col], segTops, props.todayRange, {}, // forcedInvisibleMap
617
- Boolean(props.eventDrag), Boolean(props.eventResize), false);
618
- return (createElement(DayGridCell, { key: cell.key, dateProfile: props.dateProfile, todayRange: props.todayRange, date: cell.date, showDayNumber: props.showDayNumbers,
570
+ this.renderFillSegs(props.businessHourSegs, 'non-business'),
571
+ this.renderFillSegs(props.bgEventSegs, 'bg-event'),
572
+ this.renderFillSegs(highlightSegs, 'highlight'),
573
+ createElement("div", { className: 'fc-flex-row fc-liquid fc-rel' }, props.cells.map((cell, col) => {
574
+ const normalFgNodes = this.renderFgSegs(maxMainTop, renderableSegsByCol[col], segTops, props.todayRange, forcedInvisibleMap);
575
+ return (createElement(DayGridCell, { key: cell.key, dateProfile: props.dateProfile, todayRange: props.todayRange, date: cell.date, showDayNumber: props.showDayNumbers, isCompact: props.isCompact, isTall: props.isTall, borderStart: Boolean(col),
619
576
  // content
620
- segs: fgEventSegsByCol[col], hiddenSegs: hiddenSegsByCol[col], fgLiquidHeight: fgLiquidHeight, fg: (createElement(Fragment, null,
621
- createElement(Fragment, null, normalFgNodes),
622
- createElement(Fragment, null, mirrorFgNodes))), bg: (createElement(Fragment, null,
623
- this.renderFillSegs(highlightSegsByCol[col], 'highlight'),
624
- this.renderFillSegs(businessHoursByCol[col], 'non-business'),
625
- this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))), eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
577
+ segs: segsByCol[col], hiddenSegs: hiddenSegsByCol[col], fgLiquidHeight: fgLiquidHeight, fg: (createElement(Fragment, null, normalFgNodes)), eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
626
578
  // render hooks
627
- extraRenderProps: cell.extraRenderProps, extraDateSpan: cell.extraDateSpan, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames,
579
+ renderProps: cell.renderProps, dateSpanProps: cell.dateSpanProps, attrs: cell.attrs, className: cell.className,
628
580
  // dimensions
629
581
  fgHeight: heightsByCol[col], width: props.colWidth,
630
582
  // refs
631
- innerHeightRef: cellInnerHeightRefMap.createRef(cell.key), headerHeightRef: cellHeaderHeightRefMap.createRef(cell.key) }));
632
- }),
633
- props.showWeekNumbers && (createElement(WeekNumberContainer, { elTag: "a", elClasses: ['fc-daygrid-week-number'], elAttrs: buildNavLinkAttrs(context, weekDate, 'week'), date: weekDate, defaultFormat: DEFAULT_WEEK_NUM_FORMAT }))));
634
- }
635
- renderFgSegs(segs, segTops, todayRange, forcedInvisibleMap, isDragging, isResizing, isDateSelecting) {
583
+ headerHeightRef: headerHeightRefMap.createRef(cell.key), mainHeightRef: mainHeightRefMap.createRef(cell.key) }));
584
+ })),
585
+ props.showWeekNumbers && (createElement(WeekNumberContainer, { tag: "a", attrs: buildNavLinkAttrs(context, weekDate, 'week'), className: 'fc-daygrid-week-number', date: weekDate, defaultFormat: DEFAULT_WEEK_NUM_FORMAT })),
586
+ this.renderFgSegs(maxMainTop, mirrorSegs, segTops, props.todayRange, {}, // forcedInvisibleMap
587
+ Boolean(props.eventDrag), Boolean(props.eventResize), false)));
588
+ }
589
+ renderFgSegs(headerHeight, segs, segTops, todayRange, forcedInvisibleMap, isDragging, isResizing, isDateSelecting) {
590
+ var _a;
636
591
  const { props, context, segHeightRefMap } = this;
637
592
  const { isRtl } = context;
638
593
  const { colWidth, eventSelection } = props;
@@ -641,30 +596,26 @@ class DayGridRow extends BaseComponent {
641
596
  const isMirror = isDragging || isResizing || isDateSelecting;
642
597
  const nodes = [];
643
598
  for (const seg of segs) {
644
- const { left, right, width } = computeHorizontalsFromSeg(seg, colWidth, colCnt, isRtl);
645
- // TODO: optimize ID creation? all related
646
- const { eventRange } = seg;
599
+ const key = getEventPartKey(seg);
600
+ const { standinFor, eventRange } = seg;
647
601
  const { instanceId } = eventRange.instance;
648
- const segSpanId = getSegSpanId(seg);
649
- const segStartId = getSegStartId(seg);
650
- const top = segTops[segStartId];
651
- const isVisible = !seg.isStandin &&
652
- top != null &&
653
- !forcedInvisibleMap[instanceId];
654
- /*
655
- TODO: is this comment still relevant? vvvvvvvv
656
- known bug: events that are force to be list-item but span multiple days still take up space in later columns
657
- todo: in print view, for multi-day events, don't display title within non-start/end segs
658
- */
659
- nodes.push(createElement(DayGridEventHarness, { key: segSpanId, style: {
660
- visibility: isVisible ? '' : 'hidden',
602
+ if (standinFor) {
603
+ continue;
604
+ }
605
+ const { left, right } = computeHorizontalsFromSeg(seg, colWidth, colCnt, isRtl);
606
+ const localTop = (_a = segTops.get(standinFor ? getEventPartKey(standinFor) : key)) !== null && _a !== void 0 ? _a : (isMirror ? 0 : undefined);
607
+ const top = headerHeight != null && localTop != null
608
+ ? headerHeight + localTop
609
+ : undefined;
610
+ const isInvisible = standinFor || forcedInvisibleMap[instanceId] || top == null;
611
+ nodes.push(createElement(DayGridEventHarness, { key: key, className: seg.start ? 'fc-border-transparent fc-border-s' : '', style: {
612
+ visibility: isInvisible ? 'hidden' : '',
661
613
  top,
662
614
  left,
663
615
  right,
664
- width,
665
- }, heightRef: (isMirror || seg.isStandin)
666
- ? null
667
- : segHeightRefMap.createRef(segSpanId) }, hasListItemDisplay(seg) ? (createElement(DayGridListEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getEventRangeMeta(eventRange, todayRange)))) : (createElement(DayGridBlockEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getEventRangeMeta(eventRange, todayRange))))));
616
+ }, heightRef: (!standinFor && !isMirror)
617
+ ? segHeightRefMap.createRef(key)
618
+ : null }, hasListItemDisplay(seg) ? (createElement(DayGridListEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getEventRangeMeta(eventRange, todayRange)))) : (createElement(DayGridBlockEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getEventRangeMeta(eventRange, todayRange))))));
668
619
  }
669
620
  return nodes;
670
621
  }
@@ -675,17 +626,17 @@ class DayGridRow extends BaseComponent {
675
626
  const colCnt = props.cells.length;
676
627
  const nodes = [];
677
628
  for (const seg of segs) {
678
- const { left, right, width } = computeHorizontalsFromSeg(seg, colWidth, colCnt, isRtl);
679
- const isVisible = !seg.isStandin;
680
- nodes.push(createElement("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-fill-y", style: {
629
+ const key = buildEventRangeKey(seg.eventRange); // TODO: use different type of key than fg!?
630
+ const { left, right } = computeHorizontalsFromSeg(seg, colWidth, colCnt, isRtl);
631
+ const isVisible = !seg.standinFor;
632
+ nodes.push(createElement("div", { key: key, className: "fc-fill-y", style: {
681
633
  visibility: isVisible ? '' : 'hidden',
682
634
  left,
683
635
  right,
684
- width,
685
636
  } }, fillType === 'bg-event' ?
686
637
  createElement(BgEvent, Object.assign({ eventRange: seg.eventRange, isStart: seg.isStart, isEnd: seg.isEnd }, getEventRangeMeta(seg.eventRange, todayRange))) : (renderFill(fillType))));
687
638
  }
688
- return createElement(Fragment, {}, ...nodes);
639
+ return createElement(Fragment, {}, ...nodes); // TODO: shouldn't this be an array, so keyed?
689
640
  }
690
641
  // Sizing
691
642
  // -----------------------------------------------------------------------------------------------
@@ -698,9 +649,36 @@ class DayGridRow extends BaseComponent {
698
649
  componentWillUnmount() {
699
650
  this.disconnectHeight();
700
651
  setRef(this.props.heightRef, null);
701
- setRef(this.props.innerHeightRef, null);
702
652
  }
703
- // Utils
653
+ computeFgDims() {
654
+ const { cells } = this.props;
655
+ const headerHeightMap = this.headerHeightRefMap.current;
656
+ const mainHeightMap = this.mainHeightRefMap.current;
657
+ let maxMainTop;
658
+ let minMainBottom;
659
+ for (const cell of cells) {
660
+ const mainTop = headerHeightMap.get(cell.key);
661
+ const mainHeight = mainHeightMap.get(cell.key);
662
+ if (mainTop != null) {
663
+ if (maxMainTop === undefined || mainTop > maxMainTop) {
664
+ maxMainTop = mainTop;
665
+ }
666
+ if (mainHeight != null) {
667
+ const mainBottom = mainTop + mainHeight;
668
+ if (minMainBottom === undefined || mainBottom < minMainBottom) {
669
+ minMainBottom = mainBottom;
670
+ }
671
+ }
672
+ }
673
+ }
674
+ return [
675
+ maxMainTop,
676
+ minMainBottom != null && maxMainTop != null
677
+ ? minMainBottom - maxMainTop
678
+ : undefined,
679
+ ];
680
+ }
681
+ // Internal Utils
704
682
  // -----------------------------------------------------------------------------------------------
705
683
  getMirrorSegs() {
706
684
  let { props } = this;
@@ -753,7 +731,7 @@ class DayGridRows extends DateComponent {
753
731
  };
754
732
  }
755
733
  render() {
756
- let { props, state, context, rowHeightRefMap } = this;
734
+ let { props, context, rowHeightRefMap } = this;
757
735
  let { options } = context;
758
736
  let rowCnt = props.cellRows.length;
759
737
  let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt);
@@ -762,31 +740,31 @@ class DayGridRows extends DateComponent {
762
740
  let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt);
763
741
  let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt);
764
742
  let eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt);
765
- // whether the ROW should expand in height
766
- // (not to be confused with whether the fg events within the row should be molded by height of row)
767
743
  let isHeightAuto = getIsHeightAuto(options);
768
- // maintain at least aspectRatio for cells?
769
- let rowMinHeight = (state.width != null && (rowCnt >= 7 || // TODO: better way to infer if across single-month boundary
770
- isHeightAuto)) ? state.width / context.options.aspectRatio / 6 // okay to hardcode 6 (weeks) ?
771
- : null;
772
- return (createElement("div", { className: 'fc-grow fc-flex-column', style: { width: props.width }, ref: this.handleRootEl }, props.cellRows.map((cells, row) => (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,
744
+ let rowHeightsRedistribute = !props.forPrint && !isHeightAuto;
745
+ let [rowMinHeight, isCompact] = computeRowHeight(props.visibleWidth, rowCnt, isHeightAuto, props.forPrint, options);
746
+ return (createElement("div", { className: joinClassNames(
747
+ // HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
748
+ // https://stackoverflow.com/a/60256345
749
+ !props.forPrint && 'fc-flex-col', props.className), style: { width: props.width }, ref: this.handleRootEl }, props.cellRows.map((cells, row) => (createElement(DayGridRow, { key: cells[0].key, dateProfile: props.dateProfile, todayRange: props.todayRange, cells: cells, showDayNumbers: rowCnt > 1, showWeekNumbers: options.weekNumbers, forPrint: props.forPrint, isCompact: isCompact,
773
750
  // if not auto-height, distribute height of container somewhat evently to rows
774
751
  // (treat all as zero, distribute height, then ensure min-heights -- the inner content height)
775
- className: isHeightAuto ? '' : 'fc-grow fc-basis0',
752
+ className: joinClassNames(rowHeightsRedistribute && 'fc-grow fc-basis0', rowCnt > 1 && 'fc-break-inside-avoid', // don't avoid breaks for single tall row
753
+ row < rowCnt - 1 && 'fc-border-b'),
776
754
  // content
777
- 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,
755
+ fgEventSegs: fgEventSegsByRow[row], bgEventSegs: bgEventSegsByRow[row].filter(isSegAllDay) /* HACK */, businessHourSegs: businessHourSegsByRow[row], dateSelectionSegs: dateSelectionSegsByRow[row], eventSelection: props.eventSelection, eventDrag: eventDragByRow[row], eventResize: eventResizeByRow[row], dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows,
778
756
  // dimensions
779
757
  colWidth: props.colWidth, minHeight: rowMinHeight,
780
758
  // refs
781
759
  heightRef: rowHeightRefMap.createRef(cells[0].key) })))));
782
760
  }
783
761
  componentDidMount() {
784
- this.detachWidth = watchWidth(this.rootEl, (width) => {
762
+ this.disconnectWidth = watchWidth(this.rootEl, (width) => {
785
763
  this.setState({ width });
786
764
  });
787
765
  }
788
766
  componentWillUnmount() {
789
- this.detachWidth();
767
+ this.disconnectWidth();
790
768
  }
791
769
  // Hit System
792
770
  // -----------------------------------------------------------------------------------------------
@@ -803,7 +781,7 @@ class DayGridRows extends DateComponent {
803
781
  dateSpan: Object.assign({ range: {
804
782
  start: cellStartDate,
805
783
  end: cellEndDate,
806
- }, allDay: true }, cell.extraDateSpan),
784
+ }, allDay: true }, cell.dateSpanProps),
807
785
  // HACK. TODO: This is expensive to do every hit-query
808
786
  dayEl: getCellEl(getRowEl(this.rootEl, row), col),
809
787
  rect: {
@@ -821,28 +799,96 @@ class DayGridRows extends DateComponent {
821
799
  function isSegAllDay(seg) {
822
800
  return seg.eventRange.def.allDay;
823
801
  }
802
+ function computeRowHeight(visibleWidth, // should INCLUDE any scrollbar width to avoid oscillation
803
+ rowCnt, isHeightAuto, forPrint, options) {
804
+ if (visibleWidth != null) {
805
+ // ensure a consistent row min-height modelled after a month with 6 rows respecting aspectRatio
806
+ // will result in same minHeight regardless of weekends, dayMinWidth, height:auto
807
+ const rowMinHeight = visibleWidth / options.aspectRatio / 6;
808
+ return [
809
+ forPrint
810
+ // special-case for print, which condenses whole-page width without notifying
811
+ // this is value that looks natural on paper for portrait/landscape
812
+ ? '6em'
813
+ // don't give minHeight when single-month non-auto-height
814
+ // TODO: better way to detect this with DateProfile?
815
+ : (rowCnt > 6 || isHeightAuto)
816
+ ? rowMinHeight
817
+ : undefined,
818
+ // isCompact?: just before most lone +more links hit bottom of cell
819
+ rowMinHeight < 70,
820
+ ];
821
+ }
822
+ return [undefined, false];
823
+ }
824
+
825
+ class DayGridHeaderCell extends BaseComponent {
826
+ constructor() {
827
+ super(...arguments);
828
+ this.handleInnerEl = (innerEl) => {
829
+ if (this.disconectInnerHeight) {
830
+ this.disconectInnerHeight();
831
+ this.disconectInnerHeight = undefined;
832
+ }
833
+ if (innerEl) {
834
+ this.disconectInnerHeight = watchHeight(innerEl, (height) => {
835
+ setRef(this.props.innerHeightRef, height);
836
+ });
837
+ }
838
+ else {
839
+ setRef(this.props.innerHeightRef, null);
840
+ }
841
+ };
842
+ }
843
+ render() {
844
+ const { props } = this;
845
+ const { renderConfig, dataConfig } = props;
846
+ return (createElement(ContentContainer, { tag: 'div', attrs: dataConfig.attrs, className: joinClassNames(dataConfig.className, 'fc-header-cell fc-cell fc-flex-col fc-align-center', props.borderStart && 'fc-border-s', !props.isSticky && 'fc-crop', props.colWidth == null && 'fc-liquid'), style: {
847
+ width: props.colWidth != null
848
+ ? props.colWidth * (dataConfig.colSpan || 1)
849
+ : undefined,
850
+ }, renderProps: dataConfig.renderProps, generatorName: renderConfig.generatorName, customGenerator: renderConfig.customGenerator, defaultGenerator: renderText, classNameGenerator:
851
+ // don't use custom classNames if disabled
852
+ // TODO: make DRY with DayCellContainer
853
+ dataConfig.renderProps.isDisabled ? undefined : renderConfig.classNameGenerator, didMount: renderConfig.didMount, willUnmount: renderConfig.willUnmount }, (InnerContainer) => (!dataConfig.renderProps.isDisabled && (createElement(InnerContainer, { tag: dataConfig.isNavLink ? 'a' : 'div', attrs: dataConfig.innerAttrs, className: joinClassNames('fc-cell-inner fc-flex-col fc-padding-sm', props.isSticky && 'fc-sticky-s'), elRef: this.handleInnerEl })))));
854
+ }
855
+ }
824
856
 
825
- class HeaderRow extends BaseComponent {
857
+ class DayGridHeaderRow extends BaseComponent {
858
+ constructor() {
859
+ super(...arguments);
860
+ // ref
861
+ this.innerHeightRefMap = new RefMap(() => {
862
+ afterSize(this.handleInnerHeights);
863
+ });
864
+ this.handleInnerHeights = () => {
865
+ const innerHeightMap = this.innerHeightRefMap.current;
866
+ let max = 0;
867
+ for (const innerHeight of innerHeightMap.values()) {
868
+ max = Math.max(max, innerHeight);
869
+ }
870
+ if (this.currentInnerHeight !== max) {
871
+ this.currentInnerHeight = max;
872
+ setRef(this.props.innerHeightRef, max);
873
+ }
874
+ };
875
+ }
826
876
  render() {
827
877
  const { props } = this;
828
- return (createElement("div", { role: props.cellGroup ? undefined : 'row', className: [
829
- props.cellGroup ? 'fc-flex-row' : 'fc-row',
830
- props.className || '',
831
- ].join(' ') }, props.cells.map((cell) => (createElement(Fragment, { key: props.getHeaderModelKey(cell) }, props.renderHeaderContent(cell, props.tierNum, undefined, // innerHeightRef
832
- props.colWidth))))));
878
+ return (createElement("div", { role: 'row', className: joinClassNames('fc-flex-row fc-content-box', props.className), style: { height: props.height } }, props.dataConfigs.map((dataConfig, cellI) => (createElement(DayGridHeaderCell, { key: dataConfig.key, renderConfig: props.renderConfig, dataConfig: dataConfig, isSticky: props.isSticky, borderStart: Boolean(cellI), colWidth: props.colWidth, innerHeightRef: props.innerHeightRef })))));
833
879
  }
834
880
  }
835
881
 
836
- function DayGridHeader(props) {
837
- return (createElement("div", { className: [
838
- 'fc-rowgroup',
839
- 'fc-content-box',
840
- ...(props.extraClassNames || []),
841
- ].join(' '), style: {
842
- width: props.width,
843
- paddingLeft: props.paddingLeft,
844
- paddingRight: props.paddingRight,
845
- } }, props.headerTiers.map((cells, tierNum) => (createElement(HeaderRow, { key: tierNum, tierNum: tierNum, cells: cells, renderHeaderContent: props.renderHeaderContent, getHeaderModelKey: props.getHeaderModelKey, colWidth: props.colWidth })))));
882
+ /*
883
+ TODO: kill this class in favor of DayGridHeaderRows?
884
+ */
885
+ class DayGridHeader extends BaseComponent {
886
+ render() {
887
+ const { props } = this;
888
+ return (createElement("div", { className: joinClassNames(props.className, 'fc-flex-col', props.width == null && 'fc-liquid'), style: {
889
+ width: props.width
890
+ } }, props.headerTiers.map((rowConfig, tierNum) => (createElement(DayGridHeaderRow, Object.assign({}, rowConfig, { key: tierNum, className: tierNum ? 'fc-border-t' : '', colWidth: props.colWidth }))))));
891
+ }
846
892
  }
847
893
 
848
894
  class DayGridLayoutNormal extends BaseComponent {
@@ -851,11 +897,11 @@ class DayGridLayoutNormal extends BaseComponent {
851
897
  this.handleScroller = (scroller) => {
852
898
  setRef(this.props.scrollerRef, scroller);
853
899
  };
854
- this.handleLeftScrollbarWidth = (leftScrollbarWidth) => {
855
- this.setState({ leftScrollbarWidth });
900
+ this.handleClientWidth = (clientWidth) => {
901
+ this.setState({ clientWidth });
856
902
  };
857
- this.handleRightScrollbarWidth = (rightScrollbarWidth) => {
858
- this.setState({ rightScrollbarWidth });
903
+ this.handleEndScrollbarWidth = (endScrollbarWidth) => {
904
+ this.setState({ endScrollbarWidth });
859
905
  };
860
906
  }
861
907
  render() {
@@ -864,24 +910,22 @@ class DayGridLayoutNormal extends BaseComponent {
864
910
  const verticalScrollbars = !props.forPrint && !getIsHeightAuto(options);
865
911
  const stickyHeaderDates = !props.forPrint && getStickyHeaderDates(options);
866
912
  return (createElement(Fragment, null,
867
- options.dayHeaders && (createElement(DayGridHeader, { headerTiers: props.headerTiers, renderHeaderContent: props.renderHeaderContent, getHeaderModelKey: props.getHeaderModelKey,
868
- // render hooks
869
- extraClassNames: [
870
- 'fc-daygrid-header',
871
- stickyHeaderDates ? 'fc-sticky-header' : '',
872
- ],
873
- // dimensions
874
- paddingLeft: state.leftScrollbarWidth, paddingRight: state.rightScrollbarWidth })),
875
- createElement(Scroller, { vertical: verticalScrollbars, leftScrollbarWidthRef: this.handleLeftScrollbarWidth, rightScrollbarWidthRef: this.handleRightScrollbarWidth, elClassNames: [
876
- 'fc-daygrid-body',
877
- 'fc-rowgroup',
878
- 'fc-flex-column',
879
- verticalScrollbars ? 'fc-liquid' : '',
880
- ], ref: this.handleScroller },
881
- createElement(DayGridRows // .fc-grow
882
- , { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed,
913
+ options.dayHeaders && (createElement("div", { className: joinClassNames(props.forPrint ? 'fc-print-header' : 'fc-flex-row', // col for print, row for screen
914
+ 'fc-border-b') },
915
+ createElement(DayGridHeader, { headerTiers: props.headerTiers, className: joinClassNames('fc-daygrid-header', stickyHeaderDates && 'fc-table-header-sticky') }),
916
+ Boolean(state.endScrollbarWidth) && (createElement("div", { className: 'fc-border-s fc-filler', style: { minWidth: state.endScrollbarWidth } })))),
917
+ createElement(Scroller, { vertical: verticalScrollbars, clientWidthRef: this.handleClientWidth, endScrollbarWidthRef: this.handleEndScrollbarWidth, className: joinClassNames('fc-daygrid-body',
918
+ // HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
919
+ // https://stackoverflow.com/a/60256345
920
+ !props.forPrint && 'fc-flex-col', verticalScrollbars && 'fc-liquid'), ref: this.handleScroller },
921
+ createElement(DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed, className: 'fc-grow', dayMaxEvents: props.forPrint ? undefined : options.dayMaxEvents, dayMaxEventRows: options.dayMaxEventRows,
883
922
  // content
884
923
  fgEventSegs: props.fgEventSegs, bgEventSegs: props.bgEventSegs, businessHourSegs: props.businessHourSegs, dateSelectionSegs: props.dateSelectionSegs, eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
924
+ // dimensions
925
+ visibleWidth: // TODO: DRY
926
+ state.clientWidth != null && state.endScrollbarWidth != null
927
+ ? state.clientWidth + state.endScrollbarWidth
928
+ : undefined,
885
929
  // refs
886
930
  rowHeightRefMap: props.rowHeightRefMap }))));
887
931
  }
@@ -895,14 +939,11 @@ class DayGridLayoutPannable extends BaseComponent {
895
939
  this.footerScrollerRef = createRef();
896
940
  // Sizing
897
941
  // -----------------------------------------------------------------------------------------------
898
- this.handleWidth = (width) => {
899
- this.setState({ width });
900
- };
901
- this.handleLeftScrollbarWidth = (leftScrollbarWidth) => {
902
- this.setState({ leftScrollbarWidth });
942
+ this.handleClientWidth = (clientWidth) => {
943
+ this.setState({ clientWidth });
903
944
  };
904
- this.handleRightScrollbarWidth = (rightScrollbarWidth) => {
905
- this.setState({ rightScrollbarWidth });
945
+ this.handleEndScrollbarWidth = (endScrollbarWidth) => {
946
+ this.setState({ endScrollbarWidth });
906
947
  };
907
948
  }
908
949
  render() {
@@ -912,37 +953,29 @@ class DayGridLayoutPannable extends BaseComponent {
912
953
  const stickyHeaderDates = !props.forPrint && getStickyHeaderDates(options);
913
954
  const stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(options);
914
955
  const colCnt = props.cellRows[0].length;
915
- const [canvasWidth, colWidth] = computeColWidth(colCnt, props.dayMinWidth, state.width);
956
+ const [canvasWidth, colWidth] = computeColWidth(colCnt, props.dayMinWidth, state.clientWidth);
916
957
  return (createElement(Fragment, null,
917
- options.dayHeaders && (createElement(Scroller, { horizontal: true, hideScrollbars: true, elClassNames: [
918
- 'fc-daygrid-header',
919
- 'fc-rowgroup',
920
- stickyHeaderDates ? 'fc-sticky-header' : ''
921
- ], ref: this.headerScrollerRef },
922
- createElement(DayGridHeader, { headerTiers: props.headerTiers, renderHeaderContent: props.renderHeaderContent, getHeaderModelKey: props.getHeaderModelKey,
923
- // dimensions
924
- colWidth: colWidth, width: canvasWidth, paddingLeft: state.leftScrollbarWidth, paddingRight: state.rightScrollbarWidth }))),
925
- createElement(Scroller, { vertical: verticalScrollbars, horizontal: true, hideScrollbars: stickyFooterScrollbar, widthRef: this.handleWidth, leftScrollbarWidthRef: this.handleLeftScrollbarWidth, rightScrollbarWidthRef: this.handleRightScrollbarWidth, elClassNames: [
926
- 'fc-daygrid-body',
927
- 'fc-rowgroup',
928
- 'fc-flex-column',
929
- verticalScrollbars ? 'fc-liquid' : '',
930
- ], ref: this.bodyScrollerRef },
931
- createElement(DayGridRows // .fc-grow
932
- , { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed,
958
+ options.dayHeaders && (createElement("div", { className: 'fc-print-header' },
959
+ createElement(Scroller, { horizontal: true, hideScrollbars: true, className: joinClassNames('fc-daygrid-header fc-flex-row fc-border-b', stickyHeaderDates && 'fc-table-header-sticky'), ref: this.headerScrollerRef },
960
+ createElement(DayGridHeader, { headerTiers: props.headerTiers, colWidth: colWidth, width: canvasWidth }),
961
+ Boolean(state.endScrollbarWidth) && (createElement("div", { className: 'fc-border-s fc-filler', style: { minWidth: state.endScrollbarWidth } }))))),
962
+ createElement(Scroller, { vertical: verticalScrollbars, horizontal: true, hideScrollbars: stickyFooterScrollbar ||
963
+ props.forPrint // prevents blank space in print-view on Safari
964
+ , className: joinClassNames('fc-daygrid-body',
965
+ // HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
966
+ // https://stackoverflow.com/a/60256345
967
+ !props.forPrint && 'fc-flex-col', verticalScrollbars && 'fc-liquid'), ref: this.bodyScrollerRef, clientWidthRef: this.handleClientWidth, endScrollbarWidthRef: this.handleEndScrollbarWidth },
968
+ createElement(DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed, className: 'fc-grow', dayMaxEvents: props.forPrint ? undefined : options.dayMaxEvents, dayMaxEventRows: options.dayMaxEventRows,
933
969
  // content
934
970
  fgEventSegs: props.fgEventSegs, bgEventSegs: props.bgEventSegs, businessHourSegs: props.businessHourSegs, dateSelectionSegs: props.dateSelectionSegs, eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
935
971
  // dimensions
936
- colWidth: colWidth, width: canvasWidth,
972
+ colWidth: colWidth, width: canvasWidth, visibleWidth: // TODO: DRY
973
+ state.clientWidth != null && state.endScrollbarWidth != null
974
+ ? state.clientWidth + state.endScrollbarWidth
975
+ : undefined,
937
976
  // refs
938
977
  rowHeightRefMap: props.rowHeightRefMap })),
939
- Boolean(stickyFooterScrollbar) && (createElement(Scroller, { ref: this.footerScrollerRef, horizontal: true, elClassNames: ['fc-sticky-footer'], elStyle: {
940
- marginTop: '-1px', // HACK
941
- } },
942
- createElement("div", { style: {
943
- width: canvasWidth,
944
- height: '1px', // HACK
945
- } })))));
978
+ Boolean(stickyFooterScrollbar) && (createElement(StickyFooterScrollbar, { canvasWidth: canvasWidth, scrollerRef: this.footerScrollerRef }))));
946
979
  }
947
980
  // Lifecycle
948
981
  // -----------------------------------------------------------------------------------------------
@@ -1005,7 +1038,7 @@ class DayGridLayout extends BaseComponent {
1005
1038
  const { props, context } = this;
1006
1039
  const { options } = context;
1007
1040
  const commonLayoutProps = Object.assign(Object.assign({}, props), { scrollerRef: this.scrollerRef, rowHeightRefMap: this.rowHeightRefMap });
1008
- return (createElement(ViewContainer, { viewSpec: context.viewSpec, elClasses: [props.className, 'fc-flex-column', 'fc-border'] }, options.dayMinWidth ? (createElement(DayGridLayoutPannable, Object.assign({}, commonLayoutProps, { dayMinWidth: options.dayMinWidth }))) : (createElement(DayGridLayoutNormal, Object.assign({}, commonLayoutProps)))));
1041
+ return (createElement(ViewContainer, { viewSpec: context.viewSpec, className: joinClassNames(props.className, 'fc-print-root fc-border') }, options.dayMinWidth ? (createElement(DayGridLayoutPannable, Object.assign({}, commonLayoutProps, { dayMinWidth: options.dayMinWidth }))) : (createElement(DayGridLayoutNormal, Object.assign({}, commonLayoutProps)))));
1009
1042
  }
1010
1043
  // Lifecycle
1011
1044
  // -----------------------------------------------------------------------------------------------
@@ -1032,85 +1065,12 @@ class DayGridLayout extends BaseComponent {
1032
1065
  }
1033
1066
  }
1034
1067
 
1035
- const WEEKDAY_FORMAT = createFormatter({ weekday: 'long' });
1036
- class DayOfWeekHeaderCell extends BaseComponent {
1037
- constructor() {
1038
- super(...arguments);
1039
- // ref
1040
- this.innerElRef = createRef();
1041
- }
1042
- render() {
1043
- let { props, context } = this;
1044
- let { dateEnv, theme, viewApi, options } = context;
1045
- let date = addDays(new Date(259200000), props.dow); // start with Sun, 04 Jan 1970 00:00:00 GMT
1046
- let dateMeta = {
1047
- dow: props.dow,
1048
- isDisabled: false,
1049
- isFuture: false,
1050
- isPast: false,
1051
- isToday: false,
1052
- isOther: false,
1053
- };
1054
- let text = dateEnv.format(date, props.dayHeaderFormat);
1055
- let renderProps = Object.assign(Object.assign(Object.assign(Object.assign({ date }, dateMeta), { view: viewApi }), props.extraRenderProps), { text });
1056
- return (createElement(ContentContainer, { elTag: 'div', elClasses: [
1057
- ...getDayClassNames(dateMeta, theme),
1058
- ...(props.extraClassNames || []),
1059
- 'fc-header-cell',
1060
- 'fc-cell',
1061
- props.colWidth != null ? '' : 'fc-liquid',
1062
- 'fc-flex-column',
1063
- 'fc-align-center',
1064
- ], elAttrs: props.extraDataAttrs, elStyle: {
1065
- width: props.colWidth != null // TODO: DRY
1066
- ? props.colWidth * (props.colSpan || 1)
1067
- : undefined,
1068
- }, renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => (createElement("div", { ref: this.innerElRef, className: [
1069
- 'fc-flex-column',
1070
- props.isSticky ? 'fc-sticky-x' : '',
1071
- ].join(' ') },
1072
- createElement(InnerContent, { elTag: "a", elClasses: [
1073
- 'fc-cell-inner',
1074
- 'fc-padding-sm',
1075
- ], elAttrs: {
1076
- 'aria-label': dateEnv.format(date, WEEKDAY_FORMAT),
1077
- } })))));
1078
- }
1079
- componentDidMount() {
1080
- const innerEl = this.innerElRef.current; // TODO: make dynamic with useEffect
1081
- // TODO: only attach this if refs props present
1082
- this.disconectInnerHeight = watchHeight(innerEl, (height) => {
1083
- setRef(this.props.innerHeightRef, height);
1084
- });
1085
- }
1086
- componentWillUnmount() {
1087
- this.disconectInnerHeight();
1088
- setRef(this.props.innerHeightRef, null);
1089
- }
1090
- }
1091
-
1092
- function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) {
1093
- return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt);
1094
- }
1095
- // Computes a default column header formatting string if `colFormat` is not explicitly defined
1096
- function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
1097
- // if more than one week row, or if there are a lot of columns with not much space,
1098
- // put just the day numbers will be in each cell
1099
- if (!datesRepDistinctDays || dayCnt > 10) {
1100
- return createFormatter({ weekday: 'short' }); // "Sat"
1101
- }
1102
- if (dayCnt > 1) {
1103
- return createFormatter({ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }); // "Sat 11/12"
1104
- }
1105
- return createFormatter({ weekday: 'long' }); // "Saturday"
1106
- }
1107
-
1108
1068
  class DayGridView extends BaseComponent {
1109
1069
  constructor() {
1110
1070
  super(...arguments);
1111
1071
  // memo
1112
1072
  this.buildDayTableModel = memoize(buildDayTableModel);
1113
- this.buildHeaderTiers = memoize(buildHeaderTiers);
1073
+ this.buildDateRowConfigs = memoize(buildDateRowConfigs);
1114
1074
  this.createDayHeaderFormatter = memoize(createDayHeaderFormatter);
1115
1075
  // internal
1116
1076
  this.slicer = new DayTableSlicer();
@@ -1120,60 +1080,58 @@ class DayGridView extends BaseComponent {
1120
1080
  const { options } = context;
1121
1081
  const dayTableModel = this.buildDayTableModel(props.dateProfile, context.dateProfileGenerator);
1122
1082
  const datesRepDistinctDays = dayTableModel.rowCnt === 1;
1123
- const headerTiers = this.buildHeaderTiers(dayTableModel.headerDates, datesRepDistinctDays);
1124
- const slicedProps = this.slicer.sliceProps(props, props.dateProfile, options.nextDayThreshold, context, dayTableModel);
1125
1083
  const dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dayTableModel.colCnt);
1126
- return (createElement(NowTimer, { unit: "day" }, (nowDate, todayRange) => (createElement(DayGridLayout, { dateProfile: props.dateProfile, todayRange: todayRange, cellRows: dayTableModel.cellRows, forPrint: props.forPrint, className: 'fc-daygrid-view',
1127
- // header content
1128
- headerTiers: headerTiers, renderHeaderContent: (model, tier, innerHeightRef, colWidth) => {
1129
- if (model.date) {
1130
- return (createElement(DateHeaderCell, Object.assign({}, model, { dateProfile: props.dateProfile, todayRange: todayRange, navLink: dayTableModel.colCnt > 1, dayHeaderFormat: dayHeaderFormat, colSpan: model.colSpan, colWidth: colWidth })));
1131
- }
1132
- else {
1133
- return (createElement(DayOfWeekHeaderCell, Object.assign({}, model, { dayHeaderFormat: dayHeaderFormat, colSpan: model.colSpan, colWidth: colWidth })));
1134
- }
1135
- }, getHeaderModelKey: (model) => {
1136
- // can use model.key???
1137
- if (model.date) {
1138
- return model.date.toUTCString();
1139
- }
1140
- return model.dow;
1141
- },
1142
- // body content
1143
- fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection }))));
1084
+ const slicedProps = this.slicer.sliceProps(props, props.dateProfile, options.nextDayThreshold, context, dayTableModel);
1085
+ return (createElement(NowTimer, { unit: "day" }, (nowDate, todayRange) => {
1086
+ const headerTiers = this.buildDateRowConfigs(dayTableModel.headerDates, datesRepDistinctDays, props.dateProfile, todayRange, dayHeaderFormat, context);
1087
+ return (createElement(DayGridLayout, { dateProfile: props.dateProfile, todayRange: todayRange, cellRows: dayTableModel.cellRows, forPrint: props.forPrint, className: 'fc-daygrid',
1088
+ // header content
1089
+ headerTiers: headerTiers,
1090
+ // body content
1091
+ fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection }));
1092
+ }));
1144
1093
  }
1145
1094
  }
1146
1095
 
1147
- /*
1148
- TODO: is it even worth doing this "advanced" version?
1149
- */
1150
- class HeaderRowAdvanced extends BaseComponent {
1151
- constructor() {
1152
- super(...arguments);
1153
- // ref
1154
- this.innerHeightRefMap = new RefMap(() => {
1155
- afterSize(this.handleInnerHeights);
1096
+ class TableDateProfileGenerator extends DateProfileGenerator {
1097
+ // Computes the date range that will be rendered
1098
+ buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
1099
+ let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay);
1100
+ let { props } = this;
1101
+ return buildDayTableRenderRange({
1102
+ currentRange: renderRange,
1103
+ snapToWeek: /^(year|month)$/.test(currentRangeUnit),
1104
+ fixedWeekCount: props.fixedWeekCount,
1105
+ dateEnv: props.dateEnv,
1156
1106
  });
1157
- this.handleInnerHeights = () => {
1158
- const innerHeightMap = this.innerHeightRefMap.current;
1159
- let max = 0;
1160
- for (const innerHeight of innerHeightMap.values()) {
1161
- max = Math.max(max, innerHeight);
1162
- }
1163
- if (this.currentInnerHeight !== max) {
1164
- this.currentInnerHeight = max;
1165
- setRef(this.props.innerHeightRef, max);
1166
- }
1167
- };
1168
1107
  }
1169
- render() {
1170
- const { props } = this;
1171
- return (createElement("div", { role: 'row', className: 'fc-row', style: { height: props.height } }, props.cells.map((cell) => {
1172
- const key = props.getHeaderModelKey(cell);
1173
- return (createElement(Fragment, { key: props.getHeaderModelKey(cell) }, props.renderHeaderContent(cell, props.tierNum, this.innerHeightRefMap.createRef(key), // innerHeightRef
1174
- props.colWidth)));
1175
- })));
1108
+ }
1109
+ function buildDayTableRenderRange(props) {
1110
+ let { dateEnv, currentRange } = props;
1111
+ let { start, end } = currentRange;
1112
+ let endOfWeek;
1113
+ // year and month views should be aligned with weeks. this is already done for week
1114
+ if (props.snapToWeek) {
1115
+ start = dateEnv.startOfWeek(start);
1116
+ // make end-of-week if not already
1117
+ endOfWeek = dateEnv.startOfWeek(end);
1118
+ if (endOfWeek.valueOf() !== end.valueOf()) {
1119
+ end = addWeeks(endOfWeek, 1);
1120
+ }
1121
+ }
1122
+ // ensure 6 weeks
1123
+ if (props.fixedWeekCount) {
1124
+ // TODO: instead of these date-math gymnastics (for multimonth view),
1125
+ // compute dateprofiles of all months, then use start of first and end of last.
1126
+ let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth(addDays(currentRange.end, -1)));
1127
+ let rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
1128
+ diffWeeks(lastMonthRenderStart, end));
1129
+ end = addWeeks(end, 6 - rowCnt);
1176
1130
  }
1131
+ return { start, end };
1177
1132
  }
1178
1133
 
1179
- export { COMPACT_CELL_WIDTH, DateHeaderCell, DayGridLayout, DayGridRow, DayGridRows, DayGridView, DayOfWeekHeaderCell, DayTableSlicer, HeaderRow, HeaderRowAdvanced, TableDateProfileGenerator, buildDayTableModel, buildDayTableRenderRange, computeColFromPosition, computeColWidth, createDayHeaderFormatter, getCellEl, getRowEl };
1134
+ var css_248z = ":root{--fc-daygrid-event-dot-width:8px}.fc-daygrid-day.fc-day-today{background-color:var(--fc-today-bg-color)}.fc-daygrid-day-header{display:flex;flex-direction:row-reverse}.fc-day-other .fc-daygrid-day-header{opacity:.3}.fc-daygrid-day-number{padding:4px;position:relative}.fc-daygrid-month-start{font-size:1.1em;font-weight:700}.fc-daygrid-day-body{display:flex;flex-direction:column;margin-bottom:1px}.fc-daygrid-day-body-tall{margin-bottom:1em;min-height:2em}.fc-daygrid-day-body:only-child{margin-top:2px}.fc-daygrid-more-link{border-radius:3px;cursor:pointer;font-size:var(--fc-small-font-size);margin:0 2px 1px;max-width:100%;overflow:hidden;padding:2px;position:relative;white-space:nowrap}.fc-daygrid-more-link:hover{background-color:rgba(0,0,0,.1)}.fc-daygrid-more-link-button{align-self:flex-start}.fc-daygrid-more-link-block{border:1px solid var(--fc-event-border-color);padding:1px}.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}.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-bottom:1px}.fc-media-print .fc-daygrid-event{overflow:hidden!important;white-space:nowrap!important}.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;z-index:2}.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-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-height:0;min-width:0}";
1135
+ injectStyles(css_248z);
1136
+
1137
+ export { DayGridHeaderRow, DayGridLayout, DayGridRow, DayGridRows, DayGridView, DayTableSlicer, TableDateProfileGenerator, buildDateDataConfigs, buildDateRenderConfig, buildDateRowConfig, buildDateRowConfigs, buildDayTableModel, buildDayTableRenderRange, computeColFromPosition, computeColWidth, computeRowHeight, createDayHeaderFormatter, getCellEl, getRowEl };