@fullcalendar/daygrid 6.1.14 → 7.0.0-beta.0
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 +867 -679
- package/index.global.min.js +2 -2
- package/index.js +2 -2
- package/internal.cjs +901 -713
- package/internal.d.ts +206 -80
- package/internal.js +890 -711
- package/package.json +2 -2
package/internal.cjs
CHANGED
|
@@ -5,128 +5,251 @@ 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) {
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
94
|
+
const rowHeight = rowHeightMap.get(key);
|
|
95
|
+
if (rowHeight == null) {
|
|
96
|
+
return; // denote unknown
|
|
97
|
+
}
|
|
98
|
+
top += rowHeight;
|
|
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);
|
|
83
123
|
}
|
|
84
|
-
return (preact_cjs.createElement(internal_cjs.ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
|
|
85
|
-
preact_cjs.createElement(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: props.forPrint, colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }], sections: sections })));
|
|
86
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();
|
|
96
204
|
}
|
|
97
|
-
return byRow;
|
|
98
205
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
206
|
+
|
|
207
|
+
function splitSegsByRow(segs, rowCnt) {
|
|
208
|
+
const byRow = [];
|
|
209
|
+
for (let row = 0; row < rowCnt; row++) {
|
|
210
|
+
byRow[row] = [];
|
|
103
211
|
}
|
|
104
|
-
for (
|
|
105
|
-
|
|
212
|
+
for (const seg of segs) {
|
|
213
|
+
byRow[seg.row].push(seg);
|
|
106
214
|
}
|
|
107
|
-
return
|
|
215
|
+
return byRow;
|
|
108
216
|
}
|
|
109
217
|
function splitInteractionByRow(ui, rowCnt) {
|
|
110
|
-
|
|
218
|
+
const byRow = [];
|
|
111
219
|
if (!ui) {
|
|
112
|
-
for (let
|
|
113
|
-
byRow[
|
|
220
|
+
for (let row = 0; row < rowCnt; row++) {
|
|
221
|
+
byRow[row] = null;
|
|
114
222
|
}
|
|
115
223
|
}
|
|
116
224
|
else {
|
|
117
|
-
for (let
|
|
118
|
-
byRow[
|
|
225
|
+
for (let row = 0; row < rowCnt; row++) {
|
|
226
|
+
byRow[row] = {
|
|
119
227
|
affectedInstances: ui.affectedInstances,
|
|
120
228
|
isEvent: ui.isEvent,
|
|
121
229
|
segs: [],
|
|
122
230
|
};
|
|
123
231
|
}
|
|
124
|
-
for (
|
|
232
|
+
for (const seg of ui.segs) {
|
|
125
233
|
byRow[seg.row].segs.push(seg);
|
|
126
234
|
}
|
|
127
235
|
}
|
|
128
236
|
return byRow;
|
|
129
237
|
}
|
|
238
|
+
function splitSegsByCol(segs, colCnt) {
|
|
239
|
+
let byCol = [];
|
|
240
|
+
for (let col = 0; col < colCnt; col++) {
|
|
241
|
+
byCol.push([]);
|
|
242
|
+
}
|
|
243
|
+
for (let seg of segs) {
|
|
244
|
+
for (let col = seg.firstCol; col <= seg.lastCol; col++) {
|
|
245
|
+
if (seg.firstCol !== col) {
|
|
246
|
+
seg = Object.assign(Object.assign({}, seg), { firstCol: col, lastCol: col, isStart: false, isEnd: seg.isEnd && seg.lastCol === col, isStandin: true });
|
|
247
|
+
}
|
|
248
|
+
byCol[col].push(seg);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return byCol;
|
|
252
|
+
}
|
|
130
253
|
|
|
131
254
|
const DEFAULT_TABLE_EVENT_TIME_FORMAT = internal_cjs.createFormatter({
|
|
132
255
|
hour: 'numeric',
|
|
@@ -144,14 +267,14 @@ function hasListItemDisplay(seg) {
|
|
|
144
267
|
);
|
|
145
268
|
}
|
|
146
269
|
|
|
147
|
-
class
|
|
270
|
+
class DayGridBlockEvent extends internal_cjs.BaseComponent {
|
|
148
271
|
render() {
|
|
149
272
|
let { props } = this;
|
|
150
273
|
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.seg.eventRange.def.allDay })));
|
|
151
274
|
}
|
|
152
275
|
}
|
|
153
276
|
|
|
154
|
-
class
|
|
277
|
+
class DayGridListEvent extends internal_cjs.BaseComponent {
|
|
155
278
|
render() {
|
|
156
279
|
let { props, context } = this;
|
|
157
280
|
let { options } = context;
|
|
@@ -168,80 +291,83 @@ function renderInnerContent(renderProps) {
|
|
|
168
291
|
preact_cjs.createElement("div", { className: "fc-event-title" }, renderProps.event.title || preact_cjs.createElement(preact_cjs.Fragment, null, "\u00A0"))));
|
|
169
292
|
}
|
|
170
293
|
|
|
171
|
-
class
|
|
172
|
-
constructor() {
|
|
173
|
-
super(...arguments);
|
|
174
|
-
this.compileSegs = internal_cjs.memoize(compileSegs);
|
|
175
|
-
}
|
|
294
|
+
class DayGridMoreLink extends internal_cjs.BaseComponent {
|
|
176
295
|
render() {
|
|
177
296
|
let { props } = this;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
297
|
+
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: () => {
|
|
298
|
+
let forcedInvisibleMap = // TODO: more convenient/DRY
|
|
299
|
+
(props.eventDrag ? props.eventDrag.affectedInstances : null) ||
|
|
181
300
|
(props.eventResize ? props.eventResize.affectedInstances : null) ||
|
|
182
301
|
{};
|
|
183
|
-
return (preact_cjs.createElement(preact_cjs.Fragment, null,
|
|
302
|
+
return (preact_cjs.createElement(preact_cjs.Fragment, null, props.segs.map((seg) => {
|
|
184
303
|
let instanceId = seg.eventRange.instance.instanceId;
|
|
185
|
-
return (preact_cjs.createElement("div", {
|
|
186
|
-
visibility:
|
|
187
|
-
} }, hasListItemDisplay(seg) ? (preact_cjs.createElement(
|
|
304
|
+
return (preact_cjs.createElement("div", { key: instanceId, style: {
|
|
305
|
+
visibility: forcedInvisibleMap[instanceId] ? 'hidden' : '',
|
|
306
|
+
} }, hasListItemDisplay(seg) ? (preact_cjs.createElement(DayGridListEvent, Object.assign({ seg: seg, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, internal_cjs.getSegMeta(seg, props.todayRange)))) : (preact_cjs.createElement(DayGridBlockEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, internal_cjs.getSegMeta(seg, props.todayRange))))));
|
|
188
307
|
})));
|
|
189
308
|
} }));
|
|
190
309
|
}
|
|
191
310
|
}
|
|
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
311
|
|
|
204
|
-
|
|
205
|
-
class TableCell extends internal_cjs.DateComponent {
|
|
312
|
+
class DayGridCell extends internal_cjs.DateComponent {
|
|
206
313
|
constructor() {
|
|
207
314
|
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
|
-
};
|
|
315
|
+
// ref
|
|
316
|
+
this.innerElRef = preact_cjs.createRef();
|
|
317
|
+
this.headerWrapElRef = preact_cjs.createRef();
|
|
216
318
|
}
|
|
217
319
|
render() {
|
|
218
|
-
let {
|
|
320
|
+
let { props, context } = this;
|
|
219
321
|
let { options, dateEnv } = context;
|
|
220
|
-
|
|
221
|
-
// TODO: memoize this?
|
|
322
|
+
// TODO: memoize this
|
|
222
323
|
const isMonthStart = props.showDayNumber &&
|
|
223
|
-
shouldDisplayMonthStart(date, dateProfile.currentRange, dateEnv);
|
|
224
|
-
return (preact_cjs.createElement(internal_cjs.DayCellContainer, { elTag: "
|
|
225
|
-
'fc-daygrid-
|
|
324
|
+
shouldDisplayMonthStart(props.date, props.dateProfile.currentRange, dateEnv);
|
|
325
|
+
return (preact_cjs.createElement(internal_cjs.DayCellContainer, { elTag: "div", elClasses: [
|
|
326
|
+
'fc-daygrid-cell',
|
|
327
|
+
'fc-cell',
|
|
328
|
+
props.width != null ? '' : 'fc-liquid',
|
|
329
|
+
'fc-flex-column',
|
|
226
330
|
...(props.extraClassNames || []),
|
|
227
|
-
], elAttrs: Object.assign(Object.assign(
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
331
|
+
], elAttrs: Object.assign(Object.assign({}, props.extraDataAttrs), { role: 'gridcell' }), elStyle: {
|
|
332
|
+
width: props.width
|
|
333
|
+
}, 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: [
|
|
334
|
+
'fc-daygrid-cell-inner',
|
|
335
|
+
props.fgLiquidHeight ? 'fc-liquid' : ''
|
|
336
|
+
].join(' ') },
|
|
337
|
+
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
338
|
preact_cjs.createElement(InnerContent, { elTag: "a", elClasses: [
|
|
232
|
-
'fc-daygrid-
|
|
339
|
+
'fc-daygrid-cell-number',
|
|
233
340
|
isMonthStart && 'fc-daygrid-month-start',
|
|
234
|
-
], elAttrs:
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
preact_cjs.createElement("div", { className: "fc-daygrid-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
341
|
+
], elAttrs: internal_cjs.buildNavLinkAttrs(context, props.date) })))),
|
|
342
|
+
preact_cjs.createElement("div", { className: "fc-daygrid-cell-main", style: {
|
|
343
|
+
height: props.fgLiquidHeight ? '' : props.fgHeight
|
|
344
|
+
} }, props.fg),
|
|
345
|
+
preact_cjs.createElement("div", { className: "fc-daygrid-cell-footer", style: props.fgLiquidHeight
|
|
346
|
+
? { position: 'relative', top: props.fgHeight }
|
|
347
|
+
: {} },
|
|
348
|
+
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 })),
|
|
349
|
+
props.bg))));
|
|
350
|
+
}
|
|
351
|
+
componentDidMount() {
|
|
352
|
+
const innerEl = this.innerElRef.current; // TODO: make dynamic with useEffect
|
|
353
|
+
const headerWrapEl = this.headerWrapElRef.current; // "
|
|
354
|
+
// TODO: only attach this if refs props present
|
|
355
|
+
this.detachInnerHeight = internal_cjs.watchHeight(innerEl, (height) => {
|
|
356
|
+
internal_cjs.setRef(this.props.innerHeightRef, height);
|
|
357
|
+
});
|
|
358
|
+
this.detachHeaderHeight = internal_cjs.watchHeight(headerWrapEl, (height) => {
|
|
359
|
+
internal_cjs.setRef(this.props.headerHeightRef, height);
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
componentWillUnmount() {
|
|
363
|
+
this.detachInnerHeight();
|
|
364
|
+
this.detachHeaderHeight();
|
|
365
|
+
internal_cjs.setRef(this.props.innerHeightRef, null);
|
|
366
|
+
internal_cjs.setRef(this.props.headerHeightRef, null);
|
|
243
367
|
}
|
|
244
368
|
}
|
|
369
|
+
// Utils
|
|
370
|
+
// -------------------------------------------------------------------------------------------------
|
|
245
371
|
function renderTopInner(props) {
|
|
246
372
|
return props.dayNumberText || preact_cjs.createElement(preact_cjs.Fragment, null, "\u00A0");
|
|
247
373
|
}
|
|
@@ -261,26 +387,43 @@ function shouldDisplayMonthStart(date, currentRange, dateEnv) {
|
|
|
261
387
|
(dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf()));
|
|
262
388
|
}
|
|
263
389
|
|
|
264
|
-
|
|
390
|
+
/*
|
|
391
|
+
Unique per-START-column, good for cataloging by top
|
|
392
|
+
*/
|
|
393
|
+
function getSegStartId(seg) {
|
|
265
394
|
return seg.eventRange.instance.instanceId + ':' + seg.firstCol;
|
|
266
395
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
function
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
396
|
+
/*
|
|
397
|
+
Unique per-START-and-END-column, good for cataloging by width/height
|
|
398
|
+
*/
|
|
399
|
+
function getSegSpanId(seg) {
|
|
400
|
+
return getSegStartId(seg) + ':' + seg.lastCol;
|
|
401
|
+
}
|
|
402
|
+
function computeFgSegVerticals(segs, segHeightMap, // keyed by segSpanId
|
|
403
|
+
cells, topOrigin, maxHeight, strictOrder, dayMaxEvents, dayMaxEventRows) {
|
|
404
|
+
// initialize column-based arrays
|
|
405
|
+
const colCnt = cells.length;
|
|
406
|
+
const hiddenSegsByCol = [];
|
|
407
|
+
const heightsByCol = [];
|
|
408
|
+
for (let col = 0; col < colCnt; col++) {
|
|
409
|
+
hiddenSegsByCol.push([]);
|
|
410
|
+
heightsByCol.push(0);
|
|
411
|
+
}
|
|
412
|
+
// create entries to be given to DayGridSegHierarchy
|
|
413
|
+
const segEntries = segs.map((seg, index) => ({
|
|
414
|
+
index: index,
|
|
415
|
+
seg,
|
|
416
|
+
span: {
|
|
417
|
+
start: seg.firstCol,
|
|
418
|
+
end: seg.lastCol + 1,
|
|
419
|
+
},
|
|
420
|
+
}));
|
|
421
|
+
// configure hierarchy position-generator
|
|
422
|
+
let hierarchy = new DayGridSegHierarchy((segEntry) => (segHeightMap.get(getSegSpanId(segs[segEntry.index]))));
|
|
423
|
+
hierarchy.allowReslicing = false;
|
|
281
424
|
hierarchy.strictOrder = strictOrder;
|
|
282
425
|
if (dayMaxEvents === true || dayMaxEventRows === true) {
|
|
283
|
-
hierarchy.maxCoord =
|
|
426
|
+
hierarchy.maxCoord = maxHeight;
|
|
284
427
|
hierarchy.hiddenConsumes = true;
|
|
285
428
|
}
|
|
286
429
|
else if (typeof dayMaxEvents === 'number') {
|
|
@@ -290,172 +433,30 @@ dayMaxEvents, dayMaxEventRows, strictOrder, segHeights, maxContentHeight, cells)
|
|
|
290
433
|
hierarchy.maxStackCnt = dayMaxEventRows;
|
|
291
434
|
hierarchy.hiddenConsumes = true;
|
|
292
435
|
}
|
|
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
|
-
});
|
|
436
|
+
// compile segTops & heightsByCol
|
|
437
|
+
const hiddenSegEntries = hierarchy.addSegs(segEntries);
|
|
438
|
+
const segRects = hierarchy.toRects();
|
|
439
|
+
const segTops = {};
|
|
440
|
+
for (const segRect of segRects) {
|
|
441
|
+
const seg = segs[segRect.index];
|
|
442
|
+
segTops[getSegStartId(seg)] = topOrigin + segRect.levelCoord;
|
|
443
|
+
let { start: col, end: endCol } = segRect.span;
|
|
444
|
+
for (; col < endCol; col++) {
|
|
445
|
+
heightsByCol[col] = Math.max(heightsByCol[col], segRect.levelCoord + segRect.thickness);
|
|
335
446
|
}
|
|
336
447
|
}
|
|
337
|
-
//
|
|
338
|
-
for (
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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
|
-
});
|
|
448
|
+
// compile # of invisible segs per-column
|
|
449
|
+
for (const hiddenSegEntry of hiddenSegEntries) {
|
|
450
|
+
const { span } = hiddenSegEntry;
|
|
451
|
+
const hiddenSeg = segs[hiddenSegEntry.index];
|
|
452
|
+
for (let col = span.start; col < span.end; col++) {
|
|
453
|
+
hiddenSegsByCol[col].push(hiddenSeg);
|
|
360
454
|
}
|
|
361
455
|
}
|
|
362
|
-
|
|
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
|
-
}
|
|
423
|
-
}
|
|
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
|
-
}
|
|
435
|
-
for (let rect of rects) {
|
|
436
|
-
for (let col = rect.span.start; col < rect.span.end; col += 1) {
|
|
437
|
-
rectsByEachCol[col].push(rect);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
return rectsByEachCol;
|
|
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() });
|
|
456
|
+
return [segTops, heightsByCol, hiddenSegsByCol];
|
|
458
457
|
}
|
|
458
|
+
// DayGridSegHierarchy
|
|
459
|
+
// -------------------------------------------------------------------------------------------------
|
|
459
460
|
class DayGridSegHierarchy extends internal_cjs.SegHierarchy {
|
|
460
461
|
constructor() {
|
|
461
462
|
super(...arguments);
|
|
@@ -503,74 +504,205 @@ class DayGridSegHierarchy extends internal_cjs.SegHierarchy {
|
|
|
503
504
|
}
|
|
504
505
|
}
|
|
505
506
|
|
|
506
|
-
class
|
|
507
|
+
class DayGridEventHarness extends preact_cjs.Component {
|
|
507
508
|
constructor() {
|
|
508
509
|
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"
|
|
510
|
+
// ref
|
|
513
511
|
this.rootElRef = preact_cjs.createRef();
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
512
|
+
}
|
|
513
|
+
render() {
|
|
514
|
+
const { props } = this;
|
|
515
|
+
return (preact_cjs.createElement("div", { className: "fc-abs", style: props.style, ref: this.rootElRef }, props.children));
|
|
516
|
+
}
|
|
517
|
+
componentDidMount() {
|
|
518
|
+
const rootEl = this.rootElRef.current; // TODO: make dynamic with useEffect
|
|
519
|
+
this.detachHeight = internal_cjs.watchHeight(rootEl, (height) => {
|
|
520
|
+
internal_cjs.setRef(this.props.heightRef, height);
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
componentWillUnmount() {
|
|
524
|
+
this.detachHeight();
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const DEFAULT_WEEK_NUM_FORMAT = internal_cjs.createFormatter({ week: 'narrow' });
|
|
529
|
+
const COMPACT_CELL_WIDTH = 80;
|
|
530
|
+
class DayGridRow extends internal_cjs.BaseComponent {
|
|
531
|
+
constructor() {
|
|
532
|
+
super(...arguments);
|
|
533
|
+
this.cellInnerHeightRefMap = new internal_cjs.RefMap(() => {
|
|
534
|
+
internal_cjs.afterSize(this.handleInnerHeights);
|
|
535
|
+
});
|
|
536
|
+
this.cellHeaderHeightRefMap = new internal_cjs.RefMap(() => {
|
|
537
|
+
internal_cjs.afterSize(this.handleHeaderHeights);
|
|
538
|
+
});
|
|
539
|
+
this.segHeightRefMap = new internal_cjs.RefMap(() => {
|
|
540
|
+
internal_cjs.afterSize(this.handleSegHeights);
|
|
541
|
+
});
|
|
542
|
+
this.handleRootEl = (rootEl) => {
|
|
543
|
+
this.rootEl = rootEl;
|
|
544
|
+
internal_cjs.setRef(this.props.rootElRef, rootEl);
|
|
545
|
+
};
|
|
546
|
+
// Sizing
|
|
547
|
+
// -----------------------------------------------------------------------------------------------
|
|
548
|
+
this.handleHeaderHeights = () => {
|
|
549
|
+
const cellHeaderHeightMap = this.cellHeaderHeightRefMap.current;
|
|
550
|
+
let max = 0;
|
|
551
|
+
for (const height of cellHeaderHeightMap.values()) {
|
|
552
|
+
max = Math.max(max, height);
|
|
553
|
+
}
|
|
554
|
+
if (this.state.headerHeight !== max) {
|
|
555
|
+
this.setState({ headerHeight: max });
|
|
556
|
+
}
|
|
518
557
|
};
|
|
519
|
-
this.
|
|
520
|
-
|
|
521
|
-
|
|
558
|
+
this.handleInnerHeights = () => {
|
|
559
|
+
const { props } = this;
|
|
560
|
+
const fgLiquidHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
|
|
561
|
+
const cellInnerHeightMap = this.cellInnerHeightRefMap.current;
|
|
562
|
+
let max = 0;
|
|
563
|
+
for (const height of cellInnerHeightMap.values()) {
|
|
564
|
+
max = Math.max(max, height);
|
|
565
|
+
}
|
|
566
|
+
if (fgLiquidHeight) {
|
|
567
|
+
if (this.state.innerHeight !== max) {
|
|
568
|
+
this.setState({ innerHeight: max }); // will trigger event rerender
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
internal_cjs.setRef(props.innerHeightRef, max);
|
|
522
573
|
}
|
|
523
574
|
};
|
|
575
|
+
this.handleSegHeights = () => {
|
|
576
|
+
this.setState({ segHeightRev: this.segHeightRefMap.rev }); // will trigger event rerender
|
|
577
|
+
};
|
|
524
578
|
}
|
|
525
579
|
render() {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
580
|
+
const { props, state, context, cellInnerHeightRefMap, cellHeaderHeightRefMap } = this;
|
|
581
|
+
const { cells } = props;
|
|
582
|
+
const { options } = context;
|
|
583
|
+
const weekDate = props.cells[0].date;
|
|
584
|
+
const colCnt = props.cells.length;
|
|
585
|
+
const fgLiquidHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
|
|
586
|
+
// TODO: memoize? sort all types of segs?
|
|
587
|
+
const fgEventSegs = internal_cjs.sortEventSegs(props.fgEventSegs, options.eventOrder);
|
|
588
|
+
// TODO: memoize?
|
|
589
|
+
const fgEventSegsByCol = splitSegsByCol(fgEventSegs, colCnt);
|
|
590
|
+
const bgEventSegsByCol = splitSegsByCol(props.bgEventSegs, colCnt);
|
|
591
|
+
const businessHoursByCol = splitSegsByCol(props.businessHourSegs, colCnt);
|
|
592
|
+
const highlightSegsByCol = splitSegsByCol(this.getHighlightSegs(), colCnt); // TODO: doesn't need standins
|
|
593
|
+
const mirrorSegsByCol = splitSegsByCol(this.getMirrorSegs(), colCnt); // TODO: doesn't need standins
|
|
594
|
+
// TODO: memoize?
|
|
595
|
+
const [segTops, heightsByCol, hiddenSegsByCol] = computeFgSegVerticals(fgEventSegs, this.segHeightRefMap.current, cells, state.headerHeight, (fgLiquidHeight && state.innerHeight != null && state.headerHeight != null)
|
|
596
|
+
? state.innerHeight - state.headerHeight
|
|
597
|
+
: undefined, options.eventOrderStrict, props.dayMaxEvents, props.dayMaxEventRows);
|
|
598
|
+
const forcedInvisibleMap = // TODO: more convenient/DRY
|
|
535
599
|
(props.eventDrag && props.eventDrag.affectedInstances) ||
|
|
536
600
|
(props.eventResize && props.eventResize.affectedInstances) ||
|
|
537
601
|
{};
|
|
538
|
-
return (preact_cjs.createElement("
|
|
539
|
-
|
|
602
|
+
return (preact_cjs.createElement("div", { role: props.cellGroup ? undefined : 'row', className: [
|
|
603
|
+
'fc-daygrid-row',
|
|
604
|
+
props.forceVSpacing
|
|
605
|
+
? 'fc-daygrid-row-spacious'
|
|
606
|
+
: props.compact
|
|
607
|
+
? 'fc-daygrid-row-compact'
|
|
608
|
+
: '',
|
|
609
|
+
props.cellGroup ? 'fc-flex-row' : 'fc-row',
|
|
610
|
+
'fc-rel',
|
|
611
|
+
props.className || '',
|
|
612
|
+
].join(' '), style: {
|
|
613
|
+
minHeight: props.minHeight,
|
|
614
|
+
}, ref: this.handleRootEl },
|
|
540
615
|
props.cells.map((cell, col) => {
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
616
|
+
const normalFgNodes = this.renderFgSegs(fgEventSegsByCol[col], segTops, props.todayRange, forcedInvisibleMap);
|
|
617
|
+
const mirrorFgNodes = this.renderFgSegs(mirrorSegsByCol[col], segTops, props.todayRange, {}, // forcedInvisibleMap
|
|
618
|
+
Boolean(props.eventDrag), Boolean(props.eventResize), false);
|
|
619
|
+
return (preact_cjs.createElement(DayGridCell, { key: cell.key, dateProfile: props.dateProfile, todayRange: props.todayRange, date: cell.date, showDayNumber: props.showDayNumbers,
|
|
620
|
+
// content
|
|
621
|
+
segs: fgEventSegsByCol[col], hiddenSegs: hiddenSegsByCol[col], fgLiquidHeight: fgLiquidHeight, fg: (preact_cjs.createElement(preact_cjs.Fragment, null,
|
|
545
622
|
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,
|
|
623
|
+
preact_cjs.createElement(preact_cjs.Fragment, null, mirrorFgNodes))), bg: (preact_cjs.createElement(preact_cjs.Fragment, null,
|
|
548
624
|
this.renderFillSegs(highlightSegsByCol[col], 'highlight'),
|
|
549
625
|
this.renderFillSegs(businessHoursByCol[col], 'non-business'),
|
|
550
|
-
this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))),
|
|
551
|
-
|
|
626
|
+
this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))), eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
|
|
627
|
+
// render hooks
|
|
628
|
+
extraRenderProps: cell.extraRenderProps, extraDateSpan: cell.extraDateSpan, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames,
|
|
629
|
+
// dimensions
|
|
630
|
+
fgHeight: heightsByCol[col], width: props.colWidth,
|
|
631
|
+
// refs
|
|
632
|
+
innerHeightRef: cellInnerHeightRefMap.createRef(cell.key), headerHeightRef: cellHeaderHeightRefMap.createRef(cell.key) }));
|
|
633
|
+
}),
|
|
634
|
+
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 }))));
|
|
635
|
+
}
|
|
636
|
+
renderFgSegs(segs, segTops, todayRange, forcedInvisibleMap, isDragging, isResizing, isDateSelecting) {
|
|
637
|
+
const { props, context, segHeightRefMap } = this;
|
|
638
|
+
const { isRtl } = context;
|
|
639
|
+
const { colWidth, eventSelection } = props;
|
|
640
|
+
const colCnt = props.cells.length;
|
|
641
|
+
const defaultDisplayEventEnd = props.cells.length === 1;
|
|
642
|
+
const isMirror = isDragging || isResizing || isDateSelecting;
|
|
643
|
+
const nodes = [];
|
|
644
|
+
for (const seg of segs) {
|
|
645
|
+
const { left, right, width } = computeHorizontalsFromSeg(seg, colWidth, colCnt, isRtl);
|
|
646
|
+
// TODO: optimize ID creation? all related
|
|
647
|
+
const { instanceId } = seg.eventRange.instance;
|
|
648
|
+
const segSpanId = getSegSpanId(seg);
|
|
649
|
+
const segStartId = getSegStartId(seg);
|
|
650
|
+
const top = segTops[segStartId];
|
|
651
|
+
const isVisible = !seg.isStandin &&
|
|
652
|
+
top != null &&
|
|
653
|
+
!forcedInvisibleMap[instanceId];
|
|
654
|
+
/*
|
|
655
|
+
TODO: is this comment still relevant? vvvvvvvv
|
|
656
|
+
known bug: events that are force to be list-item but span multiple days still take up space in later columns
|
|
657
|
+
todo: in print view, for multi-day events, don't display title within non-start/end segs
|
|
658
|
+
*/
|
|
659
|
+
nodes.push(preact_cjs.createElement(DayGridEventHarness, { key: segSpanId, style: {
|
|
660
|
+
visibility: isVisible ? '' : 'hidden',
|
|
661
|
+
top,
|
|
662
|
+
left,
|
|
663
|
+
right,
|
|
664
|
+
width,
|
|
665
|
+
}, heightRef: (isMirror || seg.isStandin)
|
|
666
|
+
? null
|
|
667
|
+
: segHeightRefMap.createRef(segSpanId) }, hasListItemDisplay(seg) ? (preact_cjs.createElement(DayGridListEvent, Object.assign({ seg: seg, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal_cjs.getSegMeta(seg, todayRange)))) : (preact_cjs.createElement(DayGridBlockEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal_cjs.getSegMeta(seg, todayRange))))));
|
|
668
|
+
}
|
|
669
|
+
return nodes;
|
|
552
670
|
}
|
|
553
|
-
|
|
554
|
-
this
|
|
555
|
-
|
|
671
|
+
renderFillSegs(segs, fillType) {
|
|
672
|
+
const { props, context } = this;
|
|
673
|
+
const { isRtl } = context;
|
|
674
|
+
const { todayRange, colWidth } = props;
|
|
675
|
+
const colCnt = props.cells.length;
|
|
676
|
+
const nodes = [];
|
|
677
|
+
for (const seg of segs) {
|
|
678
|
+
const { left, right, width } = computeHorizontalsFromSeg(seg, colWidth, colCnt, isRtl);
|
|
679
|
+
const isVisible = !seg.isStandin;
|
|
680
|
+
nodes.push(preact_cjs.createElement("div", { key: internal_cjs.buildEventRangeKey(seg.eventRange), className: "fc-fill-y", style: {
|
|
681
|
+
visibility: isVisible ? '' : 'hidden',
|
|
682
|
+
left,
|
|
683
|
+
right,
|
|
684
|
+
width,
|
|
685
|
+
} }, fillType === 'bg-event' ?
|
|
686
|
+
preact_cjs.createElement(internal_cjs.BgEvent, Object.assign({ seg: seg }, internal_cjs.getSegMeta(seg, todayRange))) :
|
|
687
|
+
internal_cjs.renderFill(fillType)));
|
|
688
|
+
}
|
|
689
|
+
return preact_cjs.createElement(preact_cjs.Fragment, {}, ...nodes);
|
|
556
690
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
691
|
+
// Sizing
|
|
692
|
+
// -----------------------------------------------------------------------------------------------
|
|
693
|
+
componentDidMount() {
|
|
694
|
+
const { rootEl } = this; // TODO: make dynamic with useEffect
|
|
695
|
+
this.disconnectHeight = internal_cjs.watchHeight(rootEl, (contentHeight) => {
|
|
696
|
+
internal_cjs.setRef(this.props.heightRef, contentHeight);
|
|
697
|
+
});
|
|
560
698
|
}
|
|
561
699
|
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;
|
|
700
|
+
this.disconnectHeight();
|
|
701
|
+
internal_cjs.setRef(this.props.heightRef, null);
|
|
702
|
+
internal_cjs.setRef(this.props.innerHeightRef, null);
|
|
573
703
|
}
|
|
704
|
+
// Utils
|
|
705
|
+
// -----------------------------------------------------------------------------------------------
|
|
574
706
|
getMirrorSegs() {
|
|
575
707
|
let { props } = this;
|
|
576
708
|
if (props.eventResize && props.eventResize.segs.length) { // messy check
|
|
@@ -578,420 +710,476 @@ class TableRow extends internal_cjs.DateComponent {
|
|
|
578
710
|
}
|
|
579
711
|
return [];
|
|
580
712
|
}
|
|
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);
|
|
713
|
+
getHighlightSegs() {
|
|
714
|
+
let { props } = this;
|
|
715
|
+
if (props.eventDrag && props.eventDrag.segs.length) { // messy check
|
|
716
|
+
return props.eventDrag.segs;
|
|
680
717
|
}
|
|
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;
|
|
718
|
+
if (props.eventResize && props.eventResize.segs.length) { // messy check
|
|
719
|
+
return props.eventResize.segs;
|
|
715
720
|
}
|
|
721
|
+
return props.dateSelectionSegs;
|
|
716
722
|
}
|
|
717
|
-
return topsByInstanceId;
|
|
718
723
|
}
|
|
719
724
|
|
|
720
|
-
class
|
|
725
|
+
class DayGridRows extends internal_cjs.DateComponent {
|
|
721
726
|
constructor() {
|
|
722
727
|
super(...arguments);
|
|
728
|
+
// memo
|
|
723
729
|
this.splitBusinessHourSegs = internal_cjs.memoize(splitSegsByRow);
|
|
724
730
|
this.splitBgEventSegs = internal_cjs.memoize(splitSegsByRow);
|
|
725
731
|
this.splitFgEventSegs = internal_cjs.memoize(splitSegsByRow);
|
|
726
732
|
this.splitDateSelectionSegs = internal_cjs.memoize(splitSegsByRow);
|
|
727
733
|
this.splitEventDrag = internal_cjs.memoize(splitInteractionByRow);
|
|
728
734
|
this.splitEventResize = internal_cjs.memoize(splitInteractionByRow);
|
|
729
|
-
|
|
735
|
+
// internal
|
|
736
|
+
this.rowHeightRefMap = new internal_cjs.RefMap((height, key) => {
|
|
737
|
+
// HACKy way of syncing RefMap results with prop
|
|
738
|
+
const { rowHeightRefMap } = this.props;
|
|
739
|
+
if (rowHeightRefMap) {
|
|
740
|
+
rowHeightRefMap.handleValue(height, key);
|
|
741
|
+
}
|
|
742
|
+
});
|
|
743
|
+
this.handleRootEl = (rootEl) => {
|
|
744
|
+
this.rootEl = rootEl;
|
|
745
|
+
if (rootEl) {
|
|
746
|
+
this.context.registerInteractiveComponent(this, {
|
|
747
|
+
el: rootEl,
|
|
748
|
+
isHitComboAllowed: this.props.isHitComboAllowed,
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
else {
|
|
752
|
+
this.context.unregisterInteractiveComponent(this);
|
|
753
|
+
}
|
|
754
|
+
};
|
|
730
755
|
}
|
|
731
756
|
render() {
|
|
732
|
-
let { props, context } = this;
|
|
733
|
-
let
|
|
734
|
-
let
|
|
735
|
-
let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);
|
|
757
|
+
let { props, state, context, rowHeightRefMap } = this;
|
|
758
|
+
let { options } = context;
|
|
759
|
+
let rowCnt = props.cellRows.length;
|
|
736
760
|
let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt);
|
|
761
|
+
let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);
|
|
762
|
+
let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt);
|
|
737
763
|
let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt);
|
|
738
764
|
let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt);
|
|
739
765
|
let eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt);
|
|
740
|
-
//
|
|
741
|
-
//
|
|
742
|
-
let
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
766
|
+
// whether the ROW should expand in height
|
|
767
|
+
// (not to be confused with whether the fg events within the row should be molded by height of row)
|
|
768
|
+
let isHeightAuto = internal_cjs.getIsHeightAuto(options);
|
|
769
|
+
// maintain at least aspectRatio for cells?
|
|
770
|
+
let rowMinHeight = (state.width != null && (rowCnt >= 7 || // TODO: better way to infer if across single-month boundary
|
|
771
|
+
isHeightAuto)) ? state.width / context.options.aspectRatio / 6 // okay to hardcode 6 (weeks) ?
|
|
772
|
+
: null;
|
|
773
|
+
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,
|
|
774
|
+
// if not auto-height, distribute height of container somewhat evently to rows
|
|
775
|
+
// (treat all as zero, distribute height, then ensure min-heights -- the inner content height)
|
|
776
|
+
className: isHeightAuto ? '' : 'fc-grow fc-basis0',
|
|
777
|
+
// content
|
|
778
|
+
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,
|
|
779
|
+
// dimensions
|
|
780
|
+
colWidth: props.colWidth, minHeight: rowMinHeight,
|
|
781
|
+
// refs
|
|
782
|
+
heightRef: rowHeightRefMap.createRef(cells[0].key) })))));
|
|
749
783
|
}
|
|
750
784
|
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
|
-
}
|
|
785
|
+
this.unwatchWidth = internal_cjs.watchWidth(this.rootEl, (width) => {
|
|
786
|
+
this.setState({ width });
|
|
787
|
+
});
|
|
771
788
|
}
|
|
772
789
|
componentWillUnmount() {
|
|
773
|
-
|
|
774
|
-
this.context.unregisterInteractiveComponent(this);
|
|
775
|
-
this.rootEl = null;
|
|
776
|
-
}
|
|
790
|
+
this.unwatchWidth();
|
|
777
791
|
}
|
|
778
792
|
// 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 };
|
|
793
|
+
// -----------------------------------------------------------------------------------------------
|
|
794
|
+
queryHit(positionLeft, positionTop, elWidth) {
|
|
795
|
+
const { props, context } = this;
|
|
796
|
+
const colCnt = props.cellRows[0].length;
|
|
797
|
+
const { col, left, right } = computeColFromPosition(positionLeft, elWidth, props.colWidth, colCnt, context.isRtl);
|
|
798
|
+
const { row, top, bottom } = computeRowFromPosition(positionTop, props.cellRows, this.rowHeightRefMap.current);
|
|
799
|
+
const cell = props.cellRows[row][col];
|
|
800
|
+
const cellStartDate = cell.date;
|
|
801
|
+
const cellEndDate = internal_cjs.addDays(cellStartDate, 1);
|
|
802
|
+
return {
|
|
803
|
+
dateProfile: props.dateProfile,
|
|
804
|
+
dateSpan: Object.assign({ range: {
|
|
805
|
+
start: cellStartDate,
|
|
806
|
+
end: cellEndDate,
|
|
807
|
+
}, allDay: true }, cell.extraDateSpan),
|
|
808
|
+
// HACK. TODO: This is expensive to do every hit-query
|
|
809
|
+
dayEl: getCellEl(getRowEl(this.rootEl, row), col),
|
|
810
|
+
rect: {
|
|
811
|
+
left,
|
|
812
|
+
right,
|
|
813
|
+
top,
|
|
814
|
+
bottom,
|
|
815
|
+
},
|
|
816
|
+
layer: 0,
|
|
817
|
+
};
|
|
815
818
|
}
|
|
816
819
|
}
|
|
820
|
+
// Utils
|
|
821
|
+
// -------------------------------------------------------------------------------------------------
|
|
817
822
|
function isSegAllDay(seg) {
|
|
818
823
|
return seg.eventRange.def.allDay;
|
|
819
824
|
}
|
|
820
825
|
|
|
821
|
-
class
|
|
826
|
+
class HeaderRow extends internal_cjs.BaseComponent {
|
|
827
|
+
render() {
|
|
828
|
+
const { props } = this;
|
|
829
|
+
return (preact_cjs.createElement("div", { role: props.cellGroup ? undefined : 'row', className: [
|
|
830
|
+
props.cellGroup ? 'fc-flex-row' : 'fc-row',
|
|
831
|
+
props.className || '',
|
|
832
|
+
].join(' ') }, props.cells.map((cell) => (preact_cjs.createElement(preact_cjs.Fragment, { key: props.getHeaderModelKey(cell) }, props.renderHeaderContent(cell, props.tierNum, undefined, // innerHeightRef
|
|
833
|
+
props.colWidth))))));
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
function DayGridHeader(props) {
|
|
838
|
+
return (preact_cjs.createElement("div", { className: [
|
|
839
|
+
'fc-rowgroup',
|
|
840
|
+
'fc-content-box',
|
|
841
|
+
...(props.extraClassNames || []),
|
|
842
|
+
].join(' '), style: {
|
|
843
|
+
width: props.width,
|
|
844
|
+
paddingLeft: props.paddingLeft,
|
|
845
|
+
paddingRight: props.paddingRight,
|
|
846
|
+
} }, props.headerTiers.map((cells, tierNum) => (preact_cjs.createElement(HeaderRow, { key: tierNum, tierNum: tierNum, cells: cells, renderHeaderContent: props.renderHeaderContent, getHeaderModelKey: props.getHeaderModelKey, colWidth: props.colWidth })))));
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
class DayGridLayoutNormal extends internal_cjs.BaseComponent {
|
|
822
850
|
constructor() {
|
|
823
851
|
super(...arguments);
|
|
824
|
-
this.
|
|
825
|
-
|
|
852
|
+
this.handleScroller = (scroller) => {
|
|
853
|
+
internal_cjs.setRef(this.props.scrollerRef, scroller);
|
|
854
|
+
};
|
|
855
|
+
this.handleLeftScrollbarWidth = (leftScrollbarWidth) => {
|
|
856
|
+
this.setState({ leftScrollbarWidth });
|
|
857
|
+
};
|
|
858
|
+
this.handleRightScrollbarWidth = (rightScrollbarWidth) => {
|
|
859
|
+
this.setState({ rightScrollbarWidth });
|
|
860
|
+
};
|
|
826
861
|
}
|
|
827
862
|
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 })))));
|
|
863
|
+
const { props, state, context } = this;
|
|
864
|
+
const { options } = context;
|
|
865
|
+
const verticalScrollbars = !props.forPrint && !internal_cjs.getIsHeightAuto(options);
|
|
866
|
+
const stickyHeaderDates = !props.forPrint && internal_cjs.getStickyHeaderDates(options);
|
|
867
|
+
return (preact_cjs.createElement(preact_cjs.Fragment, null,
|
|
868
|
+
options.dayHeaders && (preact_cjs.createElement(DayGridHeader, { headerTiers: props.headerTiers, renderHeaderContent: props.renderHeaderContent, getHeaderModelKey: props.getHeaderModelKey,
|
|
869
|
+
// render hooks
|
|
870
|
+
extraClassNames: [
|
|
871
|
+
'fc-daygrid-header',
|
|
872
|
+
stickyHeaderDates ? 'fc-sticky-header' : '',
|
|
873
|
+
],
|
|
874
|
+
// dimensions
|
|
875
|
+
paddingLeft: state.leftScrollbarWidth, paddingRight: state.rightScrollbarWidth })),
|
|
876
|
+
preact_cjs.createElement(internal_cjs.Scroller, { vertical: verticalScrollbars, leftScrollbarWidthRef: this.handleLeftScrollbarWidth, rightScrollbarWidthRef: this.handleRightScrollbarWidth, elClassNames: [
|
|
877
|
+
'fc-daygrid-body',
|
|
878
|
+
'fc-rowgroup',
|
|
879
|
+
'fc-flex-column',
|
|
880
|
+
verticalScrollbars ? 'fc-liquid' : '',
|
|
881
|
+
], ref: this.handleScroller },
|
|
882
|
+
preact_cjs.createElement(DayGridRows // .fc-grow
|
|
883
|
+
, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed,
|
|
884
|
+
// content
|
|
885
|
+
fgEventSegs: props.fgEventSegs, bgEventSegs: props.bgEventSegs, businessHourSegs: props.businessHourSegs, dateSelectionSegs: props.dateSelectionSegs, eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
|
|
886
|
+
// refs
|
|
887
|
+
rowHeightRefMap: props.rowHeightRefMap }))));
|
|
857
888
|
}
|
|
858
|
-
|
|
859
|
-
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
class DayGridLayoutPannable extends internal_cjs.BaseComponent {
|
|
892
|
+
constructor() {
|
|
893
|
+
super(...arguments);
|
|
894
|
+
this.headerScrollerRef = preact_cjs.createRef();
|
|
895
|
+
this.bodyScrollerRef = preact_cjs.createRef();
|
|
896
|
+
this.footerScrollerRef = preact_cjs.createRef();
|
|
897
|
+
// Sizing
|
|
898
|
+
// -----------------------------------------------------------------------------------------------
|
|
899
|
+
this.handleWidth = (width) => {
|
|
900
|
+
this.setState({ width });
|
|
901
|
+
};
|
|
902
|
+
this.handleLeftScrollbarWidth = (leftScrollbarWidth) => {
|
|
903
|
+
this.setState({ leftScrollbarWidth });
|
|
904
|
+
};
|
|
905
|
+
this.handleRightScrollbarWidth = (rightScrollbarWidth) => {
|
|
906
|
+
this.setState({ rightScrollbarWidth });
|
|
907
|
+
};
|
|
860
908
|
}
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
909
|
+
render() {
|
|
910
|
+
const { props, state, context } = this;
|
|
911
|
+
const { options } = context;
|
|
912
|
+
const verticalScrollbars = !props.forPrint && !internal_cjs.getIsHeightAuto(options);
|
|
913
|
+
const stickyHeaderDates = !props.forPrint && internal_cjs.getStickyHeaderDates(options);
|
|
914
|
+
const stickyFooterScrollbar = !props.forPrint && internal_cjs.getStickyFooterScrollbar(options);
|
|
915
|
+
const colCnt = props.cellRows[0].length;
|
|
916
|
+
const [canvasWidth, colWidth] = computeColWidth(colCnt, props.dayMinWidth, state.width);
|
|
917
|
+
return (preact_cjs.createElement(preact_cjs.Fragment, null,
|
|
918
|
+
options.dayHeaders && (preact_cjs.createElement(internal_cjs.Scroller, { horizontal: true, hideScrollbars: true, elClassNames: [
|
|
919
|
+
'fc-daygrid-header',
|
|
920
|
+
'fc-rowgroup',
|
|
921
|
+
stickyHeaderDates ? 'fc-sticky-header' : ''
|
|
922
|
+
], ref: this.headerScrollerRef },
|
|
923
|
+
preact_cjs.createElement(DayGridHeader, { headerTiers: props.headerTiers, renderHeaderContent: props.renderHeaderContent, getHeaderModelKey: props.getHeaderModelKey,
|
|
924
|
+
// dimensions
|
|
925
|
+
colWidth: colWidth, width: canvasWidth, paddingLeft: state.leftScrollbarWidth, paddingRight: state.rightScrollbarWidth }))),
|
|
926
|
+
preact_cjs.createElement(internal_cjs.Scroller, { vertical: verticalScrollbars, horizontal: true, hideScrollbars: stickyFooterScrollbar, widthRef: this.handleWidth, leftScrollbarWidthRef: this.handleLeftScrollbarWidth, rightScrollbarWidthRef: this.handleRightScrollbarWidth, elClassNames: [
|
|
927
|
+
'fc-daygrid-body',
|
|
928
|
+
'fc-rowgroup',
|
|
929
|
+
'fc-flex-column',
|
|
930
|
+
verticalScrollbars ? 'fc-liquid' : '',
|
|
931
|
+
], ref: this.bodyScrollerRef },
|
|
932
|
+
preact_cjs.createElement(DayGridRows // .fc-grow
|
|
933
|
+
, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed,
|
|
934
|
+
// content
|
|
935
|
+
fgEventSegs: props.fgEventSegs, bgEventSegs: props.bgEventSegs, businessHourSegs: props.businessHourSegs, dateSelectionSegs: props.dateSelectionSegs, eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
|
|
936
|
+
// dimensions
|
|
937
|
+
colWidth: colWidth, width: canvasWidth,
|
|
938
|
+
// refs
|
|
939
|
+
rowHeightRefMap: props.rowHeightRefMap })),
|
|
940
|
+
Boolean(stickyFooterScrollbar) && (preact_cjs.createElement(internal_cjs.Scroller, { ref: this.footerScrollerRef, horizontal: true, elClassNames: ['fc-sticky-footer'], elStyle: {
|
|
941
|
+
marginTop: '-1px', // HACK
|
|
942
|
+
} },
|
|
943
|
+
preact_cjs.createElement("div", { style: {
|
|
944
|
+
width: canvasWidth,
|
|
945
|
+
height: '1px', // HACK
|
|
946
|
+
} })))));
|
|
868
947
|
}
|
|
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
|
-
}
|
|
948
|
+
// Lifecycle
|
|
949
|
+
// -----------------------------------------------------------------------------------------------
|
|
950
|
+
componentDidMount() {
|
|
951
|
+
// scroller
|
|
952
|
+
const ScrollerSyncer = internal_cjs.getScrollerSyncerClass(this.context.pluginHooks);
|
|
953
|
+
this.syncedScroller = new ScrollerSyncer(true); // horizontal=true
|
|
954
|
+
internal_cjs.setRef(this.props.scrollerRef, this.syncedScroller);
|
|
955
|
+
this.updateSyncedScroller();
|
|
887
956
|
}
|
|
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...
|
|
957
|
+
componentDidUpdate() {
|
|
958
|
+
// scroller
|
|
959
|
+
this.updateSyncedScroller();
|
|
894
960
|
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
961
|
+
componentWillUnmount() {
|
|
962
|
+
// scroller
|
|
963
|
+
this.syncedScroller.destroy();
|
|
964
|
+
}
|
|
965
|
+
// Scrolling
|
|
966
|
+
// -----------------------------------------------------------------------------------------------
|
|
967
|
+
updateSyncedScroller() {
|
|
968
|
+
const { isRtl } = this.context;
|
|
969
|
+
this.syncedScroller.handleChildren([
|
|
970
|
+
this.headerScrollerRef.current,
|
|
971
|
+
this.bodyScrollerRef.current,
|
|
972
|
+
this.footerScrollerRef.current,
|
|
973
|
+
], isRtl);
|
|
898
974
|
}
|
|
899
|
-
return el;
|
|
900
975
|
}
|
|
901
976
|
|
|
902
|
-
class
|
|
977
|
+
class DayGridLayout extends internal_cjs.BaseComponent {
|
|
903
978
|
constructor() {
|
|
904
979
|
super(...arguments);
|
|
905
|
-
|
|
980
|
+
// ref
|
|
981
|
+
this.scrollerRef = preact_cjs.createRef();
|
|
982
|
+
this.rowHeightRefMap = new internal_cjs.RefMap();
|
|
983
|
+
// Scrolling
|
|
984
|
+
// -----------------------------------------------------------------------------------------------
|
|
985
|
+
this.timeScrollResponder = new internal_cjs.ScrollResponder((_time) => {
|
|
986
|
+
// HACK to scroll to day
|
|
987
|
+
const rowHeightMap = this.rowHeightRefMap.current;
|
|
988
|
+
const scroller = this.scrollerRef.current;
|
|
989
|
+
const scrollTop = computeTopFromDate(this.props.dateProfile.currentDate, this.props.cellRows, rowHeightMap);
|
|
990
|
+
if (scrollTop != null) {
|
|
991
|
+
scroller.scrollTo({ y: scrollTop });
|
|
992
|
+
return true;
|
|
993
|
+
}
|
|
994
|
+
return false;
|
|
995
|
+
});
|
|
906
996
|
}
|
|
907
|
-
|
|
908
|
-
|
|
997
|
+
render() {
|
|
998
|
+
const { props, context } = this;
|
|
999
|
+
const { options } = context;
|
|
1000
|
+
const commonLayoutProps = Object.assign(Object.assign({}, props), { scrollerRef: this.scrollerRef, rowHeightRefMap: this.rowHeightRefMap });
|
|
1001
|
+
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)))));
|
|
1002
|
+
}
|
|
1003
|
+
// Lifecycle
|
|
1004
|
+
// -----------------------------------------------------------------------------------------------
|
|
1005
|
+
componentDidMount() {
|
|
1006
|
+
const { context } = this;
|
|
1007
|
+
const { options } = context;
|
|
1008
|
+
context.emitter.on('_timeScrollRequest', this.timeScrollResponder.handleScroll);
|
|
1009
|
+
this.timeScrollResponder.handleScroll(options.scrollTime);
|
|
1010
|
+
}
|
|
1011
|
+
componentDidUpdate(prevProps) {
|
|
1012
|
+
const { options } = this.context;
|
|
1013
|
+
if (prevProps.dateProfile !== this.props.dateProfile && options.scrollTimeReset) {
|
|
1014
|
+
this.timeScrollResponder.handleScroll(options.scrollTime);
|
|
1015
|
+
}
|
|
1016
|
+
else {
|
|
1017
|
+
this.timeScrollResponder.drain();
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
componentWillUnmount() {
|
|
1021
|
+
this.context.emitter.off('_timeScrollRequest', this.timeScrollResponder.handleScroll);
|
|
909
1022
|
}
|
|
910
1023
|
}
|
|
911
1024
|
|
|
912
|
-
|
|
1025
|
+
const WEEKDAY_FORMAT = internal_cjs.createFormatter({ weekday: 'long' });
|
|
1026
|
+
class DayOfWeekHeaderCell extends internal_cjs.BaseComponent {
|
|
913
1027
|
constructor() {
|
|
914
1028
|
super(...arguments);
|
|
915
|
-
|
|
916
|
-
this.
|
|
1029
|
+
// ref
|
|
1030
|
+
this.innerElRef = preact_cjs.createRef();
|
|
917
1031
|
}
|
|
918
1032
|
render() {
|
|
919
1033
|
let { props, context } = this;
|
|
920
|
-
|
|
1034
|
+
let { dateEnv, theme, viewApi, options } = context;
|
|
1035
|
+
let date = internal_cjs.addDays(new Date(259200000), props.dow); // start with Sun, 04 Jan 1970 00:00:00 GMT
|
|
1036
|
+
let dateMeta = {
|
|
1037
|
+
dow: props.dow,
|
|
1038
|
+
isDisabled: false,
|
|
1039
|
+
isFuture: false,
|
|
1040
|
+
isPast: false,
|
|
1041
|
+
isToday: false,
|
|
1042
|
+
isOther: false,
|
|
1043
|
+
};
|
|
1044
|
+
let text = dateEnv.format(date, props.dayHeaderFormat);
|
|
1045
|
+
let renderProps = Object.assign(Object.assign(Object.assign(Object.assign({ date }, dateMeta), { view: viewApi }), props.extraRenderProps), { text });
|
|
1046
|
+
return (preact_cjs.createElement(internal_cjs.ContentContainer, { elTag: 'div', elClasses: [
|
|
1047
|
+
...internal_cjs.getDayClassNames(dateMeta, theme),
|
|
1048
|
+
...(props.extraClassNames || []),
|
|
1049
|
+
'fc-header-cell',
|
|
1050
|
+
'fc-cell',
|
|
1051
|
+
props.colWidth != null ? '' : 'fc-liquid',
|
|
1052
|
+
'fc-flex-column',
|
|
1053
|
+
'fc-align-center',
|
|
1054
|
+
], elAttrs: props.extraDataAttrs, elStyle: {
|
|
1055
|
+
width: props.colWidth != null // TODO: DRY
|
|
1056
|
+
? props.colWidth * (props.colSpan || 1)
|
|
1057
|
+
: undefined,
|
|
1058
|
+
}, 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: [
|
|
1059
|
+
'fc-flex-column',
|
|
1060
|
+
props.isSticky ? 'fc-sticky-x' : '',
|
|
1061
|
+
].join(' ') },
|
|
1062
|
+
preact_cjs.createElement(InnerContent, { elTag: "a", elClasses: [
|
|
1063
|
+
'fc-cell-inner',
|
|
1064
|
+
'fc-padding-sm',
|
|
1065
|
+
], elAttrs: {
|
|
1066
|
+
'aria-label': dateEnv.format(date, WEEKDAY_FORMAT),
|
|
1067
|
+
} })))));
|
|
1068
|
+
}
|
|
1069
|
+
componentDidMount() {
|
|
1070
|
+
const innerEl = this.innerElRef.current; // TODO: make dynamic with useEffect
|
|
1071
|
+
// TODO: only attach this if refs props present
|
|
1072
|
+
this.disconectInnerHeight = internal_cjs.watchHeight(innerEl, (height) => {
|
|
1073
|
+
internal_cjs.setRef(this.props.innerHeightRef, height);
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
componentWillUnmount() {
|
|
1077
|
+
this.disconectInnerHeight();
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) {
|
|
1082
|
+
return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt);
|
|
1083
|
+
}
|
|
1084
|
+
// Computes a default column header formatting string if `colFormat` is not explicitly defined
|
|
1085
|
+
function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
|
|
1086
|
+
// if more than one week row, or if there are a lot of columns with not much space,
|
|
1087
|
+
// put just the day numbers will be in each cell
|
|
1088
|
+
if (!datesRepDistinctDays || dayCnt > 10) {
|
|
1089
|
+
return internal_cjs.createFormatter({ weekday: 'short' }); // "Sat"
|
|
921
1090
|
}
|
|
1091
|
+
if (dayCnt > 1) {
|
|
1092
|
+
return internal_cjs.createFormatter({ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }); // "Sat 11/12"
|
|
1093
|
+
}
|
|
1094
|
+
return internal_cjs.createFormatter({ weekday: 'long' }); // "Saturday"
|
|
922
1095
|
}
|
|
923
1096
|
|
|
924
|
-
class
|
|
1097
|
+
class DayGridView extends internal_cjs.BaseComponent {
|
|
925
1098
|
constructor() {
|
|
926
1099
|
super(...arguments);
|
|
1100
|
+
// memo
|
|
927
1101
|
this.buildDayTableModel = internal_cjs.memoize(buildDayTableModel);
|
|
928
|
-
this.
|
|
929
|
-
this.
|
|
930
|
-
//
|
|
1102
|
+
this.buildHeaderTiers = internal_cjs.memoize(buildHeaderTiers);
|
|
1103
|
+
this.createDayHeaderFormatter = internal_cjs.memoize(createDayHeaderFormatter);
|
|
1104
|
+
// internal
|
|
1105
|
+
this.slicer = new DayTableSlicer();
|
|
931
1106
|
}
|
|
932
1107
|
render() {
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1108
|
+
const { props, context } = this;
|
|
1109
|
+
const { options } = context;
|
|
1110
|
+
const dayTableModel = this.buildDayTableModel(props.dateProfile, context.dateProfileGenerator);
|
|
1111
|
+
const datesRepDistinctDays = dayTableModel.rowCnt === 1;
|
|
1112
|
+
const headerTiers = this.buildHeaderTiers(dayTableModel.headerDates, datesRepDistinctDays);
|
|
1113
|
+
const slicedProps = this.slicer.sliceProps(props, props.dateProfile, options.nextDayThreshold, context, dayTableModel);
|
|
1114
|
+
const dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dayTableModel.colCnt);
|
|
1115
|
+
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',
|
|
1116
|
+
// header content
|
|
1117
|
+
headerTiers: headerTiers, renderHeaderContent: (model, tier, innerHeightRef, colWidth) => {
|
|
1118
|
+
if (model.date) {
|
|
1119
|
+
return (preact_cjs.createElement(DateHeaderCell, Object.assign({}, model, { dateProfile: props.dateProfile, todayRange: todayRange, navLink: dayTableModel.colCnt > 1, dayHeaderFormat: dayHeaderFormat, colSpan: model.colSpan, colWidth: colWidth })));
|
|
1120
|
+
}
|
|
1121
|
+
else {
|
|
1122
|
+
return (preact_cjs.createElement(DayOfWeekHeaderCell, Object.assign({}, model, { dayHeaderFormat: dayHeaderFormat, colSpan: model.colSpan, colWidth: colWidth })));
|
|
1123
|
+
}
|
|
1124
|
+
}, getHeaderModelKey: (model) => {
|
|
1125
|
+
// can use model.key???
|
|
1126
|
+
if (model.date) {
|
|
1127
|
+
return model.date.toUTCString();
|
|
1128
|
+
}
|
|
1129
|
+
return model.dow;
|
|
1130
|
+
},
|
|
1131
|
+
// body content
|
|
1132
|
+
fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection }))));
|
|
941
1133
|
}
|
|
942
1134
|
}
|
|
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
1135
|
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
dateEnv: props.dateEnv,
|
|
1136
|
+
/*
|
|
1137
|
+
TODO: is it even worth doing this "advanced" version?
|
|
1138
|
+
*/
|
|
1139
|
+
class HeaderRowAdvanced extends internal_cjs.BaseComponent {
|
|
1140
|
+
constructor() {
|
|
1141
|
+
super(...arguments);
|
|
1142
|
+
// ref
|
|
1143
|
+
this.innerHeightRefMap = new internal_cjs.RefMap(() => {
|
|
1144
|
+
internal_cjs.afterSize(this.handleInnerHeights);
|
|
958
1145
|
});
|
|
1146
|
+
this.handleInnerHeights = () => {
|
|
1147
|
+
const innerHeightMap = this.innerHeightRefMap.current;
|
|
1148
|
+
let max = 0;
|
|
1149
|
+
for (const innerHeight of innerHeightMap.values()) {
|
|
1150
|
+
max = Math.max(max, innerHeight);
|
|
1151
|
+
}
|
|
1152
|
+
if (this.currentInnerHeight !== max) {
|
|
1153
|
+
this.currentInnerHeight = max;
|
|
1154
|
+
internal_cjs.setRef(this.props.innerHeightRef, max);
|
|
1155
|
+
}
|
|
1156
|
+
};
|
|
959
1157
|
}
|
|
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);
|
|
1158
|
+
render() {
|
|
1159
|
+
const { props } = this;
|
|
1160
|
+
return (preact_cjs.createElement("div", { role: 'row', className: 'fc-row', style: { height: props.height } }, props.cells.map((cell) => {
|
|
1161
|
+
const key = props.getHeaderModelKey(cell);
|
|
1162
|
+
return (preact_cjs.createElement(preact_cjs.Fragment, { key: props.getHeaderModelKey(cell) }, props.renderHeaderContent(cell, props.tierNum, this.innerHeightRefMap.createRef(key), // innerHeightRef
|
|
1163
|
+
props.colWidth)));
|
|
1164
|
+
})));
|
|
982
1165
|
}
|
|
983
|
-
return { start, end };
|
|
984
1166
|
}
|
|
985
1167
|
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
exports.
|
|
990
|
-
exports.
|
|
1168
|
+
exports.COMPACT_CELL_WIDTH = COMPACT_CELL_WIDTH;
|
|
1169
|
+
exports.DateHeaderCell = DateHeaderCell;
|
|
1170
|
+
exports.DayGridLayout = DayGridLayout;
|
|
1171
|
+
exports.DayGridRow = DayGridRow;
|
|
1172
|
+
exports.DayGridRows = DayGridRows;
|
|
1173
|
+
exports.DayGridView = DayGridView;
|
|
1174
|
+
exports.DayOfWeekHeaderCell = DayOfWeekHeaderCell;
|
|
991
1175
|
exports.DayTableSlicer = DayTableSlicer;
|
|
992
|
-
exports.
|
|
1176
|
+
exports.HeaderRow = HeaderRow;
|
|
1177
|
+
exports.HeaderRowAdvanced = HeaderRowAdvanced;
|
|
993
1178
|
exports.TableDateProfileGenerator = TableDateProfileGenerator;
|
|
994
|
-
exports.TableRows = TableRows;
|
|
995
|
-
exports.TableView = TableView;
|
|
996
1179
|
exports.buildDayTableModel = buildDayTableModel;
|
|
997
1180
|
exports.buildDayTableRenderRange = buildDayTableRenderRange;
|
|
1181
|
+
exports.computeColFromPosition = computeColFromPosition;
|
|
1182
|
+
exports.computeColWidth = computeColWidth;
|
|
1183
|
+
exports.createDayHeaderFormatter = createDayHeaderFormatter;
|
|
1184
|
+
exports.getCellEl = getCellEl;
|
|
1185
|
+
exports.getRowEl = getRowEl;
|