@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/index.global.js +580 -621
- package/index.global.min.js +2 -2
- package/internal.cjs +614 -655
- package/internal.d.ts +130 -172
- package/internal.js +611 -653
- package/package.json +2 -2
package/internal.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
|
152
|
-
|
|
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
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
|
236
|
-
|
|
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.
|
|
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, {
|
|
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(
|
|
281
|
-
|
|
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, {
|
|
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
|
|
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.
|
|
315
|
-
this.
|
|
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, {
|
|
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
|
-
},
|
|
332
|
-
|
|
333
|
-
props.
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
createElement(
|
|
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
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
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.
|
|
362
|
-
this
|
|
363
|
-
setRef(
|
|
364
|
-
setRef(
|
|
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
|
-
|
|
376
|
+
Ensures relative order of DayRowEventRange stays consistent with segs
|
|
390
377
|
*/
|
|
391
|
-
function
|
|
392
|
-
|
|
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
|
-
|
|
387
|
+
TODO: move this so @fullcalendar/daygrid
|
|
396
388
|
*/
|
|
397
|
-
function
|
|
398
|
-
|
|
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
|
|
401
|
-
|
|
402
|
-
|
|
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
|
-
|
|
428
|
-
|
|
397
|
+
const colTempWidth = viewportWidth / colCnt;
|
|
398
|
+
if (colTempWidth < colMinWidth) {
|
|
399
|
+
return [colMinWidth * colCnt, colMinWidth];
|
|
429
400
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
|
|
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
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
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
|
|
465
|
+
return { row, top, bottom };
|
|
455
466
|
}
|
|
456
|
-
//
|
|
467
|
+
// Hit Element
|
|
457
468
|
// -------------------------------------------------------------------------------------------------
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
return
|
|
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:
|
|
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.
|
|
505
|
+
this.disconnectHeight = watchHeight(rootEl, (height) => {
|
|
518
506
|
setRef(this.props.heightRef, height);
|
|
519
507
|
});
|
|
520
508
|
}
|
|
521
509
|
componentWillUnmount() {
|
|
522
|
-
this.
|
|
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.
|
|
533
|
-
afterSize(this.
|
|
519
|
+
this.headerHeightRefMap = new RefMap(() => {
|
|
520
|
+
afterSize(this.handleSegPositioning);
|
|
534
521
|
});
|
|
535
|
-
this.
|
|
536
|
-
|
|
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.
|
|
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
|
-
|
|
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,
|
|
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
|
|
589
|
-
const
|
|
590
|
-
|
|
591
|
-
const
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
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:
|
|
602
|
-
|
|
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.
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
632
|
-
}),
|
|
633
|
-
props.showWeekNumbers && (createElement(WeekNumberContainer, {
|
|
634
|
-
|
|
635
|
-
|
|
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
|
|
645
|
-
|
|
646
|
-
const { eventRange } = seg;
|
|
599
|
+
const key = getEventPartKey(seg);
|
|
600
|
+
const { standinFor, eventRange } = seg;
|
|
647
601
|
const { instanceId } = eventRange.instance;
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
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
|
-
|
|
665
|
-
|
|
666
|
-
?
|
|
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
|
|
679
|
-
const
|
|
680
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
769
|
-
let rowMinHeight = (
|
|
770
|
-
|
|
771
|
-
:
|
|
772
|
-
|
|
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:
|
|
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:
|
|
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.
|
|
762
|
+
this.disconnectWidth = watchWidth(this.rootEl, (width) => {
|
|
785
763
|
this.setState({ width });
|
|
786
764
|
});
|
|
787
765
|
}
|
|
788
766
|
componentWillUnmount() {
|
|
789
|
-
this.
|
|
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.
|
|
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
|
|
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:
|
|
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
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
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.
|
|
855
|
-
this.setState({
|
|
900
|
+
this.handleClientWidth = (clientWidth) => {
|
|
901
|
+
this.setState({ clientWidth });
|
|
856
902
|
};
|
|
857
|
-
this.
|
|
858
|
-
this.setState({
|
|
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(
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
//
|
|
874
|
-
|
|
875
|
-
|
|
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.
|
|
899
|
-
this.setState({
|
|
900
|
-
};
|
|
901
|
-
this.handleLeftScrollbarWidth = (leftScrollbarWidth) => {
|
|
902
|
-
this.setState({ leftScrollbarWidth });
|
|
942
|
+
this.handleClientWidth = (clientWidth) => {
|
|
943
|
+
this.setState({ clientWidth });
|
|
903
944
|
};
|
|
904
|
-
this.
|
|
905
|
-
this.setState({
|
|
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.
|
|
956
|
+
const [canvasWidth, colWidth] = computeColWidth(colCnt, props.dayMinWidth, state.clientWidth);
|
|
916
957
|
return (createElement(Fragment, null,
|
|
917
|
-
options.dayHeaders && (createElement(
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
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(
|
|
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,
|
|
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.
|
|
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
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
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
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
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
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
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
|
-
|
|
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 };
|