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