@fullcalendar/timeline 7.0.0-beta.4 → 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 +348 -315
- package/index.global.min.js +2 -2
- package/index.js +1 -1
- package/internal.cjs +345 -312
- package/internal.d.ts +21 -18
- package/internal.js +344 -312
- 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
|
|
@@ -473,7 +475,11 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
473
475
|
omitTime: !tDateProfile.isTimeScale,
|
|
474
476
|
}) }, (dateMeta.isToday ? { 'aria-current': 'date' } : {})), style: {
|
|
475
477
|
width: props.width,
|
|
476
|
-
}, 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 }))));
|
|
477
483
|
}
|
|
478
484
|
componentDidMount() {
|
|
479
485
|
const innerEl = this.innerElRef.current;
|
|
@@ -508,7 +514,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
508
514
|
let { tDateProfile, slotWidth } = props;
|
|
509
515
|
let { slotDates, isWeekStarts } = tDateProfile;
|
|
510
516
|
let isDay = !tDateProfile.isTimeScale && !tDateProfile.largeUnit;
|
|
511
|
-
return (preact.createElement("div", { "aria-hidden": true, 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) => {
|
|
512
518
|
let key = slotDate.toISOString();
|
|
513
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),
|
|
514
520
|
// ref
|
|
@@ -519,50 +525,132 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
519
525
|
}
|
|
520
526
|
}
|
|
521
527
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
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();
|
|
530
535
|
}
|
|
531
|
-
|
|
532
|
-
|
|
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 }))));
|
|
533
569
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
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
|
+
});
|
|
538
582
|
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
583
|
+
componentWillUnmount() {
|
|
584
|
+
const { props } = this;
|
|
585
|
+
this.detachSize();
|
|
586
|
+
internal$1.setRef(props.innerWidthRef, null);
|
|
587
|
+
internal$1.setRef(props.innerHeightRef, null);
|
|
543
588
|
}
|
|
544
|
-
return snapCoverage;
|
|
545
589
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
if (!hcoord) {
|
|
551
|
-
return {};
|
|
552
|
-
}
|
|
553
|
-
if (isRtl) {
|
|
554
|
-
return { right: hcoord.start, width: hcoord.size };
|
|
555
|
-
}
|
|
556
|
-
else {
|
|
557
|
-
return { left: hcoord.start, width: hcoord.size };
|
|
558
|
-
}
|
|
590
|
+
// Utils
|
|
591
|
+
// -------------------------------------------------------------------------------------------------
|
|
592
|
+
function renderInnerContent(renderProps) {
|
|
593
|
+
return renderProps.text;
|
|
559
594
|
}
|
|
560
|
-
function
|
|
561
|
-
|
|
562
|
-
|
|
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
|
+
};
|
|
563
632
|
}
|
|
564
|
-
|
|
565
|
-
|
|
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);
|
|
566
654
|
}
|
|
567
655
|
}
|
|
568
656
|
|
|
@@ -617,13 +705,38 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
617
705
|
}
|
|
618
706
|
function dateToCoord(// pixels
|
|
619
707
|
date, dateEnv, tDateProfile, slotWidth) {
|
|
620
|
-
let snapCoverage = computeDateSnapCoverage(date, tDateProfile, dateEnv);
|
|
708
|
+
let snapCoverage = computeDateSnapCoverage$1(date, tDateProfile, dateEnv);
|
|
621
709
|
let slotCoverage = snapCoverage / tDateProfile.snapsPerSlot;
|
|
622
710
|
return slotCoverage * slotWidth;
|
|
623
711
|
}
|
|
624
712
|
/*
|
|
625
713
|
returned value is between 0 and the number of snaps
|
|
626
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
|
|
627
740
|
function computeDateSnapCoverage(date, tDateProfile, dateEnv) {
|
|
628
741
|
let snapDiff = dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.snapDuration);
|
|
629
742
|
if (snapDiff < 0) {
|
|
@@ -642,7 +755,107 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
642
755
|
// always round up in this case. works for start AND end dates in a range.
|
|
643
756
|
snapCoverage = Math.ceil(snapCoverage);
|
|
644
757
|
}
|
|
645
|
-
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
|
+
}
|
|
646
859
|
}
|
|
647
860
|
|
|
648
861
|
function computeManySegHorizontals(segs, segMinWidth, dateEnv, tDateProfile, slotWidth) {
|
|
@@ -709,83 +922,6 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
709
922
|
];
|
|
710
923
|
}
|
|
711
924
|
|
|
712
|
-
class TimelineLaneBg extends internal$1.BaseComponent {
|
|
713
|
-
render() {
|
|
714
|
-
let { props } = this;
|
|
715
|
-
let highlightSeg = [].concat(props.eventResizeSegs, props.dateSelectionSegs);
|
|
716
|
-
return (preact.createElement(preact.Fragment, null,
|
|
717
|
-
this.renderSegs(props.businessHourSegs || [], 'non-business'),
|
|
718
|
-
this.renderSegs(props.bgEventSegs || [], 'bg-event'),
|
|
719
|
-
this.renderSegs(highlightSeg, 'highlight')));
|
|
720
|
-
}
|
|
721
|
-
renderSegs(segs, fillType) {
|
|
722
|
-
let { tDateProfile, todayRange, nowDate, slotWidth } = this.props;
|
|
723
|
-
let { dateEnv, isRtl } = this.context;
|
|
724
|
-
return (preact.createElement(preact.Fragment, null, segs.map((seg) => {
|
|
725
|
-
let hStyle; // TODO
|
|
726
|
-
if (slotWidth != null) {
|
|
727
|
-
let segHorizontal = computeSegHorizontals(seg, undefined, dateEnv, tDateProfile, slotWidth);
|
|
728
|
-
hStyle = horizontalsToCss(segHorizontal, isRtl);
|
|
729
|
-
}
|
|
730
|
-
return (preact.createElement("div", { key: internal$1.buildEventRangeKey(seg.eventRange), className: "fc-fill-y", style: hStyle }, fillType === 'bg-event' ?
|
|
731
|
-
preact.createElement(internal$1.BgEvent, Object.assign({ eventRange: seg.eventRange, isStart: seg.isStart, isEnd: seg.isEnd }, internal$1.getEventRangeMeta(seg.eventRange, todayRange, nowDate))) : (internal$1.renderFill(fillType))));
|
|
732
|
-
})));
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
class TimelineLaneSlicer extends internal$1.Slicer {
|
|
737
|
-
sliceRange(origRange, dateProfile, dateProfileGenerator, tDateProfile, dateEnv) {
|
|
738
|
-
let normalRange = normalizeRange(origRange, tDateProfile, dateEnv);
|
|
739
|
-
let segs = [];
|
|
740
|
-
// protect against when the span is entirely in an invalid date region
|
|
741
|
-
if (computeDateSnapCoverage$1(normalRange.start, tDateProfile, dateEnv)
|
|
742
|
-
< computeDateSnapCoverage$1(normalRange.end, tDateProfile, dateEnv)) {
|
|
743
|
-
// intersect the footprint's range with the grid's range
|
|
744
|
-
let slicedRange = internal$1.intersectRanges(normalRange, tDateProfile.normalizedRange);
|
|
745
|
-
if (slicedRange) {
|
|
746
|
-
segs.push({
|
|
747
|
-
startDate: slicedRange.start,
|
|
748
|
-
endDate: slicedRange.end,
|
|
749
|
-
isStart: slicedRange.start.valueOf() === normalRange.start.valueOf()
|
|
750
|
-
&& isValidDate(slicedRange.start, tDateProfile, dateProfile, dateProfileGenerator),
|
|
751
|
-
isEnd: slicedRange.end.valueOf() === normalRange.end.valueOf()
|
|
752
|
-
&& isValidDate(internal$1.addMs(slicedRange.end, -1), tDateProfile, dateProfile, dateProfileGenerator),
|
|
753
|
-
});
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
return segs;
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
const DEFAULT_TIME_FORMAT = internal$1.createFormatter({
|
|
761
|
-
hour: 'numeric',
|
|
762
|
-
minute: '2-digit',
|
|
763
|
-
omitZeroMinute: true,
|
|
764
|
-
meridiem: 'narrow',
|
|
765
|
-
});
|
|
766
|
-
class TimelineEvent extends internal$1.BaseComponent {
|
|
767
|
-
render() {
|
|
768
|
-
let { props, context } = this;
|
|
769
|
-
let { options } = context;
|
|
770
|
-
return (preact.createElement(internal$1.StandardEvent, Object.assign({}, props, { className: internal$1.joinClassNames('fc-timeline-event', options.eventOverlap === false // TODO: fix bad default
|
|
771
|
-
&& 'fc-timeline-event-spacious', 'fc-h-event'), defaultTimeFormat: DEFAULT_TIME_FORMAT, defaultDisplayEventTime: !props.isTimeScale })));
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
class TimelineLaneMoreLink extends internal$1.BaseComponent {
|
|
776
|
-
render() {
|
|
777
|
-
let { props } = this;
|
|
778
|
-
let { hiddenSegs, resourceId, forcedInvisibleMap } = props;
|
|
779
|
-
let dateSpanProps = resourceId ? { resourceId } : {};
|
|
780
|
-
return (preact.createElement(internal$1.MoreLinkContainer, { className: 'fc-timeline-more-link', allDayDate: null, segs: hiddenSegs, hiddenSegs: hiddenSegs, dateProfile: props.dateProfile, todayRange: props.todayRange, dateSpanProps: dateSpanProps, popoverContent: () => (preact.createElement(preact.Fragment, null, hiddenSegs.map((seg) => {
|
|
781
|
-
let { eventRange } = seg;
|
|
782
|
-
let instanceId = eventRange.instance.instanceId;
|
|
783
|
-
return (preact.createElement("div", { key: instanceId, style: { visibility: forcedInvisibleMap[instanceId] ? 'hidden' : '' } },
|
|
784
|
-
preact.createElement(TimelineEvent, Object.assign({ isTimeScale: props.isTimeScale, eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection }, internal$1.getEventRangeMeta(eventRange, props.todayRange, props.nowDate)))));
|
|
785
|
-
}))) }, (InnerContent) => (preact.createElement(InnerContent, { tag: "div", className: 'fc-timeline-more-link-inner fc-sticky-s' }))));
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
|
|
789
925
|
/*
|
|
790
926
|
TODO: make DRY with other Event Harnesses
|
|
791
927
|
*/
|
|
@@ -811,10 +947,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
811
947
|
}
|
|
812
948
|
}
|
|
813
949
|
|
|
814
|
-
|
|
815
|
-
TODO: split TimelineLaneBg and TimelineLaneFg?
|
|
816
|
-
*/
|
|
817
|
-
class TimelineLane extends internal$1.BaseComponent {
|
|
950
|
+
class TimelineFg extends internal$1.BaseComponent {
|
|
818
951
|
constructor() {
|
|
819
952
|
super(...arguments);
|
|
820
953
|
// memo
|
|
@@ -826,8 +959,6 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
826
959
|
this.moreLinkHeightRefMap = new internal$1.RefMap(() => {
|
|
827
960
|
internal$1.afterSize(this.handleMoreLinkHeights);
|
|
828
961
|
});
|
|
829
|
-
// internal
|
|
830
|
-
this.slicer = new TimelineLaneSlicer();
|
|
831
962
|
this.handleMoreLinkHeights = () => {
|
|
832
963
|
this.setState({ moreLinkHeightRev: this.moreLinkHeightRefMap.rev }); // will trigger rerender
|
|
833
964
|
};
|
|
@@ -841,39 +972,30 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
841
972
|
render() {
|
|
842
973
|
let { props, context, segHeightRefMap, moreLinkHeightRefMap } = this;
|
|
843
974
|
let { options } = context;
|
|
844
|
-
let {
|
|
845
|
-
let
|
|
846
|
-
|
|
847
|
-
let mirrorSegs = (slicedProps.eventDrag ? slicedProps.eventDrag.segs : null) ||
|
|
848
|
-
(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) ||
|
|
849
978
|
[];
|
|
850
|
-
let fgSegs = this.sortEventSegs(
|
|
979
|
+
let fgSegs = this.sortEventSegs(props.fgEventSegs, options.eventOrder);
|
|
851
980
|
let fgSegHorizontals = props.slotWidth != null
|
|
852
981
|
? computeManySegHorizontals(fgSegs, options.eventMinWidth, context.dateEnv, tDateProfile, props.slotWidth)
|
|
853
982
|
: {};
|
|
854
983
|
let [fgSegTops, hiddenGroups, hiddenGroupTops, totalHeight] = computeFgSegPlacements(fgSegs, fgSegHorizontals, segHeightRefMap.current, moreLinkHeightRefMap.current, options.eventOrderStrict, options.eventMaxStack);
|
|
984
|
+
this.totalHeight = totalHeight;
|
|
855
985
|
let forcedInvisibleMap = // TODO: more convenient/DRY
|
|
856
|
-
(
|
|
857
|
-
(
|
|
986
|
+
(props.eventDrag ? props.eventDrag.affectedInstances : null) ||
|
|
987
|
+
(props.eventResize ? props.eventResize.affectedInstances : null) ||
|
|
858
988
|
{};
|
|
859
|
-
return (preact.createElement(
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
false, // isResizing
|
|
870
|
-
false),
|
|
871
|
-
this.renderFgSegs(mirrorSegs, props.slotWidth // TODO: memoize
|
|
872
|
-
? computeManySegHorizontals(mirrorSegs, options.eventMinWidth, context.dateEnv, tDateProfile, props.slotWidth)
|
|
873
|
-
: {}, fgSegTops, {}, // forcedInvisibleMap
|
|
874
|
-
[], // hiddenGroups
|
|
875
|
-
new Map(), // hiddenGroupTops
|
|
876
|
-
Boolean(slicedProps.eventDrag), Boolean(slicedProps.eventResize), false))));
|
|
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)));
|
|
877
999
|
}
|
|
878
1000
|
renderFgSegs(segs, segHorizontals, segTops, forcedInvisibleMap, hiddenGroups, hiddenGroupTops, isDragging, isResizing, isDateSelecting) {
|
|
879
1001
|
let { props, context, segHeightRefMap, moreLinkHeightRefMap } = this;
|
|
@@ -895,155 +1017,43 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
895
1017
|
}, context.isRtl)), heightRef: moreLinkHeightRefMap.createRef(hiddenGroup.key) },
|
|
896
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 }))))));
|
|
897
1019
|
}
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
constructor() {
|
|
902
|
-
super(...arguments);
|
|
903
|
-
// memo
|
|
904
|
-
this.refineRenderProps = internal$1.memoizeObjArg(refineRenderProps);
|
|
905
|
-
// ref
|
|
906
|
-
this.innerElRef = preact.createRef();
|
|
907
|
-
}
|
|
908
|
-
render() {
|
|
909
|
-
let { props, context } = this;
|
|
910
|
-
let { dateEnv, options } = context;
|
|
911
|
-
let { cell, dateProfile, tDateProfile } = props;
|
|
912
|
-
// the cell.rowUnit is f'd
|
|
913
|
-
// giving 'month' for a 3-day view
|
|
914
|
-
// workaround: to infer day, do NOT time
|
|
915
|
-
let dateMeta = internal$1.getDateMeta(cell.date, props.todayRange, props.nowDate, dateProfile);
|
|
916
|
-
let renderProps = this.refineRenderProps({
|
|
917
|
-
level: props.rowLevel,
|
|
918
|
-
dateMarker: cell.date,
|
|
919
|
-
text: cell.text,
|
|
920
|
-
dateEnv: context.dateEnv,
|
|
921
|
-
viewApi: context.viewApi,
|
|
922
|
-
});
|
|
923
|
-
let isNavLink = !dateMeta.isDisabled && (cell.rowUnit && cell.rowUnit !== 'time');
|
|
924
|
-
return (preact.createElement(internal$1.ContentContainer, { tag: "div", className: internal$1.joinClassNames('fc-timeline-slot-label fc-timeline-slot', cell.isWeekStart && 'fc-timeline-slot-em', // TODO: document this semantic className
|
|
925
|
-
'fc-header-cell fc-cell fc-flex-col fc-justify-center', props.borderStart && 'fc-border-s', props.isCentered ? 'fc-align-center' : 'fc-align-start',
|
|
926
|
-
// TODO: so slot classnames for week/month/bigger. see note above about rowUnit
|
|
927
|
-
cell.rowUnit === 'time' ?
|
|
928
|
-
internal$1.getSlotClassName(dateMeta) :
|
|
929
|
-
internal$1.getDayClassName(dateMeta)), attrs: Object.assign({ 'data-date': dateEnv.formatIso(cell.date, {
|
|
930
|
-
omitTime: !tDateProfile.isTimeScale,
|
|
931
|
-
omitTimeZoneOffset: true,
|
|
932
|
-
}) }, (dateMeta.isToday ? { 'aria-current': 'date' } : {})), style: {
|
|
933
|
-
width: props.slotWidth != null
|
|
934
|
-
? props.slotWidth * cell.colspan
|
|
935
|
-
: undefined,
|
|
936
|
-
}, renderProps: renderProps, generatorName: "slotLabelContent", customGenerator: options.slotLabelContent, defaultGenerator: renderInnerContent, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (preact.createElement(InnerContent, { tag: 'div', attrs: isNavLink
|
|
937
|
-
// not tabbable because parent is aria-hidden
|
|
938
|
-
? internal$1.buildNavLinkAttrs(context, cell.date, cell.rowUnit, undefined, /* isTabbable = */ false)
|
|
939
|
-
: {} // don't bother with aria-hidden because parent already hidden
|
|
940
|
-
, className: internal$1.joinClassNames('fc-cell-inner fc-padding-md', props.isSticky && 'fc-sticky-s'), elRef: this.innerElRef }))));
|
|
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 renderInnerContent(renderProps) {
|
|
965
|
-
return renderProps.text;
|
|
966
|
-
}
|
|
967
|
-
function refineRenderProps(input) {
|
|
968
|
-
return {
|
|
969
|
-
level: input.level,
|
|
970
|
-
date: input.dateEnv.toDate(input.dateMarker),
|
|
971
|
-
view: input.viewApi,
|
|
972
|
-
text: input.text,
|
|
973
|
-
};
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
class TimelineHeaderRow extends internal$1.BaseComponent {
|
|
977
|
-
constructor() {
|
|
978
|
-
super(...arguments);
|
|
979
|
-
// refs
|
|
980
|
-
this.innerWidthRefMap = new internal$1.RefMap(() => {
|
|
981
|
-
internal$1.afterSize(this.handleInnerWidths);
|
|
982
|
-
});
|
|
983
|
-
this.innerHeightRefMap = new internal$1.RefMap(() => {
|
|
984
|
-
internal$1.afterSize(this.handleInnerHeights);
|
|
985
|
-
});
|
|
986
|
-
this.handleInnerWidths = () => {
|
|
987
|
-
const innerWidthMap = this.innerWidthRefMap.current;
|
|
988
|
-
let max = 0;
|
|
989
|
-
for (const innerWidth of innerWidthMap.values()) {
|
|
990
|
-
max = Math.max(max, innerWidth);
|
|
991
|
-
}
|
|
992
|
-
// TODO: ensure not equal?
|
|
993
|
-
internal$1.setRef(this.props.innerWidthRef, max);
|
|
994
|
-
};
|
|
995
|
-
this.handleInnerHeights = () => {
|
|
996
|
-
const innerHeightMap = this.innerHeightRefMap.current;
|
|
997
|
-
let max = 0;
|
|
998
|
-
for (const innerHeight of innerHeightMap.values()) {
|
|
999
|
-
max = Math.max(max, innerHeight);
|
|
1000
|
-
}
|
|
1001
|
-
// TODO: ensure not equal?
|
|
1002
|
-
internal$1.setRef(this.props.innerHeighRef, max);
|
|
1003
|
-
};
|
|
1020
|
+
/*
|
|
1021
|
+
componentDidMount(): void {
|
|
1022
|
+
// might want to do firedTotalHeight, but won't be ready on first render
|
|
1004
1023
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
// TODO: make this part of the cell obj?
|
|
1012
|
-
// TODO: rowUnit seems wrong sometimes. says 'month' when it should be day
|
|
1013
|
-
// TODO: rowUnit is relevant to whole row. put it on a row object, not the cells
|
|
1014
|
-
// TODO: use rowUnit to key the Row itself?
|
|
1015
|
-
const key = cell.rowUnit + ':' + cell.date.toISOString();
|
|
1016
|
-
return (preact.createElement(TimelineHeaderCell, { key: key, cell: cell, rowLevel: props.rowLevel, dateProfile: props.dateProfile, tDateProfile: props.tDateProfile, todayRange: props.todayRange, nowDate: props.nowDate, isCentered: isCentered, isSticky: isSticky, borderStart: Boolean(cellI),
|
|
1017
|
-
// refs
|
|
1018
|
-
innerWidthRef: innerWidthRefMap.createRef(key), innerHeightRef: innerHeightRefMap.createRef(key),
|
|
1019
|
-
// dimensions
|
|
1020
|
-
slotWidth: props.slotWidth }));
|
|
1021
|
-
})));
|
|
1024
|
+
*/
|
|
1025
|
+
componentDidUpdate() {
|
|
1026
|
+
if (this.totalHeight !== this.firedTotalHeight) {
|
|
1027
|
+
this.firedTotalHeight = this.totalHeight;
|
|
1028
|
+
internal$1.setRef(this.props.heightRef, this.totalHeight);
|
|
1029
|
+
}
|
|
1022
1030
|
}
|
|
1023
1031
|
componentWillUnmount() {
|
|
1024
|
-
internal$1.setRef(this.props.
|
|
1025
|
-
internal$1.setRef(this.props.innerHeighRef, null);
|
|
1032
|
+
internal$1.setRef(this.props.heightRef, null);
|
|
1026
1033
|
}
|
|
1027
1034
|
}
|
|
1028
1035
|
|
|
1029
|
-
class
|
|
1036
|
+
class TimelineBg extends internal$1.BaseComponent {
|
|
1030
1037
|
render() {
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
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')));
|
|
1037
1044
|
}
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
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
|
+
})));
|
|
1047
1057
|
}
|
|
1048
1058
|
}
|
|
1049
1059
|
|
|
@@ -1061,6 +1071,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1061
1071
|
internal$1.afterSize(this.handleSlotInnerWidths);
|
|
1062
1072
|
});
|
|
1063
1073
|
this.scrollTime = null;
|
|
1074
|
+
this.slicer = new TimelineLaneSlicer();
|
|
1064
1075
|
// Sizing
|
|
1065
1076
|
// -----------------------------------------------------------------------------------------------
|
|
1066
1077
|
this.handleBodySlotInnerWidth = (innerWidth) => {
|
|
@@ -1068,27 +1079,30 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1068
1079
|
internal$1.afterSize(this.handleSlotInnerWidths);
|
|
1069
1080
|
};
|
|
1070
1081
|
this.handleSlotInnerWidths = () => {
|
|
1071
|
-
const
|
|
1072
|
-
const
|
|
1073
|
-
if (
|
|
1074
|
-
|
|
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
|
+
}
|
|
1075
1089
|
}
|
|
1076
1090
|
};
|
|
1077
|
-
this.
|
|
1091
|
+
this.handleTotalWidth = (totalWidth) => {
|
|
1078
1092
|
this.setState({
|
|
1079
|
-
|
|
1093
|
+
totalWidth,
|
|
1080
1094
|
});
|
|
1081
1095
|
};
|
|
1082
|
-
this.
|
|
1096
|
+
this.handleClientWidth = (clientWidth) => {
|
|
1083
1097
|
this.setState({
|
|
1084
|
-
|
|
1098
|
+
clientWidth,
|
|
1085
1099
|
});
|
|
1086
1100
|
};
|
|
1087
1101
|
this.handleTimeScrollRequest = (scrollTime) => {
|
|
1088
1102
|
this.scrollTime = scrollTime;
|
|
1089
1103
|
this.applyTimeScroll();
|
|
1090
1104
|
};
|
|
1091
|
-
this.handleTimeScrollEnd = (
|
|
1105
|
+
this.handleTimeScrollEnd = (isUser) => {
|
|
1092
1106
|
if (isUser) {
|
|
1093
1107
|
this.scrollTime = null;
|
|
1094
1108
|
}
|
|
@@ -1108,6 +1122,10 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1108
1122
|
render() {
|
|
1109
1123
|
const { props, state, context } = this;
|
|
1110
1124
|
const { options } = context;
|
|
1125
|
+
const { totalWidth, clientWidth } = state;
|
|
1126
|
+
const endScrollbarWidth = (totalWidth != null && clientWidth != null)
|
|
1127
|
+
? totalWidth - clientWidth
|
|
1128
|
+
: undefined;
|
|
1111
1129
|
/* date */
|
|
1112
1130
|
const tDateProfile = this.tDateProfile = this.buildTimelineDateProfile(props.dateProfile, context.dateEnv, options, context.dateProfileGenerator);
|
|
1113
1131
|
const { cellRows } = tDateProfile;
|
|
@@ -1118,8 +1136,11 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1118
1136
|
const stickyFooterScrollbar = !props.forPrint && internal$1.getStickyFooterScrollbar(options);
|
|
1119
1137
|
/* table positions */
|
|
1120
1138
|
const [canvasWidth, slotWidth] = this.computeSlotWidth(tDateProfile.slotCnt, tDateProfile.slotsPerLabel, options.slotMinWidth, state.slotInnerWidth, // is ACTUALLY the label width. rename?
|
|
1121
|
-
|
|
1139
|
+
clientWidth);
|
|
1122
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);
|
|
1123
1144
|
return (preact.createElement(internal$1.NowTimer, { unit: timerUnit }, (nowDate, todayRange) => {
|
|
1124
1145
|
const enableNowIndicator = // TODO: DRY
|
|
1125
1146
|
options.nowIndicator &&
|
|
@@ -1139,18 +1160,30 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1139
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) }));
|
|
1140
1161
|
}),
|
|
1141
1162
|
enableNowIndicator && (preact.createElement(TimelineNowIndicatorArrow, { tDateProfile: tDateProfile, nowDate: nowDate, slotWidth: slotWidth }))),
|
|
1142
|
-
Boolean(
|
|
1143
|
-
preact.createElement(internal$1.Scroller, { vertical: verticalScrolling, horizontal: true, hideScrollbars:
|
|
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 },
|
|
1144
1167
|
preact.createElement("div", { "aria-label": options.eventsHint, className: "fc-rel fc-grow", style: { width: canvasWidth }, ref: this.handeBodyEl },
|
|
1145
1168
|
preact.createElement(TimelineSlats, { dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange,
|
|
1146
1169
|
// ref
|
|
1147
1170
|
innerWidthRef: this.handleBodySlotInnerWidth,
|
|
1148
1171
|
// dimensions
|
|
1149
1172
|
slotWidth: slotWidth }),
|
|
1150
|
-
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' }),
|
|
1151
1184
|
enableNowIndicator && (preact.createElement(TimelineNowIndicatorLine, { tDateProfile: tDateProfile, nowDate: nowDate, slotWidth: slotWidth })))),
|
|
1152
|
-
stickyFooterScrollbar && (preact.createElement(internal$1.
|
|
1153
|
-
|
|
1185
|
+
Boolean(stickyFooterScrollbar) && (preact.createElement(internal$1.FooterScrollbar, { isSticky: true, canvasWidth: canvasWidth, scrollerRef: this.footerScrollerRef })),
|
|
1186
|
+
preact.createElement(internal$1.Ruler, { widthRef: this.handleTotalWidth })));
|
|
1154
1187
|
}));
|
|
1155
1188
|
}
|
|
1156
1189
|
// Lifecycle
|
|
@@ -1235,8 +1268,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1235
1268
|
top: 0,
|
|
1236
1269
|
bottom: elHeight,
|
|
1237
1270
|
},
|
|
1238
|
-
|
|
1239
|
-
dayEl: this.bodyEl.querySelectorAll('.fc-timeline-slot')[slatIndex],
|
|
1271
|
+
getDayEl: () => getTimelineSlotEl(this.bodyEl, slatIndex),
|
|
1240
1272
|
layer: 0,
|
|
1241
1273
|
};
|
|
1242
1274
|
}
|
|
@@ -1244,12 +1276,12 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1244
1276
|
}
|
|
1245
1277
|
}
|
|
1246
1278
|
|
|
1247
|
-
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}";
|
|
1248
1280
|
internal$1.injectStyles(css_248z);
|
|
1249
1281
|
|
|
1250
1282
|
var plugin = core.createPlugin({
|
|
1251
1283
|
name: '@fullcalendar/timeline',
|
|
1252
|
-
premiumReleaseDate: '2025-
|
|
1284
|
+
premiumReleaseDate: '2025-02-21',
|
|
1253
1285
|
deps: [premiumCommonPlugin__default["default"]],
|
|
1254
1286
|
initialView: 'timelineDay',
|
|
1255
1287
|
views: {
|
|
@@ -1280,8 +1312,8 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1280
1312
|
var internal = {
|
|
1281
1313
|
__proto__: null,
|
|
1282
1314
|
TimelineView: TimelineView,
|
|
1283
|
-
|
|
1284
|
-
|
|
1315
|
+
TimelineFg: TimelineFg,
|
|
1316
|
+
TimelineBg: TimelineBg,
|
|
1285
1317
|
TimelineSlats: TimelineSlats,
|
|
1286
1318
|
buildTimelineDateProfile: buildTimelineDateProfile,
|
|
1287
1319
|
createVerticalStyle: createVerticalStyle,
|
|
@@ -1291,7 +1323,8 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
|
|
|
1291
1323
|
TimelineLaneSlicer: TimelineLaneSlicer,
|
|
1292
1324
|
TimelineHeaderRow: TimelineHeaderRow,
|
|
1293
1325
|
TimelineNowIndicatorArrow: TimelineNowIndicatorArrow,
|
|
1294
|
-
TimelineNowIndicatorLine: TimelineNowIndicatorLine
|
|
1326
|
+
TimelineNowIndicatorLine: TimelineNowIndicatorLine,
|
|
1327
|
+
getTimelineSlotEl: getTimelineSlotEl
|
|
1295
1328
|
};
|
|
1296
1329
|
|
|
1297
1330
|
core.globalPlugins.push(plugin);
|