@fullcalendar/daygrid 7.0.0-beta.3 → 7.0.0-beta.5
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/LICENSE.md +1 -1
- package/README.md +6 -1
- package/{index.cjs → cjs/index.cjs} +15 -4
- package/cjs/internal.cjs +1339 -0
- package/esm/index.d.ts +23 -0
- package/{index.js → esm/index.js} +14 -3
- package/{internal.d.ts → esm/internal.d.ts} +54 -29
- package/{internal.js → esm/internal.js} +454 -280
- package/{index.global.js → global.js} +469 -281
- package/global.min.js +6 -0
- package/package.json +22 -19
- package/index.d.ts +0 -6
- package/index.global.min.js +0 -6
- package/internal.cjs +0 -1159
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { Slicer,
|
|
2
|
-
import { createElement, Fragment, createRef, Component } from '@fullcalendar/core/preact
|
|
1
|
+
import { Slicer, computeMajorUnit, isMajorUnit, addDays, getDateMeta, findWeekdayText, findDayNumberText, buildDateStr, formatDayString, buildNavLinkAttrs, WEEKDAY_ONLY_FORMAT, getEventKey, createFormatter, BaseComponent, MoreLinkContainer, StandardEvent, getEventRangeMeta, DateComponent, memoize, memoizeObjArg, setRef, watchSize, isDimsEqual, joinArrayishClassNames, generateClassName, ContentContainer, addMs, findMonthText, SegHierarchy, DaySeriesModel, DayTableModel, fracToCssDim, watchHeight, RefMap, afterSize, sortEventSegs, renderText, buildEventRangeKey, BgEvent, renderFill, getIsHeightAuto, getStickyHeaderDates, Scroller, Ruler, getStickyFooterScrollbar, FooterScrollbar, getScrollerSyncerClass, ViewContainer, NowTimer, DateProfileGenerator, addWeeks, diffWeeks } from '@fullcalendar/core/internal';
|
|
2
|
+
import { createElement, Fragment, createRef, Component } from '@fullcalendar/core/preact';
|
|
3
|
+
import { joinClassNames } from '@fullcalendar/core';
|
|
4
|
+
import classNames from '@fullcalendar/core/internal-classnames';
|
|
3
5
|
|
|
4
6
|
class DayTableSlicer extends Slicer {
|
|
5
7
|
constructor() {
|
|
@@ -16,55 +18,96 @@ class DayTableSlicer extends Slicer {
|
|
|
16
18
|
// but can share some of the same types/utils
|
|
17
19
|
// Date Cells
|
|
18
20
|
// -------------------------------------------------------------------------------------------------
|
|
19
|
-
const WEEKDAY_FORMAT = createFormatter({ weekday: 'long' });
|
|
20
21
|
const firstSunday = new Date(259200000);
|
|
21
|
-
function buildDateRowConfigs(
|
|
22
|
-
|
|
22
|
+
function buildDateRowConfigs(dates, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, // TODO: rename to dateHeaderFormat?
|
|
23
|
+
context) {
|
|
24
|
+
const rowConfig = buildDateRowConfig(dates, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, context);
|
|
25
|
+
const majorUnit = computeMajorUnit(dateProfile, context.dateEnv);
|
|
26
|
+
// HACK mutate isMajor
|
|
27
|
+
if (datesRepDistinctDays) {
|
|
28
|
+
for (const dataConfig of rowConfig.dataConfigs) {
|
|
29
|
+
if (isMajorUnit(dataConfig.dateMarker, majorUnit, context.dateEnv)) {
|
|
30
|
+
dataConfig.renderProps.isMajor = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return [rowConfig];
|
|
23
35
|
}
|
|
24
36
|
/*
|
|
25
37
|
Should this receive resource data attributes?
|
|
26
38
|
Or ResourceApi object itself?
|
|
27
39
|
*/
|
|
28
|
-
function buildDateRowConfig(
|
|
29
|
-
context, colSpan) {
|
|
40
|
+
function buildDateRowConfig(dateMarkers, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, // TODO: rename to dateHeaderFormat?
|
|
41
|
+
context, colSpan, isMajorMod) {
|
|
30
42
|
return {
|
|
43
|
+
isDateRow: true,
|
|
31
44
|
renderConfig: buildDateRenderConfig(context),
|
|
32
|
-
dataConfigs: buildDateDataConfigs(
|
|
45
|
+
dataConfigs: buildDateDataConfigs(dateMarkers, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, context, colSpan, undefined, undefined, undefined, undefined, isMajorMod)
|
|
33
46
|
};
|
|
34
47
|
}
|
|
48
|
+
/*
|
|
49
|
+
For header cells: how to connect w/ custom rendering
|
|
50
|
+
Applies to all cells in a row
|
|
51
|
+
*/
|
|
35
52
|
function buildDateRenderConfig(context) {
|
|
36
53
|
const { options } = context;
|
|
37
54
|
return {
|
|
38
55
|
generatorName: 'dayHeaderContent',
|
|
39
56
|
customGenerator: options.dayHeaderContent,
|
|
40
|
-
classNameGenerator: options.
|
|
57
|
+
classNameGenerator: options.dayHeaderClass,
|
|
58
|
+
innerClassNameGenerator: options.dayHeaderInnerClass,
|
|
41
59
|
didMount: options.dayHeaderDidMount,
|
|
42
60
|
willUnmount: options.dayHeaderWillUnmount,
|
|
61
|
+
align: options.dayHeaderAlign,
|
|
62
|
+
sticky: options.dayHeaderSticky,
|
|
43
63
|
};
|
|
44
64
|
}
|
|
45
|
-
|
|
46
|
-
|
|
65
|
+
const dowDates = [];
|
|
66
|
+
for (let dow = 0; dow < 7; dow++) {
|
|
67
|
+
dowDates.push(addDays(new Date(259200000), dow)); // start with Sun, 04 Jan 1970 00:00:00 GMT)
|
|
68
|
+
}
|
|
69
|
+
/*
|
|
70
|
+
For header cells: data
|
|
71
|
+
*/
|
|
72
|
+
function buildDateDataConfigs(dateMarkers, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, // TODO: rename to dateHeaderFormat?
|
|
73
|
+
context, colSpan = 1, keyPrefix = '', extraRenderProps = {}, // TODO
|
|
74
|
+
extraAttrs = {}, // TODO
|
|
75
|
+
className = '', isMajorMod) {
|
|
47
76
|
const { dateEnv, viewApi, options } = context;
|
|
48
77
|
return datesRepDistinctDays
|
|
49
|
-
?
|
|
50
|
-
const dateMeta = getDateMeta(
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
const
|
|
78
|
+
? dateMarkers.map((dateMarker, i) => {
|
|
79
|
+
const dateMeta = getDateMeta(dateMarker, dateEnv, dateProfile, todayRange);
|
|
80
|
+
const isMajor = isMajorMod != null && !(i % isMajorMod);
|
|
81
|
+
const [text, textParts] = dateEnv.format(dateMarker, dayHeaderFormat);
|
|
82
|
+
const hasNavLink = options.navLinks && !dateMeta.isDisabled &&
|
|
83
|
+
dateMarkers.length > 1; // don't show navlink to day if only one day
|
|
84
|
+
const renderProps = Object.assign(Object.assign(Object.assign({}, dateMeta), extraRenderProps), { text,
|
|
85
|
+
textParts,
|
|
86
|
+
get weekdayText() { return findWeekdayText(textParts); },
|
|
87
|
+
get dayNumberText() { return datesRepDistinctDays ? findDayNumberText(textParts) : ''; },
|
|
88
|
+
isMajor, isNarrow: false, isSticky: false, inPopover: false, level: 0, // HACK. gets overridden
|
|
89
|
+
hasNavLink, view: viewApi });
|
|
90
|
+
const fullDateStr = buildDateStr(context, dateMarker);
|
|
91
|
+
// for DayGridHeaderCell
|
|
54
92
|
return {
|
|
55
|
-
key: keyPrefix +
|
|
93
|
+
key: keyPrefix + dateMarker.toUTCString(),
|
|
94
|
+
dateMarker,
|
|
56
95
|
renderProps,
|
|
57
|
-
attrs: { '
|
|
58
|
-
|
|
96
|
+
attrs: Object.assign(Object.assign(Object.assign({ 'aria-label': fullDateStr }, (dateMeta.isToday ? { 'aria-current': 'date' } : {})), { 'data-date': formatDayString(dateMarker) }), extraAttrs),
|
|
97
|
+
// for navlink
|
|
98
|
+
innerAttrs: hasNavLink
|
|
99
|
+
? buildNavLinkAttrs(context, dateMarker, undefined, fullDateStr)
|
|
100
|
+
: { 'aria-hidden': true },
|
|
59
101
|
colSpan,
|
|
60
|
-
|
|
61
|
-
className
|
|
102
|
+
hasNavLink,
|
|
103
|
+
className,
|
|
62
104
|
};
|
|
63
105
|
})
|
|
64
|
-
:
|
|
65
|
-
const dow =
|
|
106
|
+
: dateMarkers.map((dateMarker, i) => {
|
|
107
|
+
const dow = dateMarker.getUTCDay();
|
|
66
108
|
const normDate = addDays(firstSunday, dow);
|
|
67
|
-
const
|
|
109
|
+
const dateMeta = {
|
|
110
|
+
date: dateEnv.toDate(dateMarker),
|
|
68
111
|
dow,
|
|
69
112
|
isDisabled: false,
|
|
70
113
|
isFuture: false,
|
|
@@ -72,14 +115,25 @@ context, colSpan = 1, keyPrefix = '') {
|
|
|
72
115
|
isToday: false,
|
|
73
116
|
isOther: false,
|
|
74
117
|
};
|
|
75
|
-
const
|
|
76
|
-
const
|
|
118
|
+
const isMajor = isMajorMod != null && !(i % isMajorMod);
|
|
119
|
+
const [text, textParts] = dateEnv.format(normDate, dayHeaderFormat);
|
|
120
|
+
const renderProps = Object.assign(Object.assign(Object.assign({}, dateMeta), { date: dowDates[dow], isMajor, isNarrow: false, isSticky: false, inPopover: false, hasNavLink: false, level: 0, view: viewApi, text,
|
|
121
|
+
textParts,
|
|
122
|
+
get weekdayText() { return findWeekdayText(textParts); },
|
|
123
|
+
get dayNumberText() { return datesRepDistinctDays ? findDayNumberText(textParts) : ''; } }), extraRenderProps);
|
|
124
|
+
const fullWeekDayStr = dateEnv.format(normDate, WEEKDAY_ONLY_FORMAT)[0];
|
|
125
|
+
// for DayGridHeaderCell
|
|
77
126
|
return {
|
|
78
127
|
key: keyPrefix + String(dow),
|
|
128
|
+
dateMarker,
|
|
79
129
|
renderProps,
|
|
80
|
-
|
|
130
|
+
attrs: Object.assign({ 'aria-label': fullWeekDayStr }, extraAttrs),
|
|
131
|
+
// NOT a navlink
|
|
132
|
+
innerAttrs: {
|
|
133
|
+
'aria-hidden': true, // label already on cell
|
|
134
|
+
},
|
|
81
135
|
colSpan,
|
|
82
|
-
className
|
|
136
|
+
className,
|
|
83
137
|
};
|
|
84
138
|
});
|
|
85
139
|
}
|
|
@@ -95,9 +149,9 @@ function getEventPartKey(seg) {
|
|
|
95
149
|
}
|
|
96
150
|
// DayGridRange utils (TODO: move)
|
|
97
151
|
// -------------------------------------------------------------------------------------------------
|
|
98
|
-
function splitSegsByRow(segs,
|
|
152
|
+
function splitSegsByRow(segs, rowCount) {
|
|
99
153
|
const byRow = [];
|
|
100
|
-
for (let row = 0; row <
|
|
154
|
+
for (let row = 0; row < rowCount; row++) {
|
|
101
155
|
byRow[row] = [];
|
|
102
156
|
}
|
|
103
157
|
for (const seg of segs) {
|
|
@@ -105,15 +159,15 @@ function splitSegsByRow(segs, rowCnt) {
|
|
|
105
159
|
}
|
|
106
160
|
return byRow;
|
|
107
161
|
}
|
|
108
|
-
function splitInteractionByRow(ui,
|
|
162
|
+
function splitInteractionByRow(ui, rowCount) {
|
|
109
163
|
const byRow = [];
|
|
110
164
|
if (!ui) {
|
|
111
|
-
for (let row = 0; row <
|
|
165
|
+
for (let row = 0; row < rowCount; row++) {
|
|
112
166
|
byRow[row] = null;
|
|
113
167
|
}
|
|
114
168
|
}
|
|
115
169
|
else {
|
|
116
|
-
for (let row = 0; row <
|
|
170
|
+
for (let row = 0; row < rowCount; row++) {
|
|
117
171
|
byRow[row] = {
|
|
118
172
|
affectedInstances: ui.affectedInstances,
|
|
119
173
|
isEvent: ui.isEvent,
|
|
@@ -146,61 +200,55 @@ function hasListItemDisplay(seg) {
|
|
|
146
200
|
);
|
|
147
201
|
}
|
|
148
202
|
|
|
149
|
-
class DayGridBlockEvent extends BaseComponent {
|
|
150
|
-
render() {
|
|
151
|
-
let { props } = this;
|
|
152
|
-
return (createElement(StandardEvent, Object.assign({}, props, { className: 'fc-daygrid-block-event fc-daygrid-event fc-h-event', defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: props.defaultDisplayEventEnd, disableResizing: !props.eventRange.def.allDay })));
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
class DayGridListEvent extends BaseComponent {
|
|
157
|
-
render() {
|
|
158
|
-
let { props, context } = this;
|
|
159
|
-
let { options } = context;
|
|
160
|
-
let { eventRange } = props;
|
|
161
|
-
let timeFormat = options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT;
|
|
162
|
-
let timeText = buildEventRangeTimeText(timeFormat, eventRange,
|
|
163
|
-
/* slicedStart = */ undefined,
|
|
164
|
-
/* slicedEnd = */ undefined, props.isStart, props.isEnd, context,
|
|
165
|
-
/* defaultDisplayEventTime = */ true, props.defaultDisplayEventEnd);
|
|
166
|
-
let anchorAttrs = getEventRangeAnchorAttrs(eventRange, context);
|
|
167
|
-
return (createElement(EventContainer, Object.assign({}, props, { tag: anchorAttrs ? 'a' : 'div', attrs: anchorAttrs, className: 'fc-daygrid-dot-event fc-daygrid-event', defaultGenerator: renderInnerContent, timeText: timeText, isResizing: false, isDateSelecting: false })));
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
function renderInnerContent(renderProps) {
|
|
171
|
-
return (createElement(Fragment, null,
|
|
172
|
-
createElement("div", { className: "fc-daygrid-event-dot", style: { borderColor: renderProps.borderColor || renderProps.backgroundColor } }),
|
|
173
|
-
renderProps.timeText && (createElement("div", { className: "fc-event-time" }, renderProps.timeText)),
|
|
174
|
-
createElement("div", { className: "fc-event-title" }, renderProps.event.title || createElement(Fragment, null, "\u00A0"))));
|
|
175
|
-
}
|
|
176
|
-
|
|
177
203
|
class DayGridMoreLink extends BaseComponent {
|
|
178
204
|
render() {
|
|
179
205
|
let { props } = this;
|
|
180
|
-
return (createElement(MoreLinkContainer, {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
let
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
visibility: forcedInvisibleMap[instanceId] ? 'hidden' : '',
|
|
192
|
-
} }, hasListItemDisplay(seg) ? (createElement(DayGridListEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, getEventRangeMeta(eventRange, props.todayRange)))) : (createElement(DayGridBlockEvent, Object.assign({ eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, getEventRangeMeta(eventRange, props.todayRange))))));
|
|
193
|
-
})));
|
|
194
|
-
} }));
|
|
206
|
+
return (createElement(MoreLinkContainer, { display: 'row', className: props.className, isNarrow: props.isNarrow, isMicro: props.isMicro, dateProfile: props.dateProfile, todayRange: props.todayRange, allDayDate: props.allDayDate, segs: props.segs, hiddenSegs: props.hiddenSegs, alignElRef: props.alignElRef, alignParentTop: props.alignParentTop, dateSpanProps: props.dateSpanProps, popoverContent: () => (createElement(Fragment, null, props.segs.map((seg) => {
|
|
207
|
+
let { eventRange } = seg;
|
|
208
|
+
let { instanceId } = eventRange.instance;
|
|
209
|
+
let isDragging = Boolean(props.eventDrag && props.eventDrag.affectedInstances[instanceId]);
|
|
210
|
+
let isResizing = Boolean(props.eventResize && props.eventResize.affectedInstances[instanceId]);
|
|
211
|
+
let isInvisible = isDragging || isResizing;
|
|
212
|
+
return (createElement("div", { key: instanceId, style: {
|
|
213
|
+
visibility: isInvisible ? 'hidden' : undefined,
|
|
214
|
+
} },
|
|
215
|
+
createElement(StandardEvent, Object.assign({ display: hasListItemDisplay(seg) ? 'list-item' : 'row', eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isResizing: isResizing, isMirror: false, isSelected: instanceId === props.eventSelection, defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: false }, getEventRangeMeta(eventRange, props.todayRange)))));
|
|
216
|
+
}))) }));
|
|
195
217
|
}
|
|
196
218
|
}
|
|
197
219
|
|
|
198
220
|
class DayGridCell extends DateComponent {
|
|
199
221
|
constructor() {
|
|
200
222
|
super(...arguments);
|
|
223
|
+
// memo
|
|
224
|
+
this.getDateMeta = memoize(getDateMeta);
|
|
225
|
+
this.refineRenderProps = memoizeObjArg(refineRenderProps);
|
|
201
226
|
// ref
|
|
202
227
|
this.rootElRef = createRef();
|
|
203
|
-
this.
|
|
228
|
+
this.handleBodyEl = (bodyEl) => {
|
|
229
|
+
if (this.disconnectBodyHeight) {
|
|
230
|
+
this.disconnectBodyHeight();
|
|
231
|
+
this.disconnectBodyHeight = undefined;
|
|
232
|
+
setRef(this.props.headerHeightRef, null);
|
|
233
|
+
setRef(this.props.mainHeightRef, null);
|
|
234
|
+
}
|
|
235
|
+
if (bodyEl) {
|
|
236
|
+
// we want to fire on ANY size change, because we do more advanced stuff
|
|
237
|
+
this.disconnectBodyHeight = watchSize(bodyEl, (_bodyWidth, bodyHeight) => {
|
|
238
|
+
const { props } = this;
|
|
239
|
+
const mainRect = bodyEl.getBoundingClientRect();
|
|
240
|
+
const rootRect = this.rootElRef.current.getBoundingClientRect();
|
|
241
|
+
const headerHeight = mainRect.top - rootRect.top;
|
|
242
|
+
if (!isDimsEqual(this.headerHeight, headerHeight)) {
|
|
243
|
+
this.headerHeight = headerHeight;
|
|
244
|
+
setRef(props.headerHeightRef, headerHeight);
|
|
245
|
+
}
|
|
246
|
+
if (props.fgLiquidHeight) {
|
|
247
|
+
setRef(props.mainHeightRef, bodyHeight);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
};
|
|
204
252
|
}
|
|
205
253
|
render() {
|
|
206
254
|
let { props, context } = this;
|
|
@@ -208,43 +256,53 @@ class DayGridCell extends DateComponent {
|
|
|
208
256
|
// TODO: memoize this
|
|
209
257
|
const isMonthStart = props.showDayNumber &&
|
|
210
258
|
shouldDisplayMonthStart(props.date, props.dateProfile.currentRange, dateEnv);
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if (!isDimsEqual(this.headerHeight, headerHeight)) {
|
|
229
|
-
this.headerHeight = headerHeight;
|
|
230
|
-
setRef(props.headerHeightRef, headerHeight);
|
|
231
|
-
}
|
|
232
|
-
if (props.fgLiquidHeight) {
|
|
233
|
-
setRef(props.mainHeightRef, bodyHeight);
|
|
234
|
-
}
|
|
259
|
+
const dateMeta = this.getDateMeta(props.date, dateEnv, props.dateProfile, props.todayRange);
|
|
260
|
+
const baseClassName = joinClassNames(props.borderStart ? classNames.borderOnlyS : classNames.borderNone, props.width != null ? '' : classNames.liquid, classNames.flexCol);
|
|
261
|
+
const hasNavLink = options.navLinks;
|
|
262
|
+
const renderProps = this.refineRenderProps({
|
|
263
|
+
date: props.date,
|
|
264
|
+
isMajor: props.isMajor,
|
|
265
|
+
isNarrow: props.isNarrow,
|
|
266
|
+
dateMeta: dateMeta,
|
|
267
|
+
hasLabel: props.showDayNumber,
|
|
268
|
+
hasMonthLabel: isMonthStart,
|
|
269
|
+
hasNavLink,
|
|
270
|
+
renderProps: props.renderProps,
|
|
271
|
+
viewApi: context.viewApi,
|
|
272
|
+
dateEnv: context.dateEnv,
|
|
273
|
+
monthStartFormat: options.monthStartFormat,
|
|
274
|
+
dayCellFormat: options.dayCellFormat,
|
|
275
|
+
businessHours: Boolean(options.businessHours),
|
|
235
276
|
});
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
277
|
+
if (dateMeta.isDisabled) {
|
|
278
|
+
return (createElement("div", { role: 'gridcell', "aria-disabled": true, className: joinArrayishClassNames(generateClassName(options.dayCellClass, renderProps), props.className, baseClassName), style: {
|
|
279
|
+
width: props.width
|
|
280
|
+
} }));
|
|
281
|
+
}
|
|
282
|
+
const fullDateStr = buildDateStr(context, props.date);
|
|
283
|
+
return (createElement(ContentContainer, { tag: "div", elRef: this.rootElRef, className: joinClassNames(props.className, baseClassName), attrs: Object.assign(Object.assign(Object.assign(Object.assign({}, props.attrs), { role: 'gridcell', 'aria-label': fullDateStr }), (renderProps.isToday ? { 'aria-current': 'date' } : {})), { 'data-date': formatDayString(props.date) }), style: {
|
|
284
|
+
width: props.width,
|
|
285
|
+
}, renderProps: renderProps, generatorName: "dayCellTopContent" // !!! for top
|
|
286
|
+
, customGenerator: options.dayCellTopContent /* !!! for top */, defaultGenerator: renderTopInner, classNameGenerator: options.dayCellClass, didMount: options.dayCellDidMount, willUnmount: options.dayCellWillUnmount }, (InnerContent) => (createElement(Fragment, null,
|
|
287
|
+
createElement("div", { className: joinClassNames(classNames.rel, // puts it above bg-fills, which are positioned on TOP of this component :|
|
|
288
|
+
generateClassName(options.dayCellTopClass, renderProps)) }, props.showDayNumber && (createElement(InnerContent // the dayCellTopContent
|
|
289
|
+
, { tag: 'div', attrs: hasNavLink
|
|
290
|
+
? buildNavLinkAttrs(context, props.date, undefined, fullDateStr)
|
|
291
|
+
: { 'aria-hidden': true } // label already on cell
|
|
292
|
+
, className: generateClassName(options.dayCellTopInnerClass, renderProps) }))),
|
|
293
|
+
createElement("div", { className: joinClassNames(classNames.flexCol, props.fgLiquidHeight ? classNames.liquid : classNames.grow), ref: this.handleBodyEl },
|
|
294
|
+
createElement("div", { className: generateClassName(options.dayCellInnerClass, renderProps), style: { minHeight: props.fgHeight } }, props.fg),
|
|
295
|
+
createElement(DayGridMoreLink, { className: classNames.rel, allDayDate: props.date, segs: props.segs, hiddenSegs: props.hiddenSegs, alignElRef: this.rootElRef, alignParentTop: props.showDayNumber
|
|
296
|
+
? '[role=row]'
|
|
297
|
+
: `.${classNames.internalView}`, dateSpanProps: props.dateSpanProps, dateProfile: props.dateProfile, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange, isNarrow: props.isNarrow, isMicro: props.isMicro })),
|
|
298
|
+
createElement("div", { className: joinClassNames(classNames.rel, // puts it above bg-fills
|
|
299
|
+
generateClassName(options.dayCellBottomClass, renderProps)) })))));
|
|
242
300
|
}
|
|
243
301
|
}
|
|
244
302
|
// Utils
|
|
245
303
|
// -------------------------------------------------------------------------------------------------
|
|
246
304
|
function renderTopInner(props) {
|
|
247
|
-
return props.
|
|
305
|
+
return props.text || createElement(Fragment, null, "\u00A0"); // TODO: DRY?
|
|
248
306
|
}
|
|
249
307
|
function shouldDisplayMonthStart(date, currentRange, dateEnv) {
|
|
250
308
|
const { start: currentStart, end: currentEnd } = currentRange;
|
|
@@ -261,6 +319,16 @@ function shouldDisplayMonthStart(date, currentRange, dateEnv) {
|
|
|
261
319
|
// a month-start that's within the current range?
|
|
262
320
|
(dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf()));
|
|
263
321
|
}
|
|
322
|
+
function refineRenderProps(raw) {
|
|
323
|
+
let { date, dateEnv, hasLabel, hasMonthLabel, hasNavLink, businessHours } = raw;
|
|
324
|
+
let [text, textParts] = hasLabel
|
|
325
|
+
? dateEnv.format(date, hasMonthLabel ? raw.monthStartFormat : raw.dayCellFormat)
|
|
326
|
+
: ['', []];
|
|
327
|
+
return Object.assign(Object.assign(Object.assign({}, raw.dateMeta), raw.renderProps), { text,
|
|
328
|
+
textParts, isMajor: raw.isMajor, isNarrow: raw.isNarrow, inPopover: false, hasNavLink,
|
|
329
|
+
get dayNumberText() { return findDayNumberText(textParts); },
|
|
330
|
+
get monthText() { return findMonthText(textParts); }, options: { businessHours }, view: raw.viewApi });
|
|
331
|
+
}
|
|
264
332
|
|
|
265
333
|
function computeFgSegVerticals(segs, segHeightMap, cells, maxHeight, strictOrder, allowSlicing = true, dayMaxEvents, dayMaxEventRows) {
|
|
266
334
|
let maxCoord;
|
|
@@ -383,20 +451,19 @@ function compileSegMap(segs, segMap) {
|
|
|
383
451
|
return res;
|
|
384
452
|
}
|
|
385
453
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
return new DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
|
|
454
|
+
function buildDayTableModel(dateProfile, dateProfileGenerator, dateEnv) {
|
|
455
|
+
const daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
|
|
456
|
+
const breakOnWeeks = /year|month|week/.test(dateProfile.currentRangeUnit);
|
|
457
|
+
const majorUnit = !breakOnWeeks && computeMajorUnit(dateProfile, dateEnv);
|
|
458
|
+
return new DayTableModel(daySeries, breakOnWeeks, dateEnv, majorUnit);
|
|
392
459
|
}
|
|
393
|
-
function computeColWidth(
|
|
460
|
+
function computeColWidth(colCount, colMinWidth, viewportWidth) {
|
|
394
461
|
if (viewportWidth == null) {
|
|
395
462
|
return [undefined, undefined];
|
|
396
463
|
}
|
|
397
|
-
const colTempWidth = viewportWidth /
|
|
464
|
+
const colTempWidth = viewportWidth / colCount;
|
|
398
465
|
if (colTempWidth < colMinWidth) {
|
|
399
|
-
return [colMinWidth *
|
|
466
|
+
return [colMinWidth * colCount, colMinWidth];
|
|
400
467
|
}
|
|
401
468
|
return [viewportWidth, undefined];
|
|
402
469
|
}
|
|
@@ -422,29 +489,24 @@ function computeTopFromDate(date, cellRows, rowHeightMap, adjust = 0) {
|
|
|
422
489
|
/*
|
|
423
490
|
FYI, `width` is not dependable for aligning completely to farside
|
|
424
491
|
*/
|
|
425
|
-
function computeHorizontalsFromSeg(seg, colWidth,
|
|
492
|
+
function computeHorizontalsFromSeg(seg, colWidth, colCount) {
|
|
426
493
|
let fromStart;
|
|
427
494
|
let fromEnd;
|
|
428
495
|
if (colWidth != null) {
|
|
429
496
|
fromStart = seg.start * colWidth;
|
|
430
|
-
fromEnd = (
|
|
497
|
+
fromEnd = (colCount - seg.end) * colWidth;
|
|
431
498
|
}
|
|
432
499
|
else {
|
|
433
|
-
const colWidthFrac = 1 /
|
|
500
|
+
const colWidthFrac = 1 / colCount;
|
|
434
501
|
fromStart = fracToCssDim(seg.start * colWidthFrac);
|
|
435
502
|
fromEnd = fracToCssDim(1 - seg.end * colWidthFrac);
|
|
436
503
|
}
|
|
437
|
-
|
|
438
|
-
return { right: fromStart, left: fromEnd };
|
|
439
|
-
}
|
|
440
|
-
else {
|
|
441
|
-
return { left: fromStart, right: fromEnd };
|
|
442
|
-
}
|
|
504
|
+
return { insetInlineStart: fromStart, insetInlineEnd: fromEnd };
|
|
443
505
|
}
|
|
444
|
-
function computeColFromPosition(positionLeft, elWidth, colWidth,
|
|
445
|
-
const realColWidth = colWidth != null ? colWidth : elWidth /
|
|
506
|
+
function computeColFromPosition(positionLeft, elWidth, colWidth, colCount, isRtl) {
|
|
507
|
+
const realColWidth = colWidth != null ? colWidth : elWidth / colCount;
|
|
446
508
|
const colFromLeft = Math.floor(positionLeft / realColWidth);
|
|
447
|
-
const col = isRtl ? (
|
|
509
|
+
const col = isRtl ? (colCount - colFromLeft - 1) : colFromLeft;
|
|
448
510
|
const left = colFromLeft * realColWidth;
|
|
449
511
|
const right = left + realColWidth;
|
|
450
512
|
return { col, left, right };
|
|
@@ -467,13 +529,17 @@ function computeRowFromPosition(positionTop, cellRows, rowHeightMap) {
|
|
|
467
529
|
// Hit Element
|
|
468
530
|
// -------------------------------------------------------------------------------------------------
|
|
469
531
|
function getRowEl(rootEl, row) {
|
|
470
|
-
return rootEl.querySelectorAll('
|
|
532
|
+
return rootEl.querySelectorAll('[role=row]')[row];
|
|
471
533
|
}
|
|
472
534
|
function getCellEl(rowEl, col) {
|
|
473
|
-
return rowEl.querySelectorAll('
|
|
535
|
+
return rowEl.querySelectorAll('[role=gridcell]')[col];
|
|
474
536
|
}
|
|
475
537
|
// Header Formatting
|
|
476
538
|
// -------------------------------------------------------------------------------------------------
|
|
539
|
+
const dayMicroWidth = 50;
|
|
540
|
+
const dayHeaderMicroFormat = createFormatter({
|
|
541
|
+
weekday: 'narrow'
|
|
542
|
+
});
|
|
477
543
|
function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) {
|
|
478
544
|
return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt);
|
|
479
545
|
}
|
|
@@ -481,13 +547,23 @@ function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt)
|
|
|
481
547
|
function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
|
|
482
548
|
// if more than one week row, or if there are a lot of columns with not much space,
|
|
483
549
|
// put just the day numbers will be in each cell
|
|
484
|
-
if (!datesRepDistinctDays
|
|
550
|
+
if (!datesRepDistinctDays) {
|
|
485
551
|
return createFormatter({ weekday: 'short' }); // "Sat"
|
|
486
552
|
}
|
|
487
553
|
if (dayCnt > 1) {
|
|
488
|
-
return createFormatter({
|
|
554
|
+
return createFormatter({
|
|
555
|
+
weekday: 'short',
|
|
556
|
+
weekdayJustify: 'start',
|
|
557
|
+
day: 'numeric',
|
|
558
|
+
omitCommas: true,
|
|
559
|
+
});
|
|
489
560
|
}
|
|
490
|
-
return createFormatter({
|
|
561
|
+
return createFormatter({
|
|
562
|
+
weekday: 'long',
|
|
563
|
+
weekdayJustify: 'start',
|
|
564
|
+
day: 'numeric',
|
|
565
|
+
omitCommas: true,
|
|
566
|
+
});
|
|
491
567
|
}
|
|
492
568
|
|
|
493
569
|
class DayGridEventHarness extends Component {
|
|
@@ -498,7 +574,7 @@ class DayGridEventHarness extends Component {
|
|
|
498
574
|
}
|
|
499
575
|
render() {
|
|
500
576
|
const { props } = this;
|
|
501
|
-
return (createElement("div", { className: joinClassNames(props.className,
|
|
577
|
+
return (createElement("div", { className: joinClassNames(props.className, classNames.abs), style: props.style, ref: this.rootElRef }, props.children));
|
|
502
578
|
}
|
|
503
579
|
componentDidMount() {
|
|
504
580
|
const rootEl = this.rootElRef.current; // TODO: make dynamic with useEffect
|
|
@@ -528,6 +604,8 @@ class DayGridRow extends BaseComponent {
|
|
|
528
604
|
this.segHeightRefMap = new RefMap(() => {
|
|
529
605
|
afterSize(this.handleSegPositioning);
|
|
530
606
|
});
|
|
607
|
+
// memo
|
|
608
|
+
this.buildWeekNumberRenderProps = memoize(buildWeekNumberRenderProps);
|
|
531
609
|
this.handleRootEl = (rootEl) => {
|
|
532
610
|
this.rootEl = rootEl;
|
|
533
611
|
setRef(this.props.rootElRef, rootEl);
|
|
@@ -540,7 +618,7 @@ class DayGridRow extends BaseComponent {
|
|
|
540
618
|
const { props, context, headerHeightRefMap, mainHeightRefMap } = this;
|
|
541
619
|
const { cells } = props;
|
|
542
620
|
const { options } = context;
|
|
543
|
-
const
|
|
621
|
+
const weekDateMarker = props.cells[0].date;
|
|
544
622
|
const fgLiquidHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
|
|
545
623
|
// TODO: memoize? sort all types of segs?
|
|
546
624
|
const fgEventSegs = sortEventSegs(props.fgEventSegs, options.eventOrder);
|
|
@@ -559,20 +637,29 @@ class DayGridRow extends BaseComponent {
|
|
|
559
637
|
}
|
|
560
638
|
const highlightSegs = this.getHighlightSegs();
|
|
561
639
|
const mirrorSegs = this.getMirrorSegs();
|
|
562
|
-
const
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
640
|
+
const hasNavLink = options.navLinks;
|
|
641
|
+
const fullWeekStr = buildDateStr(context, weekDateMarker, 'week');
|
|
642
|
+
const weekNumberRenderProps = this.buildWeekNumberRenderProps(weekDateMarker, context, props.cellIsNarrow, hasNavLink);
|
|
643
|
+
return (createElement("div", { role: props.role /* !!! */, "aria-label": props.role === 'row' // HACK
|
|
644
|
+
? fullWeekStr
|
|
645
|
+
: undefined // can't have label on non-role div
|
|
646
|
+
, className: joinArrayishClassNames(options.dayRowClass, props.className, classNames.flexRow, classNames.rel, // origin for inlineWeekNumber?
|
|
647
|
+
classNames.isolate, (props.forPrint && props.basis !== undefined) && // basis implies siblings (must share height)
|
|
648
|
+
classNames.printSiblingRow), style: {
|
|
649
|
+
'flex-basis': props.basis,
|
|
569
650
|
}, ref: this.handleRootEl },
|
|
651
|
+
(props.showWeekNumbers && !props.cellIsMicro) && (createElement(ContentContainer, { tag: 'div', attrs: Object.assign(Object.assign({}, (hasNavLink
|
|
652
|
+
? buildNavLinkAttrs(context, weekDateMarker, 'week', fullWeekStr, /* isTabbable = */ false)
|
|
653
|
+
: {})), { 'role': undefined, 'aria-hidden': true }),
|
|
654
|
+
// put above all cells (TODO: put explicit z0 on each cell?)
|
|
655
|
+
className: classNames.z1, renderProps: weekNumberRenderProps, generatorName: "inlineWeekNumberContent", customGenerator: options.inlineWeekNumberContent, defaultGenerator: renderText, classNameGenerator: options.inlineWeekNumberClass, didMount: options.inlineWeekNumberDidMount, willUnmount: options.inlineWeekNumberWillUnmount })),
|
|
570
656
|
this.renderFillSegs(props.businessHourSegs, 'non-business'),
|
|
571
657
|
this.renderFillSegs(props.bgEventSegs, 'bg-event'),
|
|
572
658
|
this.renderFillSegs(highlightSegs, 'highlight'),
|
|
573
|
-
|
|
574
|
-
const normalFgNodes = this.renderFgSegs(maxMainTop, renderableSegsByCol[col], segTops, props.todayRange,
|
|
575
|
-
|
|
659
|
+
props.cells.map((cell, col) => {
|
|
660
|
+
const normalFgNodes = this.renderFgSegs(maxMainTop, renderableSegsByCol[col], segTops, props.todayRange,
|
|
661
|
+
/* isMirror = */ false);
|
|
662
|
+
return (createElement(DayGridCell, { key: cell.key, dateProfile: props.dateProfile, todayRange: props.todayRange, date: cell.date, isMajor: cell.isMajor, showDayNumber: props.showDayNumbers, isNarrow: props.cellIsNarrow, isMicro: props.cellIsMicro, borderStart: Boolean(col),
|
|
576
663
|
// content
|
|
577
664
|
segs: segsByCol[col], hiddenSegs: hiddenSegsByCol[col], fgLiquidHeight: fgLiquidHeight, fg: (createElement(Fragment, null, normalFgNodes)), eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
|
|
578
665
|
// render hooks
|
|
@@ -581,19 +668,16 @@ class DayGridRow extends BaseComponent {
|
|
|
581
668
|
fgHeight: heightsByCol[col], width: props.colWidth,
|
|
582
669
|
// refs
|
|
583
670
|
headerHeightRef: headerHeightRefMap.createRef(cell.key), mainHeightRef: mainHeightRefMap.createRef(cell.key) }));
|
|
584
|
-
})
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
Boolean(props.eventDrag), Boolean(props.eventResize), false)));
|
|
671
|
+
}),
|
|
672
|
+
this.renderFgSegs(maxMainTop, mirrorSegs, segTops, props.todayRange,
|
|
673
|
+
/* isMirror = */ true)));
|
|
588
674
|
}
|
|
589
|
-
renderFgSegs(headerHeight, segs, segTops, todayRange,
|
|
675
|
+
renderFgSegs(headerHeight, segs, segTops, todayRange, isMirror) {
|
|
590
676
|
var _a;
|
|
591
|
-
const { props,
|
|
592
|
-
const {
|
|
593
|
-
const
|
|
594
|
-
const colCnt = props.cells.length;
|
|
677
|
+
const { props, segHeightRefMap } = this;
|
|
678
|
+
const { colWidth, eventSelection, cellIsMicro } = props;
|
|
679
|
+
const colCount = props.cells.length;
|
|
595
680
|
const defaultDisplayEventEnd = props.cells.length === 1;
|
|
596
|
-
const isMirror = isDragging || isResizing || isDateSelecting;
|
|
597
681
|
const nodes = [];
|
|
598
682
|
for (const seg of segs) {
|
|
599
683
|
const key = getEventPartKey(seg);
|
|
@@ -602,39 +686,43 @@ class DayGridRow extends BaseComponent {
|
|
|
602
686
|
if (standinFor) {
|
|
603
687
|
continue;
|
|
604
688
|
}
|
|
605
|
-
const {
|
|
689
|
+
const { insetInlineStart, insetInlineEnd } = computeHorizontalsFromSeg(seg, colWidth, colCount);
|
|
606
690
|
const localTop = (_a = segTops.get(standinFor ? getEventPartKey(standinFor) : key)) !== null && _a !== void 0 ? _a : (isMirror ? 0 : undefined);
|
|
607
691
|
const top = headerHeight != null && localTop != null
|
|
608
692
|
? headerHeight + localTop
|
|
609
693
|
: undefined;
|
|
610
|
-
const
|
|
611
|
-
|
|
612
|
-
|
|
694
|
+
const isDragging = Boolean(props.eventDrag && props.eventDrag.affectedInstances[instanceId]);
|
|
695
|
+
const isResizing = Boolean(props.eventResize && props.eventResize.affectedInstances[instanceId]);
|
|
696
|
+
const isInvisible = !isMirror && (isDragging || isResizing || standinFor || top == null);
|
|
697
|
+
const isListItem = hasListItemDisplay(seg);
|
|
698
|
+
nodes.push(createElement(DayGridEventHarness, { key: key, className: seg.start ? classNames.fakeBorderS : '', style: {
|
|
699
|
+
visibility: isInvisible ? 'hidden' : undefined,
|
|
613
700
|
top,
|
|
614
|
-
|
|
615
|
-
|
|
701
|
+
insetInlineStart,
|
|
702
|
+
insetInlineEnd,
|
|
703
|
+
zIndex: 0, // container inner z-indexes
|
|
616
704
|
}, heightRef: (!standinFor && !isMirror)
|
|
617
705
|
? segHeightRefMap.createRef(key)
|
|
618
|
-
: null },
|
|
706
|
+
: null },
|
|
707
|
+
createElement(StandardEvent, Object.assign({ display: isListItem ? 'list-item' : 'row', eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isResizing: isResizing, isMirror: isMirror, isSelected: instanceId === eventSelection, isNarrow: props.cellIsNarrow, defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: defaultDisplayEventEnd, disableResizing: isListItem, forcedTimeText: cellIsMicro ? '' : undefined }, getEventRangeMeta(eventRange, todayRange)))));
|
|
619
708
|
}
|
|
620
709
|
return nodes;
|
|
621
710
|
}
|
|
622
711
|
renderFillSegs(segs, fillType) {
|
|
623
712
|
const { props, context } = this;
|
|
624
|
-
const { isRtl } = context;
|
|
625
713
|
const { todayRange, colWidth } = props;
|
|
626
|
-
const
|
|
714
|
+
const colCount = props.cells.length;
|
|
627
715
|
const nodes = [];
|
|
628
716
|
for (const seg of segs) {
|
|
629
717
|
const key = buildEventRangeKey(seg.eventRange); // TODO: use different type of key than fg!?
|
|
630
|
-
const {
|
|
718
|
+
const { insetInlineStart, insetInlineEnd } = computeHorizontalsFromSeg(seg, colWidth, colCount);
|
|
631
719
|
const isVisible = !seg.standinFor;
|
|
632
|
-
nodes.push(createElement("div", { key: key, className:
|
|
720
|
+
nodes.push(createElement("div", { key: key, className: classNames.fillY, style: {
|
|
633
721
|
visibility: isVisible ? '' : 'hidden',
|
|
634
|
-
|
|
635
|
-
|
|
722
|
+
insetInlineStart,
|
|
723
|
+
insetInlineEnd,
|
|
636
724
|
} }, fillType === 'bg-event' ?
|
|
637
|
-
createElement(BgEvent, Object.assign({ eventRange: seg.eventRange, isStart: seg.isStart, isEnd: seg.isEnd }, getEventRangeMeta(seg.eventRange, todayRange))) : (renderFill(fillType))));
|
|
725
|
+
createElement(BgEvent, Object.assign({ eventRange: seg.eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isNarrow: props.cellIsNarrow, isVertical: false }, getEventRangeMeta(seg.eventRange, todayRange))) : (renderFill(fillType, context.options))));
|
|
638
726
|
}
|
|
639
727
|
return createElement(Fragment, {}, ...nodes); // TODO: shouldn't this be an array, so keyed?
|
|
640
728
|
}
|
|
@@ -698,6 +786,22 @@ class DayGridRow extends BaseComponent {
|
|
|
698
786
|
return props.dateSelectionSegs;
|
|
699
787
|
}
|
|
700
788
|
}
|
|
789
|
+
// Utils
|
|
790
|
+
// -------------------------------------------------------------------------------------------------
|
|
791
|
+
function buildWeekNumberRenderProps(weekDateMarker, context, isNarrow, hasNavLink) {
|
|
792
|
+
const { dateEnv, options } = context;
|
|
793
|
+
const weekNum = dateEnv.computeWeekNumber(weekDateMarker);
|
|
794
|
+
const [weekNumText, weekNumTextParts] = dateEnv.format(weekDateMarker, options.weekNumberFormat || DEFAULT_WEEK_NUM_FORMAT);
|
|
795
|
+
const weekDateZoned = dateEnv.toDate(weekDateMarker);
|
|
796
|
+
return {
|
|
797
|
+
num: weekNum,
|
|
798
|
+
text: weekNumText,
|
|
799
|
+
textParts: weekNumTextParts,
|
|
800
|
+
date: weekDateZoned,
|
|
801
|
+
isNarrow,
|
|
802
|
+
hasNavLink,
|
|
803
|
+
};
|
|
804
|
+
}
|
|
701
805
|
|
|
702
806
|
class DayGridRows extends DateComponent {
|
|
703
807
|
constructor() {
|
|
@@ -733,45 +837,36 @@ class DayGridRows extends DateComponent {
|
|
|
733
837
|
render() {
|
|
734
838
|
let { props, context, rowHeightRefMap } = this;
|
|
735
839
|
let { options } = context;
|
|
736
|
-
let
|
|
737
|
-
let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs,
|
|
738
|
-
let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs,
|
|
739
|
-
let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs,
|
|
740
|
-
let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs,
|
|
741
|
-
let eventDragByRow = this.splitEventDrag(props.eventDrag,
|
|
742
|
-
let eventResizeByRow = this.splitEventResize(props.eventResize,
|
|
840
|
+
let rowCount = props.cellRows.length;
|
|
841
|
+
let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCount);
|
|
842
|
+
let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCount);
|
|
843
|
+
let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCount);
|
|
844
|
+
let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCount);
|
|
845
|
+
let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCount);
|
|
846
|
+
let eventResizeByRow = this.splitEventResize(props.eventResize, rowCount);
|
|
743
847
|
let isHeightAuto = getIsHeightAuto(options);
|
|
744
848
|
let rowHeightsRedistribute = !props.forPrint && !isHeightAuto;
|
|
745
|
-
let
|
|
746
|
-
return (createElement("div", { className: joinClassNames(
|
|
849
|
+
let rowBasis = computeRowBasis(props.visibleWidth, rowCount, isHeightAuto, options);
|
|
850
|
+
return (createElement("div", { role: 'rowgroup', className: joinClassNames(props.className,
|
|
747
851
|
// HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
|
|
748
852
|
// https://stackoverflow.com/a/60256345
|
|
749
|
-
!props.forPrint &&
|
|
853
|
+
!props.forPrint && classNames.flexCol), style: { width: props.width }, ref: this.handleRootEl }, props.cellRows.map((cells, row) => (createElement(DayGridRow, { key: cells[0].key, role: 'row', dateProfile: props.dateProfile, todayRange: props.todayRange, cells: cells, cellIsNarrow: props.cellIsNarrow, cellIsMicro: props.cellIsMicro, showDayNumbers: rowCount > 1, showWeekNumbers: rowCount > 1 && options.weekNumbers, forPrint: props.forPrint,
|
|
750
854
|
// if not auto-height, distribute height of container somewhat evently to rows
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
row < rowCnt - 1 && 'fc-border-b'),
|
|
855
|
+
className: joinClassNames(rowHeightsRedistribute && classNames.grow, rowCount > 1 && classNames.breakInsideAvoid, // don't avoid breaks for single tall row
|
|
856
|
+
row < rowCount - 1 ? classNames.borderOnlyB : classNames.borderNone),
|
|
754
857
|
// content
|
|
755
858
|
fgEventSegs: fgEventSegsByRow[row], bgEventSegs: bgEventSegsByRow[row].filter(isSegAllDay) /* HACK */, businessHourSegs: businessHourSegsByRow[row], dateSelectionSegs: dateSelectionSegsByRow[row], eventSelection: props.eventSelection, eventDrag: eventDragByRow[row], eventResize: eventResizeByRow[row], dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows,
|
|
756
859
|
// dimensions
|
|
757
|
-
colWidth: props.colWidth,
|
|
860
|
+
colWidth: props.colWidth, basis: rowBasis,
|
|
758
861
|
// refs
|
|
759
862
|
heightRef: rowHeightRefMap.createRef(cells[0].key) })))));
|
|
760
863
|
}
|
|
761
|
-
componentDidMount() {
|
|
762
|
-
this.disconnectWidth = watchWidth(this.rootEl, (width) => {
|
|
763
|
-
this.setState({ width });
|
|
764
|
-
});
|
|
765
|
-
}
|
|
766
|
-
componentWillUnmount() {
|
|
767
|
-
this.disconnectWidth();
|
|
768
|
-
}
|
|
769
864
|
// Hit System
|
|
770
865
|
// -----------------------------------------------------------------------------------------------
|
|
771
|
-
queryHit(positionLeft, positionTop, elWidth) {
|
|
772
|
-
const { props
|
|
773
|
-
const
|
|
774
|
-
const { col, left, right } = computeColFromPosition(positionLeft, elWidth, props.colWidth,
|
|
866
|
+
queryHit(isRtl, positionLeft, positionTop, elWidth) {
|
|
867
|
+
const { props } = this;
|
|
868
|
+
const colCount = props.cellRows[0].length;
|
|
869
|
+
const { col, left, right } = computeColFromPosition(positionLeft, elWidth, props.colWidth, colCount, isRtl);
|
|
775
870
|
const { row, top, bottom } = computeRowFromPosition(positionTop, props.cellRows, this.rowHeightRefMap.current);
|
|
776
871
|
const cell = props.cellRows[row][col];
|
|
777
872
|
const cellStartDate = cell.date;
|
|
@@ -782,8 +877,7 @@ class DayGridRows extends DateComponent {
|
|
|
782
877
|
start: cellStartDate,
|
|
783
878
|
end: cellEndDate,
|
|
784
879
|
}, allDay: true }, cell.dateSpanProps),
|
|
785
|
-
|
|
786
|
-
dayEl: getCellEl(getRowEl(this.rootEl, row), col),
|
|
880
|
+
getDayEl: () => getCellEl(getRowEl(this.rootEl, row), col),
|
|
787
881
|
rect: {
|
|
788
882
|
left,
|
|
789
883
|
right,
|
|
@@ -799,40 +893,41 @@ class DayGridRows extends DateComponent {
|
|
|
799
893
|
function isSegAllDay(seg) {
|
|
800
894
|
return seg.eventRange.def.allDay;
|
|
801
895
|
}
|
|
802
|
-
|
|
803
|
-
|
|
896
|
+
/*
|
|
897
|
+
Amount of height a row should consume prior to expanding
|
|
898
|
+
We don't want to use min-height with flexbox because we leverage min-height:auto,
|
|
899
|
+
which yields value based on natural height of events
|
|
900
|
+
*/
|
|
901
|
+
function computeRowBasis(visibleWidth, // should INCLUDE any scrollbar width to avoid oscillation
|
|
902
|
+
rowCount, isHeightAuto, options) {
|
|
804
903
|
if (visibleWidth != null) {
|
|
805
904
|
// ensure a consistent row min-height modelled after a month with 6 rows respecting aspectRatio
|
|
806
905
|
// will result in same minHeight regardless of weekends, dayMinWidth, height:auto
|
|
807
|
-
const
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
// this is value that looks natural on paper for portrait/landscape
|
|
812
|
-
? '6em'
|
|
813
|
-
// don't give minHeight when single-month non-auto-height
|
|
814
|
-
// TODO: better way to detect this with DateProfile?
|
|
815
|
-
: (rowCnt > 6 || isHeightAuto)
|
|
816
|
-
? rowMinHeight
|
|
817
|
-
: undefined,
|
|
818
|
-
// isCompact?: just before most lone +more links hit bottom of cell
|
|
819
|
-
rowMinHeight < 70,
|
|
820
|
-
];
|
|
906
|
+
const rowBasis = visibleWidth / options.aspectRatio / 6;
|
|
907
|
+
// don't give minHeight when single-month non-auto-height
|
|
908
|
+
// TODO: better way to detect this with DateProfile?
|
|
909
|
+
return (rowCount > 6 || isHeightAuto) ? rowBasis : 0;
|
|
821
910
|
}
|
|
822
|
-
return
|
|
911
|
+
return 0;
|
|
823
912
|
}
|
|
824
913
|
|
|
825
914
|
class DayGridHeaderCell extends BaseComponent {
|
|
826
915
|
constructor() {
|
|
827
916
|
super(...arguments);
|
|
828
917
|
this.handleInnerEl = (innerEl) => {
|
|
829
|
-
if (this.
|
|
830
|
-
this.
|
|
831
|
-
this.
|
|
918
|
+
if (this.disconnectSize) {
|
|
919
|
+
this.disconnectSize();
|
|
920
|
+
this.disconnectSize = undefined;
|
|
832
921
|
}
|
|
833
922
|
if (innerEl) {
|
|
834
|
-
this.
|
|
923
|
+
this.disconnectSize = watchSize(innerEl, (width, height) => {
|
|
835
924
|
setRef(this.props.innerHeightRef, height);
|
|
925
|
+
/*
|
|
926
|
+
TODO: DRY with TimelineHeaderCell
|
|
927
|
+
*/
|
|
928
|
+
if (this.align === 'center' && this.isSticky) {
|
|
929
|
+
this.setState({ innerWidth: width });
|
|
930
|
+
}
|
|
836
931
|
});
|
|
837
932
|
}
|
|
838
933
|
else {
|
|
@@ -841,16 +936,54 @@ class DayGridHeaderCell extends BaseComponent {
|
|
|
841
936
|
};
|
|
842
937
|
}
|
|
843
938
|
render() {
|
|
844
|
-
const { props } = this;
|
|
939
|
+
const { props, state, context } = this;
|
|
845
940
|
const { renderConfig, dataConfig } = props;
|
|
846
|
-
|
|
941
|
+
// HACK
|
|
942
|
+
const isDisabled = dataConfig.renderProps.isDisabled;
|
|
943
|
+
const finalRenderProps = Object.assign(Object.assign({}, dataConfig.renderProps), { isNarrow: props.cellIsNarrow, level: props.rowLevel });
|
|
944
|
+
if (props.cellIsMicro) {
|
|
945
|
+
// TODO: only if not distinct dates
|
|
946
|
+
const [microText, microTextParts] = context.dateEnv.format(dataConfig.dateMarker, dayHeaderMicroFormat);
|
|
947
|
+
finalRenderProps.text = finalRenderProps.weekdayText = microText;
|
|
948
|
+
finalRenderProps.textParts = microTextParts;
|
|
949
|
+
}
|
|
950
|
+
/*
|
|
951
|
+
TODO: DRY with TimelineHeaderCell
|
|
952
|
+
*/
|
|
953
|
+
const alignInput = renderConfig.align;
|
|
954
|
+
const align = this.align =
|
|
955
|
+
typeof alignInput === 'function'
|
|
956
|
+
? alignInput({ level: props.rowLevel, inPopover: dataConfig.renderProps.inPopover, isNarrow: props.cellIsNarrow })
|
|
957
|
+
: alignInput;
|
|
958
|
+
const stickyInput = renderConfig.sticky;
|
|
959
|
+
const isSticky = this.isSticky =
|
|
960
|
+
props.rowLevel && stickyInput !== false;
|
|
961
|
+
let edgeCoord;
|
|
962
|
+
if (isSticky) {
|
|
963
|
+
if (align === 'center') {
|
|
964
|
+
if (state.innerWidth != null) {
|
|
965
|
+
edgeCoord = `calc(50% - ${state.innerWidth / 2}px)`;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
else {
|
|
969
|
+
edgeCoord = (typeof stickyInput === 'number' ||
|
|
970
|
+
typeof stickyInput === 'string') ? stickyInput : 0;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
return (createElement(ContentContainer, { tag: 'div', attrs: Object.assign({ role: 'columnheader', 'aria-colspan': dataConfig.colSpan }, dataConfig.attrs), className: joinClassNames(dataConfig.className, classNames.tight, classNames.flexCol, props.borderStart ? classNames.borderOnlyS : classNames.borderNone, align === 'center' ? classNames.alignCenter :
|
|
974
|
+
align === 'end' ? classNames.alignEnd :
|
|
975
|
+
classNames.alignStart, props.colWidth == null && classNames.liquid, !isSticky && classNames.crop), style: {
|
|
847
976
|
width: props.colWidth != null
|
|
848
977
|
? props.colWidth * (dataConfig.colSpan || 1)
|
|
849
978
|
: undefined,
|
|
850
|
-
}, renderProps:
|
|
979
|
+
}, renderProps: finalRenderProps, generatorName: renderConfig.generatorName, customGenerator: renderConfig.customGenerator, defaultGenerator: renderText, classNameGenerator:
|
|
851
980
|
// don't use custom classNames if disabled
|
|
852
981
|
// TODO: make DRY with DayCellContainer
|
|
853
|
-
|
|
982
|
+
isDisabled ? undefined : renderConfig.classNameGenerator, didMount: renderConfig.didMount, willUnmount: renderConfig.willUnmount }, (InnerContainer) => (createElement("div", { ref: this.handleInnerEl, className: joinClassNames(classNames.flexCol, classNames.rigid, isSticky && classNames.sticky), style: {
|
|
983
|
+
left: edgeCoord,
|
|
984
|
+
right: edgeCoord,
|
|
985
|
+
} },
|
|
986
|
+
createElement(InnerContainer, { tag: 'div', attrs: dataConfig.innerAttrs, className: generateClassName(renderConfig.innerClassNameGenerator, finalRenderProps) })))));
|
|
854
987
|
}
|
|
855
988
|
}
|
|
856
989
|
|
|
@@ -874,8 +1007,14 @@ class DayGridHeaderRow extends BaseComponent {
|
|
|
874
1007
|
};
|
|
875
1008
|
}
|
|
876
1009
|
render() {
|
|
877
|
-
const { props } = this;
|
|
878
|
-
|
|
1010
|
+
const { props, context } = this;
|
|
1011
|
+
const { options } = context;
|
|
1012
|
+
return (createElement("div", { role: props.role /* !!! */, "aria-rowindex": props.rowIndex != null ? 1 + props.rowIndex : undefined, className: joinArrayishClassNames(options.dayHeaderRowClass, props.className, classNames.flexRow, classNames.contentBox, props.borderBottom ? classNames.borderOnlyB : classNames.borderNone), style: {
|
|
1013
|
+
height: props.height,
|
|
1014
|
+
} }, props.dataConfigs.map((dataConfig, cellI) => (createElement(DayGridHeaderCell, { key: dataConfig.key, renderConfig: props.renderConfig, dataConfig: dataConfig, borderStart: Boolean(cellI), colWidth: props.colWidth, innerHeightRef: this.innerHeightRefMap.createRef(dataConfig.key), cellIsNarrow: props.cellIsNarrow, cellIsMicro: props.cellIsMicro, rowLevel: props.rowLevel })))));
|
|
1015
|
+
}
|
|
1016
|
+
componentWillUnmount() {
|
|
1017
|
+
setRef(this.props.innerHeightRef, null);
|
|
879
1018
|
}
|
|
880
1019
|
}
|
|
881
1020
|
|
|
@@ -885,9 +1024,10 @@ TODO: kill this class in favor of DayGridHeaderRows?
|
|
|
885
1024
|
class DayGridHeader extends BaseComponent {
|
|
886
1025
|
render() {
|
|
887
1026
|
const { props } = this;
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
1027
|
+
const { headerTiers } = props;
|
|
1028
|
+
return (createElement("div", { role: 'rowgroup', className: joinClassNames(props.className, classNames.flexCol, props.width == null && classNames.liquid), style: {
|
|
1029
|
+
width: props.width,
|
|
1030
|
+
} }, headerTiers.map((rowConfig, i) => (createElement(DayGridHeaderRow, Object.assign({}, rowConfig, { key: i, role: 'row', borderBottom: i < headerTiers.length - 1, colWidth: props.colWidth, cellIsNarrow: props.cellIsNarrow, cellIsMicro: props.cellIsMicro, rowLevel: headerTiers.length - i - 1 }))))));
|
|
891
1031
|
}
|
|
892
1032
|
}
|
|
893
1033
|
|
|
@@ -897,37 +1037,54 @@ class DayGridLayoutNormal extends BaseComponent {
|
|
|
897
1037
|
this.handleScroller = (scroller) => {
|
|
898
1038
|
setRef(this.props.scrollerRef, scroller);
|
|
899
1039
|
};
|
|
1040
|
+
this.handleTotalWidth = (totalWidth) => {
|
|
1041
|
+
this.setState({ totalWidth });
|
|
1042
|
+
};
|
|
900
1043
|
this.handleClientWidth = (clientWidth) => {
|
|
901
1044
|
this.setState({ clientWidth });
|
|
902
1045
|
};
|
|
903
|
-
this.handleEndScrollbarWidth = (endScrollbarWidth) => {
|
|
904
|
-
this.setState({ endScrollbarWidth });
|
|
905
|
-
};
|
|
906
1046
|
}
|
|
907
1047
|
render() {
|
|
908
1048
|
const { props, state, context } = this;
|
|
909
1049
|
const { options } = context;
|
|
1050
|
+
const { totalWidth, clientWidth } = state;
|
|
1051
|
+
let endScrollbarWidth = (totalWidth != null && clientWidth != null)
|
|
1052
|
+
? totalWidth - clientWidth
|
|
1053
|
+
: undefined;
|
|
1054
|
+
// HACK when clientWidth does NOT include body-border, compared to totalWidth
|
|
1055
|
+
if (endScrollbarWidth < 3) {
|
|
1056
|
+
endScrollbarWidth = 0;
|
|
1057
|
+
}
|
|
910
1058
|
const verticalScrollbars = !props.forPrint && !getIsHeightAuto(options);
|
|
911
1059
|
const stickyHeaderDates = !props.forPrint && getStickyHeaderDates(options);
|
|
1060
|
+
const colCount = props.cellRows[0].length;
|
|
1061
|
+
const cellWidth = clientWidth != null ? clientWidth / colCount : undefined;
|
|
1062
|
+
const cellIsMicro = cellWidth != null && cellWidth <= dayMicroWidth;
|
|
1063
|
+
const cellIsNarrow = cellIsMicro || (cellWidth != null && cellWidth <= options.dayNarrowWidth);
|
|
912
1064
|
return (createElement(Fragment, null,
|
|
913
|
-
options.dayHeaders && (createElement("div", { className: joinClassNames(
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
1065
|
+
options.dayHeaders && (createElement("div", { className: joinClassNames(generateClassName(options.tableHeaderClass, {
|
|
1066
|
+
isSticky: stickyHeaderDates,
|
|
1067
|
+
}), props.borderlessX && classNames.borderlessX, classNames.printHeader, // either flexCol or table-header-group
|
|
1068
|
+
stickyHeaderDates && classNames.tableHeaderSticky) },
|
|
1069
|
+
createElement("div", { className: classNames.flexRow },
|
|
1070
|
+
createElement(DayGridHeader, { headerTiers: props.headerTiers, cellIsNarrow: cellIsNarrow, cellIsMicro: cellIsMicro }),
|
|
1071
|
+
Boolean(endScrollbarWidth) && (createElement("div", { className: joinArrayishClassNames(generateClassName(options.fillerClass, { isHeader: true }), classNames.borderOnlyS), style: { minWidth: endScrollbarWidth } }))),
|
|
1072
|
+
createElement("div", { className: generateClassName(options.dayHeaderDividerClass, {
|
|
1073
|
+
isSticky: stickyHeaderDates,
|
|
1074
|
+
options: { allDaySlot: Boolean(options.allDaySlot) },
|
|
1075
|
+
}) }))),
|
|
1076
|
+
createElement(Scroller, { vertical: verticalScrollbars, className: joinArrayishClassNames(options.tableBodyClass, props.borderlessX && classNames.borderlessX, stickyHeaderDates && classNames.borderlessTop, (stickyHeaderDates || props.noEdgeEffects) && classNames.noEdgeEffects,
|
|
918
1077
|
// HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
|
|
919
1078
|
// https://stackoverflow.com/a/60256345
|
|
920
|
-
!props.forPrint &&
|
|
921
|
-
createElement(DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed, className:
|
|
1079
|
+
!props.forPrint && classNames.flexCol, verticalScrollbars && classNames.liquid), ref: this.handleScroller, clientWidthRef: this.handleClientWidth },
|
|
1080
|
+
createElement(DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed, className: classNames.grow, dayMaxEvents: props.forPrint ? undefined : options.dayMaxEvents, dayMaxEventRows: options.dayMaxEventRows,
|
|
922
1081
|
// content
|
|
923
1082
|
fgEventSegs: props.fgEventSegs, bgEventSegs: props.bgEventSegs, businessHourSegs: props.businessHourSegs, dateSelectionSegs: props.dateSelectionSegs, eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
|
|
924
1083
|
// dimensions
|
|
925
|
-
visibleWidth:
|
|
926
|
-
state.clientWidth != null && state.endScrollbarWidth != null
|
|
927
|
-
? state.clientWidth + state.endScrollbarWidth
|
|
928
|
-
: undefined,
|
|
1084
|
+
visibleWidth: totalWidth, cellIsNarrow: cellIsNarrow, cellIsMicro: cellIsMicro,
|
|
929
1085
|
// refs
|
|
930
|
-
rowHeightRefMap: props.rowHeightRefMap }))
|
|
1086
|
+
rowHeightRefMap: props.rowHeightRefMap })),
|
|
1087
|
+
createElement(Ruler, { widthRef: this.handleTotalWidth })));
|
|
931
1088
|
}
|
|
932
1089
|
}
|
|
933
1090
|
|
|
@@ -939,43 +1096,54 @@ class DayGridLayoutPannable extends BaseComponent {
|
|
|
939
1096
|
this.footerScrollerRef = createRef();
|
|
940
1097
|
// Sizing
|
|
941
1098
|
// -----------------------------------------------------------------------------------------------
|
|
1099
|
+
this.handleTotalWidth = (totalWidth) => {
|
|
1100
|
+
this.setState({ totalWidth });
|
|
1101
|
+
};
|
|
942
1102
|
this.handleClientWidth = (clientWidth) => {
|
|
943
1103
|
this.setState({ clientWidth });
|
|
944
1104
|
};
|
|
945
|
-
this.handleEndScrollbarWidth = (endScrollbarWidth) => {
|
|
946
|
-
this.setState({ endScrollbarWidth });
|
|
947
|
-
};
|
|
948
1105
|
}
|
|
949
1106
|
render() {
|
|
950
1107
|
const { props, state, context } = this;
|
|
951
1108
|
const { options } = context;
|
|
1109
|
+
const { totalWidth, clientWidth } = state;
|
|
1110
|
+
const endScrollbarWidth = (totalWidth != null && clientWidth != null)
|
|
1111
|
+
? totalWidth - clientWidth
|
|
1112
|
+
: undefined;
|
|
952
1113
|
const verticalScrollbars = !props.forPrint && !getIsHeightAuto(options);
|
|
953
1114
|
const stickyHeaderDates = !props.forPrint && getStickyHeaderDates(options);
|
|
954
1115
|
const stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(options);
|
|
955
|
-
const
|
|
956
|
-
const [canvasWidth, colWidth] = computeColWidth(
|
|
1116
|
+
const colCount = props.cellRows[0].length;
|
|
1117
|
+
const [canvasWidth, colWidth] = computeColWidth(colCount, props.dayMinWidth, clientWidth);
|
|
1118
|
+
const cellIsMicro = colWidth != null && colWidth <= dayMicroWidth;
|
|
1119
|
+
const cellIsNarrow = cellIsMicro || (colWidth != null && colWidth <= options.dayNarrowWidth);
|
|
957
1120
|
return (createElement(Fragment, null,
|
|
958
|
-
options.dayHeaders && (createElement("div", { className:
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
1121
|
+
options.dayHeaders && (createElement("div", { className: joinClassNames(generateClassName(options.tableHeaderClass, {
|
|
1122
|
+
isSticky: stickyHeaderDates,
|
|
1123
|
+
}), props.borderlessX && classNames.borderlessX, classNames.printHeader, // either flexCol or table-header-group
|
|
1124
|
+
stickyHeaderDates && classNames.tableHeaderSticky) },
|
|
1125
|
+
createElement(Scroller, { horizontal: true, hideScrollbars: true, className: classNames.flexRow, ref: this.headerScrollerRef },
|
|
1126
|
+
createElement(DayGridHeader, { headerTiers: props.headerTiers, colWidth: colWidth, width: canvasWidth, cellIsNarrow: cellIsNarrow, cellIsMicro: cellIsMicro }),
|
|
1127
|
+
Boolean(endScrollbarWidth) && (createElement("div", { className: joinArrayishClassNames(generateClassName(options.fillerClass, { isHeader: true }), classNames.borderOnlyS), style: { minWidth: endScrollbarWidth } }))),
|
|
1128
|
+
createElement("div", { className: generateClassName(options.dayHeaderDividerClass, {
|
|
1129
|
+
isSticky: stickyHeaderDates,
|
|
1130
|
+
options: { allDaySlot: Boolean(options.allDaySlot) },
|
|
1131
|
+
}) }))),
|
|
962
1132
|
createElement(Scroller, { vertical: verticalScrollbars, horizontal: true, hideScrollbars: stickyFooterScrollbar ||
|
|
963
1133
|
props.forPrint // prevents blank space in print-view on Safari
|
|
964
|
-
, className:
|
|
1134
|
+
, className: joinArrayishClassNames(options.tableBodyClass, props.borderlessX && classNames.borderlessX, stickyHeaderDates && classNames.borderlessTop, (stickyHeaderDates || props.noEdgeEffects) && classNames.noEdgeEffects,
|
|
965
1135
|
// HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
|
|
966
1136
|
// https://stackoverflow.com/a/60256345
|
|
967
|
-
!props.forPrint &&
|
|
968
|
-
createElement(DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed, className:
|
|
1137
|
+
!props.forPrint && classNames.flexCol, verticalScrollbars && classNames.liquid), ref: this.bodyScrollerRef, clientWidthRef: this.handleClientWidth },
|
|
1138
|
+
createElement(DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: props.cellRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed, className: classNames.grow, dayMaxEvents: props.forPrint ? undefined : options.dayMaxEvents, dayMaxEventRows: options.dayMaxEventRows,
|
|
969
1139
|
// content
|
|
970
1140
|
fgEventSegs: props.fgEventSegs, bgEventSegs: props.bgEventSegs, businessHourSegs: props.businessHourSegs, dateSelectionSegs: props.dateSelectionSegs, eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection,
|
|
971
1141
|
// dimensions
|
|
972
|
-
colWidth: colWidth, width: canvasWidth, visibleWidth:
|
|
973
|
-
state.clientWidth != null && state.endScrollbarWidth != null
|
|
974
|
-
? state.clientWidth + state.endScrollbarWidth
|
|
975
|
-
: undefined,
|
|
1142
|
+
colWidth: colWidth, width: canvasWidth, visibleWidth: totalWidth, cellIsNarrow: cellIsNarrow, cellIsMicro: cellIsMicro,
|
|
976
1143
|
// refs
|
|
977
1144
|
rowHeightRefMap: props.rowHeightRefMap })),
|
|
978
|
-
Boolean(stickyFooterScrollbar) && (createElement(
|
|
1145
|
+
Boolean(stickyFooterScrollbar) && (createElement(FooterScrollbar, { isSticky: true, canvasWidth: canvasWidth, scrollerRef: this.footerScrollerRef })),
|
|
1146
|
+
createElement(Ruler, { widthRef: this.handleTotalWidth })));
|
|
979
1147
|
}
|
|
980
1148
|
// Lifecycle
|
|
981
1149
|
// -----------------------------------------------------------------------------------------------
|
|
@@ -1030,21 +1198,30 @@ class DayGridLayout extends BaseComponent {
|
|
|
1030
1198
|
}
|
|
1031
1199
|
}
|
|
1032
1200
|
};
|
|
1033
|
-
this.
|
|
1034
|
-
|
|
1201
|
+
this.handleScrollEnd = (isUser) => {
|
|
1202
|
+
if (isUser) {
|
|
1203
|
+
this.scrollDate = null;
|
|
1204
|
+
}
|
|
1035
1205
|
};
|
|
1036
1206
|
}
|
|
1037
1207
|
render() {
|
|
1038
1208
|
const { props, context } = this;
|
|
1039
1209
|
const { options } = context;
|
|
1040
1210
|
const commonLayoutProps = Object.assign(Object.assign({}, props), { scrollerRef: this.scrollerRef, rowHeightRefMap: this.rowHeightRefMap });
|
|
1041
|
-
return (createElement(ViewContainer, { viewSpec: context.viewSpec,
|
|
1211
|
+
return (createElement(ViewContainer, { viewSpec: context.viewSpec, attrs: {
|
|
1212
|
+
role: 'grid',
|
|
1213
|
+
'aria-rowcount': props.headerTiers.length + props.cellRows.length,
|
|
1214
|
+
'aria-colcount': props.cellRows[0].length,
|
|
1215
|
+
'aria-labelledby': props.labelId,
|
|
1216
|
+
'aria-label': props.labelStr,
|
|
1217
|
+
}, className: joinArrayishClassNames(props.className, classNames.printRoot, // either flexCol or table
|
|
1218
|
+
options.tableClass), borderlessX: props.borderlessX, borderlessTop: props.borderlessTop, borderlessBottom: props.borderlessBottom, noEdgeEffects: props.noEdgeEffects }, options.dayMinWidth ? (createElement(DayGridLayoutPannable, Object.assign({}, commonLayoutProps, { dayMinWidth: options.dayMinWidth }))) : (createElement(DayGridLayoutNormal, Object.assign({}, commonLayoutProps)))));
|
|
1042
1219
|
}
|
|
1043
1220
|
// Lifecycle
|
|
1044
1221
|
// -----------------------------------------------------------------------------------------------
|
|
1045
1222
|
componentDidMount() {
|
|
1046
1223
|
this.resetScroll();
|
|
1047
|
-
this.scrollerRef.current.addScrollEndListener(this.
|
|
1224
|
+
this.scrollerRef.current.addScrollEndListener(this.handleScrollEnd);
|
|
1048
1225
|
}
|
|
1049
1226
|
componentDidUpdate(prevProps) {
|
|
1050
1227
|
if (prevProps.dateProfile !== this.props.dateProfile && this.context.options.scrollTimeReset) {
|
|
@@ -1052,14 +1229,13 @@ class DayGridLayout extends BaseComponent {
|
|
|
1052
1229
|
}
|
|
1053
1230
|
}
|
|
1054
1231
|
componentWillUnmount() {
|
|
1055
|
-
this.scrollerRef.current.removeScrollEndListener(this.
|
|
1232
|
+
this.scrollerRef.current.removeScrollEndListener(this.handleScrollEnd);
|
|
1056
1233
|
}
|
|
1057
1234
|
// Scrolling
|
|
1058
1235
|
// -----------------------------------------------------------------------------------------------
|
|
1059
1236
|
resetScroll() {
|
|
1060
1237
|
this.scrollDate = this.props.dateProfile.currentDate;
|
|
1061
1238
|
this.updateScrollY();
|
|
1062
|
-
// updateScrollX
|
|
1063
1239
|
const scroller = this.scrollerRef.current;
|
|
1064
1240
|
scroller.scrollTo({ x: 0 });
|
|
1065
1241
|
}
|
|
@@ -1077,18 +1253,19 @@ class DayGridView extends BaseComponent {
|
|
|
1077
1253
|
}
|
|
1078
1254
|
render() {
|
|
1079
1255
|
const { props, context } = this;
|
|
1080
|
-
const {
|
|
1081
|
-
const
|
|
1082
|
-
const
|
|
1083
|
-
const
|
|
1084
|
-
const
|
|
1256
|
+
const { dateProfile } = props;
|
|
1257
|
+
const { options, dateEnv } = context;
|
|
1258
|
+
const dayTableModel = this.buildDayTableModel(dateProfile, context.dateProfileGenerator, dateEnv);
|
|
1259
|
+
const datesRepDistinctDays = dayTableModel.rowCount === 1;
|
|
1260
|
+
const dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dayTableModel.colCount);
|
|
1261
|
+
const slicedProps = this.slicer.sliceProps(props, dateProfile, options.nextDayThreshold, context, dayTableModel);
|
|
1085
1262
|
return (createElement(NowTimer, { unit: "day" }, (nowDate, todayRange) => {
|
|
1086
|
-
const headerTiers = this.buildDateRowConfigs(dayTableModel.headerDates, datesRepDistinctDays,
|
|
1087
|
-
return (createElement(DayGridLayout, {
|
|
1263
|
+
const headerTiers = this.buildDateRowConfigs(dayTableModel.headerDates, datesRepDistinctDays, dateProfile, todayRange, dayHeaderFormat, context);
|
|
1264
|
+
return (createElement(DayGridLayout, { labelId: props.labelId, labelStr: props.labelStr, dateProfile: dateProfile, todayRange: todayRange, cellRows: dayTableModel.cellRows, forPrint: props.forPrint, className: props.className,
|
|
1088
1265
|
// header content
|
|
1089
1266
|
headerTiers: headerTiers,
|
|
1090
1267
|
// body content
|
|
1091
|
-
fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection }));
|
|
1268
|
+
fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection, borderlessX: props.borderlessX, borderlessTop: props.borderlessTop, borderlessBottom: props.borderlessBottom, noEdgeEffects: props.noEdgeEffects }));
|
|
1092
1269
|
}));
|
|
1093
1270
|
}
|
|
1094
1271
|
}
|
|
@@ -1124,14 +1301,11 @@ function buildDayTableRenderRange(props) {
|
|
|
1124
1301
|
// TODO: instead of these date-math gymnastics (for multimonth view),
|
|
1125
1302
|
// compute dateprofiles of all months, then use start of first and end of last.
|
|
1126
1303
|
let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth(addDays(currentRange.end, -1)));
|
|
1127
|
-
let
|
|
1304
|
+
let rowCount = Math.ceil(// could be partial weeks due to hiddenDays
|
|
1128
1305
|
diffWeeks(lastMonthRenderStart, end));
|
|
1129
|
-
end = addWeeks(end, 6 -
|
|
1306
|
+
end = addWeeks(end, 6 - rowCount);
|
|
1130
1307
|
}
|
|
1131
1308
|
return { start, end };
|
|
1132
1309
|
}
|
|
1133
1310
|
|
|
1134
|
-
|
|
1135
|
-
injectStyles(css_248z);
|
|
1136
|
-
|
|
1137
|
-
export { DayGridHeaderRow, DayGridLayout, DayGridRow, DayGridRows, DayGridView, DayTableSlicer, TableDateProfileGenerator, buildDateDataConfigs, buildDateRenderConfig, buildDateRowConfig, buildDateRowConfigs, buildDayTableModel, buildDayTableRenderRange, computeColFromPosition, computeColWidth, computeRowHeight, createDayHeaderFormatter, getCellEl, getRowEl };
|
|
1311
|
+
export { DayGridHeaderRow, DayGridLayout, DayGridRow, DayGridRows, DayGridView, DayTableSlicer, TableDateProfileGenerator, buildDateDataConfigs, buildDateRenderConfig, buildDateRowConfig, buildDateRowConfigs, buildDayTableModel, buildDayTableRenderRange, computeColFromPosition, computeColWidth, computeRowBasis, createDayHeaderFormatter, dayHeaderMicroFormat, dayMicroWidth, getCellEl, getRowEl };
|