@fullcalendar/daygrid 6.1.15 → 7.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.global.js +887 -684
- package/index.global.min.js +2 -2
- package/index.js +2 -2
- package/internal.cjs +921 -718
- package/internal.d.ts +209 -80
- package/internal.js +910 -716
- package/package.json +2 -2
package/internal.cjs
CHANGED
|
@@ -5,128 +5,252 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var internal_cjs = require('@fullcalendar/core/internal.cjs');
|
|
6
6
|
var preact_cjs = require('@fullcalendar/core/preact.cjs');
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class TableView extends internal_cjs.DateComponent {
|
|
8
|
+
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}";
|
|
9
|
+
internal_cjs.injectStyles(css_248z);
|
|
10
|
+
|
|
11
|
+
class DayTableSlicer extends internal_cjs.Slicer {
|
|
13
12
|
constructor() {
|
|
14
13
|
super(...arguments);
|
|
15
|
-
this.
|
|
14
|
+
this.forceDayIfListItem = true;
|
|
16
15
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
sections.push({
|
|
34
|
-
type: 'body',
|
|
35
|
-
key: 'body',
|
|
36
|
-
liquid: true,
|
|
37
|
-
chunk: { content: bodyContent },
|
|
16
|
+
sliceRange(dateRange, dayTableModel) {
|
|
17
|
+
return dayTableModel.sliceRange(dateRange);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class TableDateProfileGenerator extends internal_cjs.DateProfileGenerator {
|
|
22
|
+
// Computes the date range that will be rendered
|
|
23
|
+
buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
|
|
24
|
+
let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay);
|
|
25
|
+
let { props } = this;
|
|
26
|
+
return buildDayTableRenderRange({
|
|
27
|
+
currentRange: renderRange,
|
|
28
|
+
snapToWeek: /^(year|month)$/.test(currentRangeUnit),
|
|
29
|
+
fixedWeekCount: props.fixedWeekCount,
|
|
30
|
+
dateEnv: props.dateEnv,
|
|
38
31
|
});
|
|
39
|
-
return (preact_cjs.createElement(internal_cjs.ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
|
|
40
|
-
preact_cjs.createElement(internal_cjs.SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [] /* TODO: make optional? */, sections: sections })));
|
|
41
32
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
33
|
+
}
|
|
34
|
+
function buildDayTableRenderRange(props) {
|
|
35
|
+
let { dateEnv, currentRange } = props;
|
|
36
|
+
let { start, end } = currentRange;
|
|
37
|
+
let endOfWeek;
|
|
38
|
+
// year and month views should be aligned with weeks. this is already done for week
|
|
39
|
+
if (props.snapToWeek) {
|
|
40
|
+
start = dateEnv.startOfWeek(start);
|
|
41
|
+
// make end-of-week if not already
|
|
42
|
+
endOfWeek = dateEnv.startOfWeek(end);
|
|
43
|
+
if (endOfWeek.valueOf() !== end.valueOf()) {
|
|
44
|
+
end = internal_cjs.addWeeks(endOfWeek, 1);
|
|
46
45
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
46
|
+
}
|
|
47
|
+
// ensure 6 weeks
|
|
48
|
+
if (props.fixedWeekCount) {
|
|
49
|
+
// TODO: instead of these date-math gymnastics (for multimonth view),
|
|
50
|
+
// compute dateprofiles of all months, then use start of first and end of last.
|
|
51
|
+
let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth(internal_cjs.addDays(currentRange.end, -1)));
|
|
52
|
+
let rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
|
|
53
|
+
internal_cjs.diffWeeks(lastMonthRenderStart, end));
|
|
54
|
+
end = internal_cjs.addWeeks(end, 6 - rowCnt);
|
|
55
|
+
}
|
|
56
|
+
return { start, end };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function renderInner(renderProps) {
|
|
60
|
+
return renderProps.text;
|
|
61
|
+
}
|
|
62
|
+
function buildDayTableModel(dateProfile, dateProfileGenerator) {
|
|
63
|
+
let daySeries = new internal_cjs.DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
|
|
64
|
+
return new internal_cjs.DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
|
|
65
|
+
}
|
|
66
|
+
function computeColWidth(colCnt, colMinWidth, viewportWidth) {
|
|
67
|
+
if (viewportWidth == null) {
|
|
68
|
+
return [undefined, undefined];
|
|
69
|
+
}
|
|
70
|
+
const colTempWidth = viewportWidth / colCnt;
|
|
71
|
+
if (colTempWidth < colMinWidth) {
|
|
72
|
+
return [colMinWidth * colCnt, colMinWidth];
|
|
73
|
+
}
|
|
74
|
+
return [viewportWidth, undefined];
|
|
75
|
+
}
|
|
76
|
+
function buildHeaderTiers(dates, datesRepDistinctDays) {
|
|
77
|
+
return [
|
|
78
|
+
datesRepDistinctDays
|
|
79
|
+
? dates.map((date) => ({ colSpan: 1, date }))
|
|
80
|
+
: dates.map((date) => ({ colSpan: 1, dow: date.getUTCDay() }))
|
|
81
|
+
];
|
|
82
|
+
}
|
|
83
|
+
// Positioning
|
|
84
|
+
// -------------------------------------------------------------------------------------------------
|
|
85
|
+
function computeTopFromDate(date, cellRows, rowHeightMap, adjust = 0) {
|
|
86
|
+
let top = 0;
|
|
87
|
+
for (const cells of cellRows) {
|
|
88
|
+
const start = cells[0].date;
|
|
89
|
+
const end = cells[cells.length - 1].date;
|
|
90
|
+
const key = start.toISOString();
|
|
91
|
+
if (date >= start && date <= end) {
|
|
92
|
+
return top;
|
|
63
93
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
liquid: true,
|
|
68
|
-
chunks: [{
|
|
69
|
-
key: 'main',
|
|
70
|
-
content: bodyContent,
|
|
71
|
-
}],
|
|
72
|
-
});
|
|
73
|
-
if (stickyFooterScrollbar) {
|
|
74
|
-
sections.push({
|
|
75
|
-
type: 'footer',
|
|
76
|
-
key: 'footer',
|
|
77
|
-
isSticky: true,
|
|
78
|
-
chunks: [{
|
|
79
|
-
key: 'main',
|
|
80
|
-
content: internal_cjs.renderScrollShim,
|
|
81
|
-
}],
|
|
82
|
-
});
|
|
94
|
+
const rowHeight = rowHeightMap.get(key);
|
|
95
|
+
if (rowHeight == null) {
|
|
96
|
+
return; // denote unknown
|
|
83
97
|
}
|
|
84
|
-
|
|
85
|
-
preact_cjs.createElement(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: props.forPrint, colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }], sections: sections })));
|
|
98
|
+
top += rowHeight + adjust;
|
|
86
99
|
}
|
|
100
|
+
return top;
|
|
101
|
+
}
|
|
102
|
+
function computeHorizontalsFromSeg(seg, colWidth, colCnt, isRtl) {
|
|
103
|
+
let left;
|
|
104
|
+
let right;
|
|
105
|
+
let width;
|
|
106
|
+
if (colWidth != null) {
|
|
107
|
+
width = (seg.lastCol - seg.firstCol + 1) * colWidth;
|
|
108
|
+
if (isRtl) {
|
|
109
|
+
right = seg.firstCol * colWidth;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
left = seg.firstCol * colWidth;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
const colWidthFrac = 1 / colCnt;
|
|
117
|
+
width = internal_cjs.fracToCssDim((seg.lastCol - seg.firstCol + 1) * colWidthFrac);
|
|
118
|
+
if (isRtl) {
|
|
119
|
+
right = internal_cjs.fracToCssDim(seg.firstCol * colWidthFrac);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
left = internal_cjs.fracToCssDim(seg.firstCol * colWidthFrac);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return { left, right, width };
|
|
126
|
+
}
|
|
127
|
+
function computeColFromPosition(positionLeft, elWidth, colWidth, colCnt, isRtl) {
|
|
128
|
+
const realColWidth = colWidth != null ? colWidth : elWidth / colCnt;
|
|
129
|
+
const colFromLeft = Math.floor(positionLeft / realColWidth);
|
|
130
|
+
const col = isRtl ? (colCnt - colFromLeft - 1) : colFromLeft;
|
|
131
|
+
const left = colFromLeft * realColWidth;
|
|
132
|
+
const right = left + realColWidth;
|
|
133
|
+
return { col, left, right };
|
|
134
|
+
}
|
|
135
|
+
function computeRowFromPosition(positionTop, cellRows, rowHeightMap) {
|
|
136
|
+
let row = 0;
|
|
137
|
+
let top = 0;
|
|
138
|
+
let bottom = 0;
|
|
139
|
+
for (const cells of cellRows) {
|
|
140
|
+
const key = cells[0].key;
|
|
141
|
+
top = bottom;
|
|
142
|
+
bottom = top + rowHeightMap.get(key);
|
|
143
|
+
if (positionTop < bottom) {
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
row++;
|
|
147
|
+
}
|
|
148
|
+
return { row, top, bottom };
|
|
149
|
+
}
|
|
150
|
+
// Hit Element
|
|
151
|
+
// -------------------------------------------------------------------------------------------------
|
|
152
|
+
function getRowEl(rootEl, row) {
|
|
153
|
+
return rootEl.querySelectorAll(':scope > [role=row]')[row];
|
|
154
|
+
}
|
|
155
|
+
function getCellEl(rowEl, col) {
|
|
156
|
+
return rowEl.querySelectorAll(':scope > [role=gridcell]')[col];
|
|
87
157
|
}
|
|
88
158
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
159
|
+
class DateHeaderCell extends internal_cjs.BaseComponent {
|
|
160
|
+
constructor() {
|
|
161
|
+
super(...arguments);
|
|
162
|
+
// ref
|
|
163
|
+
this.innerElRef = preact_cjs.createRef();
|
|
93
164
|
}
|
|
94
|
-
|
|
95
|
-
|
|
165
|
+
render() {
|
|
166
|
+
let { props, context } = this;
|
|
167
|
+
let { dateProfile, date, extraRenderProps, extraDataAttrs } = props;
|
|
168
|
+
let { dateEnv, options, theme, viewApi } = context;
|
|
169
|
+
let dayMeta = internal_cjs.getDateMeta(date, props.todayRange, null, dateProfile);
|
|
170
|
+
let text = dateEnv.format(date, props.dayHeaderFormat);
|
|
171
|
+
let navLinkAttrs = (!dayMeta.isDisabled && props.navLink)
|
|
172
|
+
? internal_cjs.buildNavLinkAttrs(context, date)
|
|
173
|
+
: {};
|
|
174
|
+
let renderProps = Object.assign(Object.assign(Object.assign({ date: dateEnv.toDate(date), view: viewApi }, extraRenderProps), { text }), dayMeta);
|
|
175
|
+
return (preact_cjs.createElement(internal_cjs.ContentContainer, { elTag: 'div', elClasses: [
|
|
176
|
+
...internal_cjs.getDayClassNames(dayMeta, theme),
|
|
177
|
+
...(props.extraClassNames || []),
|
|
178
|
+
'fc-header-cell',
|
|
179
|
+
'fc-cell',
|
|
180
|
+
props.colWidth != null ? '' : 'fc-liquid',
|
|
181
|
+
'fc-flex-column',
|
|
182
|
+
'fc-align-center',
|
|
183
|
+
], elAttrs: Object.assign({ 'data-date': !dayMeta.isDisabled ? internal_cjs.formatDayString(date) : undefined }, extraDataAttrs), elStyle: {
|
|
184
|
+
width: props.colWidth != null // TODO: DRY
|
|
185
|
+
? props.colWidth * (props.colSpan || 1)
|
|
186
|
+
: undefined,
|
|
187
|
+
}, renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContainer) => (preact_cjs.createElement("div", { ref: this.innerElRef, className: [
|
|
188
|
+
'fc-flex-column',
|
|
189
|
+
props.isSticky ? 'fc-sticky-x' : '',
|
|
190
|
+
].join(' ') }, !dayMeta.isDisabled && (preact_cjs.createElement(InnerContainer, { elTag: "a", elAttrs: navLinkAttrs, elClasses: [
|
|
191
|
+
'fc-cell-inner',
|
|
192
|
+
'fc-padding-sm',
|
|
193
|
+
] }))))));
|
|
194
|
+
}
|
|
195
|
+
componentDidMount() {
|
|
196
|
+
const innerEl = this.innerElRef.current; // TODO: make dynamic with useEffect
|
|
197
|
+
// TODO: only attach this if refs props present
|
|
198
|
+
this.disconectInnerHeight = internal_cjs.watchHeight(innerEl, (height) => {
|
|
199
|
+
internal_cjs.setRef(this.props.innerHeightRef, height);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
componentWillUnmount() {
|
|
203
|
+
this.disconectInnerHeight();
|
|
204
|
+
internal_cjs.setRef(this.props.innerHeightRef, null);
|
|
96
205
|
}
|
|
97
|
-
return byRow;
|
|
98
206
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
207
|
+
|
|
208
|
+
function splitSegsByRow(segs, rowCnt) {
|
|
209
|
+
const byRow = [];
|
|
210
|
+
for (let row = 0; row < rowCnt; row++) {
|
|
211
|
+
byRow[row] = [];
|
|
103
212
|
}
|
|
104
|
-
for (
|
|
105
|
-
|
|
213
|
+
for (const seg of segs) {
|
|
214
|
+
byRow[seg.row].push(seg);
|
|
106
215
|
}
|
|
107
|
-
return
|
|
216
|
+
return byRow;
|
|
108
217
|
}
|
|
109
218
|
function splitInteractionByRow(ui, rowCnt) {
|
|
110
|
-
|
|
219
|
+
const byRow = [];
|
|
111
220
|
if (!ui) {
|
|
112
|
-
for (let
|
|
113
|
-
byRow[
|
|
221
|
+
for (let row = 0; row < rowCnt; row++) {
|
|
222
|
+
byRow[row] = null;
|
|
114
223
|
}
|
|
115
224
|
}
|
|
116
225
|
else {
|
|
117
|
-
for (let
|
|
118
|
-
byRow[
|
|
226
|
+
for (let row = 0; row < rowCnt; row++) {
|
|
227
|
+
byRow[row] = {
|
|
119
228
|
affectedInstances: ui.affectedInstances,
|
|
120
229
|
isEvent: ui.isEvent,
|
|
121
230
|
segs: [],
|
|
122
231
|
};
|
|
123
232
|
}
|
|
124
|
-
for (
|
|
233
|
+
for (const seg of ui.segs) {
|
|
125
234
|
byRow[seg.row].segs.push(seg);
|
|
126
235
|
}
|
|
127
236
|
}
|
|
128
237
|
return byRow;
|
|
129
238
|
}
|
|
239
|
+
function splitSegsByCol(segs, colCnt) {
|
|
240
|
+
let byCol = [];
|
|
241
|
+
for (let col = 0; col < colCnt; col++) {
|
|
242
|
+
byCol.push([]);
|
|
243
|
+
}
|
|
244
|
+
for (let seg of segs) {
|
|
245
|
+
for (let col = seg.firstCol; col <= seg.lastCol; col++) {
|
|
246
|
+
if (seg.firstCol !== col) {
|
|
247
|
+
seg = Object.assign(Object.assign({}, seg), { firstCol: col, lastCol: col, isStart: false, isEnd: seg.isEnd && seg.lastCol === col, isStandin: true });
|
|
248
|
+
}
|
|
249
|
+
byCol[col].push(seg);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return byCol;
|
|
253
|
+
}
|
|
130
254
|
|
|
131
255
|
const DEFAULT_TABLE_EVENT_TIME_FORMAT = internal_cjs.createFormatter({
|
|
132
256
|
hour: 'numeric',
|
|
@@ -144,21 +268,21 @@ function hasListItemDisplay(seg) {
|
|
|
144
268
|
);
|
|
145
269
|
}
|
|
146
270
|
|
|
147
|
-
class
|
|
271
|
+
class DayGridBlockEvent extends internal_cjs.BaseComponent {
|
|
148
272
|
render() {
|
|
149
273
|
let { props } = this;
|
|
150
|
-
return (preact_cjs.createElement(internal_cjs.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.
|
|
274
|
+
return (preact_cjs.createElement(internal_cjs.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 })));
|
|
151
275
|
}
|
|
152
276
|
}
|
|
153
277
|
|
|
154
|
-
class
|
|
278
|
+
class DayGridListEvent extends internal_cjs.BaseComponent {
|
|
155
279
|
render() {
|
|
156
280
|
let { props, context } = this;
|
|
157
281
|
let { options } = context;
|
|
158
|
-
let {
|
|
282
|
+
let { eventRange } = props;
|
|
159
283
|
let timeFormat = options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT;
|
|
160
|
-
let timeText = internal_cjs.
|
|
161
|
-
return (preact_cjs.createElement(internal_cjs.EventContainer, Object.assign({}, props, { elTag: "a", elClasses: ['fc-daygrid-event', 'fc-daygrid-dot-event'], elAttrs: internal_cjs.
|
|
284
|
+
let timeText = internal_cjs.buildEventRangeTimeText(eventRange, timeFormat, context, true, props.defaultDisplayEventEnd);
|
|
285
|
+
return (preact_cjs.createElement(internal_cjs.EventContainer, Object.assign({}, props, { elTag: "a", elClasses: ['fc-daygrid-event', 'fc-daygrid-dot-event'], elAttrs: internal_cjs.getEventRangeAnchorAttrs(eventRange, context), defaultGenerator: renderInnerContent, timeText: timeText, isResizing: false, isDateSelecting: false })));
|
|
162
286
|
}
|
|
163
287
|
}
|
|
164
288
|
function renderInnerContent(renderProps) {
|
|
@@ -168,80 +292,84 @@ function renderInnerContent(renderProps) {
|
|
|
168
292
|
preact_cjs.createElement("div", { className: "fc-event-title" }, renderProps.event.title || preact_cjs.createElement(preact_cjs.Fragment, null, "\u00A0"))));
|
|
169
293
|
}
|
|
170
294
|
|
|
171
|
-
class
|
|
172
|
-
constructor() {
|
|
173
|
-
super(...arguments);
|
|
174
|
-
this.compileSegs = internal_cjs.memoize(compileSegs);
|
|
175
|
-
}
|
|
295
|
+
class DayGridMoreLink extends internal_cjs.BaseComponent {
|
|
176
296
|
render() {
|
|
177
297
|
let { props } = this;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
298
|
+
return (preact_cjs.createElement(internal_cjs.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: () => {
|
|
299
|
+
let forcedInvisibleMap = // TODO: more convenient/DRY
|
|
300
|
+
(props.eventDrag ? props.eventDrag.affectedInstances : null) ||
|
|
181
301
|
(props.eventResize ? props.eventResize.affectedInstances : null) ||
|
|
182
302
|
{};
|
|
183
|
-
return (preact_cjs.createElement(preact_cjs.Fragment, null,
|
|
184
|
-
let
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
303
|
+
return (preact_cjs.createElement(preact_cjs.Fragment, null, props.segs.map((seg) => {
|
|
304
|
+
let { eventRange } = seg;
|
|
305
|
+
let instanceId = eventRange.instance.instanceId;
|
|
306
|
+
return (preact_cjs.createElement("div", { key: instanceId, style: {
|
|
307
|
+
visibility: forcedInvisibleMap[instanceId] ? 'hidden' : '',
|
|
308
|
+
} }, hasListItemDisplay(seg) ? (preact_cjs.createElement(DayGridListEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, internal_cjs.getEventRangeMeta(eventRange, props.todayRange)))) : (preact_cjs.createElement(DayGridBlockEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, internal_cjs.getEventRangeMeta(eventRange, props.todayRange))))));
|
|
188
309
|
})));
|
|
189
310
|
} }));
|
|
190
311
|
}
|
|
191
312
|
}
|
|
192
|
-
function compileSegs(singlePlacements) {
|
|
193
|
-
let allSegs = [];
|
|
194
|
-
let invisibleSegs = [];
|
|
195
|
-
for (let placement of singlePlacements) {
|
|
196
|
-
allSegs.push(placement.seg);
|
|
197
|
-
if (!placement.isVisible) {
|
|
198
|
-
invisibleSegs.push(placement.seg);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
return { allSegs, invisibleSegs };
|
|
202
|
-
}
|
|
203
313
|
|
|
204
|
-
|
|
205
|
-
class TableCell extends internal_cjs.DateComponent {
|
|
314
|
+
class DayGridCell extends internal_cjs.DateComponent {
|
|
206
315
|
constructor() {
|
|
207
316
|
super(...arguments);
|
|
208
|
-
|
|
209
|
-
this.
|
|
210
|
-
|
|
211
|
-
};
|
|
212
|
-
this.handleRootEl = (el) => {
|
|
213
|
-
internal_cjs.setRef(this.rootElRef, el);
|
|
214
|
-
internal_cjs.setRef(this.props.elRef, el);
|
|
215
|
-
};
|
|
317
|
+
// ref
|
|
318
|
+
this.innerElRef = preact_cjs.createRef();
|
|
319
|
+
this.headerWrapElRef = preact_cjs.createRef();
|
|
216
320
|
}
|
|
217
321
|
render() {
|
|
218
|
-
let {
|
|
322
|
+
let { props, context } = this;
|
|
219
323
|
let { options, dateEnv } = context;
|
|
220
|
-
|
|
221
|
-
// TODO: memoize this?
|
|
324
|
+
// TODO: memoize this
|
|
222
325
|
const isMonthStart = props.showDayNumber &&
|
|
223
|
-
shouldDisplayMonthStart(date, dateProfile.currentRange, dateEnv);
|
|
224
|
-
return (preact_cjs.createElement(internal_cjs.DayCellContainer, { elTag: "
|
|
225
|
-
'fc-daygrid-
|
|
326
|
+
shouldDisplayMonthStart(props.date, props.dateProfile.currentRange, dateEnv);
|
|
327
|
+
return (preact_cjs.createElement(internal_cjs.DayCellContainer, { elTag: "div", elClasses: [
|
|
328
|
+
'fc-daygrid-cell',
|
|
329
|
+
'fc-cell',
|
|
330
|
+
props.width != null ? '' : 'fc-liquid',
|
|
331
|
+
'fc-flex-column',
|
|
226
332
|
...(props.extraClassNames || []),
|
|
227
|
-
], elAttrs: Object.assign(Object.assign(
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
333
|
+
], elAttrs: Object.assign(Object.assign({}, props.extraDataAttrs), { role: 'gridcell' }), elStyle: {
|
|
334
|
+
width: props.width
|
|
335
|
+
}, extraRenderProps: props.extraRenderProps, defaultGenerator: renderTopInner, date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, isMonthStart: isMonthStart }, (InnerContent, renderProps) => (preact_cjs.createElement("div", { ref: this.innerElRef, className: [
|
|
336
|
+
'fc-daygrid-cell-inner',
|
|
337
|
+
props.fgLiquidHeight ? 'fc-liquid' : ''
|
|
338
|
+
].join(' ') },
|
|
339
|
+
preact_cjs.createElement("div", { ref: this.headerWrapElRef, className: "fc-flex-column" }, !renderProps.isDisabled && (props.showDayNumber || internal_cjs.hasCustomDayCellContent(options)) && (preact_cjs.createElement("div", { className: "fc-daygrid-cell-header" },
|
|
231
340
|
preact_cjs.createElement(InnerContent, { elTag: "a", elClasses: [
|
|
232
|
-
'fc-daygrid-
|
|
341
|
+
'fc-daygrid-cell-number',
|
|
233
342
|
isMonthStart && 'fc-daygrid-month-start',
|
|
234
|
-
], elAttrs:
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
preact_cjs.createElement("div", { className: "fc-daygrid-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
343
|
+
], elAttrs: internal_cjs.buildNavLinkAttrs(context, props.date) })))),
|
|
344
|
+
preact_cjs.createElement("div", { className: "fc-daygrid-cell-main", style: {
|
|
345
|
+
height: props.fgLiquidHeight ? '' : props.fgHeight
|
|
346
|
+
} }, props.fg),
|
|
347
|
+
preact_cjs.createElement("div", { className: "fc-daygrid-cell-footer", style: props.fgLiquidHeight
|
|
348
|
+
? { position: 'relative', top: props.fgHeight }
|
|
349
|
+
: {} },
|
|
350
|
+
preact_cjs.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 })),
|
|
351
|
+
props.bg))));
|
|
352
|
+
}
|
|
353
|
+
componentDidMount() {
|
|
354
|
+
const innerEl = this.innerElRef.current; // TODO: make dynamic with useEffect
|
|
355
|
+
const headerWrapEl = this.headerWrapElRef.current; // "
|
|
356
|
+
// TODO: only attach this if refs props present
|
|
357
|
+
this.detachInnerHeight = internal_cjs.watchHeight(innerEl, (height) => {
|
|
358
|
+
internal_cjs.setRef(this.props.innerHeightRef, height);
|
|
359
|
+
});
|
|
360
|
+
this.detachHeaderHeight = internal_cjs.watchHeight(headerWrapEl, (height) => {
|
|
361
|
+
internal_cjs.setRef(this.props.headerHeightRef, height);
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
componentWillUnmount() {
|
|
365
|
+
this.detachInnerHeight();
|
|
366
|
+
this.detachHeaderHeight();
|
|
367
|
+
internal_cjs.setRef(this.props.innerHeightRef, null);
|
|
368
|
+
internal_cjs.setRef(this.props.headerHeightRef, null);
|
|
243
369
|
}
|
|
244
370
|
}
|
|
371
|
+
// Utils
|
|
372
|
+
// -------------------------------------------------------------------------------------------------
|
|
245
373
|
function renderTopInner(props) {
|
|
246
374
|
return props.dayNumberText || preact_cjs.createElement(preact_cjs.Fragment, null, "\u00A0");
|
|
247
375
|
}
|
|
@@ -261,26 +389,43 @@ function shouldDisplayMonthStart(date, currentRange, dateEnv) {
|
|
|
261
389
|
(dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf()));
|
|
262
390
|
}
|
|
263
391
|
|
|
264
|
-
|
|
392
|
+
/*
|
|
393
|
+
Unique per-START-column, good for cataloging by top
|
|
394
|
+
*/
|
|
395
|
+
function getSegStartId(seg) {
|
|
265
396
|
return seg.eventRange.instance.instanceId + ':' + seg.firstCol;
|
|
266
397
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
function
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
398
|
+
/*
|
|
399
|
+
Unique per-START-and-END-column, good for cataloging by width/height
|
|
400
|
+
*/
|
|
401
|
+
function getSegSpanId(seg) {
|
|
402
|
+
return getSegStartId(seg) + ':' + seg.lastCol;
|
|
403
|
+
}
|
|
404
|
+
function computeFgSegVerticals(segs, segHeightMap, // keyed by segSpanId
|
|
405
|
+
cells, topOrigin, maxHeight, strictOrder, dayMaxEvents, dayMaxEventRows) {
|
|
406
|
+
// initialize column-based arrays
|
|
407
|
+
const colCnt = cells.length;
|
|
408
|
+
const hiddenSegsByCol = [];
|
|
409
|
+
const heightsByCol = [];
|
|
410
|
+
for (let col = 0; col < colCnt; col++) {
|
|
411
|
+
hiddenSegsByCol.push([]);
|
|
412
|
+
heightsByCol.push(0);
|
|
413
|
+
}
|
|
414
|
+
// create entries to be given to DayGridSegHierarchy
|
|
415
|
+
const segEntries = segs.map((seg, index) => ({
|
|
416
|
+
index: index,
|
|
417
|
+
seg,
|
|
418
|
+
span: {
|
|
419
|
+
start: seg.firstCol,
|
|
420
|
+
end: seg.lastCol + 1,
|
|
421
|
+
},
|
|
422
|
+
}));
|
|
423
|
+
// configure hierarchy position-generator
|
|
424
|
+
let hierarchy = new DayGridSegHierarchy((segEntry) => (segHeightMap.get(getSegSpanId(segs[segEntry.index]))));
|
|
425
|
+
hierarchy.allowReslicing = false;
|
|
281
426
|
hierarchy.strictOrder = strictOrder;
|
|
282
427
|
if (dayMaxEvents === true || dayMaxEventRows === true) {
|
|
283
|
-
hierarchy.maxCoord =
|
|
428
|
+
hierarchy.maxCoord = maxHeight;
|
|
284
429
|
hierarchy.hiddenConsumes = true;
|
|
285
430
|
}
|
|
286
431
|
else if (typeof dayMaxEvents === 'number') {
|
|
@@ -290,172 +435,30 @@ dayMaxEvents, dayMaxEventRows, strictOrder, segHeights, maxContentHeight, cells)
|
|
|
290
435
|
hierarchy.maxStackCnt = dayMaxEventRows;
|
|
291
436
|
hierarchy.hiddenConsumes = true;
|
|
292
437
|
}
|
|
293
|
-
//
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
span: {
|
|
304
|
-
start: seg.firstCol,
|
|
305
|
-
end: seg.lastCol + 1,
|
|
306
|
-
},
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
else {
|
|
310
|
-
unknownHeightSegs.push(seg);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
let hiddenEntries = hierarchy.addSegs(segInputs);
|
|
314
|
-
let segRects = hierarchy.toRects();
|
|
315
|
-
let { singleColPlacements, multiColPlacements, leftoverMargins } = placeRects(segRects, segs, cells);
|
|
316
|
-
let moreCnts = [];
|
|
317
|
-
let moreMarginTops = [];
|
|
318
|
-
// add segs with unknown heights
|
|
319
|
-
for (let seg of unknownHeightSegs) {
|
|
320
|
-
multiColPlacements[seg.firstCol].push({
|
|
321
|
-
seg,
|
|
322
|
-
isVisible: false,
|
|
323
|
-
isAbsolute: true,
|
|
324
|
-
absoluteTop: 0,
|
|
325
|
-
marginTop: 0,
|
|
326
|
-
});
|
|
327
|
-
for (let col = seg.firstCol; col <= seg.lastCol; col += 1) {
|
|
328
|
-
singleColPlacements[col].push({
|
|
329
|
-
seg: resliceSeg(seg, col, col + 1, cells),
|
|
330
|
-
isVisible: false,
|
|
331
|
-
isAbsolute: false,
|
|
332
|
-
absoluteTop: 0,
|
|
333
|
-
marginTop: 0,
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
// add the hidden entries
|
|
338
|
-
for (let col = 0; col < cells.length; col += 1) {
|
|
339
|
-
moreCnts.push(0);
|
|
340
|
-
}
|
|
341
|
-
for (let hiddenEntry of hiddenEntries) {
|
|
342
|
-
let seg = segs[hiddenEntry.index];
|
|
343
|
-
let hiddenSpan = hiddenEntry.span;
|
|
344
|
-
multiColPlacements[hiddenSpan.start].push({
|
|
345
|
-
seg: resliceSeg(seg, hiddenSpan.start, hiddenSpan.end, cells),
|
|
346
|
-
isVisible: false,
|
|
347
|
-
isAbsolute: true,
|
|
348
|
-
absoluteTop: 0,
|
|
349
|
-
marginTop: 0,
|
|
350
|
-
});
|
|
351
|
-
for (let col = hiddenSpan.start; col < hiddenSpan.end; col += 1) {
|
|
352
|
-
moreCnts[col] += 1;
|
|
353
|
-
singleColPlacements[col].push({
|
|
354
|
-
seg: resliceSeg(seg, col, col + 1, cells),
|
|
355
|
-
isVisible: false,
|
|
356
|
-
isAbsolute: false,
|
|
357
|
-
absoluteTop: 0,
|
|
358
|
-
marginTop: 0,
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
// deal with leftover margins
|
|
363
|
-
for (let col = 0; col < cells.length; col += 1) {
|
|
364
|
-
moreMarginTops.push(leftoverMargins[col]);
|
|
365
|
-
}
|
|
366
|
-
return { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops };
|
|
367
|
-
}
|
|
368
|
-
// rects ordered by top coord, then left
|
|
369
|
-
function placeRects(allRects, segs, cells) {
|
|
370
|
-
let rectsByEachCol = groupRectsByEachCol(allRects, cells.length);
|
|
371
|
-
let singleColPlacements = [];
|
|
372
|
-
let multiColPlacements = [];
|
|
373
|
-
let leftoverMargins = [];
|
|
374
|
-
for (let col = 0; col < cells.length; col += 1) {
|
|
375
|
-
let rects = rectsByEachCol[col];
|
|
376
|
-
// compute all static segs in singlePlacements
|
|
377
|
-
let singlePlacements = [];
|
|
378
|
-
let currentHeight = 0;
|
|
379
|
-
let currentMarginTop = 0;
|
|
380
|
-
for (let rect of rects) {
|
|
381
|
-
let seg = segs[rect.index];
|
|
382
|
-
singlePlacements.push({
|
|
383
|
-
seg: resliceSeg(seg, col, col + 1, cells),
|
|
384
|
-
isVisible: true,
|
|
385
|
-
isAbsolute: false,
|
|
386
|
-
absoluteTop: rect.levelCoord,
|
|
387
|
-
marginTop: rect.levelCoord - currentHeight,
|
|
388
|
-
});
|
|
389
|
-
currentHeight = rect.levelCoord + rect.thickness;
|
|
390
|
-
}
|
|
391
|
-
// compute mixed static/absolute segs in multiPlacements
|
|
392
|
-
let multiPlacements = [];
|
|
393
|
-
currentHeight = 0;
|
|
394
|
-
currentMarginTop = 0;
|
|
395
|
-
for (let rect of rects) {
|
|
396
|
-
let seg = segs[rect.index];
|
|
397
|
-
let isAbsolute = rect.span.end - rect.span.start > 1; // multi-column?
|
|
398
|
-
let isFirstCol = rect.span.start === col;
|
|
399
|
-
currentMarginTop += rect.levelCoord - currentHeight; // amount of space since bottom of previous seg
|
|
400
|
-
currentHeight = rect.levelCoord + rect.thickness; // height will now be bottom of current seg
|
|
401
|
-
if (isAbsolute) {
|
|
402
|
-
currentMarginTop += rect.thickness;
|
|
403
|
-
if (isFirstCol) {
|
|
404
|
-
multiPlacements.push({
|
|
405
|
-
seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
|
|
406
|
-
isVisible: true,
|
|
407
|
-
isAbsolute: true,
|
|
408
|
-
absoluteTop: rect.levelCoord,
|
|
409
|
-
marginTop: 0,
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
else if (isFirstCol) {
|
|
414
|
-
multiPlacements.push({
|
|
415
|
-
seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
|
|
416
|
-
isVisible: true,
|
|
417
|
-
isAbsolute: false,
|
|
418
|
-
absoluteTop: rect.levelCoord,
|
|
419
|
-
marginTop: currentMarginTop, // claim the margin
|
|
420
|
-
});
|
|
421
|
-
currentMarginTop = 0;
|
|
422
|
-
}
|
|
438
|
+
// compile segTops & heightsByCol
|
|
439
|
+
const hiddenSegEntries = hierarchy.addSegs(segEntries);
|
|
440
|
+
const segRects = hierarchy.toRects();
|
|
441
|
+
const segTops = {};
|
|
442
|
+
for (const segRect of segRects) {
|
|
443
|
+
const seg = segs[segRect.index];
|
|
444
|
+
segTops[getSegStartId(seg)] = topOrigin + segRect.levelCoord;
|
|
445
|
+
let { start: col, end: endCol } = segRect.span;
|
|
446
|
+
for (; col < endCol; col++) {
|
|
447
|
+
heightsByCol[col] = Math.max(heightsByCol[col], segRect.levelCoord + segRect.thickness);
|
|
423
448
|
}
|
|
424
|
-
singleColPlacements.push(singlePlacements);
|
|
425
|
-
multiColPlacements.push(multiPlacements);
|
|
426
|
-
leftoverMargins.push(currentMarginTop);
|
|
427
|
-
}
|
|
428
|
-
return { singleColPlacements, multiColPlacements, leftoverMargins };
|
|
429
|
-
}
|
|
430
|
-
function groupRectsByEachCol(rects, colCnt) {
|
|
431
|
-
let rectsByEachCol = [];
|
|
432
|
-
for (let col = 0; col < colCnt; col += 1) {
|
|
433
|
-
rectsByEachCol.push([]);
|
|
434
449
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
450
|
+
// compile # of invisible segs per-column
|
|
451
|
+
for (const hiddenSegEntry of hiddenSegEntries) {
|
|
452
|
+
const { span } = hiddenSegEntry;
|
|
453
|
+
const hiddenSeg = segs[hiddenSegEntry.index];
|
|
454
|
+
for (let col = span.start; col < span.end; col++) {
|
|
455
|
+
hiddenSegsByCol[col].push(hiddenSeg);
|
|
438
456
|
}
|
|
439
457
|
}
|
|
440
|
-
return
|
|
441
|
-
}
|
|
442
|
-
function resliceSeg(seg, spanStart, spanEnd, cells) {
|
|
443
|
-
if (seg.firstCol === spanStart && seg.lastCol === spanEnd - 1) {
|
|
444
|
-
return seg;
|
|
445
|
-
}
|
|
446
|
-
let eventRange = seg.eventRange;
|
|
447
|
-
let origRange = eventRange.range;
|
|
448
|
-
let slicedRange = internal_cjs.intersectRanges(origRange, {
|
|
449
|
-
start: cells[spanStart].date,
|
|
450
|
-
end: internal_cjs.addDays(cells[spanEnd - 1].date, 1),
|
|
451
|
-
});
|
|
452
|
-
return Object.assign(Object.assign({}, seg), { firstCol: spanStart, lastCol: spanEnd - 1, eventRange: {
|
|
453
|
-
def: eventRange.def,
|
|
454
|
-
ui: Object.assign(Object.assign({}, eventRange.ui), { durationEditable: false }),
|
|
455
|
-
instance: eventRange.instance,
|
|
456
|
-
range: slicedRange,
|
|
457
|
-
}, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() });
|
|
458
|
+
return [segTops, heightsByCol, hiddenSegsByCol];
|
|
458
459
|
}
|
|
460
|
+
// DayGridSegHierarchy
|
|
461
|
+
// -------------------------------------------------------------------------------------------------
|
|
459
462
|
class DayGridSegHierarchy extends internal_cjs.SegHierarchy {
|
|
460
463
|
constructor() {
|
|
461
464
|
super(...arguments);
|
|
@@ -503,74 +506,206 @@ class DayGridSegHierarchy extends internal_cjs.SegHierarchy {
|
|
|
503
506
|
}
|
|
504
507
|
}
|
|
505
508
|
|
|
506
|
-
class
|
|
509
|
+
class DayGridEventHarness extends preact_cjs.Component {
|
|
507
510
|
constructor() {
|
|
508
511
|
super(...arguments);
|
|
509
|
-
|
|
510
|
-
this.frameElRefs = new internal_cjs.RefMap(); // the fc-daygrid-day-frame
|
|
511
|
-
this.fgElRefs = new internal_cjs.RefMap(); // the fc-daygrid-day-events
|
|
512
|
-
this.segHarnessRefs = new internal_cjs.RefMap(); // indexed by "instanceId:firstCol"
|
|
512
|
+
// ref
|
|
513
513
|
this.rootElRef = preact_cjs.createRef();
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
514
|
+
}
|
|
515
|
+
render() {
|
|
516
|
+
const { props } = this;
|
|
517
|
+
return (preact_cjs.createElement("div", { className: "fc-abs", style: props.style, ref: this.rootElRef }, props.children));
|
|
518
|
+
}
|
|
519
|
+
componentDidMount() {
|
|
520
|
+
const rootEl = this.rootElRef.current; // TODO: make dynamic with useEffect
|
|
521
|
+
this.detachHeight = internal_cjs.watchHeight(rootEl, (height) => {
|
|
522
|
+
internal_cjs.setRef(this.props.heightRef, height);
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
componentWillUnmount() {
|
|
526
|
+
this.detachHeight();
|
|
527
|
+
internal_cjs.setRef(this.props.heightRef, null);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
const DEFAULT_WEEK_NUM_FORMAT = internal_cjs.createFormatter({ week: 'narrow' });
|
|
532
|
+
const COMPACT_CELL_WIDTH = 80;
|
|
533
|
+
class DayGridRow extends internal_cjs.BaseComponent {
|
|
534
|
+
constructor() {
|
|
535
|
+
super(...arguments);
|
|
536
|
+
this.cellInnerHeightRefMap = new internal_cjs.RefMap(() => {
|
|
537
|
+
internal_cjs.afterSize(this.handleInnerHeights);
|
|
538
|
+
});
|
|
539
|
+
this.cellHeaderHeightRefMap = new internal_cjs.RefMap(() => {
|
|
540
|
+
internal_cjs.afterSize(this.handleHeaderHeights);
|
|
541
|
+
});
|
|
542
|
+
this.segHeightRefMap = new internal_cjs.RefMap(() => {
|
|
543
|
+
internal_cjs.afterSize(this.handleSegHeights);
|
|
544
|
+
});
|
|
545
|
+
this.handleRootEl = (rootEl) => {
|
|
546
|
+
this.rootEl = rootEl;
|
|
547
|
+
internal_cjs.setRef(this.props.rootElRef, rootEl);
|
|
518
548
|
};
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
549
|
+
// Sizing
|
|
550
|
+
// -----------------------------------------------------------------------------------------------
|
|
551
|
+
this.handleHeaderHeights = () => {
|
|
552
|
+
const cellHeaderHeightMap = this.cellHeaderHeightRefMap.current;
|
|
553
|
+
let max = 0;
|
|
554
|
+
for (const height of cellHeaderHeightMap.values()) {
|
|
555
|
+
max = Math.max(max, height);
|
|
556
|
+
}
|
|
557
|
+
if (this.state.headerHeight !== max) {
|
|
558
|
+
this.setState({ headerHeight: max });
|
|
522
559
|
}
|
|
523
560
|
};
|
|
561
|
+
this.handleInnerHeights = () => {
|
|
562
|
+
const { props } = this;
|
|
563
|
+
const fgLiquidHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
|
|
564
|
+
const cellInnerHeightMap = this.cellInnerHeightRefMap.current;
|
|
565
|
+
let max = 0;
|
|
566
|
+
for (const height of cellInnerHeightMap.values()) {
|
|
567
|
+
max = Math.max(max, height);
|
|
568
|
+
}
|
|
569
|
+
if (fgLiquidHeight) {
|
|
570
|
+
if (this.state.innerHeight !== max) {
|
|
571
|
+
this.setState({ innerHeight: max }); // will trigger event rerender
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
else {
|
|
575
|
+
internal_cjs.setRef(props.innerHeightRef, max);
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
this.handleSegHeights = () => {
|
|
579
|
+
this.setState({ segHeightRev: this.segHeightRefMap.rev }); // will trigger event rerender
|
|
580
|
+
};
|
|
524
581
|
}
|
|
525
582
|
render() {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
583
|
+
const { props, state, context, cellInnerHeightRefMap, cellHeaderHeightRefMap } = this;
|
|
584
|
+
const { cells } = props;
|
|
585
|
+
const { options } = context;
|
|
586
|
+
const weekDate = props.cells[0].date;
|
|
587
|
+
const colCnt = props.cells.length;
|
|
588
|
+
const fgLiquidHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
|
|
589
|
+
// TODO: memoize? sort all types of segs?
|
|
590
|
+
const fgEventSegs = internal_cjs.sortEventSegs(props.fgEventSegs, options.eventOrder);
|
|
591
|
+
// TODO: memoize?
|
|
592
|
+
const fgEventSegsByCol = splitSegsByCol(fgEventSegs, colCnt);
|
|
593
|
+
const bgEventSegsByCol = splitSegsByCol(props.bgEventSegs, colCnt);
|
|
594
|
+
const businessHoursByCol = splitSegsByCol(props.businessHourSegs, colCnt);
|
|
595
|
+
const highlightSegsByCol = splitSegsByCol(this.getHighlightSegs(), colCnt); // TODO: doesn't need standins
|
|
596
|
+
const mirrorSegsByCol = splitSegsByCol(this.getMirrorSegs(), colCnt); // TODO: doesn't need standins
|
|
597
|
+
// TODO: memoize?
|
|
598
|
+
const [segTops, heightsByCol, hiddenSegsByCol] = computeFgSegVerticals(fgEventSegs, this.segHeightRefMap.current, cells, state.headerHeight, (fgLiquidHeight && state.innerHeight != null && state.headerHeight != null)
|
|
599
|
+
? state.innerHeight - state.headerHeight
|
|
600
|
+
: undefined, options.eventOrderStrict, props.dayMaxEvents, props.dayMaxEventRows);
|
|
601
|
+
const forcedInvisibleMap = // TODO: more convenient/DRY
|
|
535
602
|
(props.eventDrag && props.eventDrag.affectedInstances) ||
|
|
536
603
|
(props.eventResize && props.eventResize.affectedInstances) ||
|
|
537
604
|
{};
|
|
538
|
-
return (preact_cjs.createElement("
|
|
539
|
-
|
|
605
|
+
return (preact_cjs.createElement("div", { role: props.cellGroup ? undefined : 'row', className: [
|
|
606
|
+
'fc-daygrid-row',
|
|
607
|
+
props.forceVSpacing
|
|
608
|
+
? 'fc-daygrid-row-spacious'
|
|
609
|
+
: props.compact
|
|
610
|
+
? 'fc-daygrid-row-compact'
|
|
611
|
+
: '',
|
|
612
|
+
props.cellGroup ? 'fc-flex-row' : 'fc-row',
|
|
613
|
+
'fc-rel',
|
|
614
|
+
props.className || '',
|
|
615
|
+
].join(' '), style: {
|
|
616
|
+
minHeight: props.minHeight,
|
|
617
|
+
}, ref: this.handleRootEl },
|
|
540
618
|
props.cells.map((cell, col) => {
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
619
|
+
const normalFgNodes = this.renderFgSegs(fgEventSegsByCol[col], segTops, props.todayRange, forcedInvisibleMap);
|
|
620
|
+
const mirrorFgNodes = this.renderFgSegs(mirrorSegsByCol[col], segTops, props.todayRange, {}, // forcedInvisibleMap
|
|
621
|
+
Boolean(props.eventDrag), Boolean(props.eventResize), false);
|
|
622
|
+
return (preact_cjs.createElement(DayGridCell, { key: cell.key, dateProfile: props.dateProfile, todayRange: props.todayRange, date: cell.date, showDayNumber: props.showDayNumbers,
|
|
623
|
+
// content
|
|
624
|
+
segs: fgEventSegsByCol[col], hiddenSegs: hiddenSegsByCol[col], fgLiquidHeight: fgLiquidHeight, fg: (preact_cjs.createElement(preact_cjs.Fragment, null,
|
|
545
625
|
preact_cjs.createElement(preact_cjs.Fragment, null, normalFgNodes),
|
|
546
|
-
preact_cjs.createElement(preact_cjs.Fragment, null, mirrorFgNodes))),
|
|
547
|
-
preact_cjs.createElement(preact_cjs.Fragment, null,
|
|
626
|
+
preact_cjs.createElement(preact_cjs.Fragment, null, mirrorFgNodes))), bg: (preact_cjs.createElement(preact_cjs.Fragment, null,
|
|
548
627
|
this.renderFillSegs(highlightSegsByCol[col], 'highlight'),
|
|
549
628
|
this.renderFillSegs(businessHoursByCol[col], 'non-business'),
|
|
550
|
-
this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))),
|
|
551
|
-
|
|
629
|
+
this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))), eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
|
|
630
|
+
// render hooks
|
|
631
|
+
extraRenderProps: cell.extraRenderProps, extraDateSpan: cell.extraDateSpan, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames,
|
|
632
|
+
// dimensions
|
|
633
|
+
fgHeight: heightsByCol[col], width: props.colWidth,
|
|
634
|
+
// refs
|
|
635
|
+
innerHeightRef: cellInnerHeightRefMap.createRef(cell.key), headerHeightRef: cellHeaderHeightRefMap.createRef(cell.key) }));
|
|
636
|
+
}),
|
|
637
|
+
props.showWeekNumbers && (preact_cjs.createElement(internal_cjs.WeekNumberContainer, { elTag: "a", elClasses: ['fc-daygrid-week-number'], elAttrs: internal_cjs.buildNavLinkAttrs(context, weekDate, 'week'), date: weekDate, defaultFormat: DEFAULT_WEEK_NUM_FORMAT }))));
|
|
638
|
+
}
|
|
639
|
+
renderFgSegs(segs, segTops, todayRange, forcedInvisibleMap, isDragging, isResizing, isDateSelecting) {
|
|
640
|
+
const { props, context, segHeightRefMap } = this;
|
|
641
|
+
const { isRtl } = context;
|
|
642
|
+
const { colWidth, eventSelection } = props;
|
|
643
|
+
const colCnt = props.cells.length;
|
|
644
|
+
const defaultDisplayEventEnd = props.cells.length === 1;
|
|
645
|
+
const isMirror = isDragging || isResizing || isDateSelecting;
|
|
646
|
+
const nodes = [];
|
|
647
|
+
for (const seg of segs) {
|
|
648
|
+
const { left, right, width } = computeHorizontalsFromSeg(seg, colWidth, colCnt, isRtl);
|
|
649
|
+
// TODO: optimize ID creation? all related
|
|
650
|
+
const { eventRange } = seg;
|
|
651
|
+
const { instanceId } = eventRange.instance;
|
|
652
|
+
const segSpanId = getSegSpanId(seg);
|
|
653
|
+
const segStartId = getSegStartId(seg);
|
|
654
|
+
const top = segTops[segStartId];
|
|
655
|
+
const isVisible = !seg.isStandin &&
|
|
656
|
+
top != null &&
|
|
657
|
+
!forcedInvisibleMap[instanceId];
|
|
658
|
+
/*
|
|
659
|
+
TODO: is this comment still relevant? vvvvvvvv
|
|
660
|
+
known bug: events that are force to be list-item but span multiple days still take up space in later columns
|
|
661
|
+
todo: in print view, for multi-day events, don't display title within non-start/end segs
|
|
662
|
+
*/
|
|
663
|
+
nodes.push(preact_cjs.createElement(DayGridEventHarness, { key: segSpanId, style: {
|
|
664
|
+
visibility: isVisible ? '' : 'hidden',
|
|
665
|
+
top,
|
|
666
|
+
left,
|
|
667
|
+
right,
|
|
668
|
+
width,
|
|
669
|
+
}, heightRef: (isMirror || seg.isStandin)
|
|
670
|
+
? null
|
|
671
|
+
: segHeightRefMap.createRef(segSpanId) }, hasListItemDisplay(seg) ? (preact_cjs.createElement(DayGridListEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal_cjs.getEventRangeMeta(eventRange, todayRange)))) : (preact_cjs.createElement(DayGridBlockEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal_cjs.getEventRangeMeta(eventRange, todayRange))))));
|
|
672
|
+
}
|
|
673
|
+
return nodes;
|
|
552
674
|
}
|
|
553
|
-
|
|
554
|
-
this
|
|
555
|
-
|
|
675
|
+
renderFillSegs(segs, fillType) {
|
|
676
|
+
const { props, context } = this;
|
|
677
|
+
const { isRtl } = context;
|
|
678
|
+
const { todayRange, colWidth } = props;
|
|
679
|
+
const colCnt = props.cells.length;
|
|
680
|
+
const nodes = [];
|
|
681
|
+
for (const seg of segs) {
|
|
682
|
+
const { left, right, width } = computeHorizontalsFromSeg(seg, colWidth, colCnt, isRtl);
|
|
683
|
+
const isVisible = !seg.isStandin;
|
|
684
|
+
nodes.push(preact_cjs.createElement("div", { key: internal_cjs.buildEventRangeKey(seg.eventRange), className: "fc-fill-y", style: {
|
|
685
|
+
visibility: isVisible ? '' : 'hidden',
|
|
686
|
+
left,
|
|
687
|
+
right,
|
|
688
|
+
width,
|
|
689
|
+
} }, fillType === 'bg-event' ?
|
|
690
|
+
preact_cjs.createElement(internal_cjs.BgEvent, Object.assign({ eventRange: seg.eventRange, isStart: seg.isStart, isEnd: seg.isEnd }, internal_cjs.getEventRangeMeta(seg.eventRange, todayRange))) : (internal_cjs.renderFill(fillType))));
|
|
691
|
+
}
|
|
692
|
+
return preact_cjs.createElement(preact_cjs.Fragment, {}, ...nodes);
|
|
556
693
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
694
|
+
// Sizing
|
|
695
|
+
// -----------------------------------------------------------------------------------------------
|
|
696
|
+
componentDidMount() {
|
|
697
|
+
const { rootEl } = this; // TODO: make dynamic with useEffect
|
|
698
|
+
this.disconnectHeight = internal_cjs.watchHeight(rootEl, (contentHeight) => {
|
|
699
|
+
internal_cjs.setRef(this.props.heightRef, contentHeight);
|
|
700
|
+
});
|
|
560
701
|
}
|
|
561
702
|
componentWillUnmount() {
|
|
562
|
-
this.
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
let { props } = this;
|
|
566
|
-
if (props.eventDrag && props.eventDrag.segs.length) { // messy check
|
|
567
|
-
return props.eventDrag.segs;
|
|
568
|
-
}
|
|
569
|
-
if (props.eventResize && props.eventResize.segs.length) { // messy check
|
|
570
|
-
return props.eventResize.segs;
|
|
571
|
-
}
|
|
572
|
-
return props.dateSelectionSegs;
|
|
703
|
+
this.disconnectHeight();
|
|
704
|
+
internal_cjs.setRef(this.props.heightRef, null);
|
|
705
|
+
internal_cjs.setRef(this.props.innerHeightRef, null);
|
|
573
706
|
}
|
|
707
|
+
// Utils
|
|
708
|
+
// -----------------------------------------------------------------------------------------------
|
|
574
709
|
getMirrorSegs() {
|
|
575
710
|
let { props } = this;
|
|
576
711
|
if (props.eventResize && props.eventResize.segs.length) { // messy check
|
|
@@ -578,420 +713,488 @@ class TableRow extends internal_cjs.DateComponent {
|
|
|
578
713
|
}
|
|
579
714
|
return [];
|
|
580
715
|
}
|
|
581
|
-
|
|
582
|
-
let {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
let defaultDisplayEventEnd = this.props.cells.length === 1; // colCnt === 1
|
|
586
|
-
let isMirror = isDragging || isResizing || isDateSelecting;
|
|
587
|
-
let nodes = [];
|
|
588
|
-
if (framePositions) {
|
|
589
|
-
for (let placement of segPlacements) {
|
|
590
|
-
let { seg } = placement;
|
|
591
|
-
let { instanceId } = seg.eventRange.instance;
|
|
592
|
-
let isVisible = placement.isVisible && !isForcedInvisible[instanceId];
|
|
593
|
-
let isAbsolute = placement.isAbsolute;
|
|
594
|
-
let left = '';
|
|
595
|
-
let right = '';
|
|
596
|
-
if (isAbsolute) {
|
|
597
|
-
if (context.isRtl) {
|
|
598
|
-
right = 0;
|
|
599
|
-
left = framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol];
|
|
600
|
-
}
|
|
601
|
-
else {
|
|
602
|
-
left = 0;
|
|
603
|
-
right = framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol];
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
/*
|
|
607
|
-
known bug: events that are force to be list-item but span multiple days still take up space in later columns
|
|
608
|
-
todo: in print view, for multi-day events, don't display title within non-start/end segs
|
|
609
|
-
*/
|
|
610
|
-
nodes.push(preact_cjs.createElement("div", { className: 'fc-daygrid-event-harness' + (isAbsolute ? ' fc-daygrid-event-harness-abs' : ''), key: generateSegKey(seg), ref: isMirror ? null : this.segHarnessRefs.createRef(generateSegUid(seg)), style: {
|
|
611
|
-
visibility: isVisible ? '' : 'hidden',
|
|
612
|
-
marginTop: isAbsolute ? '' : placement.marginTop,
|
|
613
|
-
top: isAbsolute ? placement.absoluteTop : '',
|
|
614
|
-
left,
|
|
615
|
-
right,
|
|
616
|
-
} }, hasListItemDisplay(seg) ? (preact_cjs.createElement(TableListItemEvent, Object.assign({ seg: seg, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal_cjs.getSegMeta(seg, todayRange)))) : (preact_cjs.createElement(TableBlockEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal_cjs.getSegMeta(seg, todayRange))))));
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
return nodes;
|
|
620
|
-
}
|
|
621
|
-
renderFillSegs(segs, fillType) {
|
|
622
|
-
let { isRtl } = this.context;
|
|
623
|
-
let { todayRange } = this.props;
|
|
624
|
-
let { framePositions } = this.state;
|
|
625
|
-
let nodes = [];
|
|
626
|
-
if (framePositions) {
|
|
627
|
-
for (let seg of segs) {
|
|
628
|
-
let leftRightCss = isRtl ? {
|
|
629
|
-
right: 0,
|
|
630
|
-
left: framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol],
|
|
631
|
-
} : {
|
|
632
|
-
left: 0,
|
|
633
|
-
right: framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol],
|
|
634
|
-
};
|
|
635
|
-
nodes.push(preact_cjs.createElement("div", { key: internal_cjs.buildEventRangeKey(seg.eventRange), className: "fc-daygrid-bg-harness", style: leftRightCss }, fillType === 'bg-event' ?
|
|
636
|
-
preact_cjs.createElement(internal_cjs.BgEvent, Object.assign({ seg: seg }, internal_cjs.getSegMeta(seg, todayRange))) :
|
|
637
|
-
internal_cjs.renderFill(fillType)));
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
return preact_cjs.createElement(preact_cjs.Fragment, {}, ...nodes);
|
|
641
|
-
}
|
|
642
|
-
updateSizing(isExternalSizingChange) {
|
|
643
|
-
let { props, state, frameElRefs } = this;
|
|
644
|
-
if (!props.forPrint &&
|
|
645
|
-
props.clientWidth !== null // positioning ready?
|
|
646
|
-
) {
|
|
647
|
-
if (isExternalSizingChange) {
|
|
648
|
-
let frameEls = props.cells.map((cell) => frameElRefs.currentMap[cell.key]);
|
|
649
|
-
if (frameEls.length) {
|
|
650
|
-
let originEl = this.rootElRef.current;
|
|
651
|
-
let newPositionCache = new internal_cjs.PositionCache(originEl, frameEls, true, // isHorizontal
|
|
652
|
-
false);
|
|
653
|
-
if (!state.framePositions || !state.framePositions.similarTo(newPositionCache)) {
|
|
654
|
-
this.setState({
|
|
655
|
-
framePositions: new internal_cjs.PositionCache(originEl, frameEls, true, // isHorizontal
|
|
656
|
-
false),
|
|
657
|
-
});
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
const oldSegHeights = this.state.segHeights;
|
|
662
|
-
const newSegHeights = this.querySegHeights();
|
|
663
|
-
const limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
|
|
664
|
-
this.safeSetState({
|
|
665
|
-
// HACK to prevent oscillations of events being shown/hidden from max-event-rows
|
|
666
|
-
// Essentially, once you compute an element's height, never null-out.
|
|
667
|
-
// TODO: always display all events, as visibility:hidden?
|
|
668
|
-
segHeights: Object.assign(Object.assign({}, oldSegHeights), newSegHeights),
|
|
669
|
-
maxContentHeight: limitByContentHeight ? this.computeMaxContentHeight() : null,
|
|
670
|
-
});
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
querySegHeights() {
|
|
674
|
-
let segElMap = this.segHarnessRefs.currentMap;
|
|
675
|
-
let segHeights = {};
|
|
676
|
-
// get the max height amongst instance segs
|
|
677
|
-
for (let segUid in segElMap) {
|
|
678
|
-
let height = Math.round(segElMap[segUid].getBoundingClientRect().height);
|
|
679
|
-
segHeights[segUid] = Math.max(segHeights[segUid] || 0, height);
|
|
716
|
+
getHighlightSegs() {
|
|
717
|
+
let { props } = this;
|
|
718
|
+
if (props.eventDrag && props.eventDrag.segs.length) { // messy check
|
|
719
|
+
return props.eventDrag.segs;
|
|
680
720
|
}
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
computeMaxContentHeight() {
|
|
684
|
-
let firstKey = this.props.cells[0].key;
|
|
685
|
-
let cellEl = this.cellElRefs.currentMap[firstKey];
|
|
686
|
-
let fcContainerEl = this.fgElRefs.currentMap[firstKey];
|
|
687
|
-
return cellEl.getBoundingClientRect().bottom - fcContainerEl.getBoundingClientRect().top;
|
|
688
|
-
}
|
|
689
|
-
getCellEls() {
|
|
690
|
-
let elMap = this.cellElRefs.currentMap;
|
|
691
|
-
return this.props.cells.map((cell) => elMap[cell.key]);
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
TableRow.addStateEquality({
|
|
695
|
-
segHeights: internal_cjs.isPropsEqual,
|
|
696
|
-
});
|
|
697
|
-
function buildMirrorPlacements(mirrorSegs, colPlacements) {
|
|
698
|
-
if (!mirrorSegs.length) {
|
|
699
|
-
return [];
|
|
700
|
-
}
|
|
701
|
-
let topsByInstanceId = buildAbsoluteTopHash(colPlacements); // TODO: cache this at first render?
|
|
702
|
-
return mirrorSegs.map((seg) => ({
|
|
703
|
-
seg,
|
|
704
|
-
isVisible: true,
|
|
705
|
-
isAbsolute: true,
|
|
706
|
-
absoluteTop: topsByInstanceId[seg.eventRange.instance.instanceId],
|
|
707
|
-
marginTop: 0,
|
|
708
|
-
}));
|
|
709
|
-
}
|
|
710
|
-
function buildAbsoluteTopHash(colPlacements) {
|
|
711
|
-
let topsByInstanceId = {};
|
|
712
|
-
for (let placements of colPlacements) {
|
|
713
|
-
for (let placement of placements) {
|
|
714
|
-
topsByInstanceId[placement.seg.eventRange.instance.instanceId] = placement.absoluteTop;
|
|
721
|
+
if (props.eventResize && props.eventResize.segs.length) { // messy check
|
|
722
|
+
return props.eventResize.segs;
|
|
715
723
|
}
|
|
724
|
+
return props.dateSelectionSegs;
|
|
716
725
|
}
|
|
717
|
-
return topsByInstanceId;
|
|
718
726
|
}
|
|
719
727
|
|
|
720
|
-
class
|
|
728
|
+
class DayGridRows extends internal_cjs.DateComponent {
|
|
721
729
|
constructor() {
|
|
722
730
|
super(...arguments);
|
|
731
|
+
// memo
|
|
723
732
|
this.splitBusinessHourSegs = internal_cjs.memoize(splitSegsByRow);
|
|
724
733
|
this.splitBgEventSegs = internal_cjs.memoize(splitSegsByRow);
|
|
725
734
|
this.splitFgEventSegs = internal_cjs.memoize(splitSegsByRow);
|
|
726
735
|
this.splitDateSelectionSegs = internal_cjs.memoize(splitSegsByRow);
|
|
727
736
|
this.splitEventDrag = internal_cjs.memoize(splitInteractionByRow);
|
|
728
737
|
this.splitEventResize = internal_cjs.memoize(splitInteractionByRow);
|
|
729
|
-
|
|
738
|
+
// internal
|
|
739
|
+
this.rowHeightRefMap = new internal_cjs.RefMap((height, key) => {
|
|
740
|
+
// HACKy way of syncing RefMap results with prop
|
|
741
|
+
const { rowHeightRefMap } = this.props;
|
|
742
|
+
if (rowHeightRefMap) {
|
|
743
|
+
rowHeightRefMap.handleValue(height, key);
|
|
744
|
+
}
|
|
745
|
+
});
|
|
746
|
+
this.handleRootEl = (rootEl) => {
|
|
747
|
+
this.rootEl = rootEl;
|
|
748
|
+
if (rootEl) {
|
|
749
|
+
this.context.registerInteractiveComponent(this, {
|
|
750
|
+
el: rootEl,
|
|
751
|
+
isHitComboAllowed: this.props.isHitComboAllowed,
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
else {
|
|
755
|
+
this.context.unregisterInteractiveComponent(this);
|
|
756
|
+
}
|
|
757
|
+
};
|
|
730
758
|
}
|
|
731
759
|
render() {
|
|
732
|
-
let { props, context } = this;
|
|
733
|
-
let
|
|
734
|
-
let
|
|
735
|
-
let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);
|
|
760
|
+
let { props, state, context, rowHeightRefMap } = this;
|
|
761
|
+
let { options } = context;
|
|
762
|
+
let rowCnt = props.cellRows.length;
|
|
736
763
|
let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt);
|
|
764
|
+
let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);
|
|
765
|
+
let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt);
|
|
737
766
|
let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt);
|
|
738
767
|
let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt);
|
|
739
768
|
let eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt);
|
|
740
|
-
//
|
|
741
|
-
//
|
|
742
|
-
let
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
769
|
+
// whether the ROW should expand in height
|
|
770
|
+
// (not to be confused with whether the fg events within the row should be molded by height of row)
|
|
771
|
+
let isHeightAuto = internal_cjs.getIsHeightAuto(options);
|
|
772
|
+
// maintain at least aspectRatio for cells?
|
|
773
|
+
let rowMinHeight = (state.width != null && (rowCnt >= 7 || // TODO: better way to infer if across single-month boundary
|
|
774
|
+
isHeightAuto)) ? state.width / context.options.aspectRatio / 6 // okay to hardcode 6 (weeks) ?
|
|
775
|
+
: null;
|
|
776
|
+
return (preact_cjs.createElement("div", { className: 'fc-grow fc-flex-column', style: { width: props.width }, ref: this.handleRootEl }, props.cellRows.map((cells, row) => (preact_cjs.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,
|
|
777
|
+
// if not auto-height, distribute height of container somewhat evently to rows
|
|
778
|
+
// (treat all as zero, distribute height, then ensure min-heights -- the inner content height)
|
|
779
|
+
className: isHeightAuto ? '' : 'fc-grow fc-basis0',
|
|
780
|
+
// content
|
|
781
|
+
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,
|
|
782
|
+
// dimensions
|
|
783
|
+
colWidth: props.colWidth, minHeight: rowMinHeight,
|
|
784
|
+
// refs
|
|
785
|
+
heightRef: rowHeightRefMap.createRef(cells[0].key) })))));
|
|
749
786
|
}
|
|
750
787
|
componentDidMount() {
|
|
751
|
-
this.
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
// for if started with zero cells
|
|
755
|
-
this.registerInteractiveComponent();
|
|
756
|
-
}
|
|
757
|
-
registerInteractiveComponent() {
|
|
758
|
-
if (!this.rootEl) {
|
|
759
|
-
// HACK: need a daygrid wrapper parent to do positioning
|
|
760
|
-
// NOTE: a daygrid resource view w/o resources can have zero cells
|
|
761
|
-
const firstCellEl = this.rowRefs.currentMap[0].getCellEls()[0];
|
|
762
|
-
const rootEl = firstCellEl ? firstCellEl.closest('.fc-daygrid-body') : null;
|
|
763
|
-
if (rootEl) {
|
|
764
|
-
this.rootEl = rootEl;
|
|
765
|
-
this.context.registerInteractiveComponent(this, {
|
|
766
|
-
el: rootEl,
|
|
767
|
-
isHitComboAllowed: this.props.isHitComboAllowed,
|
|
768
|
-
});
|
|
769
|
-
}
|
|
770
|
-
}
|
|
788
|
+
this.detachWidth = internal_cjs.watchWidth(this.rootEl, (width) => {
|
|
789
|
+
this.setState({ width });
|
|
790
|
+
});
|
|
771
791
|
}
|
|
772
792
|
componentWillUnmount() {
|
|
773
|
-
|
|
774
|
-
this.context.unregisterInteractiveComponent(this);
|
|
775
|
-
this.rootEl = null;
|
|
776
|
-
}
|
|
793
|
+
this.detachWidth();
|
|
777
794
|
}
|
|
778
795
|
// Hit System
|
|
779
|
-
//
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
};
|
|
805
|
-
}
|
|
806
|
-
return null;
|
|
807
|
-
}
|
|
808
|
-
getCellEl(row, col) {
|
|
809
|
-
return this.rowRefs.currentMap[row].getCellEls()[col]; // TODO: not optimal
|
|
810
|
-
}
|
|
811
|
-
getCellRange(row, col) {
|
|
812
|
-
let start = this.props.cells[row][col].date;
|
|
813
|
-
let end = internal_cjs.addDays(start, 1);
|
|
814
|
-
return { start, end };
|
|
796
|
+
// -----------------------------------------------------------------------------------------------
|
|
797
|
+
queryHit(positionLeft, positionTop, elWidth) {
|
|
798
|
+
const { props, context } = this;
|
|
799
|
+
const colCnt = props.cellRows[0].length;
|
|
800
|
+
const { col, left, right } = computeColFromPosition(positionLeft, elWidth, props.colWidth, colCnt, context.isRtl);
|
|
801
|
+
const { row, top, bottom } = computeRowFromPosition(positionTop, props.cellRows, this.rowHeightRefMap.current);
|
|
802
|
+
const cell = props.cellRows[row][col];
|
|
803
|
+
const cellStartDate = cell.date;
|
|
804
|
+
const cellEndDate = internal_cjs.addDays(cellStartDate, 1);
|
|
805
|
+
return {
|
|
806
|
+
dateProfile: props.dateProfile,
|
|
807
|
+
dateSpan: Object.assign({ range: {
|
|
808
|
+
start: cellStartDate,
|
|
809
|
+
end: cellEndDate,
|
|
810
|
+
}, allDay: true }, cell.extraDateSpan),
|
|
811
|
+
// HACK. TODO: This is expensive to do every hit-query
|
|
812
|
+
dayEl: getCellEl(getRowEl(this.rootEl, row), col),
|
|
813
|
+
rect: {
|
|
814
|
+
left,
|
|
815
|
+
right,
|
|
816
|
+
top,
|
|
817
|
+
bottom,
|
|
818
|
+
},
|
|
819
|
+
layer: 0,
|
|
820
|
+
};
|
|
815
821
|
}
|
|
816
822
|
}
|
|
823
|
+
// Utils
|
|
824
|
+
// -------------------------------------------------------------------------------------------------
|
|
817
825
|
function isSegAllDay(seg) {
|
|
818
826
|
return seg.eventRange.def.allDay;
|
|
819
827
|
}
|
|
820
828
|
|
|
821
|
-
class
|
|
829
|
+
class HeaderRow extends internal_cjs.BaseComponent {
|
|
830
|
+
render() {
|
|
831
|
+
const { props } = this;
|
|
832
|
+
return (preact_cjs.createElement("div", { role: props.cellGroup ? undefined : 'row', className: [
|
|
833
|
+
props.cellGroup ? 'fc-flex-row' : 'fc-row',
|
|
834
|
+
props.className || '',
|
|
835
|
+
].join(' ') }, props.cells.map((cell) => (preact_cjs.createElement(preact_cjs.Fragment, { key: props.getHeaderModelKey(cell) }, props.renderHeaderContent(cell, props.tierNum, undefined, // innerHeightRef
|
|
836
|
+
props.colWidth))))));
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
function DayGridHeader(props) {
|
|
841
|
+
return (preact_cjs.createElement("div", { className: [
|
|
842
|
+
'fc-rowgroup',
|
|
843
|
+
'fc-content-box',
|
|
844
|
+
...(props.extraClassNames || []),
|
|
845
|
+
].join(' '), style: {
|
|
846
|
+
width: props.width,
|
|
847
|
+
paddingLeft: props.paddingLeft,
|
|
848
|
+
paddingRight: props.paddingRight,
|
|
849
|
+
} }, props.headerTiers.map((cells, tierNum) => (preact_cjs.createElement(HeaderRow, { key: tierNum, tierNum: tierNum, cells: cells, renderHeaderContent: props.renderHeaderContent, getHeaderModelKey: props.getHeaderModelKey, colWidth: props.colWidth })))));
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
class DayGridLayoutNormal extends internal_cjs.BaseComponent {
|
|
822
853
|
constructor() {
|
|
823
854
|
super(...arguments);
|
|
824
|
-
this.
|
|
825
|
-
|
|
855
|
+
this.handleScroller = (scroller) => {
|
|
856
|
+
internal_cjs.setRef(this.props.scrollerRef, scroller);
|
|
857
|
+
};
|
|
858
|
+
this.handleLeftScrollbarWidth = (leftScrollbarWidth) => {
|
|
859
|
+
this.setState({ leftScrollbarWidth });
|
|
860
|
+
};
|
|
861
|
+
this.handleRightScrollbarWidth = (rightScrollbarWidth) => {
|
|
862
|
+
this.setState({ rightScrollbarWidth });
|
|
863
|
+
};
|
|
826
864
|
}
|
|
827
865
|
render() {
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
} },
|
|
854
|
-
props.colGroupNode,
|
|
855
|
-
preact_cjs.createElement("tbody", { role: "presentation" },
|
|
856
|
-
preact_cjs.createElement(TableRows, { dateProfile: props.dateProfile, cells: props.cells, renderRowIntro: props.renderRowIntro, showWeekNumbers: props.showWeekNumbers, clientWidth: props.clientWidth, clientHeight: props.clientHeight, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, dayMaxEvents: dayMaxEvents, dayMaxEventRows: dayMaxEventRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed })))));
|
|
866
|
+
const { props, state, context } = this;
|
|
867
|
+
const { options } = context;
|
|
868
|
+
const verticalScrollbars = !props.forPrint && !internal_cjs.getIsHeightAuto(options);
|
|
869
|
+
const stickyHeaderDates = !props.forPrint && internal_cjs.getStickyHeaderDates(options);
|
|
870
|
+
return (preact_cjs.createElement(preact_cjs.Fragment, null,
|
|
871
|
+
options.dayHeaders && (preact_cjs.createElement(DayGridHeader, { headerTiers: props.headerTiers, renderHeaderContent: props.renderHeaderContent, getHeaderModelKey: props.getHeaderModelKey,
|
|
872
|
+
// render hooks
|
|
873
|
+
extraClassNames: [
|
|
874
|
+
'fc-daygrid-header',
|
|
875
|
+
stickyHeaderDates ? 'fc-sticky-header' : '',
|
|
876
|
+
],
|
|
877
|
+
// dimensions
|
|
878
|
+
paddingLeft: state.leftScrollbarWidth, paddingRight: state.rightScrollbarWidth })),
|
|
879
|
+
preact_cjs.createElement(internal_cjs.Scroller, { vertical: verticalScrollbars, leftScrollbarWidthRef: this.handleLeftScrollbarWidth, rightScrollbarWidthRef: this.handleRightScrollbarWidth, elClassNames: [
|
|
880
|
+
'fc-daygrid-body',
|
|
881
|
+
'fc-rowgroup',
|
|
882
|
+
'fc-flex-column',
|
|
883
|
+
verticalScrollbars ? 'fc-liquid' : '',
|
|
884
|
+
], ref: this.handleScroller },
|
|
885
|
+
preact_cjs.createElement(DayGridRows // .fc-grow
|
|
886
|
+
, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed,
|
|
887
|
+
// content
|
|
888
|
+
fgEventSegs: props.fgEventSegs, bgEventSegs: props.bgEventSegs, businessHourSegs: props.businessHourSegs, dateSelectionSegs: props.dateSelectionSegs, eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
|
|
889
|
+
// refs
|
|
890
|
+
rowHeightRefMap: props.rowHeightRefMap }))));
|
|
857
891
|
}
|
|
858
|
-
|
|
859
|
-
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
class DayGridLayoutPannable extends internal_cjs.BaseComponent {
|
|
895
|
+
constructor() {
|
|
896
|
+
super(...arguments);
|
|
897
|
+
this.headerScrollerRef = preact_cjs.createRef();
|
|
898
|
+
this.bodyScrollerRef = preact_cjs.createRef();
|
|
899
|
+
this.footerScrollerRef = preact_cjs.createRef();
|
|
900
|
+
// Sizing
|
|
901
|
+
// -----------------------------------------------------------------------------------------------
|
|
902
|
+
this.handleWidth = (width) => {
|
|
903
|
+
this.setState({ width });
|
|
904
|
+
};
|
|
905
|
+
this.handleLeftScrollbarWidth = (leftScrollbarWidth) => {
|
|
906
|
+
this.setState({ leftScrollbarWidth });
|
|
907
|
+
};
|
|
908
|
+
this.handleRightScrollbarWidth = (rightScrollbarWidth) => {
|
|
909
|
+
this.setState({ rightScrollbarWidth });
|
|
910
|
+
};
|
|
860
911
|
}
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
912
|
+
render() {
|
|
913
|
+
const { props, state, context } = this;
|
|
914
|
+
const { options } = context;
|
|
915
|
+
const verticalScrollbars = !props.forPrint && !internal_cjs.getIsHeightAuto(options);
|
|
916
|
+
const stickyHeaderDates = !props.forPrint && internal_cjs.getStickyHeaderDates(options);
|
|
917
|
+
const stickyFooterScrollbar = !props.forPrint && internal_cjs.getStickyFooterScrollbar(options);
|
|
918
|
+
const colCnt = props.cellRows[0].length;
|
|
919
|
+
const [canvasWidth, colWidth] = computeColWidth(colCnt, props.dayMinWidth, state.width);
|
|
920
|
+
return (preact_cjs.createElement(preact_cjs.Fragment, null,
|
|
921
|
+
options.dayHeaders && (preact_cjs.createElement(internal_cjs.Scroller, { horizontal: true, hideScrollbars: true, elClassNames: [
|
|
922
|
+
'fc-daygrid-header',
|
|
923
|
+
'fc-rowgroup',
|
|
924
|
+
stickyHeaderDates ? 'fc-sticky-header' : ''
|
|
925
|
+
], ref: this.headerScrollerRef },
|
|
926
|
+
preact_cjs.createElement(DayGridHeader, { headerTiers: props.headerTiers, renderHeaderContent: props.renderHeaderContent, getHeaderModelKey: props.getHeaderModelKey,
|
|
927
|
+
// dimensions
|
|
928
|
+
colWidth: colWidth, width: canvasWidth, paddingLeft: state.leftScrollbarWidth, paddingRight: state.rightScrollbarWidth }))),
|
|
929
|
+
preact_cjs.createElement(internal_cjs.Scroller, { vertical: verticalScrollbars, horizontal: true, hideScrollbars: stickyFooterScrollbar, widthRef: this.handleWidth, leftScrollbarWidthRef: this.handleLeftScrollbarWidth, rightScrollbarWidthRef: this.handleRightScrollbarWidth, elClassNames: [
|
|
930
|
+
'fc-daygrid-body',
|
|
931
|
+
'fc-rowgroup',
|
|
932
|
+
'fc-flex-column',
|
|
933
|
+
verticalScrollbars ? 'fc-liquid' : '',
|
|
934
|
+
], ref: this.bodyScrollerRef },
|
|
935
|
+
preact_cjs.createElement(DayGridRows // .fc-grow
|
|
936
|
+
, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed,
|
|
937
|
+
// content
|
|
938
|
+
fgEventSegs: props.fgEventSegs, bgEventSegs: props.bgEventSegs, businessHourSegs: props.businessHourSegs, dateSelectionSegs: props.dateSelectionSegs, eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
|
|
939
|
+
// dimensions
|
|
940
|
+
colWidth: colWidth, width: canvasWidth,
|
|
941
|
+
// refs
|
|
942
|
+
rowHeightRefMap: props.rowHeightRefMap })),
|
|
943
|
+
Boolean(stickyFooterScrollbar) && (preact_cjs.createElement(internal_cjs.Scroller, { ref: this.footerScrollerRef, horizontal: true, elClassNames: ['fc-sticky-footer'], elStyle: {
|
|
944
|
+
marginTop: '-1px', // HACK
|
|
945
|
+
} },
|
|
946
|
+
preact_cjs.createElement("div", { style: {
|
|
947
|
+
width: canvasWidth,
|
|
948
|
+
height: '1px', // HACK
|
|
949
|
+
} })))));
|
|
868
950
|
}
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
)
|
|
877
|
-
const subjectEl = getScrollSubjectEl(this.elRef.current, this.props.dateProfile);
|
|
878
|
-
if (subjectEl) {
|
|
879
|
-
const originEl = subjectEl.closest('.fc-daygrid-body');
|
|
880
|
-
const scrollEl = originEl.closest('.fc-scroller');
|
|
881
|
-
const scrollTop = subjectEl.getBoundingClientRect().top -
|
|
882
|
-
originEl.getBoundingClientRect().top;
|
|
883
|
-
scrollEl.scrollTop = scrollTop ? (scrollTop + 1) : 0; // overcome border
|
|
884
|
-
}
|
|
885
|
-
this.needsScrollReset = false;
|
|
886
|
-
}
|
|
951
|
+
// Lifecycle
|
|
952
|
+
// -----------------------------------------------------------------------------------------------
|
|
953
|
+
componentDidMount() {
|
|
954
|
+
// scroller
|
|
955
|
+
const ScrollerSyncer = internal_cjs.getScrollerSyncerClass(this.context.pluginHooks);
|
|
956
|
+
this.syncedScroller = new ScrollerSyncer(true); // horizontal=true
|
|
957
|
+
internal_cjs.setRef(this.props.scrollerRef, this.syncedScroller);
|
|
958
|
+
this.updateSyncedScroller();
|
|
887
959
|
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
if (dateProfile.currentRangeUnit.match(/year|month/)) {
|
|
892
|
-
el = containerEl.querySelector(`[data-date="${internal_cjs.formatIsoMonthStr(dateProfile.currentDate)}-01"]`);
|
|
893
|
-
// even if view is month-based, first-of-month might be hidden...
|
|
960
|
+
componentDidUpdate() {
|
|
961
|
+
// scroller
|
|
962
|
+
this.updateSyncedScroller();
|
|
894
963
|
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
964
|
+
componentWillUnmount() {
|
|
965
|
+
// scroller
|
|
966
|
+
this.syncedScroller.destroy();
|
|
967
|
+
}
|
|
968
|
+
// Scrolling
|
|
969
|
+
// -----------------------------------------------------------------------------------------------
|
|
970
|
+
updateSyncedScroller() {
|
|
971
|
+
this.syncedScroller.handleChildren([
|
|
972
|
+
this.headerScrollerRef.current,
|
|
973
|
+
this.bodyScrollerRef.current,
|
|
974
|
+
this.footerScrollerRef.current,
|
|
975
|
+
]);
|
|
898
976
|
}
|
|
899
|
-
return el;
|
|
900
977
|
}
|
|
901
978
|
|
|
902
|
-
class
|
|
979
|
+
class DayGridLayout extends internal_cjs.BaseComponent {
|
|
903
980
|
constructor() {
|
|
904
981
|
super(...arguments);
|
|
905
|
-
|
|
982
|
+
// ref
|
|
983
|
+
this.scrollerRef = preact_cjs.createRef();
|
|
984
|
+
this.rowHeightRefMap = new internal_cjs.RefMap(() => {
|
|
985
|
+
internal_cjs.afterSize(this.updateScrollY);
|
|
986
|
+
});
|
|
987
|
+
// internal
|
|
988
|
+
this.scrollDate = null;
|
|
989
|
+
this.updateScrollY = () => {
|
|
990
|
+
const rowHeightMap = this.rowHeightRefMap.current;
|
|
991
|
+
const scroller = this.scrollerRef.current;
|
|
992
|
+
// Since updateScrollY is called by rowHeightRefMap, could be called with null during cleanup,
|
|
993
|
+
// and the scroller might not exist
|
|
994
|
+
if (scroller && this.scrollDate) {
|
|
995
|
+
let scrollTop = computeTopFromDate(this.scrollDate, this.props.cellRows, rowHeightMap, 1);
|
|
996
|
+
if (scrollTop != null) {
|
|
997
|
+
if (scrollTop) {
|
|
998
|
+
scrollTop++; // clear top border
|
|
999
|
+
}
|
|
1000
|
+
scroller.scrollTo({ y: scrollTop });
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
this.clearScroll = () => {
|
|
1005
|
+
this.scrollDate = null;
|
|
1006
|
+
};
|
|
906
1007
|
}
|
|
907
|
-
|
|
908
|
-
|
|
1008
|
+
render() {
|
|
1009
|
+
const { props, context } = this;
|
|
1010
|
+
const { options } = context;
|
|
1011
|
+
const commonLayoutProps = Object.assign(Object.assign({}, props), { scrollerRef: this.scrollerRef, rowHeightRefMap: this.rowHeightRefMap });
|
|
1012
|
+
return (preact_cjs.createElement(internal_cjs.ViewContainer, { viewSpec: context.viewSpec, elClasses: [props.className, 'fc-flex-column', 'fc-border'] }, options.dayMinWidth ? (preact_cjs.createElement(DayGridLayoutPannable, Object.assign({}, commonLayoutProps, { dayMinWidth: options.dayMinWidth }))) : (preact_cjs.createElement(DayGridLayoutNormal, Object.assign({}, commonLayoutProps)))));
|
|
1013
|
+
}
|
|
1014
|
+
// Lifecycle
|
|
1015
|
+
// -----------------------------------------------------------------------------------------------
|
|
1016
|
+
componentDidMount() {
|
|
1017
|
+
this.resetScroll();
|
|
1018
|
+
this.scrollerRef.current.addScrollEndListener(this.clearScroll);
|
|
1019
|
+
}
|
|
1020
|
+
componentDidUpdate(prevProps) {
|
|
1021
|
+
if (prevProps.dateProfile !== this.props.dateProfile && this.context.options.scrollTimeReset) {
|
|
1022
|
+
this.resetScroll();
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
componentWillUnmount() {
|
|
1026
|
+
this.scrollerRef.current.removeScrollEndListener(this.clearScroll);
|
|
1027
|
+
}
|
|
1028
|
+
// Scrolling
|
|
1029
|
+
// -----------------------------------------------------------------------------------------------
|
|
1030
|
+
resetScroll() {
|
|
1031
|
+
this.scrollDate = this.props.dateProfile.currentDate;
|
|
1032
|
+
this.updateScrollY();
|
|
1033
|
+
// updateScrollX
|
|
1034
|
+
const scroller = this.scrollerRef.current;
|
|
1035
|
+
scroller.scrollTo({ x: 0 });
|
|
909
1036
|
}
|
|
910
1037
|
}
|
|
911
1038
|
|
|
912
|
-
|
|
1039
|
+
const WEEKDAY_FORMAT = internal_cjs.createFormatter({ weekday: 'long' });
|
|
1040
|
+
class DayOfWeekHeaderCell extends internal_cjs.BaseComponent {
|
|
913
1041
|
constructor() {
|
|
914
1042
|
super(...arguments);
|
|
915
|
-
|
|
916
|
-
this.
|
|
1043
|
+
// ref
|
|
1044
|
+
this.innerElRef = preact_cjs.createRef();
|
|
917
1045
|
}
|
|
918
1046
|
render() {
|
|
919
1047
|
let { props, context } = this;
|
|
920
|
-
|
|
1048
|
+
let { dateEnv, theme, viewApi, options } = context;
|
|
1049
|
+
let date = internal_cjs.addDays(new Date(259200000), props.dow); // start with Sun, 04 Jan 1970 00:00:00 GMT
|
|
1050
|
+
let dateMeta = {
|
|
1051
|
+
dow: props.dow,
|
|
1052
|
+
isDisabled: false,
|
|
1053
|
+
isFuture: false,
|
|
1054
|
+
isPast: false,
|
|
1055
|
+
isToday: false,
|
|
1056
|
+
isOther: false,
|
|
1057
|
+
};
|
|
1058
|
+
let text = dateEnv.format(date, props.dayHeaderFormat);
|
|
1059
|
+
let renderProps = Object.assign(Object.assign(Object.assign(Object.assign({ date }, dateMeta), { view: viewApi }), props.extraRenderProps), { text });
|
|
1060
|
+
return (preact_cjs.createElement(internal_cjs.ContentContainer, { elTag: 'div', elClasses: [
|
|
1061
|
+
...internal_cjs.getDayClassNames(dateMeta, theme),
|
|
1062
|
+
...(props.extraClassNames || []),
|
|
1063
|
+
'fc-header-cell',
|
|
1064
|
+
'fc-cell',
|
|
1065
|
+
props.colWidth != null ? '' : 'fc-liquid',
|
|
1066
|
+
'fc-flex-column',
|
|
1067
|
+
'fc-align-center',
|
|
1068
|
+
], elAttrs: props.extraDataAttrs, elStyle: {
|
|
1069
|
+
width: props.colWidth != null // TODO: DRY
|
|
1070
|
+
? props.colWidth * (props.colSpan || 1)
|
|
1071
|
+
: undefined,
|
|
1072
|
+
}, renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => (preact_cjs.createElement("div", { ref: this.innerElRef, className: [
|
|
1073
|
+
'fc-flex-column',
|
|
1074
|
+
props.isSticky ? 'fc-sticky-x' : '',
|
|
1075
|
+
].join(' ') },
|
|
1076
|
+
preact_cjs.createElement(InnerContent, { elTag: "a", elClasses: [
|
|
1077
|
+
'fc-cell-inner',
|
|
1078
|
+
'fc-padding-sm',
|
|
1079
|
+
], elAttrs: {
|
|
1080
|
+
'aria-label': dateEnv.format(date, WEEKDAY_FORMAT),
|
|
1081
|
+
} })))));
|
|
1082
|
+
}
|
|
1083
|
+
componentDidMount() {
|
|
1084
|
+
const innerEl = this.innerElRef.current; // TODO: make dynamic with useEffect
|
|
1085
|
+
// TODO: only attach this if refs props present
|
|
1086
|
+
this.disconectInnerHeight = internal_cjs.watchHeight(innerEl, (height) => {
|
|
1087
|
+
internal_cjs.setRef(this.props.innerHeightRef, height);
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
componentWillUnmount() {
|
|
1091
|
+
this.disconectInnerHeight();
|
|
1092
|
+
internal_cjs.setRef(this.props.innerHeightRef, null);
|
|
921
1093
|
}
|
|
922
1094
|
}
|
|
923
1095
|
|
|
924
|
-
|
|
1096
|
+
function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) {
|
|
1097
|
+
return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt);
|
|
1098
|
+
}
|
|
1099
|
+
// Computes a default column header formatting string if `colFormat` is not explicitly defined
|
|
1100
|
+
function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
|
|
1101
|
+
// if more than one week row, or if there are a lot of columns with not much space,
|
|
1102
|
+
// put just the day numbers will be in each cell
|
|
1103
|
+
if (!datesRepDistinctDays || dayCnt > 10) {
|
|
1104
|
+
return internal_cjs.createFormatter({ weekday: 'short' }); // "Sat"
|
|
1105
|
+
}
|
|
1106
|
+
if (dayCnt > 1) {
|
|
1107
|
+
return internal_cjs.createFormatter({ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }); // "Sat 11/12"
|
|
1108
|
+
}
|
|
1109
|
+
return internal_cjs.createFormatter({ weekday: 'long' }); // "Saturday"
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
class DayGridView extends internal_cjs.BaseComponent {
|
|
925
1113
|
constructor() {
|
|
926
1114
|
super(...arguments);
|
|
1115
|
+
// memo
|
|
927
1116
|
this.buildDayTableModel = internal_cjs.memoize(buildDayTableModel);
|
|
928
|
-
this.
|
|
929
|
-
this.
|
|
930
|
-
//
|
|
1117
|
+
this.buildHeaderTiers = internal_cjs.memoize(buildHeaderTiers);
|
|
1118
|
+
this.createDayHeaderFormatter = internal_cjs.memoize(createDayHeaderFormatter);
|
|
1119
|
+
// internal
|
|
1120
|
+
this.slicer = new DayTableSlicer();
|
|
931
1121
|
}
|
|
932
1122
|
render() {
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1123
|
+
const { props, context } = this;
|
|
1124
|
+
const { options } = context;
|
|
1125
|
+
const dayTableModel = this.buildDayTableModel(props.dateProfile, context.dateProfileGenerator);
|
|
1126
|
+
const datesRepDistinctDays = dayTableModel.rowCnt === 1;
|
|
1127
|
+
const headerTiers = this.buildHeaderTiers(dayTableModel.headerDates, datesRepDistinctDays);
|
|
1128
|
+
const slicedProps = this.slicer.sliceProps(props, props.dateProfile, options.nextDayThreshold, context, dayTableModel);
|
|
1129
|
+
const dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dayTableModel.colCnt);
|
|
1130
|
+
return (preact_cjs.createElement(internal_cjs.NowTimer, { unit: "day" }, (nowDate, todayRange) => (preact_cjs.createElement(DayGridLayout, { dateProfile: props.dateProfile, todayRange: todayRange, cellRows: dayTableModel.cellRows, forPrint: props.forPrint, className: 'fc-daygrid-view',
|
|
1131
|
+
// header content
|
|
1132
|
+
headerTiers: headerTiers, renderHeaderContent: (model, tier, innerHeightRef, colWidth) => {
|
|
1133
|
+
if (model.date) {
|
|
1134
|
+
return (preact_cjs.createElement(DateHeaderCell, Object.assign({}, model, { dateProfile: props.dateProfile, todayRange: todayRange, navLink: dayTableModel.colCnt > 1, dayHeaderFormat: dayHeaderFormat, colSpan: model.colSpan, colWidth: colWidth })));
|
|
1135
|
+
}
|
|
1136
|
+
else {
|
|
1137
|
+
return (preact_cjs.createElement(DayOfWeekHeaderCell, Object.assign({}, model, { dayHeaderFormat: dayHeaderFormat, colSpan: model.colSpan, colWidth: colWidth })));
|
|
1138
|
+
}
|
|
1139
|
+
}, getHeaderModelKey: (model) => {
|
|
1140
|
+
// can use model.key???
|
|
1141
|
+
if (model.date) {
|
|
1142
|
+
return model.date.toUTCString();
|
|
1143
|
+
}
|
|
1144
|
+
return model.dow;
|
|
1145
|
+
},
|
|
1146
|
+
// body content
|
|
1147
|
+
fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection }))));
|
|
941
1148
|
}
|
|
942
1149
|
}
|
|
943
|
-
function buildDayTableModel(dateProfile, dateProfileGenerator) {
|
|
944
|
-
let daySeries = new internal_cjs.DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
|
|
945
|
-
return new internal_cjs.DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
|
|
946
|
-
}
|
|
947
1150
|
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
dateEnv: props.dateEnv,
|
|
1151
|
+
/*
|
|
1152
|
+
TODO: is it even worth doing this "advanced" version?
|
|
1153
|
+
*/
|
|
1154
|
+
class HeaderRowAdvanced extends internal_cjs.BaseComponent {
|
|
1155
|
+
constructor() {
|
|
1156
|
+
super(...arguments);
|
|
1157
|
+
// ref
|
|
1158
|
+
this.innerHeightRefMap = new internal_cjs.RefMap(() => {
|
|
1159
|
+
internal_cjs.afterSize(this.handleInnerHeights);
|
|
958
1160
|
});
|
|
1161
|
+
this.handleInnerHeights = () => {
|
|
1162
|
+
const innerHeightMap = this.innerHeightRefMap.current;
|
|
1163
|
+
let max = 0;
|
|
1164
|
+
for (const innerHeight of innerHeightMap.values()) {
|
|
1165
|
+
max = Math.max(max, innerHeight);
|
|
1166
|
+
}
|
|
1167
|
+
if (this.currentInnerHeight !== max) {
|
|
1168
|
+
this.currentInnerHeight = max;
|
|
1169
|
+
internal_cjs.setRef(this.props.innerHeightRef, max);
|
|
1170
|
+
}
|
|
1171
|
+
};
|
|
959
1172
|
}
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
start = dateEnv.startOfWeek(start);
|
|
968
|
-
// make end-of-week if not already
|
|
969
|
-
endOfWeek = dateEnv.startOfWeek(end);
|
|
970
|
-
if (endOfWeek.valueOf() !== end.valueOf()) {
|
|
971
|
-
end = internal_cjs.addWeeks(endOfWeek, 1);
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
// ensure 6 weeks
|
|
975
|
-
if (props.fixedWeekCount) {
|
|
976
|
-
// TODO: instead of these date-math gymnastics (for multimonth view),
|
|
977
|
-
// compute dateprofiles of all months, then use start of first and end of last.
|
|
978
|
-
let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth(internal_cjs.addDays(currentRange.end, -1)));
|
|
979
|
-
let rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
|
|
980
|
-
internal_cjs.diffWeeks(lastMonthRenderStart, end));
|
|
981
|
-
end = internal_cjs.addWeeks(end, 6 - rowCnt);
|
|
1173
|
+
render() {
|
|
1174
|
+
const { props } = this;
|
|
1175
|
+
return (preact_cjs.createElement("div", { role: 'row', className: 'fc-row', style: { height: props.height } }, props.cells.map((cell) => {
|
|
1176
|
+
const key = props.getHeaderModelKey(cell);
|
|
1177
|
+
return (preact_cjs.createElement(preact_cjs.Fragment, { key: props.getHeaderModelKey(cell) }, props.renderHeaderContent(cell, props.tierNum, this.innerHeightRefMap.createRef(key), // innerHeightRef
|
|
1178
|
+
props.colWidth)));
|
|
1179
|
+
})));
|
|
982
1180
|
}
|
|
983
|
-
return { start, end };
|
|
984
1181
|
}
|
|
985
1182
|
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
exports.
|
|
990
|
-
exports.
|
|
1183
|
+
exports.COMPACT_CELL_WIDTH = COMPACT_CELL_WIDTH;
|
|
1184
|
+
exports.DateHeaderCell = DateHeaderCell;
|
|
1185
|
+
exports.DayGridLayout = DayGridLayout;
|
|
1186
|
+
exports.DayGridRow = DayGridRow;
|
|
1187
|
+
exports.DayGridRows = DayGridRows;
|
|
1188
|
+
exports.DayGridView = DayGridView;
|
|
1189
|
+
exports.DayOfWeekHeaderCell = DayOfWeekHeaderCell;
|
|
991
1190
|
exports.DayTableSlicer = DayTableSlicer;
|
|
992
|
-
exports.
|
|
1191
|
+
exports.HeaderRow = HeaderRow;
|
|
1192
|
+
exports.HeaderRowAdvanced = HeaderRowAdvanced;
|
|
993
1193
|
exports.TableDateProfileGenerator = TableDateProfileGenerator;
|
|
994
|
-
exports.TableRows = TableRows;
|
|
995
|
-
exports.TableView = TableView;
|
|
996
1194
|
exports.buildDayTableModel = buildDayTableModel;
|
|
997
1195
|
exports.buildDayTableRenderRange = buildDayTableRenderRange;
|
|
1196
|
+
exports.computeColFromPosition = computeColFromPosition;
|
|
1197
|
+
exports.computeColWidth = computeColWidth;
|
|
1198
|
+
exports.createDayHeaderFormatter = createDayHeaderFormatter;
|
|
1199
|
+
exports.getCellEl = getCellEl;
|
|
1200
|
+
exports.getRowEl = getRowEl;
|