@fullcalendar/timeline 7.0.0-beta.4 → 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 +2 -2
- package/{index.cjs → cjs/index.cjs} +14 -7
- package/cjs/internal.cjs +1224 -0
- package/esm/index.d.ts +25 -0
- package/{index.js → esm/index.js} +13 -6
- package/{internal.d.ts → esm/internal.d.ts} +30 -45
- package/{internal.js → esm/internal.js} +434 -471
- package/{index.global.js → global.js} +443 -476
- package/global.min.js +6 -0
- package/package.json +24 -21
- package/index.d.ts +0 -8
- package/index.global.min.js +0 -6
- package/internal.cjs +0 -1258
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
FullCalendar Timeline Plugin v7.0.0-beta.
|
|
2
|
+
FullCalendar Timeline Plugin v7.0.0-beta.5
|
|
3
3
|
Docs & License: https://fullcalendar.io/docs/timeline-view-no-resources
|
|
4
|
-
(c)
|
|
4
|
+
(c) 2025 Adam Shaw
|
|
5
5
|
*/
|
|
6
|
-
FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$1, preact, internal$2) {
|
|
6
|
+
FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$1, classNames, preact, internal$2) {
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
9
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
10
10
|
|
|
11
11
|
var premiumCommonPlugin__default = /*#__PURE__*/_interopDefault(premiumCommonPlugin);
|
|
12
|
+
var classNames__default = /*#__PURE__*/_interopDefault(classNames);
|
|
12
13
|
|
|
13
14
|
const MIN_AUTO_LABELS = 18; // more than `12` months but less that `24` hours
|
|
14
15
|
const MAX_AUTO_SLOTS_PER_LABEL = 6; // allows 6 10-min slots in an hour
|
|
@@ -37,13 +38,13 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
37
38
|
];
|
|
38
39
|
function buildTimelineDateProfile(dateProfile, dateEnv, allOptions, dateProfileGenerator) {
|
|
39
40
|
let tDateProfile = {
|
|
40
|
-
labelInterval: allOptions.
|
|
41
|
+
labelInterval: allOptions.slotHeaderInterval,
|
|
41
42
|
slotDuration: allOptions.slotDuration,
|
|
42
43
|
};
|
|
43
44
|
validateLabelAndSlot(tDateProfile, dateProfile, dateEnv); // validate after computed grid duration
|
|
44
45
|
ensureLabelInterval(tDateProfile, dateProfile, dateEnv);
|
|
45
46
|
ensureSlotDuration(tDateProfile, dateProfile, dateEnv);
|
|
46
|
-
let input = allOptions.
|
|
47
|
+
let input = allOptions.slotHeaderFormat;
|
|
47
48
|
let rawFormats = Array.isArray(input) ? input :
|
|
48
49
|
(input != null) ? [input] :
|
|
49
50
|
computeHeaderFormats(tDateProfile, dateProfile, dateEnv, allOptions);
|
|
@@ -57,10 +58,6 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
tDateProfile.largeUnit = largeUnit;
|
|
60
|
-
tDateProfile.emphasizeWeeks =
|
|
61
|
-
internal$1.asCleanDays(tDateProfile.slotDuration) === 1 &&
|
|
62
|
-
currentRangeAs('weeks', dateProfile, dateEnv) >= 2 &&
|
|
63
|
-
!allOptions.businessHours;
|
|
64
61
|
/*
|
|
65
62
|
console.log('label interval =', timelineView.labelInterval.humanize())
|
|
66
63
|
console.log('slot duration =', timelineView.slotDuration.humanize())
|
|
@@ -96,14 +93,18 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
96
93
|
tDateProfile.timeWindowMs = timeWindowMs;
|
|
97
94
|
tDateProfile.normalizedRange = { start: normalizedStart, end: normalizedEnd };
|
|
98
95
|
let slotDates = [];
|
|
96
|
+
let slotDatesMajor = [];
|
|
99
97
|
let date = normalizedStart;
|
|
98
|
+
let majorUnit = internal$1.computeMajorUnit(dateProfile, dateEnv);
|
|
100
99
|
while (date < normalizedEnd) {
|
|
101
100
|
if (isValidDate(date, tDateProfile, dateProfile, dateProfileGenerator)) {
|
|
102
101
|
slotDates.push(date);
|
|
102
|
+
slotDatesMajor.push(internal$1.isMajorUnit(date, majorUnit, dateEnv));
|
|
103
103
|
}
|
|
104
104
|
date = dateEnv.add(date, tDateProfile.slotDuration);
|
|
105
105
|
}
|
|
106
106
|
tDateProfile.slotDates = slotDates;
|
|
107
|
+
tDateProfile.slotDatesMajor = slotDatesMajor;
|
|
107
108
|
// more...
|
|
108
109
|
let snapIndex = -1;
|
|
109
110
|
let snapDiff = 0; // index of the diff :(
|
|
@@ -127,8 +128,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
127
128
|
tDateProfile.snapCnt = snapIndex + 1; // is always one behind
|
|
128
129
|
tDateProfile.slotCnt = tDateProfile.snapCnt / tDateProfile.snapsPerSlot;
|
|
129
130
|
// more...
|
|
130
|
-
tDateProfile.
|
|
131
|
-
tDateProfile.cellRows = buildCellRows(tDateProfile, dateEnv);
|
|
131
|
+
tDateProfile.cellRows = buildCellRows(tDateProfile, dateEnv, majorUnit);
|
|
132
132
|
tDateProfile.slotsPerLabel = internal$1.wholeDivideDurations(tDateProfile.labelInterval, tDateProfile.slotDuration);
|
|
133
133
|
return tDateProfile;
|
|
134
134
|
}
|
|
@@ -189,7 +189,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
189
189
|
if (tDateProfile.labelInterval) {
|
|
190
190
|
const labelCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, tDateProfile.labelInterval);
|
|
191
191
|
if (labelCnt > internal$1.config.MAX_TIMELINE_SLOTS) {
|
|
192
|
-
console.warn('
|
|
192
|
+
console.warn('slotHeaderInterval results in too many cells');
|
|
193
193
|
tDateProfile.labelInterval = null;
|
|
194
194
|
}
|
|
195
195
|
}
|
|
@@ -205,7 +205,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
205
205
|
if (tDateProfile.labelInterval && tDateProfile.slotDuration) {
|
|
206
206
|
const slotsPerLabel = internal$1.wholeDivideDurations(tDateProfile.labelInterval, tDateProfile.slotDuration);
|
|
207
207
|
if (slotsPerLabel === null || slotsPerLabel < 1) {
|
|
208
|
-
console.warn('
|
|
208
|
+
console.warn('slotHeaderInterval must be a multiple of slotDuration');
|
|
209
209
|
tDateProfile.slotDuration = null;
|
|
210
210
|
}
|
|
211
211
|
}
|
|
@@ -280,6 +280,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
280
280
|
let format1;
|
|
281
281
|
let format2;
|
|
282
282
|
const { labelInterval } = tDateProfile;
|
|
283
|
+
const { currentRange } = dateProfile;
|
|
283
284
|
let unit = internal$1.greatestDurationDenominator(labelInterval).unit;
|
|
284
285
|
const weekNumbersVisible = allOptions.weekNumbers;
|
|
285
286
|
let format0 = (format1 = (format2 = null));
|
|
@@ -292,22 +293,22 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
292
293
|
format0 = { year: 'numeric' }; // '2015'
|
|
293
294
|
break;
|
|
294
295
|
case 'month':
|
|
295
|
-
if (
|
|
296
|
+
if (dateEnv.diffWholeYears(currentRange.start, currentRange.end) > 1) {
|
|
296
297
|
format0 = { year: 'numeric' }; // '2015'
|
|
297
298
|
}
|
|
298
299
|
format1 = { month: 'short' }; // 'Jan'
|
|
299
300
|
break;
|
|
300
301
|
case 'week':
|
|
301
|
-
if (
|
|
302
|
+
if (dateEnv.diffWholeYears(currentRange.start, currentRange.end) > 1) {
|
|
302
303
|
format0 = { year: 'numeric' }; // '2015'
|
|
303
304
|
}
|
|
304
305
|
format1 = { week: 'narrow' }; // 'Wk4'
|
|
305
306
|
break;
|
|
306
307
|
case 'day':
|
|
307
|
-
if (
|
|
308
|
+
if (dateEnv.diffWholeYears(currentRange.start, currentRange.end) > 1) {
|
|
308
309
|
format0 = { year: 'numeric', month: 'long' }; // 'January 2014'
|
|
309
310
|
}
|
|
310
|
-
else if (
|
|
311
|
+
else if (dateEnv.diffWholeMonths(currentRange.start, currentRange.end) > 1) {
|
|
311
312
|
format0 = { month: 'long' }; // 'January'
|
|
312
313
|
}
|
|
313
314
|
if (weekNumbersVisible) {
|
|
@@ -319,7 +320,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
319
320
|
if (weekNumbersVisible) {
|
|
320
321
|
format0 = { week: 'short' }; // 'Wk 4'
|
|
321
322
|
}
|
|
322
|
-
if (
|
|
323
|
+
if (internal$1.diffWholeDays(currentRange.start, currentRange.end) > 1) {
|
|
323
324
|
format1 = { weekday: 'short', day: 'numeric', month: 'numeric', omitCommas: true }; // Sat 4/7
|
|
324
325
|
}
|
|
325
326
|
format2 = {
|
|
@@ -365,39 +366,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
365
366
|
}
|
|
366
367
|
return [].concat(format0 || [], format1 || [], format2 || []);
|
|
367
368
|
}
|
|
368
|
-
|
|
369
|
-
// Won't go more precise than days.
|
|
370
|
-
// Will return `0` if there's not a clean whole interval.
|
|
371
|
-
function currentRangeAs(unit, dateProfile, dateEnv) {
|
|
372
|
-
let range = dateProfile.currentRange;
|
|
373
|
-
let res = null;
|
|
374
|
-
if (unit === 'years') {
|
|
375
|
-
res = dateEnv.diffWholeYears(range.start, range.end);
|
|
376
|
-
}
|
|
377
|
-
else if (unit === 'months') {
|
|
378
|
-
res = dateEnv.diffWholeMonths(range.start, range.end);
|
|
379
|
-
}
|
|
380
|
-
else if (unit === 'weeks') {
|
|
381
|
-
res = dateEnv.diffWholeMonths(range.start, range.end);
|
|
382
|
-
}
|
|
383
|
-
else if (unit === 'days') {
|
|
384
|
-
res = internal$1.diffWholeDays(range.start, range.end);
|
|
385
|
-
}
|
|
386
|
-
return res || 0;
|
|
387
|
-
}
|
|
388
|
-
function buildIsWeekStarts(tDateProfile, dateEnv) {
|
|
389
|
-
let { slotDates, emphasizeWeeks } = tDateProfile;
|
|
390
|
-
let prevWeekNumber = null;
|
|
391
|
-
let isWeekStarts = [];
|
|
392
|
-
for (let slotDate of slotDates) {
|
|
393
|
-
let weekNumber = dateEnv.computeWeekNumber(slotDate);
|
|
394
|
-
let isWeekStart = emphasizeWeeks && (prevWeekNumber !== null) && (prevWeekNumber !== weekNumber);
|
|
395
|
-
prevWeekNumber = weekNumber;
|
|
396
|
-
isWeekStarts.push(isWeekStart);
|
|
397
|
-
}
|
|
398
|
-
return isWeekStarts;
|
|
399
|
-
}
|
|
400
|
-
function buildCellRows(tDateProfile, dateEnv) {
|
|
369
|
+
function buildCellRows(tDateProfile, dateEnv, majorUnit) {
|
|
401
370
|
let slotDates = tDateProfile.slotDates;
|
|
402
371
|
let formats = tDateProfile.headerFormats;
|
|
403
372
|
let cellRows = formats.map(() => []); // indexed by row,col
|
|
@@ -406,23 +375,23 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
406
375
|
slotAsDays === 1 ? 'day' :
|
|
407
376
|
null;
|
|
408
377
|
// specifically for navclicks
|
|
409
|
-
let rowUnitsFromFormats = formats.map((format) => (format.
|
|
378
|
+
let rowUnitsFromFormats = formats.map((format) => (format.getSmallestUnit ? format.getSmallestUnit() : null));
|
|
410
379
|
// builds cellRows and slotCells
|
|
411
380
|
for (let i = 0; i < slotDates.length; i += 1) {
|
|
412
381
|
let date = slotDates[i];
|
|
413
|
-
let isWeekStart = tDateProfile.isWeekStarts[i];
|
|
414
382
|
for (let row = 0; row < formats.length; row += 1) {
|
|
415
383
|
let format = formats[row];
|
|
416
384
|
let rowCells = cellRows[row];
|
|
417
385
|
let leadingCell = rowCells[rowCells.length - 1];
|
|
418
386
|
let isLastRow = row === formats.length - 1;
|
|
419
387
|
let isSuperRow = formats.length > 1 && !isLastRow; // more than one row and not the last
|
|
388
|
+
let isMajor = internal$1.isMajorUnit(date, majorUnit, dateEnv);
|
|
420
389
|
let newCell = null;
|
|
421
390
|
let rowUnit = rowUnitsFromFormats[row] || (isLastRow ? guessedSlotUnit : null);
|
|
422
391
|
if (isSuperRow) {
|
|
423
|
-
let text = dateEnv.format(date, format);
|
|
392
|
+
let [text] = dateEnv.format(date, format);
|
|
424
393
|
if (!leadingCell || (leadingCell.text !== text)) {
|
|
425
|
-
newCell = buildCellObject(date, text, rowUnit);
|
|
394
|
+
newCell = buildCellObject(date, isMajor, text, rowUnit);
|
|
426
395
|
}
|
|
427
396
|
else {
|
|
428
397
|
leadingCell.colspan += 1;
|
|
@@ -430,159 +399,202 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
430
399
|
}
|
|
431
400
|
else if (!leadingCell ||
|
|
432
401
|
internal$1.isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.labelInterval))) {
|
|
433
|
-
let text = dateEnv.format(date, format);
|
|
434
|
-
newCell = buildCellObject(date, text, rowUnit);
|
|
402
|
+
let [text] = dateEnv.format(date, format);
|
|
403
|
+
newCell = buildCellObject(date, isMajor, text, rowUnit);
|
|
435
404
|
}
|
|
436
405
|
else {
|
|
437
406
|
leadingCell.colspan += 1;
|
|
438
407
|
}
|
|
439
408
|
if (newCell) {
|
|
440
|
-
newCell.weekStart = isWeekStart;
|
|
441
409
|
rowCells.push(newCell);
|
|
442
410
|
}
|
|
443
411
|
}
|
|
444
412
|
}
|
|
445
413
|
return cellRows;
|
|
446
414
|
}
|
|
447
|
-
function buildCellObject(date, text, rowUnit) {
|
|
448
|
-
return { date, text, rowUnit, colspan: 1
|
|
415
|
+
function buildCellObject(date, isMajor, text, rowUnit) {
|
|
416
|
+
return { date, isMajor, text, rowUnit, colspan: 1 }; // colspan mutated later
|
|
449
417
|
}
|
|
450
418
|
|
|
451
419
|
class TimelineSlatCell extends internal$1.BaseComponent {
|
|
452
420
|
constructor() {
|
|
453
421
|
super(...arguments);
|
|
454
|
-
//
|
|
455
|
-
this.
|
|
422
|
+
// memo
|
|
423
|
+
this.getDateMeta = internal$1.memoize(internal$1.getDateMeta);
|
|
456
424
|
}
|
|
457
425
|
render() {
|
|
458
426
|
let { props, context } = this;
|
|
459
427
|
let { dateEnv, options } = context;
|
|
460
|
-
let { date, tDateProfile,
|
|
461
|
-
let dateMeta =
|
|
462
|
-
let
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
'fc-timeline-slot-major' :
|
|
469
|
-
'fc-timeline-slot-minor'), 'fc-timeline-slot-lane fc-cell fc-flex-col fc-align-start', props.borderStart && 'fc-border-s', props.isDay ?
|
|
470
|
-
internal$1.getDayClassName(dateMeta) :
|
|
471
|
-
internal$1.getSlotClassName(dateMeta)), attrs: Object.assign({ 'data-date': dateEnv.formatIso(date, {
|
|
428
|
+
let { date, tDateProfile, isMajor } = props;
|
|
429
|
+
let dateMeta = this.getDateMeta(props.date, dateEnv, props.dateProfile, props.todayRange, props.nowDate);
|
|
430
|
+
let isMinor = tDateProfile.isTimeScale &&
|
|
431
|
+
!internal$1.isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, props.date, tDateProfile.labelInterval));
|
|
432
|
+
let renderProps = Object.assign(Object.assign({}, dateMeta), { isMajor,
|
|
433
|
+
isMinor, view: context.viewApi });
|
|
434
|
+
return (preact.createElement(internal$1.ContentContainer, { tag: "div", className: core.joinClassNames(classNames__default["default"].tight, classNames__default["default"].alignStart, // shrinks width of InnerContent
|
|
435
|
+
props.borderStart ? classNames__default["default"].borderOnlyS : classNames__default["default"].borderNone, classNames__default["default"].internalTimelineSlot), attrs: Object.assign({ 'data-date': dateEnv.formatIso(date, {
|
|
472
436
|
omitTimeZoneOffset: true,
|
|
473
437
|
omitTime: !tDateProfile.isTimeScale,
|
|
474
438
|
}) }, (dateMeta.isToday ? { 'aria-current': 'date' } : {})), style: {
|
|
475
439
|
width: props.width,
|
|
476
|
-
}, renderProps: renderProps, generatorName:
|
|
440
|
+
}, renderProps: renderProps, generatorName: undefined, classNameGenerator: options.slotLaneClass, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount }));
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
class TimelineSlats extends internal$1.BaseComponent {
|
|
445
|
+
render() {
|
|
446
|
+
let { props } = this;
|
|
447
|
+
let { tDateProfile, slotWidth } = props;
|
|
448
|
+
let { slotDates, slotDatesMajor } = tDateProfile;
|
|
449
|
+
return (preact.createElement("div", { "aria-hidden": true, className: core.joinClassNames(classNames__default["default"].flexRow, classNames__default["default"].fill), style: { height: props.height } }, slotDates.map((slotDate, i) => {
|
|
450
|
+
let key = slotDate.toISOString();
|
|
451
|
+
return (preact.createElement(TimelineSlatCell, { key: key, date: slotDate, dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: props.nowDate, todayRange: props.todayRange, isMajor: slotDatesMajor[i], borderStart: Boolean(i),
|
|
452
|
+
// dimensions
|
|
453
|
+
width: slotWidth }));
|
|
454
|
+
})));
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
class TimelineHeaderCell extends internal$1.BaseComponent {
|
|
459
|
+
constructor() {
|
|
460
|
+
super(...arguments);
|
|
461
|
+
// memo
|
|
462
|
+
this.getDateMeta = internal$1.memoize(internal$1.getDateMeta);
|
|
463
|
+
// ref
|
|
464
|
+
this.innerWrapperElRef = preact.createRef();
|
|
465
|
+
}
|
|
466
|
+
render() {
|
|
467
|
+
let { props, state, context } = this;
|
|
468
|
+
let { dateEnv, options } = context;
|
|
469
|
+
let { cell, dateProfile, tDateProfile } = props;
|
|
470
|
+
// the cell.rowUnit is f'd
|
|
471
|
+
// giving 'month' for a 3-day view
|
|
472
|
+
// workaround: to infer day, do NOT time
|
|
473
|
+
let dateMeta = this.getDateMeta(cell.date, dateEnv, dateProfile, props.todayRange, props.nowDate);
|
|
474
|
+
let hasNavLink = options.navLinks && !dateMeta.isDisabled && (cell.rowUnit && cell.rowUnit !== 'time');
|
|
475
|
+
let isTime = tDateProfile.isTimeScale && !props.rowLevel; // HACK: faulty way of determining this
|
|
476
|
+
let renderProps = Object.assign(Object.assign({}, dateMeta), { level: props.rowLevel, isMajor: cell.isMajor, isMinor: false, isNarrow: false, isTime,
|
|
477
|
+
hasNavLink, text: cell.text, isFirst: props.isFirst, view: context.viewApi });
|
|
478
|
+
const { slotHeaderAlign } = options;
|
|
479
|
+
const align = this.align =
|
|
480
|
+
typeof slotHeaderAlign === 'function'
|
|
481
|
+
? slotHeaderAlign({ level: props.rowLevel, isTime })
|
|
482
|
+
: slotHeaderAlign;
|
|
483
|
+
const isSticky = this.isSticky =
|
|
484
|
+
props.rowLevel && options.slotHeaderSticky !== false;
|
|
485
|
+
let edgeCoord;
|
|
486
|
+
if (isSticky) {
|
|
487
|
+
if (align === 'center') {
|
|
488
|
+
if (state.innerWidth != null) {
|
|
489
|
+
edgeCoord = `calc(50% - ${state.innerWidth / 2}px)`;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
else {
|
|
493
|
+
edgeCoord = (typeof options.slotHeaderSticky === 'number' ||
|
|
494
|
+
typeof options.slotHeaderSticky === 'string') ? options.slotHeaderSticky : 0;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return (preact.createElement(internal$1.ContentContainer, { tag: "div", className: internal$1.joinArrayishClassNames(classNames__default["default"].tight, classNames__default["default"].flexCol, props.isFirst ? classNames__default["default"].borderNone : classNames__default["default"].borderOnlyS, align === 'center' ? classNames__default["default"].alignCenter :
|
|
498
|
+
align === 'end' ? classNames__default["default"].alignEnd :
|
|
499
|
+
classNames__default["default"].alignStart, classNames__default["default"].internalTimelineSlot), attrs: Object.assign({ 'data-date': dateEnv.formatIso(cell.date, {
|
|
500
|
+
omitTime: !tDateProfile.isTimeScale,
|
|
501
|
+
omitTimeZoneOffset: true,
|
|
502
|
+
}) }, (dateMeta.isToday ? { 'aria-current': 'date' } : {})), style: {
|
|
503
|
+
width: props.slotWidth != null
|
|
504
|
+
? props.slotWidth * cell.colspan
|
|
505
|
+
: undefined,
|
|
506
|
+
}, renderProps: renderProps, generatorName: "slotHeaderContent", customGenerator: options.slotHeaderContent, defaultGenerator: renderInnerContent, classNameGenerator: options.slotHeaderClass, didMount: options.slotHeaderDidMount, willUnmount: options.slotHeaderWillUnmount }, (InnerContent) => (preact.createElement("div", { ref: this.innerWrapperElRef, className: core.joinClassNames(classNames__default["default"].flexCol, classNames__default["default"].rigid, isSticky && classNames__default["default"].sticky), style: {
|
|
507
|
+
left: edgeCoord,
|
|
508
|
+
right: edgeCoord,
|
|
509
|
+
} },
|
|
510
|
+
preact.createElement(InnerContent, { tag: 'div', attrs: hasNavLink
|
|
511
|
+
// not tabbable because parent is aria-hidden
|
|
512
|
+
? internal$1.buildNavLinkAttrs(context, cell.date, cell.rowUnit, undefined, /* isTabbable = */ false)
|
|
513
|
+
: {} // don't bother with aria-hidden because parent already hidden
|
|
514
|
+
, className: internal$1.generateClassName(options.slotHeaderInnerClass, renderProps) })))));
|
|
477
515
|
}
|
|
478
516
|
componentDidMount() {
|
|
479
|
-
const
|
|
480
|
-
|
|
481
|
-
|
|
517
|
+
const { props } = this;
|
|
518
|
+
const innerWrapperEl = this.innerWrapperElRef.current; // TODO: make dynamic with useEffect
|
|
519
|
+
this.disconnectSize = internal$1.watchSize(innerWrapperEl, (width, height) => {
|
|
520
|
+
internal$1.setRef(props.innerWidthRef, width);
|
|
521
|
+
internal$1.setRef(props.innerHeightRef, height);
|
|
522
|
+
if (this.align === 'center' && this.isSticky) {
|
|
523
|
+
this.setState({ innerWidth: width });
|
|
524
|
+
}
|
|
482
525
|
});
|
|
483
526
|
}
|
|
484
527
|
componentWillUnmount() {
|
|
485
|
-
this
|
|
486
|
-
|
|
528
|
+
const { props } = this;
|
|
529
|
+
this.disconnectSize();
|
|
530
|
+
internal$1.setRef(props.innerWidthRef, null);
|
|
531
|
+
internal$1.setRef(props.innerHeightRef, null);
|
|
487
532
|
}
|
|
488
533
|
}
|
|
534
|
+
// Utils
|
|
535
|
+
// -------------------------------------------------------------------------------------------------
|
|
536
|
+
function renderInnerContent(renderProps) {
|
|
537
|
+
return renderProps.text;
|
|
538
|
+
}
|
|
489
539
|
|
|
490
|
-
class
|
|
540
|
+
class TimelineHeaderRow extends internal$1.BaseComponent {
|
|
491
541
|
constructor() {
|
|
492
542
|
super(...arguments);
|
|
543
|
+
// refs
|
|
493
544
|
this.innerWidthRefMap = new internal$1.RefMap(() => {
|
|
494
545
|
internal$1.afterSize(this.handleInnerWidths);
|
|
495
546
|
});
|
|
547
|
+
this.innerHeightRefMap = new internal$1.RefMap(() => {
|
|
548
|
+
internal$1.afterSize(this.handleInnerHeights);
|
|
549
|
+
});
|
|
496
550
|
this.handleInnerWidths = () => {
|
|
497
551
|
const innerWidthMap = this.innerWidthRefMap.current;
|
|
498
552
|
let max = 0;
|
|
499
553
|
for (const innerWidth of innerWidthMap.values()) {
|
|
500
554
|
max = Math.max(max, innerWidth);
|
|
501
555
|
}
|
|
502
|
-
// TODO:
|
|
556
|
+
// TODO: ensure not equal?
|
|
503
557
|
internal$1.setRef(this.props.innerWidthRef, max);
|
|
504
558
|
};
|
|
559
|
+
this.handleInnerHeights = () => {
|
|
560
|
+
const innerHeightMap = this.innerHeightRefMap.current;
|
|
561
|
+
let max = 0;
|
|
562
|
+
for (const innerHeight of innerHeightMap.values()) {
|
|
563
|
+
max = Math.max(max, innerHeight);
|
|
564
|
+
}
|
|
565
|
+
// TODO: ensure not equal?
|
|
566
|
+
internal$1.setRef(this.props.innerHeighRef, max);
|
|
567
|
+
this.setState({ innerHeight: max });
|
|
568
|
+
};
|
|
505
569
|
}
|
|
506
570
|
render() {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
571
|
+
const { props, innerWidthRefMap, innerHeightRefMap, state, context } = this;
|
|
572
|
+
const { options } = context;
|
|
573
|
+
return (preact.createElement("div", { className: internal$1.joinArrayishClassNames(options.slotHeaderRowClass, classNames__default["default"].flexRow, classNames__default["default"].grow, props.rowLevel // not the last row?
|
|
574
|
+
? classNames__default["default"].borderOnlyB
|
|
575
|
+
: classNames__default["default"].borderNone), style: {
|
|
576
|
+
// we assign height because we allow cells to have distorted heights for visual effect
|
|
577
|
+
// but we still want to keep the overall extrenal mass
|
|
578
|
+
height: state.innerHeight,
|
|
579
|
+
} }, props.cells.map((cell, cellI) => {
|
|
580
|
+
// TODO: make this part of the cell obj?
|
|
581
|
+
// TODO: rowUnit seems wrong sometimes. says 'month' when it should be day
|
|
582
|
+
// TODO: rowUnit is relevant to whole row. put it on a row object, not the cells
|
|
583
|
+
// TODO: use rowUnit to key the Row itself?
|
|
584
|
+
const key = cell.rowUnit + ':' + cell.date.toISOString();
|
|
585
|
+
return (preact.createElement(TimelineHeaderCell, { key: key, cell: cell, rowLevel: props.rowLevel, dateProfile: props.dateProfile, tDateProfile: props.tDateProfile, todayRange: props.todayRange, nowDate: props.nowDate, isFirst: cellI === 0,
|
|
586
|
+
// refs
|
|
587
|
+
innerWidthRef: innerWidthRefMap.createRef(key), innerHeightRef: innerHeightRefMap.createRef(key),
|
|
516
588
|
// dimensions
|
|
517
|
-
|
|
589
|
+
slotWidth: props.slotWidth }));
|
|
518
590
|
})));
|
|
519
591
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
TODO: rename this file!
|
|
524
|
-
*/
|
|
525
|
-
// returned value is between 0 and the number of snaps
|
|
526
|
-
function computeDateSnapCoverage$1(date, tDateProfile, dateEnv) {
|
|
527
|
-
let snapDiff = dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.snapDuration);
|
|
528
|
-
if (snapDiff < 0) {
|
|
529
|
-
return 0;
|
|
530
|
-
}
|
|
531
|
-
if (snapDiff >= tDateProfile.snapDiffToIndex.length) {
|
|
532
|
-
return tDateProfile.snapCnt;
|
|
533
|
-
}
|
|
534
|
-
let snapDiffInt = Math.floor(snapDiff);
|
|
535
|
-
let snapCoverage = tDateProfile.snapDiffToIndex[snapDiffInt];
|
|
536
|
-
if (internal$1.isInt(snapCoverage)) { // not an in-between value
|
|
537
|
-
snapCoverage += snapDiff - snapDiffInt; // add the remainder
|
|
538
|
-
}
|
|
539
|
-
else {
|
|
540
|
-
// a fractional value, meaning the date is not visible
|
|
541
|
-
// always round up in this case. works for start AND end dates in a range.
|
|
542
|
-
snapCoverage = Math.ceil(snapCoverage);
|
|
543
|
-
}
|
|
544
|
-
return snapCoverage;
|
|
545
|
-
}
|
|
546
|
-
/*
|
|
547
|
-
TODO: DRY up with elsewhere?
|
|
548
|
-
*/
|
|
549
|
-
function horizontalsToCss(hcoord, isRtl) {
|
|
550
|
-
if (!hcoord) {
|
|
551
|
-
return {};
|
|
552
|
-
}
|
|
553
|
-
if (isRtl) {
|
|
554
|
-
return { right: hcoord.start, width: hcoord.size };
|
|
555
|
-
}
|
|
556
|
-
else {
|
|
557
|
-
return { left: hcoord.start, width: hcoord.size };
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
function horizontalCoordToCss(start, isRtl) {
|
|
561
|
-
if (isRtl) {
|
|
562
|
-
return { right: start };
|
|
563
|
-
}
|
|
564
|
-
else {
|
|
565
|
-
return { left: start };
|
|
592
|
+
componentWillUnmount() {
|
|
593
|
+
internal$1.setRef(this.props.innerWidthRef, null);
|
|
594
|
+
internal$1.setRef(this.props.innerHeighRef, null);
|
|
566
595
|
}
|
|
567
596
|
}
|
|
568
597
|
|
|
569
|
-
function createVerticalStyle(props) {
|
|
570
|
-
if (props) {
|
|
571
|
-
return {
|
|
572
|
-
top: props.start,
|
|
573
|
-
height: props.size,
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
function createHorizontalStyle(// TODO: DRY up?
|
|
578
|
-
props, isRtl) {
|
|
579
|
-
if (props) {
|
|
580
|
-
return {
|
|
581
|
-
[isRtl ? 'right' : 'left']: props.start,
|
|
582
|
-
width: props.size,
|
|
583
|
-
};
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
598
|
// Timeline-specific
|
|
587
599
|
// -------------------------------------------------------------------------------------------------
|
|
588
600
|
const MIN_SLOT_WIDTH = 30; // for real
|
|
@@ -595,17 +607,17 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
595
607
|
}
|
|
596
608
|
slatMinWidth = Math.max(slatMinWidth || 0, (labelInnerWidth + 1) / slatsPerLabel, MIN_SLOT_WIDTH);
|
|
597
609
|
const slatTryWidth = viewportWidth / slatCnt;
|
|
598
|
-
let
|
|
610
|
+
let slotLiquid;
|
|
599
611
|
let slatWidth;
|
|
600
612
|
if (slatTryWidth >= slatMinWidth) {
|
|
601
|
-
|
|
613
|
+
slotLiquid = true;
|
|
602
614
|
slatWidth = slatTryWidth;
|
|
603
615
|
}
|
|
604
616
|
else {
|
|
605
|
-
|
|
617
|
+
slotLiquid = false;
|
|
606
618
|
slatWidth = Math.max(slatMinWidth, slatTryWidth);
|
|
607
619
|
}
|
|
608
|
-
return [slatWidth * slatCnt, slatWidth,
|
|
620
|
+
return [slatWidth * slatCnt, slatWidth, slotLiquid];
|
|
609
621
|
}
|
|
610
622
|
function timeToCoord(// pixels
|
|
611
623
|
time, dateEnv, dateProfile, tDateProfile, slowWidth) {
|
|
@@ -617,13 +629,86 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
617
629
|
}
|
|
618
630
|
function dateToCoord(// pixels
|
|
619
631
|
date, dateEnv, tDateProfile, slotWidth) {
|
|
620
|
-
let snapCoverage = computeDateSnapCoverage(date, tDateProfile, dateEnv);
|
|
632
|
+
let snapCoverage = computeDateSnapCoverage$1(date, tDateProfile, dateEnv);
|
|
621
633
|
let slotCoverage = snapCoverage / tDateProfile.snapsPerSlot;
|
|
622
634
|
return slotCoverage * slotWidth;
|
|
623
635
|
}
|
|
624
636
|
/*
|
|
625
637
|
returned value is between 0 and the number of snaps
|
|
626
638
|
*/
|
|
639
|
+
function computeDateSnapCoverage$1(date, tDateProfile, dateEnv) {
|
|
640
|
+
let snapDiff = dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.snapDuration);
|
|
641
|
+
if (snapDiff < 0) {
|
|
642
|
+
return 0;
|
|
643
|
+
}
|
|
644
|
+
if (snapDiff >= tDateProfile.snapDiffToIndex.length) {
|
|
645
|
+
return tDateProfile.snapCnt;
|
|
646
|
+
}
|
|
647
|
+
let snapDiffInt = Math.floor(snapDiff);
|
|
648
|
+
let snapCoverage = tDateProfile.snapDiffToIndex[snapDiffInt];
|
|
649
|
+
if (internal$1.isInt(snapCoverage)) { // not an in-between value
|
|
650
|
+
snapCoverage += snapDiff - snapDiffInt; // add the remainder
|
|
651
|
+
}
|
|
652
|
+
else {
|
|
653
|
+
// a fractional value, meaning the date is not visible
|
|
654
|
+
// always round up in this case. works for start AND end dates in a range.
|
|
655
|
+
snapCoverage = Math.ceil(snapCoverage);
|
|
656
|
+
}
|
|
657
|
+
return snapCoverage;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
class TimelineNowIndicatorLine extends internal$1.BaseComponent {
|
|
661
|
+
render() {
|
|
662
|
+
const { props, context } = this;
|
|
663
|
+
const xStyle = props.slotWidth == null
|
|
664
|
+
? {}
|
|
665
|
+
: {
|
|
666
|
+
insetInlineStart: dateToCoord(props.nowDate, context.dateEnv, props.tDateProfile, props.slotWidth)
|
|
667
|
+
};
|
|
668
|
+
return (preact.createElement("div", { className: classNames__default["default"].fill, style: {
|
|
669
|
+
zIndex: 2,
|
|
670
|
+
pointerEvents: 'none', // TODO: className
|
|
671
|
+
} },
|
|
672
|
+
preact.createElement(internal$1.NowIndicatorLineContainer, { className: core.joinClassNames(classNames__default["default"].fillY, classNames__default["default"].noMarginY, classNames__default["default"].borderlessY), style: xStyle, date: props.nowDate }),
|
|
673
|
+
preact.createElement("div", { className: core.joinClassNames(classNames__default["default"].flexCol, // better for negative margins
|
|
674
|
+
classNames__default["default"].fillY), style: xStyle },
|
|
675
|
+
preact.createElement("div", {
|
|
676
|
+
// stickiness on NowIndicatorDot misbehaves b/c of negative marginss
|
|
677
|
+
className: classNames__default["default"].stickyT },
|
|
678
|
+
preact.createElement(internal$1.NowIndicatorDot, null)))));
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/*
|
|
683
|
+
TODO: DRY with other NowIndicator components
|
|
684
|
+
*/
|
|
685
|
+
class TimelineNowIndicatorArrow extends internal$1.BaseComponent {
|
|
686
|
+
render() {
|
|
687
|
+
const { props, context } = this;
|
|
688
|
+
const xStyle = props.slotWidth == null
|
|
689
|
+
? {}
|
|
690
|
+
: {
|
|
691
|
+
insetInlineStart: dateToCoord(props.nowDate, context.dateEnv, props.tDateProfile, props.slotWidth)
|
|
692
|
+
};
|
|
693
|
+
return (preact.createElement("div", {
|
|
694
|
+
// crop any overflow that the arrow/line might cause
|
|
695
|
+
// TODO: just do this on the entire canvas within the scroller
|
|
696
|
+
className: core.joinClassNames(classNames__default["default"].fill, classNames__default["default"].crop), style: {
|
|
697
|
+
zIndex: 2,
|
|
698
|
+
pointerEvents: 'none', // TODO: className
|
|
699
|
+
} },
|
|
700
|
+
preact.createElement(internal$1.NowIndicatorHeaderContainer, { className: classNames__default["default"].abs, style: xStyle, date: props.nowDate })));
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
function getTimelineSlotEl(parentEl, index) {
|
|
705
|
+
return parentEl.querySelectorAll(`.${classNames__default["default"].internalTimelineSlot}`)[index];
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/*
|
|
709
|
+
TODO: rename this file!
|
|
710
|
+
*/
|
|
711
|
+
// returned value is between 0 and the number of snaps
|
|
627
712
|
function computeDateSnapCoverage(date, tDateProfile, dateEnv) {
|
|
628
713
|
let snapDiff = dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.snapDuration);
|
|
629
714
|
if (snapDiff < 0) {
|
|
@@ -645,6 +730,60 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
645
730
|
return snapCoverage;
|
|
646
731
|
}
|
|
647
732
|
|
|
733
|
+
class TimelineLaneSlicer extends internal$1.Slicer {
|
|
734
|
+
sliceRange(origRange, dateProfile, dateProfileGenerator, tDateProfile, dateEnv) {
|
|
735
|
+
let normalRange = normalizeRange(origRange, tDateProfile, dateEnv);
|
|
736
|
+
let segs = [];
|
|
737
|
+
// protect against when the span is entirely in an invalid date region
|
|
738
|
+
if (computeDateSnapCoverage(normalRange.start, tDateProfile, dateEnv)
|
|
739
|
+
< computeDateSnapCoverage(normalRange.end, tDateProfile, dateEnv)) {
|
|
740
|
+
// intersect the footprint's range with the grid's range
|
|
741
|
+
let slicedRange = internal$1.intersectRanges(normalRange, tDateProfile.normalizedRange);
|
|
742
|
+
if (slicedRange) {
|
|
743
|
+
segs.push({
|
|
744
|
+
startDate: slicedRange.start,
|
|
745
|
+
endDate: slicedRange.end,
|
|
746
|
+
isStart: slicedRange.start.valueOf() === normalRange.start.valueOf()
|
|
747
|
+
&& isValidDate(slicedRange.start, tDateProfile, dateProfile, dateProfileGenerator),
|
|
748
|
+
isEnd: slicedRange.end.valueOf() === normalRange.end.valueOf()
|
|
749
|
+
&& isValidDate(internal$1.addMs(slicedRange.end, -1), tDateProfile, dateProfile, dateProfileGenerator),
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
return segs;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
const DEFAULT_TIME_FORMAT = internal$1.createFormatter({
|
|
758
|
+
hour: 'numeric',
|
|
759
|
+
minute: '2-digit',
|
|
760
|
+
omitZeroMinute: true,
|
|
761
|
+
meridiem: 'narrow',
|
|
762
|
+
});
|
|
763
|
+
class TimelineEvent extends internal$1.BaseComponent {
|
|
764
|
+
render() {
|
|
765
|
+
let { props } = this;
|
|
766
|
+
return (preact.createElement(internal$1.StandardEvent, Object.assign({}, props, { display: 'row', defaultTimeFormat: DEFAULT_TIME_FORMAT, defaultDisplayEventTime: !props.isTimeScale })));
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
class TimelineLaneMoreLink extends internal$1.BaseComponent {
|
|
771
|
+
render() {
|
|
772
|
+
let { props } = this;
|
|
773
|
+
let { hiddenSegs, resourceId } = props;
|
|
774
|
+
let dateSpanProps = resourceId ? { resourceId } : {};
|
|
775
|
+
return (preact.createElement(internal$1.MoreLinkContainer, { display: 'row', allDayDate: null, segs: hiddenSegs, hiddenSegs: hiddenSegs, dateProfile: props.dateProfile, todayRange: props.todayRange, dateSpanProps: dateSpanProps, isNarrow: false, isMicro: false, popoverContent: () => (preact.createElement(preact.Fragment, null, hiddenSegs.map((seg) => {
|
|
776
|
+
let { eventRange } = seg;
|
|
777
|
+
let { instanceId } = eventRange.instance;
|
|
778
|
+
let isDragging = Boolean(props.eventDrag && props.eventDrag.affectedInstances[instanceId]);
|
|
779
|
+
let isResizing = Boolean(props.eventResize && props.eventResize.affectedInstances[instanceId]);
|
|
780
|
+
let isInvisible = isDragging || isResizing;
|
|
781
|
+
return (preact.createElement("div", { key: instanceId, style: { visibility: isInvisible ? 'hidden' : undefined } },
|
|
782
|
+
preact.createElement(TimelineEvent, Object.assign({ isTimeScale: props.isTimeScale, eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isResizing: isResizing, isMirror: false, isSelected: instanceId === props.eventSelection }, internal$1.getEventRangeMeta(eventRange, props.todayRange, props.nowDate)))));
|
|
783
|
+
}))) }));
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
|
|
648
787
|
function computeManySegHorizontals(segs, segMinWidth, dateEnv, tDateProfile, slotWidth) {
|
|
649
788
|
const res = {};
|
|
650
789
|
for (const seg of segs) {
|
|
@@ -709,83 +848,6 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
709
848
|
];
|
|
710
849
|
}
|
|
711
850
|
|
|
712
|
-
class TimelineLaneBg extends internal$1.BaseComponent {
|
|
713
|
-
render() {
|
|
714
|
-
let { props } = this;
|
|
715
|
-
let highlightSeg = [].concat(props.eventResizeSegs, props.dateSelectionSegs);
|
|
716
|
-
return (preact.createElement(preact.Fragment, null,
|
|
717
|
-
this.renderSegs(props.businessHourSegs || [], 'non-business'),
|
|
718
|
-
this.renderSegs(props.bgEventSegs || [], 'bg-event'),
|
|
719
|
-
this.renderSegs(highlightSeg, 'highlight')));
|
|
720
|
-
}
|
|
721
|
-
renderSegs(segs, fillType) {
|
|
722
|
-
let { tDateProfile, todayRange, nowDate, slotWidth } = this.props;
|
|
723
|
-
let { dateEnv, isRtl } = this.context;
|
|
724
|
-
return (preact.createElement(preact.Fragment, null, segs.map((seg) => {
|
|
725
|
-
let hStyle; // TODO
|
|
726
|
-
if (slotWidth != null) {
|
|
727
|
-
let segHorizontal = computeSegHorizontals(seg, undefined, dateEnv, tDateProfile, slotWidth);
|
|
728
|
-
hStyle = horizontalsToCss(segHorizontal, isRtl);
|
|
729
|
-
}
|
|
730
|
-
return (preact.createElement("div", { key: internal$1.buildEventRangeKey(seg.eventRange), className: "fc-fill-y", style: hStyle }, fillType === 'bg-event' ?
|
|
731
|
-
preact.createElement(internal$1.BgEvent, Object.assign({ eventRange: seg.eventRange, isStart: seg.isStart, isEnd: seg.isEnd }, internal$1.getEventRangeMeta(seg.eventRange, todayRange, nowDate))) : (internal$1.renderFill(fillType))));
|
|
732
|
-
})));
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
class TimelineLaneSlicer extends internal$1.Slicer {
|
|
737
|
-
sliceRange(origRange, dateProfile, dateProfileGenerator, tDateProfile, dateEnv) {
|
|
738
|
-
let normalRange = normalizeRange(origRange, tDateProfile, dateEnv);
|
|
739
|
-
let segs = [];
|
|
740
|
-
// protect against when the span is entirely in an invalid date region
|
|
741
|
-
if (computeDateSnapCoverage$1(normalRange.start, tDateProfile, dateEnv)
|
|
742
|
-
< computeDateSnapCoverage$1(normalRange.end, tDateProfile, dateEnv)) {
|
|
743
|
-
// intersect the footprint's range with the grid's range
|
|
744
|
-
let slicedRange = internal$1.intersectRanges(normalRange, tDateProfile.normalizedRange);
|
|
745
|
-
if (slicedRange) {
|
|
746
|
-
segs.push({
|
|
747
|
-
startDate: slicedRange.start,
|
|
748
|
-
endDate: slicedRange.end,
|
|
749
|
-
isStart: slicedRange.start.valueOf() === normalRange.start.valueOf()
|
|
750
|
-
&& isValidDate(slicedRange.start, tDateProfile, dateProfile, dateProfileGenerator),
|
|
751
|
-
isEnd: slicedRange.end.valueOf() === normalRange.end.valueOf()
|
|
752
|
-
&& isValidDate(internal$1.addMs(slicedRange.end, -1), tDateProfile, dateProfile, dateProfileGenerator),
|
|
753
|
-
});
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
return segs;
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
const DEFAULT_TIME_FORMAT = internal$1.createFormatter({
|
|
761
|
-
hour: 'numeric',
|
|
762
|
-
minute: '2-digit',
|
|
763
|
-
omitZeroMinute: true,
|
|
764
|
-
meridiem: 'narrow',
|
|
765
|
-
});
|
|
766
|
-
class TimelineEvent extends internal$1.BaseComponent {
|
|
767
|
-
render() {
|
|
768
|
-
let { props, context } = this;
|
|
769
|
-
let { options } = context;
|
|
770
|
-
return (preact.createElement(internal$1.StandardEvent, Object.assign({}, props, { className: internal$1.joinClassNames('fc-timeline-event', options.eventOverlap === false // TODO: fix bad default
|
|
771
|
-
&& 'fc-timeline-event-spacious', 'fc-h-event'), defaultTimeFormat: DEFAULT_TIME_FORMAT, defaultDisplayEventTime: !props.isTimeScale })));
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
class TimelineLaneMoreLink extends internal$1.BaseComponent {
|
|
776
|
-
render() {
|
|
777
|
-
let { props } = this;
|
|
778
|
-
let { hiddenSegs, resourceId, forcedInvisibleMap } = props;
|
|
779
|
-
let dateSpanProps = resourceId ? { resourceId } : {};
|
|
780
|
-
return (preact.createElement(internal$1.MoreLinkContainer, { className: 'fc-timeline-more-link', allDayDate: null, segs: hiddenSegs, hiddenSegs: hiddenSegs, dateProfile: props.dateProfile, todayRange: props.todayRange, dateSpanProps: dateSpanProps, popoverContent: () => (preact.createElement(preact.Fragment, null, hiddenSegs.map((seg) => {
|
|
781
|
-
let { eventRange } = seg;
|
|
782
|
-
let instanceId = eventRange.instance.instanceId;
|
|
783
|
-
return (preact.createElement("div", { key: instanceId, style: { visibility: forcedInvisibleMap[instanceId] ? 'hidden' : '' } },
|
|
784
|
-
preact.createElement(TimelineEvent, Object.assign({ isTimeScale: props.isTimeScale, eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection }, internal$1.getEventRangeMeta(eventRange, props.todayRange, props.nowDate)))));
|
|
785
|
-
}))) }, (InnerContent) => (preact.createElement(InnerContent, { tag: "div", className: 'fc-timeline-more-link-inner fc-sticky-s' }))));
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
|
|
789
851
|
/*
|
|
790
852
|
TODO: make DRY with other Event Harnesses
|
|
791
853
|
*/
|
|
@@ -797,7 +859,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
797
859
|
}
|
|
798
860
|
render() {
|
|
799
861
|
const { props } = this;
|
|
800
|
-
return (preact.createElement("div", { className: "
|
|
862
|
+
return (preact.createElement("div", { className: classNames__default["default"].abs, style: props.style, ref: this.rootElRef }, props.children));
|
|
801
863
|
}
|
|
802
864
|
componentDidMount() {
|
|
803
865
|
const rootEl = this.rootElRef.current; // TODO: make dynamic with useEffect
|
|
@@ -811,10 +873,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
811
873
|
}
|
|
812
874
|
}
|
|
813
875
|
|
|
814
|
-
|
|
815
|
-
TODO: split TimelineLaneBg and TimelineLaneFg?
|
|
816
|
-
*/
|
|
817
|
-
class TimelineLane extends internal$1.BaseComponent {
|
|
876
|
+
class TimelineFg extends internal$1.BaseComponent {
|
|
818
877
|
constructor() {
|
|
819
878
|
super(...arguments);
|
|
820
879
|
// memo
|
|
@@ -826,8 +885,6 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
826
885
|
this.moreLinkHeightRefMap = new internal$1.RefMap(() => {
|
|
827
886
|
internal$1.afterSize(this.handleMoreLinkHeights);
|
|
828
887
|
});
|
|
829
|
-
// internal
|
|
830
|
-
this.slicer = new TimelineLaneSlicer();
|
|
831
888
|
this.handleMoreLinkHeights = () => {
|
|
832
889
|
this.setState({ moreLinkHeightRev: this.moreLinkHeightRefMap.rev }); // will trigger rerender
|
|
833
890
|
};
|
|
@@ -841,209 +898,92 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
841
898
|
render() {
|
|
842
899
|
let { props, context, segHeightRefMap, moreLinkHeightRefMap } = this;
|
|
843
900
|
let { options } = context;
|
|
844
|
-
let {
|
|
845
|
-
let
|
|
846
|
-
|
|
847
|
-
let mirrorSegs = (slicedProps.eventDrag ? slicedProps.eventDrag.segs : null) ||
|
|
848
|
-
(slicedProps.eventResize ? slicedProps.eventResize.segs : null) ||
|
|
901
|
+
let { tDateProfile } = props;
|
|
902
|
+
let mirrorSegs = (props.eventDrag ? props.eventDrag.segs : null) ||
|
|
903
|
+
(props.eventResize ? props.eventResize.segs : null) ||
|
|
849
904
|
[];
|
|
850
|
-
let fgSegs = this.sortEventSegs(
|
|
905
|
+
let fgSegs = this.sortEventSegs(props.fgEventSegs, options.eventOrder);
|
|
851
906
|
let fgSegHorizontals = props.slotWidth != null
|
|
852
907
|
? computeManySegHorizontals(fgSegs, options.eventMinWidth, context.dateEnv, tDateProfile, props.slotWidth)
|
|
853
908
|
: {};
|
|
854
909
|
let [fgSegTops, hiddenGroups, hiddenGroupTops, totalHeight] = computeFgSegPlacements(fgSegs, fgSegHorizontals, segHeightRefMap.current, moreLinkHeightRefMap.current, options.eventOrderStrict, options.eventMaxStack);
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
false),
|
|
871
|
-
this.renderFgSegs(mirrorSegs, props.slotWidth // TODO: memoize
|
|
872
|
-
? computeManySegHorizontals(mirrorSegs, options.eventMinWidth, context.dateEnv, tDateProfile, props.slotWidth)
|
|
873
|
-
: {}, fgSegTops, {}, // forcedInvisibleMap
|
|
874
|
-
[], // hiddenGroups
|
|
875
|
-
new Map(), // hiddenGroupTops
|
|
876
|
-
Boolean(slicedProps.eventDrag), Boolean(slicedProps.eventResize), false))));
|
|
877
|
-
}
|
|
878
|
-
renderFgSegs(segs, segHorizontals, segTops, forcedInvisibleMap, hiddenGroups, hiddenGroupTops, isDragging, isResizing, isDateSelecting) {
|
|
879
|
-
let { props, context, segHeightRefMap, moreLinkHeightRefMap } = this;
|
|
880
|
-
let isMirror = isDragging || isResizing || isDateSelecting;
|
|
910
|
+
this.totalHeight = totalHeight;
|
|
911
|
+
return (preact.createElement("div", { className: core.joinClassNames(classNames__default["default"].rel, classNames__default["default"].noShrink), style: {
|
|
912
|
+
height: totalHeight,
|
|
913
|
+
} },
|
|
914
|
+
this.renderFgSegs(fgSegs, fgSegHorizontals, fgSegTops, hiddenGroups, hiddenGroupTops,
|
|
915
|
+
/* isMirror = */ false),
|
|
916
|
+
this.renderFgSegs(mirrorSegs, props.slotWidth // TODO: memoize
|
|
917
|
+
? computeManySegHorizontals(mirrorSegs, options.eventMinWidth, context.dateEnv, tDateProfile, props.slotWidth)
|
|
918
|
+
: {}, fgSegTops,
|
|
919
|
+
/* hiddenGroups = */ [],
|
|
920
|
+
/* hiddenGroupTops = */ new Map(),
|
|
921
|
+
/* isMirror = */ true)));
|
|
922
|
+
}
|
|
923
|
+
renderFgSegs(segs, segHorizontals, segTops, hiddenGroups, hiddenGroupTops, isMirror) {
|
|
924
|
+
let { props, segHeightRefMap, moreLinkHeightRefMap } = this;
|
|
881
925
|
return (preact.createElement(preact.Fragment, null,
|
|
882
926
|
segs.map((seg) => {
|
|
883
927
|
const { eventRange } = seg;
|
|
884
928
|
const { instanceId } = eventRange.instance;
|
|
885
929
|
const segTop = segTops.get(instanceId);
|
|
886
|
-
const
|
|
887
|
-
const
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
930
|
+
const segHorizontalMaybe = segHorizontals[instanceId];
|
|
931
|
+
const segHorizontal = segHorizontalMaybe || {};
|
|
932
|
+
const isDragging = Boolean(props.eventDrag && props.eventDrag.affectedInstances[instanceId]);
|
|
933
|
+
const isResizing = Boolean(props.eventResize && props.eventResize.affectedInstances[instanceId]);
|
|
934
|
+
const isInvisible = !isMirror && (isDragging || isResizing || !segHorizontalMaybe || segTop == null);
|
|
935
|
+
return (preact.createElement(TimelineEventHarness, { key: instanceId, style: {
|
|
936
|
+
visibility: isInvisible ? 'hidden' : undefined,
|
|
937
|
+
zIndex: 1,
|
|
938
|
+
top: segTop || 0,
|
|
939
|
+
insetInlineStart: segHorizontal.start,
|
|
940
|
+
width: segHorizontal.size,
|
|
941
|
+
}, heightRef: isMirror ? undefined : segHeightRefMap.createRef(instanceId) },
|
|
942
|
+
preact.createElement(TimelineEvent, Object.assign({ isTimeScale: props.tDateProfile.isTimeScale, eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isResizing: isResizing, isMirror: isMirror, isSelected: instanceId === props.eventSelection }, internal$1.getEventRangeMeta(eventRange, props.todayRange, props.nowDate)))));
|
|
891
943
|
}),
|
|
892
|
-
hiddenGroups.map((hiddenGroup) => (preact.createElement(TimelineEventHarness, { key: hiddenGroup.key, style:
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
class TimelineHeaderCell extends internal$1.BaseComponent {
|
|
901
|
-
constructor() {
|
|
902
|
-
super(...arguments);
|
|
903
|
-
// memo
|
|
904
|
-
this.refineRenderProps = internal$1.memoizeObjArg(refineRenderProps);
|
|
905
|
-
// ref
|
|
906
|
-
this.innerElRef = preact.createRef();
|
|
907
|
-
}
|
|
908
|
-
render() {
|
|
909
|
-
let { props, context } = this;
|
|
910
|
-
let { dateEnv, options } = context;
|
|
911
|
-
let { cell, dateProfile, tDateProfile } = props;
|
|
912
|
-
// the cell.rowUnit is f'd
|
|
913
|
-
// giving 'month' for a 3-day view
|
|
914
|
-
// workaround: to infer day, do NOT time
|
|
915
|
-
let dateMeta = internal$1.getDateMeta(cell.date, props.todayRange, props.nowDate, dateProfile);
|
|
916
|
-
let renderProps = this.refineRenderProps({
|
|
917
|
-
level: props.rowLevel,
|
|
918
|
-
dateMarker: cell.date,
|
|
919
|
-
text: cell.text,
|
|
920
|
-
dateEnv: context.dateEnv,
|
|
921
|
-
viewApi: context.viewApi,
|
|
922
|
-
});
|
|
923
|
-
let isNavLink = !dateMeta.isDisabled && (cell.rowUnit && cell.rowUnit !== 'time');
|
|
924
|
-
return (preact.createElement(internal$1.ContentContainer, { tag: "div", className: internal$1.joinClassNames('fc-timeline-slot-label fc-timeline-slot', cell.isWeekStart && 'fc-timeline-slot-em', // TODO: document this semantic className
|
|
925
|
-
'fc-header-cell fc-cell fc-flex-col fc-justify-center', props.borderStart && 'fc-border-s', props.isCentered ? 'fc-align-center' : 'fc-align-start',
|
|
926
|
-
// TODO: so slot classnames for week/month/bigger. see note above about rowUnit
|
|
927
|
-
cell.rowUnit === 'time' ?
|
|
928
|
-
internal$1.getSlotClassName(dateMeta) :
|
|
929
|
-
internal$1.getDayClassName(dateMeta)), attrs: Object.assign({ 'data-date': dateEnv.formatIso(cell.date, {
|
|
930
|
-
omitTime: !tDateProfile.isTimeScale,
|
|
931
|
-
omitTimeZoneOffset: true,
|
|
932
|
-
}) }, (dateMeta.isToday ? { 'aria-current': 'date' } : {})), style: {
|
|
933
|
-
width: props.slotWidth != null
|
|
934
|
-
? props.slotWidth * cell.colspan
|
|
935
|
-
: undefined,
|
|
936
|
-
}, renderProps: renderProps, generatorName: "slotLabelContent", customGenerator: options.slotLabelContent, defaultGenerator: renderInnerContent, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (preact.createElement(InnerContent, { tag: 'div', attrs: isNavLink
|
|
937
|
-
// not tabbable because parent is aria-hidden
|
|
938
|
-
? internal$1.buildNavLinkAttrs(context, cell.date, cell.rowUnit, undefined, /* isTabbable = */ false)
|
|
939
|
-
: {} // don't bother with aria-hidden because parent already hidden
|
|
940
|
-
, className: internal$1.joinClassNames('fc-cell-inner fc-padding-md', props.isSticky && 'fc-sticky-s'), elRef: this.innerElRef }))));
|
|
944
|
+
hiddenGroups.map((hiddenGroup) => (preact.createElement(TimelineEventHarness, { key: hiddenGroup.key, style: {
|
|
945
|
+
top: hiddenGroupTops.get(hiddenGroup.key) || 0,
|
|
946
|
+
insetInlineStart: hiddenGroup.start,
|
|
947
|
+
width: hiddenGroup.end - hiddenGroup.start,
|
|
948
|
+
}, heightRef: moreLinkHeightRefMap.createRef(hiddenGroup.key) },
|
|
949
|
+
preact.createElement(TimelineLaneMoreLink, { hiddenSegs: hiddenGroup.segs, dateProfile: props.dateProfile, nowDate: props.nowDate, todayRange: props.todayRange, isTimeScale: props.tDateProfile.isTimeScale, eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection, resourceId: props.resourceId }))))));
|
|
941
950
|
}
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
this.detachSize = internal$1.watchSize(innerEl, (width, height) => {
|
|
946
|
-
internal$1.setRef(props.innerWidthRef, width);
|
|
947
|
-
internal$1.setRef(props.innerHeightRef, height);
|
|
948
|
-
// HACK for sticky-centering
|
|
949
|
-
innerEl.style.left = innerEl.style.right =
|
|
950
|
-
(props.isCentered && props.isSticky)
|
|
951
|
-
? `calc(50% - ${width / 2}px)`
|
|
952
|
-
: '';
|
|
953
|
-
});
|
|
954
|
-
}
|
|
955
|
-
componentWillUnmount() {
|
|
956
|
-
const { props } = this;
|
|
957
|
-
this.detachSize();
|
|
958
|
-
internal$1.setRef(props.innerWidthRef, null);
|
|
959
|
-
internal$1.setRef(props.innerHeightRef, null);
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
// Utils
|
|
963
|
-
// -------------------------------------------------------------------------------------------------
|
|
964
|
-
function renderInnerContent(renderProps) {
|
|
965
|
-
return renderProps.text;
|
|
966
|
-
}
|
|
967
|
-
function refineRenderProps(input) {
|
|
968
|
-
return {
|
|
969
|
-
level: input.level,
|
|
970
|
-
date: input.dateEnv.toDate(input.dateMarker),
|
|
971
|
-
view: input.viewApi,
|
|
972
|
-
text: input.text,
|
|
973
|
-
};
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
class TimelineHeaderRow extends internal$1.BaseComponent {
|
|
977
|
-
constructor() {
|
|
978
|
-
super(...arguments);
|
|
979
|
-
// refs
|
|
980
|
-
this.innerWidthRefMap = new internal$1.RefMap(() => {
|
|
981
|
-
internal$1.afterSize(this.handleInnerWidths);
|
|
982
|
-
});
|
|
983
|
-
this.innerHeightRefMap = new internal$1.RefMap(() => {
|
|
984
|
-
internal$1.afterSize(this.handleInnerHeights);
|
|
985
|
-
});
|
|
986
|
-
this.handleInnerWidths = () => {
|
|
987
|
-
const innerWidthMap = this.innerWidthRefMap.current;
|
|
988
|
-
let max = 0;
|
|
989
|
-
for (const innerWidth of innerWidthMap.values()) {
|
|
990
|
-
max = Math.max(max, innerWidth);
|
|
991
|
-
}
|
|
992
|
-
// TODO: ensure not equal?
|
|
993
|
-
internal$1.setRef(this.props.innerWidthRef, max);
|
|
994
|
-
};
|
|
995
|
-
this.handleInnerHeights = () => {
|
|
996
|
-
const innerHeightMap = this.innerHeightRefMap.current;
|
|
997
|
-
let max = 0;
|
|
998
|
-
for (const innerHeight of innerHeightMap.values()) {
|
|
999
|
-
max = Math.max(max, innerHeight);
|
|
1000
|
-
}
|
|
1001
|
-
// TODO: ensure not equal?
|
|
1002
|
-
internal$1.setRef(this.props.innerHeighRef, max);
|
|
1003
|
-
};
|
|
951
|
+
/*
|
|
952
|
+
componentDidMount(): void {
|
|
953
|
+
// might want to do firedTotalHeight, but won't be ready on first render
|
|
1004
954
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
// TODO: make this part of the cell obj?
|
|
1012
|
-
// TODO: rowUnit seems wrong sometimes. says 'month' when it should be day
|
|
1013
|
-
// TODO: rowUnit is relevant to whole row. put it on a row object, not the cells
|
|
1014
|
-
// TODO: use rowUnit to key the Row itself?
|
|
1015
|
-
const key = cell.rowUnit + ':' + cell.date.toISOString();
|
|
1016
|
-
return (preact.createElement(TimelineHeaderCell, { key: key, cell: cell, rowLevel: props.rowLevel, dateProfile: props.dateProfile, tDateProfile: props.tDateProfile, todayRange: props.todayRange, nowDate: props.nowDate, isCentered: isCentered, isSticky: isSticky, borderStart: Boolean(cellI),
|
|
1017
|
-
// refs
|
|
1018
|
-
innerWidthRef: innerWidthRefMap.createRef(key), innerHeightRef: innerHeightRefMap.createRef(key),
|
|
1019
|
-
// dimensions
|
|
1020
|
-
slotWidth: props.slotWidth }));
|
|
1021
|
-
})));
|
|
955
|
+
*/
|
|
956
|
+
componentDidUpdate() {
|
|
957
|
+
if (this.totalHeight !== this.firedTotalHeight) {
|
|
958
|
+
this.firedTotalHeight = this.totalHeight;
|
|
959
|
+
internal$1.setRef(this.props.heightRef, this.totalHeight);
|
|
960
|
+
}
|
|
1022
961
|
}
|
|
1023
962
|
componentWillUnmount() {
|
|
1024
|
-
internal$1.setRef(this.props.
|
|
1025
|
-
internal$1.setRef(this.props.innerHeighRef, null);
|
|
963
|
+
internal$1.setRef(this.props.heightRef, null);
|
|
1026
964
|
}
|
|
1027
965
|
}
|
|
1028
966
|
|
|
1029
|
-
class
|
|
967
|
+
class TimelineBg extends internal$1.BaseComponent {
|
|
1030
968
|
render() {
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
969
|
+
let { props } = this;
|
|
970
|
+
let highlightSeg = [].concat(props.eventResizeSegs || [], props.dateSelectionSegs);
|
|
971
|
+
return (preact.createElement(preact.Fragment, null,
|
|
972
|
+
this.renderSegs(props.businessHourSegs || [], 'non-business'),
|
|
973
|
+
this.renderSegs(props.bgEventSegs || [], 'bg-event'),
|
|
974
|
+
this.renderSegs(highlightSeg, 'highlight')));
|
|
1037
975
|
}
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
976
|
+
renderSegs(segs, fillType) {
|
|
977
|
+
let { tDateProfile, todayRange, nowDate, slotWidth } = this.props;
|
|
978
|
+
let { dateEnv, options } = this.context;
|
|
979
|
+
return (preact.createElement(preact.Fragment, null, segs.map((seg) => {
|
|
980
|
+
let hStyle = {};
|
|
981
|
+
if (slotWidth != null) {
|
|
982
|
+
let segHorizontal = computeSegHorizontals(seg, undefined, dateEnv, tDateProfile, slotWidth);
|
|
983
|
+
hStyle = { insetInlineStart: segHorizontal.start, width: segHorizontal.size };
|
|
984
|
+
}
|
|
985
|
+
return (preact.createElement("div", { key: internal$1.buildEventRangeKey(seg.eventRange), className: classNames__default["default"].fillY, style: hStyle }, fillType === 'bg-event' ? (preact.createElement(internal$1.BgEvent, Object.assign({ eventRange: seg.eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isVertical: false }, internal$1.getEventRangeMeta(seg.eventRange, todayRange, nowDate)))) : (internal$1.renderFill(fillType, options))));
|
|
986
|
+
})));
|
|
1047
987
|
}
|
|
1048
988
|
}
|
|
1049
989
|
|
|
@@ -1061,34 +1001,30 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1061
1001
|
internal$1.afterSize(this.handleSlotInnerWidths);
|
|
1062
1002
|
});
|
|
1063
1003
|
this.scrollTime = null;
|
|
1004
|
+
this.slicer = new TimelineLaneSlicer();
|
|
1064
1005
|
// Sizing
|
|
1065
1006
|
// -----------------------------------------------------------------------------------------------
|
|
1066
|
-
this.handleBodySlotInnerWidth = (innerWidth) => {
|
|
1067
|
-
this.bodySlotInnerWidth = innerWidth;
|
|
1068
|
-
internal$1.afterSize(this.handleSlotInnerWidths);
|
|
1069
|
-
};
|
|
1070
1007
|
this.handleSlotInnerWidths = () => {
|
|
1071
|
-
const
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
this.setState({ slotInnerWidth });
|
|
1008
|
+
const headerSlotInnerWidth = this.headerRowInnerWidthMap.current.get(this.tDateProfile.cellRows.length - 1);
|
|
1009
|
+
if (headerSlotInnerWidth != null && headerSlotInnerWidth !== this.state.slotInnerWidth) {
|
|
1010
|
+
this.setState({ slotInnerWidth: headerSlotInnerWidth });
|
|
1075
1011
|
}
|
|
1076
1012
|
};
|
|
1077
|
-
this.
|
|
1013
|
+
this.handleTotalWidth = (totalWidth) => {
|
|
1078
1014
|
this.setState({
|
|
1079
|
-
|
|
1015
|
+
totalWidth,
|
|
1080
1016
|
});
|
|
1081
1017
|
};
|
|
1082
|
-
this.
|
|
1018
|
+
this.handleClientWidth = (clientWidth) => {
|
|
1083
1019
|
this.setState({
|
|
1084
|
-
|
|
1020
|
+
clientWidth,
|
|
1085
1021
|
});
|
|
1086
1022
|
};
|
|
1087
1023
|
this.handleTimeScrollRequest = (scrollTime) => {
|
|
1088
1024
|
this.scrollTime = scrollTime;
|
|
1089
1025
|
this.applyTimeScroll();
|
|
1090
1026
|
};
|
|
1091
|
-
this.handleTimeScrollEnd = (
|
|
1027
|
+
this.handleTimeScrollEnd = (isUser) => {
|
|
1092
1028
|
if (isUser) {
|
|
1093
1029
|
this.scrollTime = null;
|
|
1094
1030
|
}
|
|
@@ -1108,6 +1044,10 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1108
1044
|
render() {
|
|
1109
1045
|
const { props, state, context } = this;
|
|
1110
1046
|
const { options } = context;
|
|
1047
|
+
const { totalWidth, clientWidth } = state;
|
|
1048
|
+
const endScrollbarWidth = (totalWidth != null && clientWidth != null)
|
|
1049
|
+
? totalWidth - clientWidth
|
|
1050
|
+
: undefined;
|
|
1111
1051
|
/* date */
|
|
1112
1052
|
const tDateProfile = this.tDateProfile = this.buildTimelineDateProfile(props.dateProfile, context.dateEnv, options, context.dateProfileGenerator);
|
|
1113
1053
|
const { cellRows } = tDateProfile;
|
|
@@ -1118,39 +1058,65 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1118
1058
|
const stickyFooterScrollbar = !props.forPrint && internal$1.getStickyFooterScrollbar(options);
|
|
1119
1059
|
/* table positions */
|
|
1120
1060
|
const [canvasWidth, slotWidth] = this.computeSlotWidth(tDateProfile.slotCnt, tDateProfile.slotsPerLabel, options.slotMinWidth, state.slotInnerWidth, // is ACTUALLY the label width. rename?
|
|
1121
|
-
|
|
1061
|
+
clientWidth);
|
|
1122
1062
|
this.slotWidth = slotWidth;
|
|
1063
|
+
/* sliced */
|
|
1064
|
+
let slicedProps = this.slicer.sliceProps(props, props.dateProfile, tDateProfile.isTimeScale ? null : options.nextDayThreshold, context, // wish we didn't have to pass in the rest of the args...
|
|
1065
|
+
props.dateProfile, context.dateProfileGenerator, tDateProfile, context.dateEnv);
|
|
1123
1066
|
return (preact.createElement(internal$1.NowTimer, { unit: timerUnit }, (nowDate, todayRange) => {
|
|
1124
1067
|
const enableNowIndicator = // TODO: DRY
|
|
1125
1068
|
options.nowIndicator &&
|
|
1126
1069
|
slotWidth != null &&
|
|
1127
1070
|
internal$1.rangeContainsMarker(props.dateProfile.currentRange, nowDate);
|
|
1128
|
-
return (preact.createElement(internal$1.ViewContainer, { viewSpec: context.viewSpec, className: internal$1.
|
|
1129
|
-
// HACK for Safari print-mode, where
|
|
1071
|
+
return (preact.createElement(internal$1.ViewContainer, { viewSpec: context.viewSpec, className: internal$1.joinArrayishClassNames(
|
|
1072
|
+
// HACK for Safari print-mode, where noScrollbars won't take effect for
|
|
1130
1073
|
// the below Scrollers if they have liquid flex height
|
|
1131
|
-
!props.forPrint &&
|
|
1132
|
-
preact.createElement(
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1074
|
+
!props.forPrint && classNames__default["default"].flexCol, props.className, options.tableClass, classNames__default["default"].isolate), borderlessX: props.borderlessX, borderlessTop: props.borderlessTop, borderlessBottom: props.borderlessBottom, noEdgeEffects: props.noEdgeEffects },
|
|
1075
|
+
preact.createElement("div", { className: core.joinClassNames(internal$1.generateClassName(options.tableHeaderClass, {
|
|
1076
|
+
isSticky: stickyHeaderDates,
|
|
1077
|
+
}), props.borderlessX && classNames__default["default"].borderlessX, classNames__default["default"].flexCol, stickyHeaderDates && classNames__default["default"].tableHeaderSticky), style: {
|
|
1078
|
+
zIndex: 1,
|
|
1079
|
+
} },
|
|
1080
|
+
preact.createElement(internal$1.Scroller, { horizontal: true, hideScrollbars: true, className: classNames__default["default"].flexRow, ref: this.headerScrollerRef },
|
|
1081
|
+
preact.createElement("div", {
|
|
1082
|
+
// TODO: DRY
|
|
1083
|
+
className: core.joinClassNames(classNames__default["default"].rel, // origin for now-indicator
|
|
1084
|
+
canvasWidth == null && classNames__default["default"].liquid), style: { width: canvasWidth } },
|
|
1085
|
+
cellRows.map((cells, rowIndex) => {
|
|
1086
|
+
const rowLevel = cellRows.length - rowIndex - 1;
|
|
1087
|
+
return (preact.createElement(TimelineHeaderRow, { key: rowIndex, dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange, rowLevel: rowLevel, cells: cells, slotWidth: slotWidth, innerWidthRef: this.headerRowInnerWidthMap.createRef(rowIndex) }));
|
|
1088
|
+
}),
|
|
1089
|
+
enableNowIndicator && (preact.createElement(TimelineNowIndicatorArrow, { tDateProfile: tDateProfile, nowDate: nowDate, slotWidth: slotWidth }))),
|
|
1090
|
+
Boolean(endScrollbarWidth) && (preact.createElement("div", { className: internal$1.joinArrayishClassNames(internal$1.generateClassName(options.fillerClass, { isHeader: true }), classNames__default["default"].borderOnlyS), style: { minWidth: endScrollbarWidth } }))),
|
|
1091
|
+
preact.createElement("div", { className: internal$1.generateClassName(options.slotHeaderDividerClass, {
|
|
1092
|
+
isHeader: true,
|
|
1093
|
+
options: { dayMinWidth: options.dayMinWidth },
|
|
1094
|
+
}) })),
|
|
1095
|
+
preact.createElement(internal$1.Scroller, { vertical: verticalScrolling, horizontal: true, hideScrollbars: stickyFooterScrollbar ||
|
|
1096
|
+
props.forPrint // prevents blank space in print-view on Safari
|
|
1097
|
+
, className: internal$1.joinArrayishClassNames(options.tableBodyClass, props.borderlessX && classNames__default["default"].borderlessX, stickyHeaderDates && classNames__default["default"].borderlessTop, (stickyHeaderDates || props.noEdgeEffects) && classNames__default["default"].noEdgeEffects, classNames__default["default"].flexCol, verticalScrolling && classNames__default["default"].liquid), style: {
|
|
1098
|
+
zIndex: 0,
|
|
1099
|
+
}, ref: this.bodyScrollerRef, clientWidthRef: this.handleClientWidth },
|
|
1100
|
+
preact.createElement("div", { "aria-label": options.eventsHint, className: core.joinClassNames(classNames__default["default"].rel, // for canvas origin?
|
|
1101
|
+
classNames__default["default"].grow), style: { width: canvasWidth }, ref: this.handeBodyEl },
|
|
1145
1102
|
preact.createElement(TimelineSlats, { dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange,
|
|
1146
|
-
// ref
|
|
1147
|
-
innerWidthRef: this.handleBodySlotInnerWidth,
|
|
1148
1103
|
// dimensions
|
|
1149
1104
|
slotWidth: slotWidth }),
|
|
1150
|
-
preact.createElement(
|
|
1105
|
+
preact.createElement(TimelineBg, { tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange,
|
|
1106
|
+
// content
|
|
1107
|
+
bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventResizeSegs: slicedProps.eventResize ? slicedProps.eventResize.segs : null,
|
|
1108
|
+
// dimensions
|
|
1109
|
+
slotWidth: slotWidth }),
|
|
1110
|
+
preact.createElement("div", { className: internal$1.joinArrayishClassNames(options.timelineTopClass) }),
|
|
1111
|
+
preact.createElement(TimelineFg, { dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange,
|
|
1112
|
+
// content
|
|
1113
|
+
fgEventSegs: slicedProps.fgEventSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection,
|
|
1114
|
+
// dimensions
|
|
1115
|
+
slotWidth: slotWidth }),
|
|
1116
|
+
preact.createElement("div", { className: internal$1.joinArrayishClassNames(options.timelineBottomClass) }),
|
|
1151
1117
|
enableNowIndicator && (preact.createElement(TimelineNowIndicatorLine, { tDateProfile: tDateProfile, nowDate: nowDate, slotWidth: slotWidth })))),
|
|
1152
|
-
stickyFooterScrollbar && (preact.createElement(internal$1.
|
|
1153
|
-
|
|
1118
|
+
Boolean(stickyFooterScrollbar) && (preact.createElement(internal$1.FooterScrollbar, { isSticky: true, canvasWidth: canvasWidth, scrollerRef: this.footerScrollerRef })),
|
|
1119
|
+
preact.createElement(internal$1.Ruler, { widthRef: this.handleTotalWidth })));
|
|
1154
1120
|
}));
|
|
1155
1121
|
}
|
|
1156
1122
|
// Lifecycle
|
|
@@ -1199,11 +1165,11 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1199
1165
|
this.syncedScroller.scrollTo({ x });
|
|
1200
1166
|
}
|
|
1201
1167
|
}
|
|
1202
|
-
queryHit(positionLeft, positionTop, elWidth, elHeight) {
|
|
1168
|
+
queryHit(isRtl, positionLeft, positionTop, elWidth, elHeight) {
|
|
1203
1169
|
const { props, context, tDateProfile, slotWidth } = this;
|
|
1204
1170
|
const { dateEnv } = context;
|
|
1205
1171
|
if (slotWidth) {
|
|
1206
|
-
const x =
|
|
1172
|
+
const x = isRtl ? elWidth - positionLeft : positionLeft;
|
|
1207
1173
|
const slatIndex = Math.floor(x / slotWidth);
|
|
1208
1174
|
const slatX = slatIndex * slotWidth;
|
|
1209
1175
|
const partial = (x - slatX) / slotWidth; // floating point number between 0 and 1
|
|
@@ -1215,7 +1181,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1215
1181
|
let startCoord = slatIndex * slotWidth + (snapWidth * localSnapIndex);
|
|
1216
1182
|
let endCoord = startCoord + snapWidth;
|
|
1217
1183
|
let left, right;
|
|
1218
|
-
if (
|
|
1184
|
+
if (isRtl) {
|
|
1219
1185
|
left = elWidth - endCoord;
|
|
1220
1186
|
right = elWidth - startCoord;
|
|
1221
1187
|
}
|
|
@@ -1235,8 +1201,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1235
1201
|
top: 0,
|
|
1236
1202
|
bottom: elHeight,
|
|
1237
1203
|
},
|
|
1238
|
-
|
|
1239
|
-
dayEl: this.bodyEl.querySelectorAll('.fc-timeline-slot')[slatIndex],
|
|
1204
|
+
getDayEl: () => getTimelineSlotEl(this.bodyEl, slatIndex),
|
|
1240
1205
|
layer: 0,
|
|
1241
1206
|
};
|
|
1242
1207
|
}
|
|
@@ -1244,14 +1209,17 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1244
1209
|
}
|
|
1245
1210
|
}
|
|
1246
1211
|
|
|
1247
|
-
|
|
1248
|
-
|
|
1212
|
+
const OPTION_REFINERS = {
|
|
1213
|
+
timelineTopClass: internal$1.identity,
|
|
1214
|
+
timelineBottomClass: internal$1.identity,
|
|
1215
|
+
};
|
|
1249
1216
|
|
|
1250
1217
|
var plugin = core.createPlugin({
|
|
1251
1218
|
name: '@fullcalendar/timeline',
|
|
1252
|
-
premiumReleaseDate: '2025-
|
|
1219
|
+
premiumReleaseDate: '2025-12-20',
|
|
1253
1220
|
deps: [premiumCommonPlugin__default["default"]],
|
|
1254
1221
|
initialView: 'timelineDay',
|
|
1222
|
+
optionRefiners: OPTION_REFINERS,
|
|
1255
1223
|
views: {
|
|
1256
1224
|
timeline: {
|
|
1257
1225
|
component: TimelineView,
|
|
@@ -1280,18 +1248,17 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1280
1248
|
var internal = {
|
|
1281
1249
|
__proto__: null,
|
|
1282
1250
|
TimelineView: TimelineView,
|
|
1283
|
-
|
|
1284
|
-
|
|
1251
|
+
TimelineFg: TimelineFg,
|
|
1252
|
+
TimelineBg: TimelineBg,
|
|
1285
1253
|
TimelineSlats: TimelineSlats,
|
|
1286
1254
|
buildTimelineDateProfile: buildTimelineDateProfile,
|
|
1287
|
-
createVerticalStyle: createVerticalStyle,
|
|
1288
|
-
createHorizontalStyle: createHorizontalStyle,
|
|
1289
1255
|
computeSlotWidth: computeSlotWidth,
|
|
1290
1256
|
timeToCoord: timeToCoord,
|
|
1291
1257
|
TimelineLaneSlicer: TimelineLaneSlicer,
|
|
1292
1258
|
TimelineHeaderRow: TimelineHeaderRow,
|
|
1293
1259
|
TimelineNowIndicatorArrow: TimelineNowIndicatorArrow,
|
|
1294
|
-
TimelineNowIndicatorLine: TimelineNowIndicatorLine
|
|
1260
|
+
TimelineNowIndicatorLine: TimelineNowIndicatorLine,
|
|
1261
|
+
getTimelineSlotEl: getTimelineSlotEl
|
|
1295
1262
|
};
|
|
1296
1263
|
|
|
1297
1264
|
core.globalPlugins.push(plugin);
|
|
@@ -1303,4 +1270,4 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1303
1270
|
|
|
1304
1271
|
return exports;
|
|
1305
1272
|
|
|
1306
|
-
})({}, FullCalendar, FullCalendar.PremiumCommon, FullCalendar.Internal, FullCalendar.Preact, FullCalendar.ScrollGrid.Internal);
|
|
1273
|
+
})({}, FullCalendar, FullCalendar.PremiumCommon, FullCalendar.Internal, FullCalendar.InternalClassNames, FullCalendar.Preact, FullCalendar.ScrollGrid.Internal);
|