@fullcalendar/timeline 7.0.0-beta.3 → 7.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +2 -2
- package/index.cjs +1 -1
- package/index.global.js +371 -341
- package/index.global.min.js +2 -2
- package/index.js +1 -1
- package/internal.cjs +368 -338
- package/internal.d.ts +24 -21
- package/internal.js +367 -338
- package/package.json +4 -4
package/internal.cjs
CHANGED
|
@@ -447,6 +447,8 @@ function buildCellObject(date, text, rowUnit) {
|
|
|
447
447
|
class TimelineSlatCell extends internal_cjs.BaseComponent {
|
|
448
448
|
constructor() {
|
|
449
449
|
super(...arguments);
|
|
450
|
+
// memo
|
|
451
|
+
this.getPublicDate = internal_cjs.memoize((dateEnv, date) => dateEnv.toDate(date));
|
|
450
452
|
// ref
|
|
451
453
|
this.innerElRef = preact_cjs.createRef();
|
|
452
454
|
}
|
|
@@ -455,7 +457,7 @@ class TimelineSlatCell extends internal_cjs.BaseComponent {
|
|
|
455
457
|
let { dateEnv, options } = context;
|
|
456
458
|
let { date, tDateProfile, isEm } = props;
|
|
457
459
|
let dateMeta = internal_cjs.getDateMeta(props.date, props.todayRange, props.nowDate, props.dateProfile);
|
|
458
|
-
let renderProps = Object.assign(Object.assign({ date:
|
|
460
|
+
let renderProps = Object.assign(Object.assign({ date: this.getPublicDate(dateEnv, props.date) }, dateMeta), { view: context.viewApi });
|
|
459
461
|
return (preact_cjs.createElement(internal_cjs.ContentContainer, { tag: "div",
|
|
460
462
|
// fc-align-start shrinks width of InnerContent
|
|
461
463
|
// TODO: document this semantic className fc-timeline-slot-em
|
|
@@ -464,14 +466,16 @@ class TimelineSlatCell extends internal_cjs.BaseComponent {
|
|
|
464
466
|
'fc-timeline-slot-major' :
|
|
465
467
|
'fc-timeline-slot-minor'), 'fc-timeline-slot-lane fc-cell fc-flex-col fc-align-start', props.borderStart && 'fc-border-s', props.isDay ?
|
|
466
468
|
internal_cjs.getDayClassName(dateMeta) :
|
|
467
|
-
internal_cjs.getSlotClassName(dateMeta)), attrs: {
|
|
468
|
-
'data-date': dateEnv.formatIso(date, {
|
|
469
|
+
internal_cjs.getSlotClassName(dateMeta)), attrs: Object.assign({ 'data-date': dateEnv.formatIso(date, {
|
|
469
470
|
omitTimeZoneOffset: true,
|
|
470
471
|
omitTime: !tDateProfile.isTimeScale,
|
|
471
|
-
}),
|
|
472
|
-
}, style: {
|
|
472
|
+
}) }, (dateMeta.isToday ? { 'aria-current': 'date' } : {})), style: {
|
|
473
473
|
width: props.width,
|
|
474
|
-
}, renderProps: renderProps, generatorName: "slotLaneContent", customGenerator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount }, (InnerContent) => (preact_cjs.createElement(InnerContent, { tag: "div", className: 'fc-cell-inner',
|
|
474
|
+
}, renderProps: renderProps, generatorName: "slotLaneContent", customGenerator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount }, (InnerContent) => (preact_cjs.createElement(InnerContent, { tag: "div", className: 'fc-cell-inner', style: {
|
|
475
|
+
// HACK for Safari 16.4,
|
|
476
|
+
// which can't use ResizeObserver on elements with natural width 0
|
|
477
|
+
minWidth: 1,
|
|
478
|
+
}, elRef: this.innerElRef }))));
|
|
475
479
|
}
|
|
476
480
|
componentDidMount() {
|
|
477
481
|
const innerEl = this.innerElRef.current;
|
|
@@ -506,7 +510,7 @@ class TimelineSlats extends internal_cjs.BaseComponent {
|
|
|
506
510
|
let { tDateProfile, slotWidth } = props;
|
|
507
511
|
let { slotDates, isWeekStarts } = tDateProfile;
|
|
508
512
|
let isDay = !tDateProfile.isTimeScale && !tDateProfile.largeUnit;
|
|
509
|
-
return (preact_cjs.createElement("div", { className: "fc-timeline-slots fc-
|
|
513
|
+
return (preact_cjs.createElement("div", { "aria-hidden": true, className: "fc-timeline-slots fc-flex-row fc-fill", style: { height: props.height } }, slotDates.map((slotDate, i) => {
|
|
510
514
|
let key = slotDate.toISOString();
|
|
511
515
|
return (preact_cjs.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),
|
|
512
516
|
// ref
|
|
@@ -517,50 +521,132 @@ class TimelineSlats extends internal_cjs.BaseComponent {
|
|
|
517
521
|
}
|
|
518
522
|
}
|
|
519
523
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
//
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
return 0;
|
|
524
|
+
class TimelineHeaderCell extends internal_cjs.BaseComponent {
|
|
525
|
+
constructor() {
|
|
526
|
+
super(...arguments);
|
|
527
|
+
// memo
|
|
528
|
+
this.refineRenderProps = internal_cjs.memoizeObjArg(refineRenderProps);
|
|
529
|
+
// ref
|
|
530
|
+
this.innerElRef = preact_cjs.createRef();
|
|
528
531
|
}
|
|
529
|
-
|
|
530
|
-
|
|
532
|
+
render() {
|
|
533
|
+
let { props, context } = this;
|
|
534
|
+
let { dateEnv, options } = context;
|
|
535
|
+
let { cell, dateProfile, tDateProfile } = props;
|
|
536
|
+
// the cell.rowUnit is f'd
|
|
537
|
+
// giving 'month' for a 3-day view
|
|
538
|
+
// workaround: to infer day, do NOT time
|
|
539
|
+
let dateMeta = internal_cjs.getDateMeta(cell.date, props.todayRange, props.nowDate, dateProfile);
|
|
540
|
+
let renderProps = this.refineRenderProps({
|
|
541
|
+
level: props.rowLevel,
|
|
542
|
+
dateMarker: cell.date,
|
|
543
|
+
text: cell.text,
|
|
544
|
+
dateEnv: context.dateEnv,
|
|
545
|
+
viewApi: context.viewApi,
|
|
546
|
+
});
|
|
547
|
+
let isNavLink = !dateMeta.isDisabled && (cell.rowUnit && cell.rowUnit !== 'time');
|
|
548
|
+
return (preact_cjs.createElement(internal_cjs.ContentContainer, { tag: "div", className: internal_cjs.joinClassNames('fc-timeline-slot-label fc-timeline-slot', cell.isWeekStart && 'fc-timeline-slot-em', // TODO: document this semantic className
|
|
549
|
+
'fc-header-cell fc-cell fc-flex-col fc-justify-center', props.borderStart && 'fc-border-s', props.isCentered ? 'fc-align-center' : 'fc-align-start',
|
|
550
|
+
// TODO: so slot classnames for week/month/bigger. see note above about rowUnit
|
|
551
|
+
cell.rowUnit === 'time' ?
|
|
552
|
+
internal_cjs.getSlotClassName(dateMeta) :
|
|
553
|
+
internal_cjs.getDayClassName(dateMeta)), attrs: Object.assign({ 'data-date': dateEnv.formatIso(cell.date, {
|
|
554
|
+
omitTime: !tDateProfile.isTimeScale,
|
|
555
|
+
omitTimeZoneOffset: true,
|
|
556
|
+
}) }, (dateMeta.isToday ? { 'aria-current': 'date' } : {})), style: {
|
|
557
|
+
width: props.slotWidth != null
|
|
558
|
+
? props.slotWidth * cell.colspan
|
|
559
|
+
: undefined,
|
|
560
|
+
}, renderProps: renderProps, generatorName: "slotLabelContent", customGenerator: options.slotLabelContent, defaultGenerator: renderInnerContent, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (preact_cjs.createElement(InnerContent, { tag: 'div', attrs: isNavLink
|
|
561
|
+
// not tabbable because parent is aria-hidden
|
|
562
|
+
? internal_cjs.buildNavLinkAttrs(context, cell.date, cell.rowUnit, undefined, /* isTabbable = */ false)
|
|
563
|
+
: {} // don't bother with aria-hidden because parent already hidden
|
|
564
|
+
, className: internal_cjs.joinClassNames('fc-cell-inner fc-padding-md', props.isSticky && 'fc-sticky-s'), elRef: this.innerElRef }))));
|
|
531
565
|
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
566
|
+
componentDidMount() {
|
|
567
|
+
const { props } = this;
|
|
568
|
+
const innerEl = this.innerElRef.current; // TODO: make dynamic with useEffect
|
|
569
|
+
this.detachSize = internal_cjs.watchSize(innerEl, (width, height) => {
|
|
570
|
+
internal_cjs.setRef(props.innerWidthRef, width);
|
|
571
|
+
internal_cjs.setRef(props.innerHeightRef, height);
|
|
572
|
+
// HACK for sticky-centering
|
|
573
|
+
innerEl.style.left = innerEl.style.right =
|
|
574
|
+
(props.isCentered && props.isSticky)
|
|
575
|
+
? `calc(50% - ${width / 2}px)`
|
|
576
|
+
: '';
|
|
577
|
+
});
|
|
536
578
|
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
579
|
+
componentWillUnmount() {
|
|
580
|
+
const { props } = this;
|
|
581
|
+
this.detachSize();
|
|
582
|
+
internal_cjs.setRef(props.innerWidthRef, null);
|
|
583
|
+
internal_cjs.setRef(props.innerHeightRef, null);
|
|
541
584
|
}
|
|
542
|
-
return snapCoverage;
|
|
543
585
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
if (!hcoord) {
|
|
549
|
-
return {};
|
|
550
|
-
}
|
|
551
|
-
if (isRtl) {
|
|
552
|
-
return { right: hcoord.start, width: hcoord.size };
|
|
553
|
-
}
|
|
554
|
-
else {
|
|
555
|
-
return { left: hcoord.start, width: hcoord.size };
|
|
556
|
-
}
|
|
586
|
+
// Utils
|
|
587
|
+
// -------------------------------------------------------------------------------------------------
|
|
588
|
+
function renderInnerContent(renderProps) {
|
|
589
|
+
return renderProps.text;
|
|
557
590
|
}
|
|
558
|
-
function
|
|
559
|
-
|
|
560
|
-
|
|
591
|
+
function refineRenderProps(input) {
|
|
592
|
+
return {
|
|
593
|
+
level: input.level,
|
|
594
|
+
date: input.dateEnv.toDate(input.dateMarker),
|
|
595
|
+
view: input.viewApi,
|
|
596
|
+
text: input.text,
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
class TimelineHeaderRow extends internal_cjs.BaseComponent {
|
|
601
|
+
constructor() {
|
|
602
|
+
super(...arguments);
|
|
603
|
+
// refs
|
|
604
|
+
this.innerWidthRefMap = new internal_cjs.RefMap(() => {
|
|
605
|
+
internal_cjs.afterSize(this.handleInnerWidths);
|
|
606
|
+
});
|
|
607
|
+
this.innerHeightRefMap = new internal_cjs.RefMap(() => {
|
|
608
|
+
internal_cjs.afterSize(this.handleInnerHeights);
|
|
609
|
+
});
|
|
610
|
+
this.handleInnerWidths = () => {
|
|
611
|
+
const innerWidthMap = this.innerWidthRefMap.current;
|
|
612
|
+
let max = 0;
|
|
613
|
+
for (const innerWidth of innerWidthMap.values()) {
|
|
614
|
+
max = Math.max(max, innerWidth);
|
|
615
|
+
}
|
|
616
|
+
// TODO: ensure not equal?
|
|
617
|
+
internal_cjs.setRef(this.props.innerWidthRef, max);
|
|
618
|
+
};
|
|
619
|
+
this.handleInnerHeights = () => {
|
|
620
|
+
const innerHeightMap = this.innerHeightRefMap.current;
|
|
621
|
+
let max = 0;
|
|
622
|
+
for (const innerHeight of innerHeightMap.values()) {
|
|
623
|
+
max = Math.max(max, innerHeight);
|
|
624
|
+
}
|
|
625
|
+
// TODO: ensure not equal?
|
|
626
|
+
internal_cjs.setRef(this.props.innerHeighRef, max);
|
|
627
|
+
};
|
|
561
628
|
}
|
|
562
|
-
|
|
563
|
-
|
|
629
|
+
render() {
|
|
630
|
+
const { props, innerWidthRefMap, innerHeightRefMap } = this;
|
|
631
|
+
const isCentered = !(props.tDateProfile.isTimeScale && props.isLastRow);
|
|
632
|
+
const isSticky = !props.isLastRow;
|
|
633
|
+
return (preact_cjs.createElement("div", { className: internal_cjs.joinClassNames('fc-flex-row fc-grow', // TODO: move fc-grow to parent?
|
|
634
|
+
!props.isLastRow && 'fc-border-b') }, props.cells.map((cell, cellI) => {
|
|
635
|
+
// TODO: make this part of the cell obj?
|
|
636
|
+
// TODO: rowUnit seems wrong sometimes. says 'month' when it should be day
|
|
637
|
+
// TODO: rowUnit is relevant to whole row. put it on a row object, not the cells
|
|
638
|
+
// TODO: use rowUnit to key the Row itself?
|
|
639
|
+
const key = cell.rowUnit + ':' + cell.date.toISOString();
|
|
640
|
+
return (preact_cjs.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),
|
|
641
|
+
// refs
|
|
642
|
+
innerWidthRef: innerWidthRefMap.createRef(key), innerHeightRef: innerHeightRefMap.createRef(key),
|
|
643
|
+
// dimensions
|
|
644
|
+
slotWidth: props.slotWidth }));
|
|
645
|
+
})));
|
|
646
|
+
}
|
|
647
|
+
componentWillUnmount() {
|
|
648
|
+
internal_cjs.setRef(this.props.innerWidthRef, null);
|
|
649
|
+
internal_cjs.setRef(this.props.innerHeighRef, null);
|
|
564
650
|
}
|
|
565
651
|
}
|
|
566
652
|
|
|
@@ -615,13 +701,38 @@ time, dateEnv, dateProfile, tDateProfile, slowWidth) {
|
|
|
615
701
|
}
|
|
616
702
|
function dateToCoord(// pixels
|
|
617
703
|
date, dateEnv, tDateProfile, slotWidth) {
|
|
618
|
-
let snapCoverage = computeDateSnapCoverage(date, tDateProfile, dateEnv);
|
|
704
|
+
let snapCoverage = computeDateSnapCoverage$1(date, tDateProfile, dateEnv);
|
|
619
705
|
let slotCoverage = snapCoverage / tDateProfile.snapsPerSlot;
|
|
620
706
|
return slotCoverage * slotWidth;
|
|
621
707
|
}
|
|
622
708
|
/*
|
|
623
709
|
returned value is between 0 and the number of snaps
|
|
624
710
|
*/
|
|
711
|
+
function computeDateSnapCoverage$1(date, tDateProfile, dateEnv) {
|
|
712
|
+
let snapDiff = dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.snapDuration);
|
|
713
|
+
if (snapDiff < 0) {
|
|
714
|
+
return 0;
|
|
715
|
+
}
|
|
716
|
+
if (snapDiff >= tDateProfile.snapDiffToIndex.length) {
|
|
717
|
+
return tDateProfile.snapCnt;
|
|
718
|
+
}
|
|
719
|
+
let snapDiffInt = Math.floor(snapDiff);
|
|
720
|
+
let snapCoverage = tDateProfile.snapDiffToIndex[snapDiffInt];
|
|
721
|
+
if (internal_cjs.isInt(snapCoverage)) { // not an in-between value
|
|
722
|
+
snapCoverage += snapDiff - snapDiffInt; // add the remainder
|
|
723
|
+
}
|
|
724
|
+
else {
|
|
725
|
+
// a fractional value, meaning the date is not visible
|
|
726
|
+
// always round up in this case. works for start AND end dates in a range.
|
|
727
|
+
snapCoverage = Math.ceil(snapCoverage);
|
|
728
|
+
}
|
|
729
|
+
return snapCoverage;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/*
|
|
733
|
+
TODO: rename this file!
|
|
734
|
+
*/
|
|
735
|
+
// returned value is between 0 and the number of snaps
|
|
625
736
|
function computeDateSnapCoverage(date, tDateProfile, dateEnv) {
|
|
626
737
|
let snapDiff = dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.snapDuration);
|
|
627
738
|
if (snapDiff < 0) {
|
|
@@ -640,7 +751,107 @@ function computeDateSnapCoverage(date, tDateProfile, dateEnv) {
|
|
|
640
751
|
// always round up in this case. works for start AND end dates in a range.
|
|
641
752
|
snapCoverage = Math.ceil(snapCoverage);
|
|
642
753
|
}
|
|
643
|
-
return snapCoverage;
|
|
754
|
+
return snapCoverage;
|
|
755
|
+
}
|
|
756
|
+
/*
|
|
757
|
+
TODO: DRY up with elsewhere?
|
|
758
|
+
*/
|
|
759
|
+
function horizontalsToCss(hcoord, isRtl) {
|
|
760
|
+
if (!hcoord) {
|
|
761
|
+
return {};
|
|
762
|
+
}
|
|
763
|
+
if (isRtl) {
|
|
764
|
+
return { right: hcoord.start, width: hcoord.size };
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
return { left: hcoord.start, width: hcoord.size };
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
function horizontalCoordToCss(start, isRtl) {
|
|
771
|
+
if (isRtl) {
|
|
772
|
+
return { right: start };
|
|
773
|
+
}
|
|
774
|
+
else {
|
|
775
|
+
return { left: start };
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
class TimelineNowIndicatorLine extends internal_cjs.BaseComponent {
|
|
780
|
+
render() {
|
|
781
|
+
const { props, context } = this;
|
|
782
|
+
return (preact_cjs.createElement("div", { className: "fc-timeline-now-indicator-container" },
|
|
783
|
+
preact_cjs.createElement(internal_cjs.NowIndicatorContainer // TODO: make separate component?
|
|
784
|
+
, { className: 'fc-timeline-now-indicator-line', style: props.slotWidth != null
|
|
785
|
+
? horizontalCoordToCss(dateToCoord(props.nowDate, context.dateEnv, props.tDateProfile, props.slotWidth), context.isRtl)
|
|
786
|
+
: {}, isAxis: false, date: props.nowDate })));
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
class TimelineNowIndicatorArrow extends internal_cjs.BaseComponent {
|
|
791
|
+
render() {
|
|
792
|
+
const { props, context } = this;
|
|
793
|
+
return (preact_cjs.createElement("div", { className: "fc-timeline-now-indicator-container" },
|
|
794
|
+
preact_cjs.createElement(internal_cjs.NowIndicatorContainer, { className: 'fc-timeline-now-indicator-arrow', style: props.slotWidth != null
|
|
795
|
+
? horizontalCoordToCss(dateToCoord(props.nowDate, context.dateEnv, props.tDateProfile, props.slotWidth), context.isRtl)
|
|
796
|
+
: {}, isAxis: true, date: props.nowDate })));
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
function getTimelineSlotEl(parentEl, index) {
|
|
801
|
+
return parentEl.querySelectorAll('.fc-timeline-slot')[index];
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
class TimelineLaneSlicer extends internal_cjs.Slicer {
|
|
805
|
+
sliceRange(origRange, dateProfile, dateProfileGenerator, tDateProfile, dateEnv) {
|
|
806
|
+
let normalRange = normalizeRange(origRange, tDateProfile, dateEnv);
|
|
807
|
+
let segs = [];
|
|
808
|
+
// protect against when the span is entirely in an invalid date region
|
|
809
|
+
if (computeDateSnapCoverage(normalRange.start, tDateProfile, dateEnv)
|
|
810
|
+
< computeDateSnapCoverage(normalRange.end, tDateProfile, dateEnv)) {
|
|
811
|
+
// intersect the footprint's range with the grid's range
|
|
812
|
+
let slicedRange = internal_cjs.intersectRanges(normalRange, tDateProfile.normalizedRange);
|
|
813
|
+
if (slicedRange) {
|
|
814
|
+
segs.push({
|
|
815
|
+
startDate: slicedRange.start,
|
|
816
|
+
endDate: slicedRange.end,
|
|
817
|
+
isStart: slicedRange.start.valueOf() === normalRange.start.valueOf()
|
|
818
|
+
&& isValidDate(slicedRange.start, tDateProfile, dateProfile, dateProfileGenerator),
|
|
819
|
+
isEnd: slicedRange.end.valueOf() === normalRange.end.valueOf()
|
|
820
|
+
&& isValidDate(internal_cjs.addMs(slicedRange.end, -1), tDateProfile, dateProfile, dateProfileGenerator),
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
return segs;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
const DEFAULT_TIME_FORMAT = internal_cjs.createFormatter({
|
|
829
|
+
hour: 'numeric',
|
|
830
|
+
minute: '2-digit',
|
|
831
|
+
omitZeroMinute: true,
|
|
832
|
+
meridiem: 'narrow',
|
|
833
|
+
});
|
|
834
|
+
class TimelineEvent extends internal_cjs.BaseComponent {
|
|
835
|
+
render() {
|
|
836
|
+
let { props, context } = this;
|
|
837
|
+
let { options } = context;
|
|
838
|
+
return (preact_cjs.createElement(internal_cjs.StandardEvent, Object.assign({}, props, { className: internal_cjs.joinClassNames('fc-timeline-event', options.eventOverlap === false // TODO: fix bad default
|
|
839
|
+
&& 'fc-timeline-event-spacious', 'fc-h-event'), defaultTimeFormat: DEFAULT_TIME_FORMAT, defaultDisplayEventTime: !props.isTimeScale })));
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
class TimelineLaneMoreLink extends internal_cjs.BaseComponent {
|
|
844
|
+
render() {
|
|
845
|
+
let { props } = this;
|
|
846
|
+
let { hiddenSegs, resourceId, forcedInvisibleMap } = props;
|
|
847
|
+
let dateSpanProps = resourceId ? { resourceId } : {};
|
|
848
|
+
return (preact_cjs.createElement(internal_cjs.MoreLinkContainer, { className: 'fc-timeline-more-link', allDayDate: null, segs: hiddenSegs, hiddenSegs: hiddenSegs, dateProfile: props.dateProfile, todayRange: props.todayRange, dateSpanProps: dateSpanProps, popoverContent: () => (preact_cjs.createElement(preact_cjs.Fragment, null, hiddenSegs.map((seg) => {
|
|
849
|
+
let { eventRange } = seg;
|
|
850
|
+
let instanceId = eventRange.instance.instanceId;
|
|
851
|
+
return (preact_cjs.createElement("div", { key: instanceId, style: { visibility: forcedInvisibleMap[instanceId] ? 'hidden' : '' } },
|
|
852
|
+
preact_cjs.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_cjs.getEventRangeMeta(eventRange, props.todayRange, props.nowDate)))));
|
|
853
|
+
}))) }, (InnerContent) => (preact_cjs.createElement(InnerContent, { tag: "div", className: 'fc-timeline-more-link-inner fc-sticky-s' }))));
|
|
854
|
+
}
|
|
644
855
|
}
|
|
645
856
|
|
|
646
857
|
function computeManySegHorizontals(segs, segMinWidth, dateEnv, tDateProfile, slotWidth) {
|
|
@@ -707,83 +918,6 @@ hiddenGroupHeights, strictOrder, maxDepth) {
|
|
|
707
918
|
];
|
|
708
919
|
}
|
|
709
920
|
|
|
710
|
-
class TimelineLaneBg extends internal_cjs.BaseComponent {
|
|
711
|
-
render() {
|
|
712
|
-
let { props } = this;
|
|
713
|
-
let highlightSeg = [].concat(props.eventResizeSegs, props.dateSelectionSegs);
|
|
714
|
-
return (preact_cjs.createElement(preact_cjs.Fragment, null,
|
|
715
|
-
this.renderSegs(props.businessHourSegs || [], 'non-business'),
|
|
716
|
-
this.renderSegs(props.bgEventSegs || [], 'bg-event'),
|
|
717
|
-
this.renderSegs(highlightSeg, 'highlight')));
|
|
718
|
-
}
|
|
719
|
-
renderSegs(segs, fillType) {
|
|
720
|
-
let { tDateProfile, todayRange, nowDate, slotWidth } = this.props;
|
|
721
|
-
let { dateEnv, isRtl } = this.context;
|
|
722
|
-
return (preact_cjs.createElement(preact_cjs.Fragment, null, segs.map((seg) => {
|
|
723
|
-
let hStyle; // TODO
|
|
724
|
-
if (slotWidth != null) {
|
|
725
|
-
let segHorizontal = computeSegHorizontals(seg, undefined, dateEnv, tDateProfile, slotWidth);
|
|
726
|
-
hStyle = horizontalsToCss(segHorizontal, isRtl);
|
|
727
|
-
}
|
|
728
|
-
return (preact_cjs.createElement("div", { key: internal_cjs.buildEventRangeKey(seg.eventRange), className: "fc-fill-y", style: hStyle }, fillType === 'bg-event' ?
|
|
729
|
-
preact_cjs.createElement(internal_cjs.BgEvent, Object.assign({ eventRange: seg.eventRange, isStart: seg.isStart, isEnd: seg.isEnd }, internal_cjs.getEventRangeMeta(seg.eventRange, todayRange, nowDate))) : (internal_cjs.renderFill(fillType))));
|
|
730
|
-
})));
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
class TimelineLaneSlicer extends internal_cjs.Slicer {
|
|
735
|
-
sliceRange(origRange, dateProfile, dateProfileGenerator, tDateProfile, dateEnv) {
|
|
736
|
-
let normalRange = normalizeRange(origRange, tDateProfile, dateEnv);
|
|
737
|
-
let segs = [];
|
|
738
|
-
// protect against when the span is entirely in an invalid date region
|
|
739
|
-
if (computeDateSnapCoverage$1(normalRange.start, tDateProfile, dateEnv)
|
|
740
|
-
< computeDateSnapCoverage$1(normalRange.end, tDateProfile, dateEnv)) {
|
|
741
|
-
// intersect the footprint's range with the grid's range
|
|
742
|
-
let slicedRange = internal_cjs.intersectRanges(normalRange, tDateProfile.normalizedRange);
|
|
743
|
-
if (slicedRange) {
|
|
744
|
-
segs.push({
|
|
745
|
-
startDate: slicedRange.start,
|
|
746
|
-
endDate: slicedRange.end,
|
|
747
|
-
isStart: slicedRange.start.valueOf() === normalRange.start.valueOf()
|
|
748
|
-
&& isValidDate(slicedRange.start, tDateProfile, dateProfile, dateProfileGenerator),
|
|
749
|
-
isEnd: slicedRange.end.valueOf() === normalRange.end.valueOf()
|
|
750
|
-
&& isValidDate(internal_cjs.addMs(slicedRange.end, -1), tDateProfile, dateProfile, dateProfileGenerator),
|
|
751
|
-
});
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
return segs;
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
const DEFAULT_TIME_FORMAT = internal_cjs.createFormatter({
|
|
759
|
-
hour: 'numeric',
|
|
760
|
-
minute: '2-digit',
|
|
761
|
-
omitZeroMinute: true,
|
|
762
|
-
meridiem: 'narrow',
|
|
763
|
-
});
|
|
764
|
-
class TimelineEvent extends internal_cjs.BaseComponent {
|
|
765
|
-
render() {
|
|
766
|
-
let { props, context } = this;
|
|
767
|
-
let { options } = context;
|
|
768
|
-
return (preact_cjs.createElement(internal_cjs.StandardEvent, Object.assign({}, props, { className: internal_cjs.joinClassNames('fc-timeline-event', options.eventOverlap === false // TODO: fix bad default
|
|
769
|
-
&& 'fc-timeline-event-spacious', 'fc-h-event'), defaultTimeFormat: DEFAULT_TIME_FORMAT, defaultDisplayEventTime: !props.isTimeScale })));
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
class TimelineLaneMoreLink extends internal_cjs.BaseComponent {
|
|
774
|
-
render() {
|
|
775
|
-
let { props } = this;
|
|
776
|
-
let { hiddenSegs, resourceId, forcedInvisibleMap } = props;
|
|
777
|
-
let dateSpanProps = resourceId ? { resourceId } : {};
|
|
778
|
-
return (preact_cjs.createElement(internal_cjs.MoreLinkContainer, { className: 'fc-timeline-more-link', allDayDate: null, segs: hiddenSegs, hiddenSegs: hiddenSegs, dateProfile: props.dateProfile, todayRange: props.todayRange, dateSpanProps: dateSpanProps, popoverContent: () => (preact_cjs.createElement(preact_cjs.Fragment, null, hiddenSegs.map((seg) => {
|
|
779
|
-
let { eventRange } = seg;
|
|
780
|
-
let instanceId = eventRange.instance.instanceId;
|
|
781
|
-
return (preact_cjs.createElement("div", { key: instanceId, style: { visibility: forcedInvisibleMap[instanceId] ? 'hidden' : '' } },
|
|
782
|
-
preact_cjs.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_cjs.getEventRangeMeta(eventRange, props.todayRange, props.nowDate)))));
|
|
783
|
-
}))) }, (InnerContent) => (preact_cjs.createElement(InnerContent, { tag: "div", className: 'fc-timeline-more-link-inner fc-sticky-s' }))));
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
|
|
787
921
|
/*
|
|
788
922
|
TODO: make DRY with other Event Harnesses
|
|
789
923
|
*/
|
|
@@ -809,10 +943,7 @@ class TimelineEventHarness extends preact_cjs.Component {
|
|
|
809
943
|
}
|
|
810
944
|
}
|
|
811
945
|
|
|
812
|
-
|
|
813
|
-
TODO: split TimelineLaneBg and TimelineLaneFg?
|
|
814
|
-
*/
|
|
815
|
-
class TimelineLane extends internal_cjs.BaseComponent {
|
|
946
|
+
class TimelineFg extends internal_cjs.BaseComponent {
|
|
816
947
|
constructor() {
|
|
817
948
|
super(...arguments);
|
|
818
949
|
// memo
|
|
@@ -824,8 +955,6 @@ class TimelineLane extends internal_cjs.BaseComponent {
|
|
|
824
955
|
this.moreLinkHeightRefMap = new internal_cjs.RefMap(() => {
|
|
825
956
|
internal_cjs.afterSize(this.handleMoreLinkHeights);
|
|
826
957
|
});
|
|
827
|
-
// internal
|
|
828
|
-
this.slicer = new TimelineLaneSlicer();
|
|
829
958
|
this.handleMoreLinkHeights = () => {
|
|
830
959
|
this.setState({ moreLinkHeightRev: this.moreLinkHeightRefMap.rev }); // will trigger rerender
|
|
831
960
|
};
|
|
@@ -839,39 +968,30 @@ class TimelineLane extends internal_cjs.BaseComponent {
|
|
|
839
968
|
render() {
|
|
840
969
|
let { props, context, segHeightRefMap, moreLinkHeightRefMap } = this;
|
|
841
970
|
let { options } = context;
|
|
842
|
-
let {
|
|
843
|
-
let
|
|
844
|
-
|
|
845
|
-
let mirrorSegs = (slicedProps.eventDrag ? slicedProps.eventDrag.segs : null) ||
|
|
846
|
-
(slicedProps.eventResize ? slicedProps.eventResize.segs : null) ||
|
|
971
|
+
let { tDateProfile } = props;
|
|
972
|
+
let mirrorSegs = (props.eventDrag ? props.eventDrag.segs : null) ||
|
|
973
|
+
(props.eventResize ? props.eventResize.segs : null) ||
|
|
847
974
|
[];
|
|
848
|
-
let fgSegs = this.sortEventSegs(
|
|
975
|
+
let fgSegs = this.sortEventSegs(props.fgEventSegs, options.eventOrder);
|
|
849
976
|
let fgSegHorizontals = props.slotWidth != null
|
|
850
977
|
? computeManySegHorizontals(fgSegs, options.eventMinWidth, context.dateEnv, tDateProfile, props.slotWidth)
|
|
851
978
|
: {};
|
|
852
979
|
let [fgSegTops, hiddenGroups, hiddenGroupTops, totalHeight] = computeFgSegPlacements(fgSegs, fgSegHorizontals, segHeightRefMap.current, moreLinkHeightRefMap.current, options.eventOrderStrict, options.eventMaxStack);
|
|
980
|
+
this.totalHeight = totalHeight;
|
|
853
981
|
let forcedInvisibleMap = // TODO: more convenient/DRY
|
|
854
|
-
(
|
|
855
|
-
(
|
|
982
|
+
(props.eventDrag ? props.eventDrag.affectedInstances : null) ||
|
|
983
|
+
(props.eventResize ? props.eventResize.affectedInstances : null) ||
|
|
856
984
|
{};
|
|
857
|
-
return (preact_cjs.createElement(
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
false, // isResizing
|
|
868
|
-
false),
|
|
869
|
-
this.renderFgSegs(mirrorSegs, props.slotWidth // TODO: memoize
|
|
870
|
-
? computeManySegHorizontals(mirrorSegs, options.eventMinWidth, context.dateEnv, tDateProfile, props.slotWidth)
|
|
871
|
-
: {}, fgSegTops, {}, // forcedInvisibleMap
|
|
872
|
-
[], // hiddenGroups
|
|
873
|
-
new Map(), // hiddenGroupTops
|
|
874
|
-
Boolean(slicedProps.eventDrag), Boolean(slicedProps.eventResize), false))));
|
|
985
|
+
return (preact_cjs.createElement("div", { className: 'fc-timeline-events fc-rel', style: { height: totalHeight } },
|
|
986
|
+
this.renderFgSegs(fgSegs, fgSegHorizontals, fgSegTops, forcedInvisibleMap, hiddenGroups, hiddenGroupTops, false, // isDragging
|
|
987
|
+
false, // isResizing
|
|
988
|
+
false),
|
|
989
|
+
this.renderFgSegs(mirrorSegs, props.slotWidth // TODO: memoize
|
|
990
|
+
? computeManySegHorizontals(mirrorSegs, options.eventMinWidth, context.dateEnv, tDateProfile, props.slotWidth)
|
|
991
|
+
: {}, fgSegTops, {}, // forcedInvisibleMap
|
|
992
|
+
[], // hiddenGroups
|
|
993
|
+
new Map(), // hiddenGroupTops
|
|
994
|
+
Boolean(props.eventDrag), Boolean(props.eventResize), false)));
|
|
875
995
|
}
|
|
876
996
|
renderFgSegs(segs, segHorizontals, segTops, forcedInvisibleMap, hiddenGroups, hiddenGroupTops, isDragging, isResizing, isDateSelecting) {
|
|
877
997
|
let { props, context, segHeightRefMap, moreLinkHeightRefMap } = this;
|
|
@@ -893,158 +1013,43 @@ class TimelineLane extends internal_cjs.BaseComponent {
|
|
|
893
1013
|
}, context.isRtl)), heightRef: moreLinkHeightRefMap.createRef(hiddenGroup.key) },
|
|
894
1014
|
preact_cjs.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 }))))));
|
|
895
1015
|
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
constructor() {
|
|
900
|
-
super(...arguments);
|
|
901
|
-
// memo
|
|
902
|
-
this.refineRenderProps = internal_cjs.memoizeObjArg(refineRenderProps);
|
|
903
|
-
this.buildCellNavLinkAttrs = internal_cjs.memoize(buildCellNavLinkAttrs);
|
|
904
|
-
// ref
|
|
905
|
-
this.innerElRef = preact_cjs.createRef();
|
|
906
|
-
}
|
|
907
|
-
render() {
|
|
908
|
-
let { props, context } = this;
|
|
909
|
-
let { dateEnv, options } = context;
|
|
910
|
-
let { cell, dateProfile, tDateProfile } = props;
|
|
911
|
-
// the cell.rowUnit is f'd
|
|
912
|
-
// giving 'month' for a 3-day view
|
|
913
|
-
// workaround: to infer day, do NOT time
|
|
914
|
-
let dateMeta = internal_cjs.getDateMeta(cell.date, props.todayRange, props.nowDate, dateProfile);
|
|
915
|
-
let renderProps = this.refineRenderProps({
|
|
916
|
-
level: props.rowLevel,
|
|
917
|
-
dateMarker: cell.date,
|
|
918
|
-
text: cell.text,
|
|
919
|
-
dateEnv: context.dateEnv,
|
|
920
|
-
viewApi: context.viewApi,
|
|
921
|
-
});
|
|
922
|
-
return (preact_cjs.createElement(internal_cjs.ContentContainer, { tag: "div", className: internal_cjs.joinClassNames('fc-timeline-slot-label fc-timeline-slot', cell.isWeekStart && 'fc-timeline-slot-em', // TODO: document this semantic className
|
|
923
|
-
'fc-header-cell fc-cell fc-flex-col fc-justify-center', props.borderStart && 'fc-border-s', props.isCentered ? 'fc-align-center' : 'fc-align-start',
|
|
924
|
-
// TODO: so slot classnames for week/month/bigger. see note above about rowUnit
|
|
925
|
-
cell.rowUnit === 'time' ?
|
|
926
|
-
internal_cjs.getSlotClassName(dateMeta) :
|
|
927
|
-
internal_cjs.getDayClassName(dateMeta)), attrs: {
|
|
928
|
-
'data-date': dateEnv.formatIso(cell.date, {
|
|
929
|
-
omitTime: !tDateProfile.isTimeScale,
|
|
930
|
-
omitTimeZoneOffset: true,
|
|
931
|
-
}),
|
|
932
|
-
}, 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_cjs.createElement(InnerContent, { tag: "a", attrs: this.buildCellNavLinkAttrs(context, cell.date, cell.rowUnit), className: internal_cjs.joinClassNames('fc-cell-inner fc-padding-md', props.isSticky && 'fc-sticky-s'), elRef: this.innerElRef }))));
|
|
937
|
-
}
|
|
938
|
-
componentDidMount() {
|
|
939
|
-
const { props } = this;
|
|
940
|
-
const innerEl = this.innerElRef.current; // TODO: make dynamic with useEffect
|
|
941
|
-
this.detachSize = internal_cjs.watchSize(innerEl, (width, height) => {
|
|
942
|
-
internal_cjs.setRef(props.innerWidthRef, width);
|
|
943
|
-
internal_cjs.setRef(props.innerHeightRef, height);
|
|
944
|
-
// HACK for sticky-centering
|
|
945
|
-
innerEl.style.left = innerEl.style.right =
|
|
946
|
-
(props.isCentered && props.isSticky)
|
|
947
|
-
? `calc(50% - ${width / 2}px)`
|
|
948
|
-
: '';
|
|
949
|
-
});
|
|
950
|
-
}
|
|
951
|
-
componentWillUnmount() {
|
|
952
|
-
const { props } = this;
|
|
953
|
-
this.detachSize();
|
|
954
|
-
internal_cjs.setRef(props.innerWidthRef, null);
|
|
955
|
-
internal_cjs.setRef(props.innerHeightRef, null);
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
// Utils
|
|
959
|
-
// -------------------------------------------------------------------------------------------------
|
|
960
|
-
function buildCellNavLinkAttrs(context, cellDate, rowUnit) {
|
|
961
|
-
return (rowUnit && rowUnit !== 'time')
|
|
962
|
-
? internal_cjs.buildNavLinkAttrs(context, cellDate, rowUnit)
|
|
963
|
-
: {};
|
|
964
|
-
}
|
|
965
|
-
function renderInnerContent(renderProps) {
|
|
966
|
-
return renderProps.text;
|
|
967
|
-
}
|
|
968
|
-
function refineRenderProps(input) {
|
|
969
|
-
return {
|
|
970
|
-
level: input.level,
|
|
971
|
-
date: input.dateEnv.toDate(input.dateMarker),
|
|
972
|
-
view: input.viewApi,
|
|
973
|
-
text: input.text,
|
|
974
|
-
};
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
class TimelineHeaderRow extends internal_cjs.BaseComponent {
|
|
978
|
-
constructor() {
|
|
979
|
-
super(...arguments);
|
|
980
|
-
// refs
|
|
981
|
-
this.innerWidthRefMap = new internal_cjs.RefMap(() => {
|
|
982
|
-
internal_cjs.afterSize(this.handleInnerWidths);
|
|
983
|
-
});
|
|
984
|
-
this.innerHeightRefMap = new internal_cjs.RefMap(() => {
|
|
985
|
-
internal_cjs.afterSize(this.handleInnerHeights);
|
|
986
|
-
});
|
|
987
|
-
this.handleInnerWidths = () => {
|
|
988
|
-
const innerWidthMap = this.innerWidthRefMap.current;
|
|
989
|
-
let max = 0;
|
|
990
|
-
for (const innerWidth of innerWidthMap.values()) {
|
|
991
|
-
max = Math.max(max, innerWidth);
|
|
992
|
-
}
|
|
993
|
-
// TODO: ensure not equal?
|
|
994
|
-
internal_cjs.setRef(this.props.innerWidthRef, max);
|
|
995
|
-
};
|
|
996
|
-
this.handleInnerHeights = () => {
|
|
997
|
-
const innerHeightMap = this.innerHeightRefMap.current;
|
|
998
|
-
let max = 0;
|
|
999
|
-
for (const innerHeight of innerHeightMap.values()) {
|
|
1000
|
-
max = Math.max(max, innerHeight);
|
|
1001
|
-
}
|
|
1002
|
-
// TODO: ensure not equal?
|
|
1003
|
-
internal_cjs.setRef(this.props.innerHeighRef, max);
|
|
1004
|
-
};
|
|
1016
|
+
/*
|
|
1017
|
+
componentDidMount(): void {
|
|
1018
|
+
// might want to do firedTotalHeight, but won't be ready on first render
|
|
1005
1019
|
}
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
// TODO: make this part of the cell obj?
|
|
1013
|
-
// TODO: rowUnit seems wrong sometimes. says 'month' when it should be day
|
|
1014
|
-
// TODO: rowUnit is relevant to whole row. put it on a row object, not the cells
|
|
1015
|
-
// TODO: use rowUnit to key the Row itself?
|
|
1016
|
-
const key = cell.rowUnit + ':' + cell.date.toISOString();
|
|
1017
|
-
return (preact_cjs.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),
|
|
1018
|
-
// refs
|
|
1019
|
-
innerWidthRef: innerWidthRefMap.createRef(key), innerHeightRef: innerHeightRefMap.createRef(key),
|
|
1020
|
-
// dimensions
|
|
1021
|
-
slotWidth: props.slotWidth }));
|
|
1022
|
-
})));
|
|
1020
|
+
*/
|
|
1021
|
+
componentDidUpdate() {
|
|
1022
|
+
if (this.totalHeight !== this.firedTotalHeight) {
|
|
1023
|
+
this.firedTotalHeight = this.totalHeight;
|
|
1024
|
+
internal_cjs.setRef(this.props.heightRef, this.totalHeight);
|
|
1025
|
+
}
|
|
1023
1026
|
}
|
|
1024
1027
|
componentWillUnmount() {
|
|
1025
|
-
internal_cjs.setRef(this.props.
|
|
1026
|
-
internal_cjs.setRef(this.props.innerHeighRef, null);
|
|
1028
|
+
internal_cjs.setRef(this.props.heightRef, null);
|
|
1027
1029
|
}
|
|
1028
1030
|
}
|
|
1029
1031
|
|
|
1030
|
-
class
|
|
1032
|
+
class TimelineBg extends internal_cjs.BaseComponent {
|
|
1031
1033
|
render() {
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1034
|
+
let { props } = this;
|
|
1035
|
+
let highlightSeg = [].concat(props.eventResizeSegs || [], props.dateSelectionSegs);
|
|
1036
|
+
return (preact_cjs.createElement(preact_cjs.Fragment, null,
|
|
1037
|
+
this.renderSegs(props.businessHourSegs || [], 'non-business'),
|
|
1038
|
+
this.renderSegs(props.bgEventSegs || [], 'bg-event'),
|
|
1039
|
+
this.renderSegs(highlightSeg, 'highlight')));
|
|
1038
1040
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1041
|
+
renderSegs(segs, fillType) {
|
|
1042
|
+
let { tDateProfile, todayRange, nowDate, slotWidth } = this.props;
|
|
1043
|
+
let { dateEnv, isRtl } = this.context;
|
|
1044
|
+
return (preact_cjs.createElement(preact_cjs.Fragment, null, segs.map((seg) => {
|
|
1045
|
+
let hStyle; // TODO
|
|
1046
|
+
if (slotWidth != null) {
|
|
1047
|
+
let segHorizontal = computeSegHorizontals(seg, undefined, dateEnv, tDateProfile, slotWidth);
|
|
1048
|
+
hStyle = horizontalsToCss(segHorizontal, isRtl);
|
|
1049
|
+
}
|
|
1050
|
+
return (preact_cjs.createElement("div", { key: internal_cjs.buildEventRangeKey(seg.eventRange), className: "fc-fill-y", style: hStyle }, fillType === 'bg-event' ?
|
|
1051
|
+
preact_cjs.createElement(internal_cjs.BgEvent, Object.assign({ eventRange: seg.eventRange, isStart: seg.isStart, isEnd: seg.isEnd }, internal_cjs.getEventRangeMeta(seg.eventRange, todayRange, nowDate))) : (internal_cjs.renderFill(fillType))));
|
|
1052
|
+
})));
|
|
1048
1053
|
}
|
|
1049
1054
|
}
|
|
1050
1055
|
|
|
@@ -1062,6 +1067,7 @@ class TimelineView extends internal_cjs.DateComponent {
|
|
|
1062
1067
|
internal_cjs.afterSize(this.handleSlotInnerWidths);
|
|
1063
1068
|
});
|
|
1064
1069
|
this.scrollTime = null;
|
|
1070
|
+
this.slicer = new TimelineLaneSlicer();
|
|
1065
1071
|
// Sizing
|
|
1066
1072
|
// -----------------------------------------------------------------------------------------------
|
|
1067
1073
|
this.handleBodySlotInnerWidth = (innerWidth) => {
|
|
@@ -1069,39 +1075,34 @@ class TimelineView extends internal_cjs.DateComponent {
|
|
|
1069
1075
|
internal_cjs.afterSize(this.handleSlotInnerWidths);
|
|
1070
1076
|
};
|
|
1071
1077
|
this.handleSlotInnerWidths = () => {
|
|
1072
|
-
const
|
|
1073
|
-
const
|
|
1074
|
-
if (
|
|
1075
|
-
|
|
1078
|
+
const headerSlotInnerWidth = this.headerRowInnerWidthMap.current.get(this.tDateProfile.cellRows.length - 1);
|
|
1079
|
+
const { bodySlotInnerWidth } = this;
|
|
1080
|
+
if (headerSlotInnerWidth != null && bodySlotInnerWidth != null) {
|
|
1081
|
+
const slotInnerWidth = Math.max(headerSlotInnerWidth, bodySlotInnerWidth);
|
|
1082
|
+
if (slotInnerWidth !== this.state.slotInnerWidth) {
|
|
1083
|
+
this.setState({ slotInnerWidth });
|
|
1084
|
+
}
|
|
1076
1085
|
}
|
|
1077
1086
|
};
|
|
1078
|
-
this.
|
|
1087
|
+
this.handleTotalWidth = (totalWidth) => {
|
|
1079
1088
|
this.setState({
|
|
1080
|
-
|
|
1089
|
+
totalWidth,
|
|
1081
1090
|
});
|
|
1082
1091
|
};
|
|
1083
|
-
this.
|
|
1092
|
+
this.handleClientWidth = (clientWidth) => {
|
|
1084
1093
|
this.setState({
|
|
1085
|
-
|
|
1094
|
+
clientWidth,
|
|
1086
1095
|
});
|
|
1087
1096
|
};
|
|
1088
|
-
this.
|
|
1097
|
+
this.handleTimeScrollRequest = (scrollTime) => {
|
|
1089
1098
|
this.scrollTime = scrollTime;
|
|
1090
|
-
this.
|
|
1099
|
+
this.applyTimeScroll();
|
|
1091
1100
|
};
|
|
1092
|
-
this.
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
let x = timeToCoord(scrollTime, context.dateEnv, props.dateProfile, tDateProfile, slotWidth);
|
|
1096
|
-
if (x) {
|
|
1097
|
-
x += 1; // overcome border. TODO: DRY this up
|
|
1098
|
-
}
|
|
1099
|
-
this.syncedScroller.scrollTo({ x });
|
|
1101
|
+
this.handleTimeScrollEnd = (isUser) => {
|
|
1102
|
+
if (isUser) {
|
|
1103
|
+
this.scrollTime = null;
|
|
1100
1104
|
}
|
|
1101
1105
|
};
|
|
1102
|
-
this.clearScroll = () => {
|
|
1103
|
-
this.scrollTime = null;
|
|
1104
|
-
};
|
|
1105
1106
|
// Hit System
|
|
1106
1107
|
// -----------------------------------------------------------------------------------------------
|
|
1107
1108
|
this.handeBodyEl = (el) => {
|
|
@@ -1117,6 +1118,10 @@ class TimelineView extends internal_cjs.DateComponent {
|
|
|
1117
1118
|
render() {
|
|
1118
1119
|
const { props, state, context } = this;
|
|
1119
1120
|
const { options } = context;
|
|
1121
|
+
const { totalWidth, clientWidth } = state;
|
|
1122
|
+
const endScrollbarWidth = (totalWidth != null && clientWidth != null)
|
|
1123
|
+
? totalWidth - clientWidth
|
|
1124
|
+
: undefined;
|
|
1120
1125
|
/* date */
|
|
1121
1126
|
const tDateProfile = this.tDateProfile = this.buildTimelineDateProfile(props.dateProfile, context.dateEnv, options, context.dateProfileGenerator);
|
|
1122
1127
|
const { cellRows } = tDateProfile;
|
|
@@ -1127,8 +1132,11 @@ class TimelineView extends internal_cjs.DateComponent {
|
|
|
1127
1132
|
const stickyFooterScrollbar = !props.forPrint && internal_cjs.getStickyFooterScrollbar(options);
|
|
1128
1133
|
/* table positions */
|
|
1129
1134
|
const [canvasWidth, slotWidth] = this.computeSlotWidth(tDateProfile.slotCnt, tDateProfile.slotsPerLabel, options.slotMinWidth, state.slotInnerWidth, // is ACTUALLY the label width. rename?
|
|
1130
|
-
|
|
1135
|
+
clientWidth);
|
|
1131
1136
|
this.slotWidth = slotWidth;
|
|
1137
|
+
/* sliced */
|
|
1138
|
+
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...
|
|
1139
|
+
props.dateProfile, context.dateProfileGenerator, tDateProfile, context.dateEnv);
|
|
1132
1140
|
return (preact_cjs.createElement(internal_cjs.NowTimer, { unit: timerUnit }, (nowDate, todayRange) => {
|
|
1133
1141
|
const enableNowIndicator = // TODO: DRY
|
|
1134
1142
|
options.nowIndicator &&
|
|
@@ -1148,18 +1156,30 @@ class TimelineView extends internal_cjs.DateComponent {
|
|
|
1148
1156
|
return (preact_cjs.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) }));
|
|
1149
1157
|
}),
|
|
1150
1158
|
enableNowIndicator && (preact_cjs.createElement(TimelineNowIndicatorArrow, { tDateProfile: tDateProfile, nowDate: nowDate, slotWidth: slotWidth }))),
|
|
1151
|
-
Boolean(
|
|
1152
|
-
preact_cjs.createElement(internal_cjs.Scroller, { vertical: verticalScrolling, horizontal: true, hideScrollbars:
|
|
1153
|
-
|
|
1159
|
+
Boolean(endScrollbarWidth) && (preact_cjs.createElement("div", { className: 'fc-border-s fc-filler', style: { minWidth: endScrollbarWidth } }))),
|
|
1160
|
+
preact_cjs.createElement(internal_cjs.Scroller, { vertical: verticalScrolling, horizontal: true, hideScrollbars: stickyFooterScrollbar ||
|
|
1161
|
+
props.forPrint // prevents blank space in print-view on Safari
|
|
1162
|
+
, className: internal_cjs.joinClassNames('fc-timeline-body fc-flex-col', verticalScrolling && 'fc-liquid'), ref: this.bodyScrollerRef, clientWidthRef: this.handleClientWidth },
|
|
1163
|
+
preact_cjs.createElement("div", { "aria-label": options.eventsHint, className: "fc-rel fc-grow", style: { width: canvasWidth }, ref: this.handeBodyEl },
|
|
1154
1164
|
preact_cjs.createElement(TimelineSlats, { dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange,
|
|
1155
1165
|
// ref
|
|
1156
1166
|
innerWidthRef: this.handleBodySlotInnerWidth,
|
|
1157
1167
|
// dimensions
|
|
1158
1168
|
slotWidth: slotWidth }),
|
|
1159
|
-
preact_cjs.createElement(
|
|
1169
|
+
preact_cjs.createElement(TimelineBg, { tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange,
|
|
1170
|
+
// content
|
|
1171
|
+
bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventResizeSegs: slicedProps.eventResize ? slicedProps.eventResize.segs : null,
|
|
1172
|
+
// dimensions
|
|
1173
|
+
slotWidth: slotWidth }),
|
|
1174
|
+
preact_cjs.createElement(TimelineFg, { dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange,
|
|
1175
|
+
// content
|
|
1176
|
+
fgEventSegs: slicedProps.fgEventSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection,
|
|
1177
|
+
// dimensions
|
|
1178
|
+
slotWidth: slotWidth }),
|
|
1179
|
+
preact_cjs.createElement("div", { className: 'fc-timeline-lane-footer' }),
|
|
1160
1180
|
enableNowIndicator && (preact_cjs.createElement(TimelineNowIndicatorLine, { tDateProfile: tDateProfile, nowDate: nowDate, slotWidth: slotWidth })))),
|
|
1161
|
-
stickyFooterScrollbar && (preact_cjs.createElement(internal_cjs.
|
|
1162
|
-
|
|
1181
|
+
Boolean(stickyFooterScrollbar) && (preact_cjs.createElement(internal_cjs.FooterScrollbar, { isSticky: true, canvasWidth: canvasWidth, scrollerRef: this.footerScrollerRef })),
|
|
1182
|
+
preact_cjs.createElement(internal_cjs.Ruler, { widthRef: this.handleTotalWidth })));
|
|
1163
1183
|
}));
|
|
1164
1184
|
}
|
|
1165
1185
|
// Lifecycle
|
|
@@ -1168,8 +1188,8 @@ class TimelineView extends internal_cjs.DateComponent {
|
|
|
1168
1188
|
this.syncedScroller = new internal_cjs$1.ScrollerSyncer(true); // horizontal=true
|
|
1169
1189
|
this.updateSyncedScroller();
|
|
1170
1190
|
this.resetScroll();
|
|
1171
|
-
this.context.emitter.on('_timeScrollRequest', this.
|
|
1172
|
-
this.syncedScroller.addScrollEndListener(this.
|
|
1191
|
+
this.context.emitter.on('_timeScrollRequest', this.handleTimeScrollRequest);
|
|
1192
|
+
this.syncedScroller.addScrollEndListener(this.handleTimeScrollEnd);
|
|
1173
1193
|
}
|
|
1174
1194
|
componentDidUpdate(prevProps) {
|
|
1175
1195
|
this.updateSyncedScroller();
|
|
@@ -1178,13 +1198,13 @@ class TimelineView extends internal_cjs.DateComponent {
|
|
|
1178
1198
|
}
|
|
1179
1199
|
else {
|
|
1180
1200
|
// TODO: inefficient to update so often
|
|
1181
|
-
this.
|
|
1201
|
+
this.applyTimeScroll();
|
|
1182
1202
|
}
|
|
1183
1203
|
}
|
|
1184
1204
|
componentWillUnmount() {
|
|
1185
1205
|
this.syncedScroller.destroy();
|
|
1186
|
-
this.context.emitter.off('_timeScrollRequest', this.
|
|
1187
|
-
this.syncedScroller.removeScrollEndListener(this.
|
|
1206
|
+
this.context.emitter.off('_timeScrollRequest', this.handleTimeScrollRequest);
|
|
1207
|
+
this.syncedScroller.removeScrollEndListener(this.handleTimeScrollEnd);
|
|
1188
1208
|
}
|
|
1189
1209
|
// Scrolling
|
|
1190
1210
|
// -----------------------------------------------------------------------------------------------
|
|
@@ -1196,7 +1216,17 @@ class TimelineView extends internal_cjs.DateComponent {
|
|
|
1196
1216
|
]);
|
|
1197
1217
|
}
|
|
1198
1218
|
resetScroll() {
|
|
1199
|
-
this.
|
|
1219
|
+
this.handleTimeScrollRequest(this.context.options.scrollTime);
|
|
1220
|
+
}
|
|
1221
|
+
applyTimeScroll() {
|
|
1222
|
+
const { props, context, tDateProfile, scrollTime, slotWidth } = this;
|
|
1223
|
+
if (scrollTime != null && slotWidth != null) {
|
|
1224
|
+
let x = timeToCoord(scrollTime, context.dateEnv, props.dateProfile, tDateProfile, slotWidth);
|
|
1225
|
+
if (x) {
|
|
1226
|
+
x += 1; // overcome border. TODO: DRY this up
|
|
1227
|
+
}
|
|
1228
|
+
this.syncedScroller.scrollTo({ x });
|
|
1229
|
+
}
|
|
1200
1230
|
}
|
|
1201
1231
|
queryHit(positionLeft, positionTop, elWidth, elHeight) {
|
|
1202
1232
|
const { props, context, tDateProfile, slotWidth } = this;
|
|
@@ -1234,8 +1264,7 @@ class TimelineView extends internal_cjs.DateComponent {
|
|
|
1234
1264
|
top: 0,
|
|
1235
1265
|
bottom: elHeight,
|
|
1236
1266
|
},
|
|
1237
|
-
|
|
1238
|
-
dayEl: this.bodyEl.querySelectorAll('.fc-timeline-slot')[slatIndex],
|
|
1267
|
+
getDayEl: () => getTimelineSlotEl(this.bodyEl, slatIndex),
|
|
1239
1268
|
layer: 0,
|
|
1240
1269
|
};
|
|
1241
1270
|
}
|
|
@@ -1243,12 +1272,12 @@ class TimelineView extends internal_cjs.DateComponent {
|
|
|
1243
1272
|
}
|
|
1244
1273
|
}
|
|
1245
1274
|
|
|
1246
|
-
var css_248z = ".fc-timeline-
|
|
1275
|
+
var css_248z = ".fc-timeline-lane-footer{padding-bottom:10px}.fc-timeline-overlap-disabled .fc-timeline-lane-footer{padding-bottom:0}.fc-timeline-slot-minor{border-style:dotted}.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:2}.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}";
|
|
1247
1276
|
internal_cjs.injectStyles(css_248z);
|
|
1248
1277
|
|
|
1278
|
+
exports.TimelineBg = TimelineBg;
|
|
1279
|
+
exports.TimelineFg = TimelineFg;
|
|
1249
1280
|
exports.TimelineHeaderRow = TimelineHeaderRow;
|
|
1250
|
-
exports.TimelineLane = TimelineLane;
|
|
1251
|
-
exports.TimelineLaneBg = TimelineLaneBg;
|
|
1252
1281
|
exports.TimelineLaneSlicer = TimelineLaneSlicer;
|
|
1253
1282
|
exports.TimelineNowIndicatorArrow = TimelineNowIndicatorArrow;
|
|
1254
1283
|
exports.TimelineNowIndicatorLine = TimelineNowIndicatorLine;
|
|
@@ -1258,4 +1287,5 @@ exports.buildTimelineDateProfile = buildTimelineDateProfile;
|
|
|
1258
1287
|
exports.computeSlotWidth = computeSlotWidth;
|
|
1259
1288
|
exports.createHorizontalStyle = createHorizontalStyle;
|
|
1260
1289
|
exports.createVerticalStyle = createVerticalStyle;
|
|
1290
|
+
exports.getTimelineSlotEl = getTimelineSlotEl;
|
|
1261
1291
|
exports.timeToCoord = timeToCoord;
|