@fullcalendar/timeline 7.0.0-beta.0 → 7.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs +2 -1
- package/index.global.js +170 -263
- package/index.global.min.js +2 -2
- package/index.js +2 -1
- package/internal.cjs +169 -261
- package/internal.d.ts +37 -59
- package/internal.js +170 -260
- package/package.json +4 -4
package/internal.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { config, createFormatter, greatestDurationDenominator, asCleanDays, createDuration, wholeDivideDurations, asRoughMs, addDays, startOfDay, asRoughSeconds, asRoughMinutes, diffWholeDays, isInt, computeVisibleDayRange, padStart, BaseComponent, getDateMeta, ContentContainer, joinClassNames, getDayClassName, getSlotClassName, watchWidth, setRef, RefMap, afterSize, getEventKey, SegHierarchy, groupIntersectingSegs, buildEventRangeKey, BgEvent, getEventRangeMeta, renderFill, Slicer, intersectRanges, addMs, StandardEvent, MoreLinkContainer, watchHeight, memoize, sortEventSegs, memoizeObjArg, watchSize, buildNavLinkAttrs, NowIndicatorContainer, DateComponent, getIsHeightAuto, getStickyHeaderDates, getStickyFooterScrollbar, NowTimer, rangeContainsMarker, ViewContainer, Scroller, multiplyDuration, injectStyles } from '@fullcalendar/core/internal.js';
|
|
2
2
|
import { createRef, createElement, Fragment, Component } from '@fullcalendar/core/preact.js';
|
|
3
|
-
|
|
4
|
-
var css_248z = ".fc-timeline-slots{z-index:1}.fc-timeline-slot-minor{border-style:dotted}.fc-timeline-now-indicator-container{bottom:0;left:0;overflow:hidden;position:absolute;right:0;top:0;z-index:4}.fc-timeline-now-indicator-arrow,.fc-timeline-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;pointer-events:none;position:absolute;top:0}.fc-timeline-now-indicator-arrow{border-left-color:transparent;border-right-color:transparent;border-width:6px 5px 0;margin:0 -5px}.fc-timeline-now-indicator-line{border-width:0 0 0 1px;bottom:0}.fc-timeline-events{z-index:3}.fc-timeline-events-overlap-enabled{padding-bottom:10px}.fc-timeline-event{border-radius:0;font-size:var(--fc-small-font-size);margin-bottom:1px;z-index:1}.fc-timeline-event.fc-event-mirror{z-index:2}.fc-direction-ltr .fc-timeline-event.fc-event-end{margin-right:1px}.fc-direction-rtl .fc-timeline-event.fc-event-end{margin-left:1px}.fc-timeline-event-spacious{margin-bottom:0;padding-bottom:5px;padding-top:5px}.fc-timeline-event .fc-event-inner{align-items:center;display:flex;flex-direction:row;padding:2px 1px}.fc-timeline-event:not(.fc-event-end) .fc-event-inner:after,.fc-timeline-event:not(.fc-event-start) .fc-event-inner:before{border-color:transparent #000;border-style:solid;border-width:5px;content:\"\";flex-grow:0;flex-shrink:0;height:0;margin:0 1px;opacity:.5;width:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-start) .fc-event-inner:before,.fc-direction-rtl .fc-timeline-event:not(.fc-event-end) .fc-event-inner:after{border-left:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-end) .fc-event-inner:after,.fc-direction-rtl .fc-timeline-event:not(.fc-event-start) .fc-event-inner:before{border-right:0}.fc-timeline-event .fc-event-time{font-weight:700}.fc-timeline-event .fc-event-time,.fc-timeline-event .fc-event-title{padding:0 2px}.fc-timeline-more-link{align-items:flex-start;background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;display:flex;flex-direction:column;font-size:var(--fc-small-font-size);padding:1px}.fc-direction-ltr .fc-timeline-more-link{margin-right:1px}.fc-direction-rtl .fc-timeline-more-link{margin-left:1px}.fc-timeline-more-link-inner{padding:2px}.fc-timeline-bg{bottom:0;left:0;position:absolute;right:0;top:0;z-index:2}.fc-timeline-bg .fc-non-business{z-index:1}.fc-timeline-bg .fc-bg-event{z-index:2}.fc-timeline-bg .fc-highlight{z-index:3}.fc-timeline-bg-harness{bottom:0;position:absolute;top:0}";
|
|
5
|
-
injectStyles(css_248z);
|
|
3
|
+
import { ScrollerSyncer } from '@fullcalendar/scrollgrid/internal.js';
|
|
6
4
|
|
|
7
5
|
const MIN_AUTO_LABELS = 18; // more than `12` months but less that `24` hours
|
|
8
6
|
const MAX_AUTO_SLOTS_PER_LABEL = 6; // allows 6 10-min slots in an hour
|
|
@@ -450,42 +448,36 @@ class TimelineSlatCell extends BaseComponent {
|
|
|
450
448
|
}
|
|
451
449
|
render() {
|
|
452
450
|
let { props, context } = this;
|
|
453
|
-
let { dateEnv, options
|
|
451
|
+
let { dateEnv, options } = context;
|
|
454
452
|
let { date, tDateProfile, isEm } = props;
|
|
455
453
|
let dateMeta = getDateMeta(props.date, props.todayRange, props.nowDate, props.dateProfile);
|
|
456
454
|
let renderProps = Object.assign(Object.assign({ date: dateEnv.toDate(props.date) }, dateMeta), { view: context.viewApi });
|
|
457
|
-
return (createElement(ContentContainer, {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
'fc-timeline-slot-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
'fc-timeline-slot-major' :
|
|
467
|
-
'fc-timeline-slot-minor') : '',
|
|
468
|
-
...(props.isDay ?
|
|
469
|
-
getDayClassNames(dateMeta, theme) :
|
|
470
|
-
getSlotClassNames(dateMeta, theme)),
|
|
471
|
-
], elAttrs: {
|
|
455
|
+
return (createElement(ContentContainer, { tag: "div",
|
|
456
|
+
// fc-align-start shrinks width of InnerContent
|
|
457
|
+
// TODO: document this semantic className fc-timeline-slot-em
|
|
458
|
+
className: joinClassNames('fc-timeline-slot', isEm && 'fc-timeline-slot-em', tDateProfile.isTimeScale && (isInt(dateEnv.countDurationsBetween(// best to do this here?
|
|
459
|
+
tDateProfile.normalizedRange.start, props.date, tDateProfile.labelInterval)) ?
|
|
460
|
+
'fc-timeline-slot-major' :
|
|
461
|
+
'fc-timeline-slot-minor'), 'fc-timeline-slot-lane fc-cell fc-flex-col fc-align-start', props.borderStart && 'fc-border-s', props.isDay ?
|
|
462
|
+
getDayClassName(dateMeta) :
|
|
463
|
+
getSlotClassName(dateMeta)), attrs: {
|
|
472
464
|
'data-date': dateEnv.formatIso(date, {
|
|
473
465
|
omitTimeZoneOffset: true,
|
|
474
466
|
omitTime: !tDateProfile.isTimeScale,
|
|
475
467
|
}),
|
|
476
|
-
},
|
|
468
|
+
}, style: {
|
|
477
469
|
width: props.width,
|
|
478
|
-
}, renderProps: renderProps, generatorName: "slotLaneContent", customGenerator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount }, (InnerContent) => (createElement(
|
|
479
|
-
createElement(InnerContent, { elTag: "div", elClasses: ['fc-cell-inner'] })))));
|
|
470
|
+
}, renderProps: renderProps, generatorName: "slotLaneContent", customGenerator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount }, (InnerContent) => (createElement(InnerContent, { tag: "div", className: 'fc-cell-inner', elRef: this.innerElRef }))));
|
|
480
471
|
}
|
|
481
472
|
componentDidMount() {
|
|
482
473
|
const innerEl = this.innerElRef.current;
|
|
483
|
-
this.
|
|
474
|
+
this.disconnectInnerWidth = watchWidth(innerEl, (width) => {
|
|
484
475
|
setRef(this.props.innerWidthRef, width);
|
|
485
476
|
});
|
|
486
477
|
}
|
|
487
478
|
componentWillUnmount() {
|
|
488
|
-
this.
|
|
479
|
+
this.disconnectInnerWidth();
|
|
480
|
+
setRef(this.props.innerWidthRef, null);
|
|
489
481
|
}
|
|
490
482
|
}
|
|
491
483
|
|
|
@@ -510,9 +502,9 @@ class TimelineSlats extends BaseComponent {
|
|
|
510
502
|
let { tDateProfile, slotWidth } = props;
|
|
511
503
|
let { slotDates, isWeekStarts } = tDateProfile;
|
|
512
504
|
let isDay = !tDateProfile.isTimeScale && !tDateProfile.largeUnit;
|
|
513
|
-
return (createElement("div", { className: "fc-timeline-slots fc-fill fc-flex-row" }, slotDates.map((slotDate, i) => {
|
|
505
|
+
return (createElement("div", { className: "fc-timeline-slots fc-fill fc-flex-row", style: { height: props.height } }, slotDates.map((slotDate, i) => {
|
|
514
506
|
let key = slotDate.toISOString();
|
|
515
|
-
return (createElement(TimelineSlatCell, { key: key, date: slotDate, dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: props.nowDate, todayRange: props.todayRange, isEm: isWeekStarts[i], isDay: isDay,
|
|
507
|
+
return (createElement(TimelineSlatCell, { key: key, date: slotDate, dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: props.nowDate, todayRange: props.todayRange, isEm: isWeekStarts[i], isDay: isDay, borderStart: Boolean(i),
|
|
516
508
|
// ref
|
|
517
509
|
innerWidthRef: innerWidthRefMap.createRef(key),
|
|
518
510
|
// dimensions
|
|
@@ -546,30 +538,6 @@ function computeDateSnapCoverage$1(date, tDateProfile, dateEnv) {
|
|
|
546
538
|
return snapCoverage;
|
|
547
539
|
}
|
|
548
540
|
/*
|
|
549
|
-
TODO: audit!!!
|
|
550
|
-
*/
|
|
551
|
-
function coordToCss(hcoord, isRtl) {
|
|
552
|
-
if (hcoord === null) {
|
|
553
|
-
return { left: '', right: '' };
|
|
554
|
-
}
|
|
555
|
-
if (isRtl) {
|
|
556
|
-
return { right: hcoord, left: '' };
|
|
557
|
-
}
|
|
558
|
-
return { left: hcoord, right: '' };
|
|
559
|
-
}
|
|
560
|
-
/*
|
|
561
|
-
TODO: audit!!!
|
|
562
|
-
*/
|
|
563
|
-
function coordsToCss(hcoords, isRtl) {
|
|
564
|
-
if (!hcoords) {
|
|
565
|
-
return { left: '', right: '' };
|
|
566
|
-
}
|
|
567
|
-
if (isRtl) {
|
|
568
|
-
return { right: hcoords.start, left: -hcoords.end };
|
|
569
|
-
}
|
|
570
|
-
return { left: hcoords.start, right: -hcoords.end };
|
|
571
|
-
}
|
|
572
|
-
/*
|
|
573
541
|
TODO: DRY up with elsewhere?
|
|
574
542
|
*/
|
|
575
543
|
function horizontalsToCss(hcoord, isRtl) {
|
|
@@ -600,7 +568,8 @@ function createVerticalStyle(props) {
|
|
|
600
568
|
};
|
|
601
569
|
}
|
|
602
570
|
}
|
|
603
|
-
function createHorizontalStyle(
|
|
571
|
+
function createHorizontalStyle(// TODO: DRY up?
|
|
572
|
+
props, isRtl) {
|
|
604
573
|
if (props) {
|
|
605
574
|
return {
|
|
606
575
|
[isRtl ? 'right' : 'left']: props.start,
|
|
@@ -673,13 +642,13 @@ function computeDateSnapCoverage(date, tDateProfile, dateEnv) {
|
|
|
673
642
|
function computeManySegHorizontals(segs, segMinWidth, dateEnv, tDateProfile, slotWidth) {
|
|
674
643
|
const res = {};
|
|
675
644
|
for (const seg of segs) {
|
|
676
|
-
res[seg
|
|
645
|
+
res[getEventKey(seg)] = computeSegHorizontals(seg, segMinWidth, dateEnv, tDateProfile, slotWidth);
|
|
677
646
|
}
|
|
678
647
|
return res;
|
|
679
648
|
}
|
|
680
649
|
function computeSegHorizontals(seg, segMinWidth, dateEnv, tDateProfile, slotWidth) {
|
|
681
|
-
const startCoord = dateToCoord(seg.
|
|
682
|
-
const endCoord = dateToCoord(seg.
|
|
650
|
+
const startCoord = dateToCoord(seg.startDate, dateEnv, tDateProfile, slotWidth);
|
|
651
|
+
const endCoord = dateToCoord(seg.endDate, dateEnv, tDateProfile, slotWidth);
|
|
683
652
|
let size = endCoord - startCoord;
|
|
684
653
|
if (segMinWidth) {
|
|
685
654
|
size = Math.max(size, segMinWidth);
|
|
@@ -687,95 +656,58 @@ function computeSegHorizontals(seg, segMinWidth, dateEnv, tDateProfile, slotWidt
|
|
|
687
656
|
return { start: startCoord, size };
|
|
688
657
|
}
|
|
689
658
|
function computeFgSegPlacements(// mostly horizontals
|
|
690
|
-
segs, segHorizontals,
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
segEntries.push({
|
|
700
|
-
index: i,
|
|
701
|
-
seg,
|
|
702
|
-
span: {
|
|
703
|
-
start: hcoords.start,
|
|
704
|
-
end: hcoords.start + hcoords.size,
|
|
705
|
-
},
|
|
706
|
-
thickness: height,
|
|
707
|
-
});
|
|
659
|
+
segs, segHorizontals, // TODO: use Map
|
|
660
|
+
segHeights, // keyed by instanceId
|
|
661
|
+
hiddenGroupHeights, strictOrder, maxDepth) {
|
|
662
|
+
const segRanges = [];
|
|
663
|
+
// isn't it true that there will either be ALL hcoords or NONE? can optimize
|
|
664
|
+
for (const seg of segs) {
|
|
665
|
+
const hcoords = segHorizontals[getEventKey(seg)];
|
|
666
|
+
if (hcoords) {
|
|
667
|
+
segRanges.push(Object.assign(Object.assign({}, seg), { start: hcoords.start, end: hcoords.start + hcoords.size }));
|
|
708
668
|
}
|
|
709
669
|
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
}
|
|
717
|
-
let
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
hierarchy.maxStackCnt = -1;
|
|
727
|
-
hierarchy.addSegs(hiddenGroupEntries);
|
|
728
|
-
let visibleRects = hierarchy.toRects();
|
|
729
|
-
let segTops = {};
|
|
730
|
-
let hiddenGroupTops = {};
|
|
731
|
-
for (let rect of visibleRects) {
|
|
732
|
-
const { seg, segGroup } = rect;
|
|
733
|
-
if (seg) { // regular seg
|
|
734
|
-
segTops[seg.eventRange.instance.instanceId] = rect.levelCoord;
|
|
735
|
-
}
|
|
736
|
-
else { // hiddenGroup
|
|
737
|
-
hiddenGroupTops[segGroup.key] = rect.levelCoord;
|
|
670
|
+
const hierarchy = new SegHierarchy(segRanges, (seg) => segHeights.get(getEventKey(seg)), strictOrder, undefined, // maxCoord
|
|
671
|
+
maxDepth);
|
|
672
|
+
const segTops = new Map();
|
|
673
|
+
hierarchy.traverseSegs((seg, segTop) => {
|
|
674
|
+
segTops.set(getEventKey(seg), segTop);
|
|
675
|
+
});
|
|
676
|
+
const { hiddenSegs } = hierarchy;
|
|
677
|
+
let totalHeight = 0;
|
|
678
|
+
for (const segRange of segRanges) {
|
|
679
|
+
const segKey = getEventKey(segRange);
|
|
680
|
+
const segHeight = segHeights.get(segKey);
|
|
681
|
+
const segTop = segTops.get(segKey);
|
|
682
|
+
if (segHeight != null) {
|
|
683
|
+
if (segTop != null) {
|
|
684
|
+
totalHeight = Math.max(totalHeight, segTop + segHeight);
|
|
685
|
+
}
|
|
738
686
|
}
|
|
739
687
|
}
|
|
688
|
+
const hiddenGroups = groupIntersectingSegs(hiddenSegs);
|
|
689
|
+
const hiddenGroupTops = new Map();
|
|
690
|
+
// HACK for hiddenGroup findInsertion() call
|
|
691
|
+
hierarchy.strictOrder = true;
|
|
692
|
+
for (const hiddenGroup of hiddenGroups) {
|
|
693
|
+
const { levelCoord: top } = hierarchy.findInsertion(hiddenGroup, 0);
|
|
694
|
+
const hiddenGroupHeight = hiddenGroupHeights.get(hiddenGroup.key) || 0;
|
|
695
|
+
hiddenGroupTops.set(hiddenGroup.key, top);
|
|
696
|
+
totalHeight = Math.max(totalHeight, top + hiddenGroupHeight);
|
|
697
|
+
}
|
|
740
698
|
return [
|
|
741
699
|
segTops,
|
|
742
|
-
computeMaxBottom(segs, segTops, segHeights),
|
|
743
700
|
hiddenGroups,
|
|
744
701
|
hiddenGroupTops,
|
|
702
|
+
totalHeight,
|
|
745
703
|
];
|
|
746
704
|
}
|
|
747
|
-
function computeMaxBottom(segs, segTops, segHeights) {
|
|
748
|
-
let max = 0;
|
|
749
|
-
for (const seg of segs) {
|
|
750
|
-
const { instanceId } = seg.eventRange.instance;
|
|
751
|
-
const top = segTops[instanceId];
|
|
752
|
-
const height = segHeights.get(instanceId);
|
|
753
|
-
if (top != null && height != null) {
|
|
754
|
-
max = Math.max(max, top + height);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
return max;
|
|
758
|
-
}
|
|
759
|
-
/*
|
|
760
|
-
TODO: converge with computeMaxBottom, but keys are different
|
|
761
|
-
*/
|
|
762
|
-
function computeMoreLinkMaxBottom(hiddenGroups, hiddenGroupTops, hiddenGroupHeights) {
|
|
763
|
-
let max = 0;
|
|
764
|
-
for (const hiddenGroup of hiddenGroups) {
|
|
765
|
-
const top = hiddenGroupTops[hiddenGroup.key];
|
|
766
|
-
const height = hiddenGroupHeights.get(hiddenGroup.key);
|
|
767
|
-
if (top != null && height != null) {
|
|
768
|
-
max = Math.max(max, top + height);
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
return max;
|
|
772
|
-
}
|
|
773
705
|
|
|
774
706
|
class TimelineLaneBg extends BaseComponent {
|
|
775
707
|
render() {
|
|
776
708
|
let { props } = this;
|
|
777
709
|
let highlightSeg = [].concat(props.eventResizeSegs, props.dateSelectionSegs);
|
|
778
|
-
return (createElement(
|
|
710
|
+
return (createElement(Fragment, null,
|
|
779
711
|
this.renderSegs(props.businessHourSegs || [], 'non-business'),
|
|
780
712
|
this.renderSegs(props.bgEventSegs || [], 'bg-event'),
|
|
781
713
|
this.renderSegs(highlightSeg, 'highlight')));
|
|
@@ -789,9 +721,8 @@ class TimelineLaneBg extends BaseComponent {
|
|
|
789
721
|
let segHorizontal = computeSegHorizontals(seg, undefined, dateEnv, tDateProfile, slotWidth);
|
|
790
722
|
hStyle = horizontalsToCss(segHorizontal, isRtl);
|
|
791
723
|
}
|
|
792
|
-
return (createElement("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-
|
|
793
|
-
createElement(BgEvent, Object.assign({ seg: seg },
|
|
794
|
-
renderFill(fillType)));
|
|
724
|
+
return (createElement("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-fill-y", style: hStyle }, fillType === 'bg-event' ?
|
|
725
|
+
createElement(BgEvent, Object.assign({ eventRange: seg.eventRange, isStart: seg.isStart, isEnd: seg.isEnd }, getEventRangeMeta(seg.eventRange, todayRange, nowDate))) : (renderFill(fillType))));
|
|
795
726
|
})));
|
|
796
727
|
}
|
|
797
728
|
}
|
|
@@ -807,8 +738,8 @@ class TimelineLaneSlicer extends Slicer {
|
|
|
807
738
|
let slicedRange = intersectRanges(normalRange, tDateProfile.normalizedRange);
|
|
808
739
|
if (slicedRange) {
|
|
809
740
|
segs.push({
|
|
810
|
-
|
|
811
|
-
|
|
741
|
+
startDate: slicedRange.start,
|
|
742
|
+
endDate: slicedRange.end,
|
|
812
743
|
isStart: slicedRange.start.valueOf() === normalRange.start.valueOf()
|
|
813
744
|
&& isValidDate(slicedRange.start, tDateProfile, dateProfile, dateProfileGenerator),
|
|
814
745
|
isEnd: slicedRange.end.valueOf() === normalRange.end.valueOf()
|
|
@@ -830,13 +761,8 @@ class TimelineEvent extends BaseComponent {
|
|
|
830
761
|
render() {
|
|
831
762
|
let { props, context } = this;
|
|
832
763
|
let { options } = context;
|
|
833
|
-
return (createElement(StandardEvent, Object.assign({}, props, {
|
|
834
|
-
'fc-timeline-event',
|
|
835
|
-
'fc-h-event',
|
|
836
|
-
options.eventOverlap === false // TODO: fix bad default
|
|
837
|
-
? 'fc-timeline-event-spacious'
|
|
838
|
-
: ''
|
|
839
|
-
], defaultTimeFormat: DEFAULT_TIME_FORMAT, defaultDisplayEventTime: !props.isTimeScale })));
|
|
764
|
+
return (createElement(StandardEvent, Object.assign({}, props, { className: joinClassNames('fc-timeline-event', options.eventOverlap === false // TODO: fix bad default
|
|
765
|
+
&& 'fc-timeline-event-spacious', 'fc-h-event'), defaultTimeFormat: DEFAULT_TIME_FORMAT, defaultDisplayEventTime: !props.isTimeScale })));
|
|
840
766
|
}
|
|
841
767
|
}
|
|
842
768
|
|
|
@@ -844,12 +770,13 @@ class TimelineLaneMoreLink extends BaseComponent {
|
|
|
844
770
|
render() {
|
|
845
771
|
let { props } = this;
|
|
846
772
|
let { hiddenSegs, resourceId, forcedInvisibleMap } = props;
|
|
847
|
-
let
|
|
848
|
-
return (createElement(MoreLinkContainer, {
|
|
849
|
-
let
|
|
773
|
+
let dateSpanProps = resourceId ? { resourceId } : {};
|
|
774
|
+
return (createElement(MoreLinkContainer, { className: 'fc-timeline-more-link', allDayDate: null, segs: hiddenSegs, hiddenSegs: hiddenSegs, dateProfile: props.dateProfile, todayRange: props.todayRange, dateSpanProps: dateSpanProps, popoverContent: () => (createElement(Fragment, null, hiddenSegs.map((seg) => {
|
|
775
|
+
let { eventRange } = seg;
|
|
776
|
+
let instanceId = eventRange.instance.instanceId;
|
|
850
777
|
return (createElement("div", { key: instanceId, style: { visibility: forcedInvisibleMap[instanceId] ? 'hidden' : '' } },
|
|
851
|
-
createElement(TimelineEvent, Object.assign({ isTimeScale: props.isTimeScale, seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection },
|
|
852
|
-
}))) }, (InnerContent) => (createElement(InnerContent, {
|
|
778
|
+
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 }, getEventRangeMeta(eventRange, props.todayRange, props.nowDate)))));
|
|
779
|
+
}))) }, (InnerContent) => (createElement(InnerContent, { tag: "div", className: 'fc-timeline-more-link-inner fc-sticky-s' }))));
|
|
853
780
|
}
|
|
854
781
|
}
|
|
855
782
|
|
|
@@ -868,12 +795,13 @@ class TimelineEventHarness extends Component {
|
|
|
868
795
|
}
|
|
869
796
|
componentDidMount() {
|
|
870
797
|
const rootEl = this.rootElRef.current; // TODO: make dynamic with useEffect
|
|
871
|
-
this.
|
|
798
|
+
this.disconnectHeight = watchHeight(rootEl, (height) => {
|
|
872
799
|
setRef(this.props.heightRef, height);
|
|
873
800
|
});
|
|
874
801
|
}
|
|
875
802
|
componentWillUnmount() {
|
|
876
|
-
this.
|
|
803
|
+
this.disconnectHeight();
|
|
804
|
+
setRef(this.props.heightRef, null);
|
|
877
805
|
}
|
|
878
806
|
}
|
|
879
807
|
|
|
@@ -905,7 +833,7 @@ class TimelineLane extends BaseComponent {
|
|
|
905
833
|
TODO: lots of memoization needed here!
|
|
906
834
|
*/
|
|
907
835
|
render() {
|
|
908
|
-
let { props, context, segHeightRefMap } = this;
|
|
836
|
+
let { props, context, segHeightRefMap, moreLinkHeightRefMap } = this;
|
|
909
837
|
let { options } = context;
|
|
910
838
|
let { dateProfile, tDateProfile } = props;
|
|
911
839
|
let slicedProps = this.slicer.sliceProps(props, dateProfile, tDateProfile.isTimeScale ? null : props.nextDayThreshold, context, // wish we didn't have to pass in the rest of the args...
|
|
@@ -917,10 +845,7 @@ class TimelineLane extends BaseComponent {
|
|
|
917
845
|
let fgSegHorizontals = props.slotWidth != null
|
|
918
846
|
? computeManySegHorizontals(fgSegs, options.eventMinWidth, context.dateEnv, tDateProfile, props.slotWidth)
|
|
919
847
|
: {};
|
|
920
|
-
let [fgSegTops,
|
|
921
|
-
fgSegs, fgSegHorizontals, segHeightRefMap.current, options.eventOrderStrict, options.eventMaxStack);
|
|
922
|
-
let moreLinksBottom = computeMoreLinkMaxBottom(hiddenGroups, hiddenGroupTops, this.moreLinkHeightRefMap.current);
|
|
923
|
-
let innerHeight = Math.max(moreLinksBottom, fgSegsBottom);
|
|
848
|
+
let [fgSegTops, hiddenGroups, hiddenGroupTops, totalHeight] = computeFgSegPlacements(fgSegs, fgSegHorizontals, segHeightRefMap.current, moreLinkHeightRefMap.current, options.eventOrderStrict, options.eventMaxStack);
|
|
924
849
|
let forcedInvisibleMap = // TODO: more convenient/DRY
|
|
925
850
|
(slicedProps.eventDrag ? slicedProps.eventDrag.affectedInstances : null) ||
|
|
926
851
|
(slicedProps.eventResize ? slicedProps.eventResize.affectedInstances : null) ||
|
|
@@ -931,39 +856,38 @@ class TimelineLane extends BaseComponent {
|
|
|
931
856
|
bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventResizeSegs: slicedProps.eventResize ? slicedProps.eventResize.segs : [] /* bad new empty array? */,
|
|
932
857
|
// dimensions
|
|
933
858
|
slotWidth: props.slotWidth }),
|
|
934
|
-
createElement("div", { className:
|
|
935
|
-
'fc-timeline-events'
|
|
936
|
-
'fc-content-box',
|
|
937
|
-
options.eventOverlap === false // TODO: fix bad default
|
|
938
|
-
? 'fc-timeline-events-overlap-disabled'
|
|
939
|
-
: 'fc-timeline-events-overlap-enabled'
|
|
940
|
-
].join(' '), style: { height: innerHeight } },
|
|
859
|
+
createElement("div", { className: joinClassNames('fc-timeline-events', options.eventOverlap === false // TODO: fix bad default
|
|
860
|
+
? 'fc-timeline-events-overlap-disabled'
|
|
861
|
+
: 'fc-timeline-events-overlap-enabled', 'fc-content-box'), style: { height: totalHeight } },
|
|
941
862
|
this.renderFgSegs(fgSegs, fgSegHorizontals, fgSegTops, forcedInvisibleMap, hiddenGroups, hiddenGroupTops, false, // isDragging
|
|
942
863
|
false, // isResizing
|
|
943
864
|
false),
|
|
944
865
|
this.renderFgSegs(mirrorSegs, props.slotWidth // TODO: memoize
|
|
945
866
|
? computeManySegHorizontals(mirrorSegs, options.eventMinWidth, context.dateEnv, tDateProfile, props.slotWidth)
|
|
946
867
|
: {}, fgSegTops, {}, // forcedInvisibleMap
|
|
947
|
-
[],
|
|
868
|
+
[], // hiddenGroups
|
|
869
|
+
new Map(), // hiddenGroupTops
|
|
870
|
+
Boolean(slicedProps.eventDrag), Boolean(slicedProps.eventResize), false))));
|
|
948
871
|
}
|
|
949
872
|
renderFgSegs(segs, segHorizontals, segTops, forcedInvisibleMap, hiddenGroups, hiddenGroupTops, isDragging, isResizing, isDateSelecting) {
|
|
950
873
|
let { props, context, segHeightRefMap, moreLinkHeightRefMap } = this;
|
|
951
874
|
let isMirror = isDragging || isResizing || isDateSelecting;
|
|
952
875
|
return (createElement(Fragment, null,
|
|
953
876
|
segs.map((seg) => {
|
|
954
|
-
const {
|
|
955
|
-
const
|
|
877
|
+
const { eventRange } = seg;
|
|
878
|
+
const { instanceId } = eventRange.instance;
|
|
879
|
+
const segTop = segTops.get(instanceId);
|
|
956
880
|
const segHorizontal = segHorizontals[instanceId];
|
|
957
881
|
const isVisible = isMirror ||
|
|
958
882
|
(segHorizontal && segTop != null && !forcedInvisibleMap[instanceId]);
|
|
959
883
|
return (createElement(TimelineEventHarness, { key: instanceId, style: Object.assign({ visibility: isVisible ? '' : 'hidden', top: segTop || 0 }, horizontalsToCss(segHorizontal, context.isRtl)), heightRef: isMirror ? undefined : segHeightRefMap.createRef(instanceId) },
|
|
960
|
-
createElement(TimelineEvent, Object.assign({ isTimeScale: props.tDateProfile.isTimeScale, seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === props.eventSelection /* TODO: bad for mirror? */ },
|
|
884
|
+
createElement(TimelineEvent, Object.assign({ isTimeScale: props.tDateProfile.isTimeScale, eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === props.eventSelection /* TODO: bad for mirror? */ }, getEventRangeMeta(eventRange, props.todayRange, props.nowDate)))));
|
|
961
885
|
}),
|
|
962
|
-
hiddenGroups.map((hiddenGroup) => (createElement(TimelineEventHarness, { key: hiddenGroup.key, style: Object.assign({ top: hiddenGroupTops
|
|
963
|
-
start: hiddenGroup.
|
|
964
|
-
size: hiddenGroup.
|
|
886
|
+
hiddenGroups.map((hiddenGroup) => (createElement(TimelineEventHarness, { key: hiddenGroup.key, style: Object.assign({ top: hiddenGroupTops.get(hiddenGroup.key) || 0 }, horizontalsToCss({
|
|
887
|
+
start: hiddenGroup.start,
|
|
888
|
+
size: hiddenGroup.end - hiddenGroup.start
|
|
965
889
|
}, context.isRtl)), heightRef: moreLinkHeightRefMap.createRef(hiddenGroup.key) },
|
|
966
|
-
createElement(TimelineLaneMoreLink, { hiddenSegs: hiddenGroup.segs
|
|
890
|
+
createElement(TimelineLaneMoreLink, { hiddenSegs: hiddenGroup.segs, dateProfile: props.dateProfile, nowDate: props.nowDate, todayRange: props.todayRange, isTimeScale: props.tDateProfile.isTimeScale, eventSelection: props.eventSelection, resourceId: props.resourceId, forcedInvisibleMap: forcedInvisibleMap }))))));
|
|
967
891
|
}
|
|
968
892
|
}
|
|
969
893
|
|
|
@@ -975,7 +899,6 @@ class TimelineHeaderCell extends BaseComponent {
|
|
|
975
899
|
this.buildCellNavLinkAttrs = memoize(buildCellNavLinkAttrs);
|
|
976
900
|
// ref
|
|
977
901
|
this.innerElRef = createRef();
|
|
978
|
-
// TODO: unset width/height ref on unmount?
|
|
979
902
|
}
|
|
980
903
|
render() {
|
|
981
904
|
let { props, context } = this;
|
|
@@ -992,36 +915,21 @@ class TimelineHeaderCell extends BaseComponent {
|
|
|
992
915
|
dateEnv: context.dateEnv,
|
|
993
916
|
viewApi: context.viewApi,
|
|
994
917
|
});
|
|
995
|
-
return (createElement(ContentContainer, {
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
'fc-flex-column',
|
|
1002
|
-
'fc-justify-center',
|
|
1003
|
-
props.isCentered ? 'fc-align-center' : 'fc-align-start',
|
|
1004
|
-
...( // TODO: so slot classnames for week/month/bigger. see note above about rowUnit
|
|
1005
|
-
cell.rowUnit === 'time' ?
|
|
1006
|
-
getSlotClassNames(dateMeta, context.theme) :
|
|
1007
|
-
getDayClassNames(dateMeta, context.theme)),
|
|
1008
|
-
], elAttrs: {
|
|
918
|
+
return (createElement(ContentContainer, { tag: "div", className: joinClassNames('fc-timeline-slot-label fc-timeline-slot', cell.isWeekStart && 'fc-timeline-slot-em', // TODO: document this semantic className
|
|
919
|
+
'fc-header-cell fc-cell fc-flex-col fc-justify-center', props.borderStart && 'fc-border-s', props.isCentered ? 'fc-align-center' : 'fc-align-start',
|
|
920
|
+
// TODO: so slot classnames for week/month/bigger. see note above about rowUnit
|
|
921
|
+
cell.rowUnit === 'time' ?
|
|
922
|
+
getSlotClassName(dateMeta) :
|
|
923
|
+
getDayClassName(dateMeta)), attrs: {
|
|
1009
924
|
'data-date': dateEnv.formatIso(cell.date, {
|
|
1010
925
|
omitTime: !tDateProfile.isTimeScale,
|
|
1011
926
|
omitTimeZoneOffset: true,
|
|
1012
927
|
}),
|
|
1013
|
-
},
|
|
928
|
+
}, style: {
|
|
1014
929
|
width: props.slotWidth != null
|
|
1015
930
|
? props.slotWidth * cell.colspan
|
|
1016
931
|
: undefined,
|
|
1017
|
-
}, renderProps: renderProps, generatorName: "slotLabelContent", customGenerator: options.slotLabelContent, defaultGenerator: renderInnerContent, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (createElement(
|
|
1018
|
-
'fc-flex-column',
|
|
1019
|
-
props.isSticky ? 'fc-sticky-x' : '',
|
|
1020
|
-
].join(' ') },
|
|
1021
|
-
createElement(InnerContent, { elTag: "a", elClasses: [
|
|
1022
|
-
'fc-cell-inner',
|
|
1023
|
-
'fc-padding-md',
|
|
1024
|
-
], elAttrs: this.buildCellNavLinkAttrs(context, cell.date, cell.rowUnit) })))));
|
|
932
|
+
}, renderProps: renderProps, generatorName: "slotLabelContent", customGenerator: options.slotLabelContent, defaultGenerator: renderInnerContent, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (createElement(InnerContent, { tag: "a", attrs: this.buildCellNavLinkAttrs(context, cell.date, cell.rowUnit), className: joinClassNames('fc-cell-inner fc-padding-md', props.isSticky && 'fc-sticky-s'), elRef: this.innerElRef }))));
|
|
1025
933
|
}
|
|
1026
934
|
componentDidMount() {
|
|
1027
935
|
const { props } = this;
|
|
@@ -1037,7 +945,10 @@ class TimelineHeaderCell extends BaseComponent {
|
|
|
1037
945
|
});
|
|
1038
946
|
}
|
|
1039
947
|
componentWillUnmount() {
|
|
948
|
+
const { props } = this;
|
|
1040
949
|
this.detachSize();
|
|
950
|
+
setRef(props.innerWidthRef, null);
|
|
951
|
+
setRef(props.innerHeightRef, null);
|
|
1041
952
|
}
|
|
1042
953
|
}
|
|
1043
954
|
// Utils
|
|
@@ -1092,18 +1003,24 @@ class TimelineHeaderRow extends BaseComponent {
|
|
|
1092
1003
|
const { props, innerWidthRefMap, innerHeightRefMap } = this;
|
|
1093
1004
|
const isCentered = !(props.tDateProfile.isTimeScale && props.isLastRow);
|
|
1094
1005
|
const isSticky = !props.isLastRow;
|
|
1095
|
-
return (createElement("div", { className: 'fc-row',
|
|
1006
|
+
return (createElement("div", { className: joinClassNames('fc-flex-row fc-grow', // TODO: move fc-grow to parent?
|
|
1007
|
+
!props.isLastRow && 'fc-border-b') }, props.cells.map((cell, cellI) => {
|
|
1096
1008
|
// TODO: make this part of the cell obj?
|
|
1097
1009
|
// TODO: rowUnit seems wrong sometimes. says 'month' when it should be day
|
|
1098
1010
|
// TODO: rowUnit is relevant to whole row. put it on a row object, not the cells
|
|
1011
|
+
// TODO: use rowUnit to key the Row itself?
|
|
1099
1012
|
const key = cell.rowUnit + ':' + cell.date.toISOString();
|
|
1100
|
-
return (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,
|
|
1013
|
+
return (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),
|
|
1101
1014
|
// refs
|
|
1102
1015
|
innerWidthRef: innerWidthRefMap.createRef(key), innerHeightRef: innerHeightRefMap.createRef(key),
|
|
1103
1016
|
// dimensions
|
|
1104
1017
|
slotWidth: props.slotWidth }));
|
|
1105
1018
|
})));
|
|
1106
1019
|
}
|
|
1020
|
+
componentWillUnmount() {
|
|
1021
|
+
setRef(this.props.innerWidthRef, null);
|
|
1022
|
+
setRef(this.props.innerHeighRef, null);
|
|
1023
|
+
}
|
|
1107
1024
|
}
|
|
1108
1025
|
|
|
1109
1026
|
class TimelineNowIndicatorLine extends BaseComponent {
|
|
@@ -1111,7 +1028,7 @@ class TimelineNowIndicatorLine extends BaseComponent {
|
|
|
1111
1028
|
const { props, context } = this;
|
|
1112
1029
|
return (createElement("div", { className: "fc-timeline-now-indicator-container" },
|
|
1113
1030
|
createElement(NowIndicatorContainer // TODO: make separate component?
|
|
1114
|
-
, {
|
|
1031
|
+
, { className: 'fc-timeline-now-indicator-line', style: props.slotWidth != null
|
|
1115
1032
|
? horizontalCoordToCss(dateToCoord(props.nowDate, context.dateEnv, props.tDateProfile, props.slotWidth), context.isRtl)
|
|
1116
1033
|
: {}, isAxis: false, date: props.nowDate })));
|
|
1117
1034
|
}
|
|
@@ -1121,7 +1038,7 @@ class TimelineNowIndicatorArrow extends BaseComponent {
|
|
|
1121
1038
|
render() {
|
|
1122
1039
|
const { props, context } = this;
|
|
1123
1040
|
return (createElement("div", { className: "fc-timeline-now-indicator-container" },
|
|
1124
|
-
createElement(NowIndicatorContainer, {
|
|
1041
|
+
createElement(NowIndicatorContainer, { className: 'fc-timeline-now-indicator-arrow', style: props.slotWidth != null
|
|
1125
1042
|
? horizontalCoordToCss(dateToCoord(props.nowDate, context.dateEnv, props.tDateProfile, props.slotWidth), context.isRtl)
|
|
1126
1043
|
: {}, isAxis: true, date: props.nowDate })));
|
|
1127
1044
|
}
|
|
@@ -1137,48 +1054,50 @@ class TimelineView extends DateComponent {
|
|
|
1137
1054
|
this.headerScrollerRef = createRef();
|
|
1138
1055
|
this.bodyScrollerRef = createRef();
|
|
1139
1056
|
this.footerScrollerRef = createRef();
|
|
1057
|
+
this.headerRowInnerWidthMap = new RefMap(() => {
|
|
1058
|
+
afterSize(this.handleSlotInnerWidths);
|
|
1059
|
+
});
|
|
1060
|
+
this.scrollTime = null;
|
|
1140
1061
|
// Sizing
|
|
1141
1062
|
// -----------------------------------------------------------------------------------------------
|
|
1142
|
-
this.handleHeaderSlotInnerWidth = (innerWidth) => {
|
|
1143
|
-
this.headerSlotInnerWidth = innerWidth;
|
|
1144
|
-
afterSize(this.handleSlotInnerWidths);
|
|
1145
|
-
};
|
|
1146
1063
|
this.handleBodySlotInnerWidth = (innerWidth) => {
|
|
1147
1064
|
this.bodySlotInnerWidth = innerWidth;
|
|
1148
1065
|
afterSize(this.handleSlotInnerWidths);
|
|
1149
1066
|
};
|
|
1150
1067
|
this.handleSlotInnerWidths = () => {
|
|
1151
1068
|
const { state } = this;
|
|
1152
|
-
const slotInnerWidth = Math.max(this.
|
|
1069
|
+
const slotInnerWidth = Math.max(this.headerRowInnerWidthMap.current.get(this.tDateProfile.cellRows.length - 1) || 0, this.bodySlotInnerWidth);
|
|
1153
1070
|
if (state.slotInnerWidth !== slotInnerWidth) {
|
|
1154
1071
|
this.setState({ slotInnerWidth });
|
|
1155
1072
|
}
|
|
1156
1073
|
};
|
|
1157
|
-
this.
|
|
1074
|
+
this.handleClientWidth = (clientWidth) => {
|
|
1158
1075
|
this.setState({
|
|
1159
|
-
|
|
1076
|
+
clientWidth,
|
|
1160
1077
|
});
|
|
1161
1078
|
};
|
|
1162
|
-
this.
|
|
1079
|
+
this.handleEndScrollbarWidth = (endScrollbarWidth) => {
|
|
1163
1080
|
this.setState({
|
|
1164
|
-
|
|
1081
|
+
endScrollbarWidth
|
|
1165
1082
|
});
|
|
1166
1083
|
};
|
|
1167
|
-
this.
|
|
1168
|
-
this.
|
|
1169
|
-
|
|
1170
|
-
});
|
|
1084
|
+
this.handleTimeScroll = (scrollTime) => {
|
|
1085
|
+
this.scrollTime = scrollTime;
|
|
1086
|
+
this.updateScroll();
|
|
1171
1087
|
};
|
|
1172
|
-
this.
|
|
1173
|
-
const { props, context, tDateProfile, slotWidth } = this;
|
|
1174
|
-
if (slotWidth != null) {
|
|
1175
|
-
|
|
1176
|
-
|
|
1088
|
+
this.updateScroll = () => {
|
|
1089
|
+
const { props, context, tDateProfile, scrollTime, slotWidth } = this;
|
|
1090
|
+
if (scrollTime != null && slotWidth != null) {
|
|
1091
|
+
let x = timeToCoord(scrollTime, context.dateEnv, props.dateProfile, tDateProfile, slotWidth);
|
|
1092
|
+
if (x) {
|
|
1093
|
+
x += 1; // overcome border. TODO: DRY this up
|
|
1094
|
+
}
|
|
1177
1095
|
this.syncedScroller.scrollTo({ x });
|
|
1178
|
-
return true;
|
|
1179
1096
|
}
|
|
1180
|
-
|
|
1181
|
-
|
|
1097
|
+
};
|
|
1098
|
+
this.clearScroll = () => {
|
|
1099
|
+
this.scrollTime = null;
|
|
1100
|
+
};
|
|
1182
1101
|
// Hit System
|
|
1183
1102
|
// -----------------------------------------------------------------------------------------------
|
|
1184
1103
|
this.handeBodyEl = (el) => {
|
|
@@ -1204,44 +1123,30 @@ class TimelineView extends DateComponent {
|
|
|
1204
1123
|
const stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(options);
|
|
1205
1124
|
/* table positions */
|
|
1206
1125
|
const [canvasWidth, slotWidth] = this.computeSlotWidth(tDateProfile.slotCnt, tDateProfile.slotsPerLabel, options.slotMinWidth, state.slotInnerWidth, // is ACTUALLY the label width. rename?
|
|
1207
|
-
state.
|
|
1126
|
+
state.clientWidth);
|
|
1208
1127
|
this.slotWidth = slotWidth;
|
|
1209
1128
|
return (createElement(NowTimer, { unit: timerUnit }, (nowDate, todayRange) => {
|
|
1210
1129
|
const enableNowIndicator = // TODO: DRY
|
|
1211
1130
|
options.nowIndicator &&
|
|
1212
1131
|
slotWidth != null &&
|
|
1213
1132
|
rangeContainsMarker(props.dateProfile.currentRange, nowDate);
|
|
1214
|
-
return (createElement(ViewContainer, { viewSpec: context.viewSpec,
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
'fc-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
createElement("div", { className: 'fc-rel fc-content-box' // origin for now-indicator
|
|
1225
|
-
, style: {
|
|
1226
|
-
width: canvasWidth,
|
|
1227
|
-
paddingLeft: state.leftScrollbarWidth,
|
|
1228
|
-
paddingRight: state.rightScrollbarWidth,
|
|
1229
|
-
} },
|
|
1230
|
-
createElement("div", null, cellRows.map((cells, rowLevel) => {
|
|
1133
|
+
return (createElement(ViewContainer, { viewSpec: context.viewSpec, className: joinClassNames('fc-timeline fc-border',
|
|
1134
|
+
// HACK for Safari print-mode, where fc-scroller-no-bars won't take effect for
|
|
1135
|
+
// the below Scrollers if they have liquid flex height
|
|
1136
|
+
!props.forPrint && 'fc-flex-col') },
|
|
1137
|
+
createElement(Scroller, { horizontal: true, hideScrollbars: true, className: joinClassNames('fc-timeline-header fc-flex-row fc-border-b', stickyHeaderDates && 'fc-table-header-sticky'), ref: this.headerScrollerRef },
|
|
1138
|
+
createElement("div", {
|
|
1139
|
+
// TODO: DRY
|
|
1140
|
+
className: joinClassNames('fc-rel', // origin for now-indicator
|
|
1141
|
+
canvasWidth == null && 'fc-liquid'), style: { width: canvasWidth } },
|
|
1142
|
+
cellRows.map((cells, rowLevel) => {
|
|
1231
1143
|
const isLast = rowLevel === cellRows.length - 1;
|
|
1232
|
-
return (createElement(TimelineHeaderRow, { key: rowLevel, dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange, rowLevel: rowLevel, isLastRow: isLast, cells: cells, slotWidth: slotWidth, innerWidthRef:
|
|
1233
|
-
})
|
|
1234
|
-
enableNowIndicator && (
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
'fc-timeline-body',
|
|
1239
|
-
'fc-rowgroup',
|
|
1240
|
-
verticalScrolling ? 'fc-liquid' : '',
|
|
1241
|
-
], ref: this.bodyScrollerRef, widthRef: this.handleScrollerWidth, leftScrollbarWidthRef: this.handleLeftScrollbarWidth, rightScrollbarWidthRef: this.handleRightScrollbarWidth },
|
|
1242
|
-
createElement("div", { className: "fc-rel fc-grow", style: {
|
|
1243
|
-
width: canvasWidth,
|
|
1244
|
-
}, ref: this.handeBodyEl },
|
|
1144
|
+
return (createElement(TimelineHeaderRow, { key: rowLevel, dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange, rowLevel: rowLevel, isLastRow: isLast, cells: cells, slotWidth: slotWidth, innerWidthRef: this.headerRowInnerWidthMap.createRef(rowLevel) }));
|
|
1145
|
+
}),
|
|
1146
|
+
enableNowIndicator && (createElement(TimelineNowIndicatorArrow, { tDateProfile: tDateProfile, nowDate: nowDate, slotWidth: slotWidth }))),
|
|
1147
|
+
Boolean(state.endScrollbarWidth) && (createElement("div", { className: 'fc-border-s fc-filler', style: { minWidth: state.endScrollbarWidth } }))),
|
|
1148
|
+
createElement(Scroller, { vertical: verticalScrolling, horizontal: true, hideScrollbars: props.forPrint, className: joinClassNames('fc-timeline-body fc-flex-col', verticalScrolling && 'fc-liquid'), ref: this.bodyScrollerRef, clientWidthRef: this.handleClientWidth, endScrollbarWidthRef: this.handleEndScrollbarWidth },
|
|
1149
|
+
createElement("div", { className: "fc-rel fc-grow", style: { width: canvasWidth }, ref: this.handeBodyEl },
|
|
1245
1150
|
createElement(TimelineSlats, { dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange,
|
|
1246
1151
|
// ref
|
|
1247
1152
|
innerWidthRef: this.handleBodySlotInnerWidth,
|
|
@@ -1256,27 +1161,26 @@ class TimelineView extends DateComponent {
|
|
|
1256
1161
|
// Lifecycle
|
|
1257
1162
|
// -----------------------------------------------------------------------------------------------
|
|
1258
1163
|
componentDidMount() {
|
|
1259
|
-
const { context } = this;
|
|
1260
|
-
const { options } = context;
|
|
1261
|
-
const ScrollerSyncer = getScrollerSyncerClass(this.context.pluginHooks);
|
|
1262
1164
|
this.syncedScroller = new ScrollerSyncer(true); // horizontal=true
|
|
1263
1165
|
this.updateSyncedScroller();
|
|
1264
|
-
|
|
1265
|
-
this.
|
|
1166
|
+
this.resetScroll();
|
|
1167
|
+
this.context.emitter.on('_timeScrollRequest', this.handleTimeScroll);
|
|
1168
|
+
this.syncedScroller.addScrollEndListener(this.clearScroll);
|
|
1266
1169
|
}
|
|
1267
1170
|
componentDidUpdate(prevProps) {
|
|
1268
|
-
const { options } = this.context;
|
|
1269
1171
|
this.updateSyncedScroller();
|
|
1270
|
-
if (prevProps.dateProfile !== this.props.dateProfile && options.scrollTimeReset) {
|
|
1271
|
-
this.
|
|
1172
|
+
if (prevProps.dateProfile !== this.props.dateProfile && this.context.options.scrollTimeReset) {
|
|
1173
|
+
this.resetScroll();
|
|
1272
1174
|
}
|
|
1273
1175
|
else {
|
|
1274
|
-
|
|
1176
|
+
// TODO: inefficient to update so often
|
|
1177
|
+
this.updateScroll();
|
|
1275
1178
|
}
|
|
1276
1179
|
}
|
|
1277
1180
|
componentWillUnmount() {
|
|
1278
1181
|
this.syncedScroller.destroy();
|
|
1279
|
-
this.context.emitter.off('_timeScrollRequest', this.
|
|
1182
|
+
this.context.emitter.off('_timeScrollRequest', this.handleTimeScroll);
|
|
1183
|
+
this.syncedScroller.removeScrollEndListener(this.clearScroll);
|
|
1280
1184
|
}
|
|
1281
1185
|
// Scrolling
|
|
1282
1186
|
// -----------------------------------------------------------------------------------------------
|
|
@@ -1285,7 +1189,10 @@ class TimelineView extends DateComponent {
|
|
|
1285
1189
|
this.headerScrollerRef.current,
|
|
1286
1190
|
this.bodyScrollerRef.current,
|
|
1287
1191
|
this.footerScrollerRef.current
|
|
1288
|
-
]
|
|
1192
|
+
]);
|
|
1193
|
+
}
|
|
1194
|
+
resetScroll() {
|
|
1195
|
+
this.handleTimeScroll(this.context.options.scrollTime);
|
|
1289
1196
|
}
|
|
1290
1197
|
queryHit(positionLeft, positionTop, elWidth, elHeight) {
|
|
1291
1198
|
const { props, context, tDateProfile, slotWidth } = this;
|
|
@@ -1332,4 +1239,7 @@ class TimelineView extends DateComponent {
|
|
|
1332
1239
|
}
|
|
1333
1240
|
}
|
|
1334
1241
|
|
|
1335
|
-
|
|
1242
|
+
var css_248z = ".fc-timeline-slots{z-index:1}.fc-timeline-events{position:relative;z-index:2}.fc-timeline-slot-minor{border-style:dotted}.fc-timeline-events-overlap-enabled{padding-bottom:10px}.fc-timeline-event{border-radius:0;font-size:var(--fc-small-font-size);margin-bottom:1px}.fc-direction-ltr .fc-timeline-event.fc-event-end{margin-right:1px}.fc-direction-rtl .fc-timeline-event.fc-event-end{margin-left:1px}.fc-timeline-event .fc-event-inner{align-items:center;display:flex;flex-direction:row;padding:2px 1px}.fc-timeline-event-spacious .fc-event-inner{padding-bottom:5px;padding-top:5px}.fc-timeline-event .fc-event-time{font-weight:700}.fc-timeline-event .fc-event-time,.fc-timeline-event .fc-event-title{padding:0 2px}.fc-timeline-event:not(.fc-event-end) .fc-event-inner:after,.fc-timeline-event:not(.fc-event-start) .fc-event-inner:before{border-color:transparent #000;border-style:solid;border-width:5px;content:\"\";flex-grow:0;flex-shrink:0;height:0;margin:0 1px;opacity:.5;width:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-start) .fc-event-inner:before,.fc-direction-rtl .fc-timeline-event:not(.fc-event-end) .fc-event-inner:after{border-left:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-end) .fc-event-inner:after,.fc-direction-rtl .fc-timeline-event:not(.fc-event-start) .fc-event-inner:before{border-right:0}.fc-timeline-more-link{align-items:flex-start;background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;display:flex;flex-direction:column;font-size:var(--fc-small-font-size);padding:1px}.fc-direction-ltr .fc-timeline-more-link{margin-right:1px}.fc-direction-rtl .fc-timeline-more-link{margin-left:1px}.fc-timeline-more-link-inner{padding:2px}.fc-timeline-now-indicator-container{bottom:0;left:0;overflow:hidden;pointer-events:none;position:absolute;right:0;top:0;z-index:4}.fc-timeline-now-indicator-arrow{border-bottom-style:solid;border-bottom-width:0;border-color:var(--fc-now-indicator-color);border-left:5px solid transparent;border-right:5px solid transparent;border-top-style:solid;border-top-width:6px;height:0;margin:0 -5px;position:absolute;top:0;width:0}.fc-timeline-now-indicator-line{border-left:1px solid var(--fc-now-indicator-color);bottom:0;position:absolute;top:0}";
|
|
1243
|
+
injectStyles(css_248z);
|
|
1244
|
+
|
|
1245
|
+
export { TimelineHeaderRow, TimelineLane, TimelineLaneBg, TimelineLaneSlicer, TimelineNowIndicatorArrow, TimelineNowIndicatorLine, TimelineSlats, TimelineView, buildTimelineDateProfile, computeSlotWidth, createHorizontalStyle, createVerticalStyle, timeToCoord };
|