@fullcalendar/timeline 7.0.0-beta.0 → 7.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.global.js CHANGED
@@ -1,9 +1,9 @@
1
1
  /*!
2
- FullCalendar Timeline Plugin v7.0.0-beta.0
2
+ FullCalendar Timeline Plugin v7.0.0-beta.3
3
3
  Docs & License: https://fullcalendar.io/docs/timeline-view-no-resources
4
4
  (c) 2024 Adam Shaw
5
5
  */
6
- FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$1, preact) {
6
+ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$1, preact, internal$2) {
7
7
  'use strict';
8
8
 
9
9
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
@@ -456,42 +456,36 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
456
456
  }
457
457
  render() {
458
458
  let { props, context } = this;
459
- let { dateEnv, options, theme } = context;
459
+ let { dateEnv, options } = context;
460
460
  let { date, tDateProfile, isEm } = props;
461
461
  let dateMeta = internal$1.getDateMeta(props.date, props.todayRange, props.nowDate, props.dateProfile);
462
462
  let renderProps = Object.assign(Object.assign({ date: dateEnv.toDate(props.date) }, dateMeta), { view: context.viewApi });
463
- return (preact.createElement(internal$1.ContentContainer, { elTag: "div", elClasses: [
464
- 'fc-flex-column',
465
- 'fc-align-start',
466
- 'fc-cell',
467
- 'fc-timeline-slot',
468
- 'fc-timeline-slot-lane',
469
- isEm ? 'fc-timeline-slot-em' : '',
470
- tDateProfile.isTimeScale ? (internal$1.isInt(dateEnv.countDurationsBetween(// best to do this here?
471
- tDateProfile.normalizedRange.start, props.date, tDateProfile.labelInterval)) ?
472
- 'fc-timeline-slot-major' :
473
- 'fc-timeline-slot-minor') : '',
474
- ...(props.isDay ?
475
- internal$1.getDayClassNames(dateMeta, theme) :
476
- internal$1.getSlotClassNames(dateMeta, theme)),
477
- ], elAttrs: {
463
+ return (preact.createElement(internal$1.ContentContainer, { tag: "div",
464
+ // fc-align-start shrinks width of InnerContent
465
+ // TODO: document this semantic className fc-timeline-slot-em
466
+ className: internal$1.joinClassNames('fc-timeline-slot', isEm && 'fc-timeline-slot-em', tDateProfile.isTimeScale && (internal$1.isInt(dateEnv.countDurationsBetween(// best to do this here?
467
+ tDateProfile.normalizedRange.start, props.date, tDateProfile.labelInterval)) ?
468
+ 'fc-timeline-slot-major' :
469
+ 'fc-timeline-slot-minor'), 'fc-timeline-slot-lane fc-cell fc-flex-col fc-align-start', props.borderStart && 'fc-border-s', props.isDay ?
470
+ internal$1.getDayClassName(dateMeta) :
471
+ internal$1.getSlotClassName(dateMeta)), attrs: {
478
472
  'data-date': dateEnv.formatIso(date, {
479
473
  omitTimeZoneOffset: true,
480
474
  omitTime: !tDateProfile.isTimeScale,
481
475
  }),
482
- }, elStyle: {
476
+ }, style: {
483
477
  width: props.width,
484
- }, renderProps: renderProps, generatorName: "slotLaneContent", customGenerator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount }, (InnerContent) => (preact.createElement("div", { ref: this.innerElRef, className: 'fc-flex-column' },
485
- preact.createElement(InnerContent, { elTag: "div", elClasses: ['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', elRef: this.innerElRef }))));
486
479
  }
487
480
  componentDidMount() {
488
481
  const innerEl = this.innerElRef.current;
489
- this.detachWidth = internal$1.watchWidth(innerEl, (width) => {
482
+ this.disconnectInnerWidth = internal$1.watchWidth(innerEl, (width) => {
490
483
  internal$1.setRef(this.props.innerWidthRef, width);
491
484
  });
492
485
  }
493
486
  componentWillUnmount() {
494
- this.detachWidth();
487
+ this.disconnectInnerWidth();
488
+ internal$1.setRef(this.props.innerWidthRef, null);
495
489
  }
496
490
  }
497
491
 
@@ -516,9 +510,9 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
516
510
  let { tDateProfile, slotWidth } = props;
517
511
  let { slotDates, isWeekStarts } = tDateProfile;
518
512
  let isDay = !tDateProfile.isTimeScale && !tDateProfile.largeUnit;
519
- return (preact.createElement("div", { className: "fc-timeline-slots fc-fill fc-flex-row" }, slotDates.map((slotDate, i) => {
513
+ return (preact.createElement("div", { className: "fc-timeline-slots fc-fill fc-flex-row", style: { height: props.height } }, slotDates.map((slotDate, i) => {
520
514
  let key = slotDate.toISOString();
521
- return (preact.createElement(TimelineSlatCell, { key: key, date: slotDate, dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: props.nowDate, todayRange: props.todayRange, isEm: isWeekStarts[i], isDay: isDay,
515
+ 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),
522
516
  // ref
523
517
  innerWidthRef: innerWidthRefMap.createRef(key),
524
518
  // dimensions
@@ -552,30 +546,6 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
552
546
  return snapCoverage;
553
547
  }
554
548
  /*
555
- TODO: audit!!!
556
- */
557
- function coordToCss(hcoord, isRtl) {
558
- if (hcoord === null) {
559
- return { left: '', right: '' };
560
- }
561
- if (isRtl) {
562
- return { right: hcoord, left: '' };
563
- }
564
- return { left: hcoord, right: '' };
565
- }
566
- /*
567
- TODO: audit!!!
568
- */
569
- function coordsToCss(hcoords, isRtl) {
570
- if (!hcoords) {
571
- return { left: '', right: '' };
572
- }
573
- if (isRtl) {
574
- return { right: hcoords.start, left: -hcoords.end };
575
- }
576
- return { left: hcoords.start, right: -hcoords.end };
577
- }
578
- /*
579
549
  TODO: DRY up with elsewhere?
580
550
  */
581
551
  function horizontalsToCss(hcoord, isRtl) {
@@ -606,7 +576,8 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
606
576
  };
607
577
  }
608
578
  }
609
- function createHorizontalStyle(props, isRtl) {
579
+ function createHorizontalStyle(// TODO: DRY up?
580
+ props, isRtl) {
610
581
  if (props) {
611
582
  return {
612
583
  [isRtl ? 'right' : 'left']: props.start,
@@ -679,13 +650,13 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
679
650
  function computeManySegHorizontals(segs, segMinWidth, dateEnv, tDateProfile, slotWidth) {
680
651
  const res = {};
681
652
  for (const seg of segs) {
682
- res[seg.eventRange.instance.instanceId] = computeSegHorizontals(seg, segMinWidth, dateEnv, tDateProfile, slotWidth);
653
+ res[internal$1.getEventKey(seg)] = computeSegHorizontals(seg, segMinWidth, dateEnv, tDateProfile, slotWidth);
683
654
  }
684
655
  return res;
685
656
  }
686
657
  function computeSegHorizontals(seg, segMinWidth, dateEnv, tDateProfile, slotWidth) {
687
- const startCoord = dateToCoord(seg.start, dateEnv, tDateProfile, slotWidth);
688
- const endCoord = dateToCoord(seg.end, dateEnv, tDateProfile, slotWidth);
658
+ const startCoord = dateToCoord(seg.startDate, dateEnv, tDateProfile, slotWidth);
659
+ const endCoord = dateToCoord(seg.endDate, dateEnv, tDateProfile, slotWidth);
689
660
  let size = endCoord - startCoord;
690
661
  if (segMinWidth) {
691
662
  size = Math.max(size, segMinWidth);
@@ -693,95 +664,58 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
693
664
  return { start: startCoord, size };
694
665
  }
695
666
  function computeFgSegPlacements(// mostly horizontals
696
- segs, segHorizontals, segHeights, // keyed by instanceId
697
- strictOrder, maxStackCnt) {
698
- let segEntries = [];
699
- for (let i = 0; i < segs.length; i += 1) {
700
- let seg = segs[i];
701
- let instanceId = seg.eventRange.instance.instanceId;
702
- let height = segHeights.get(instanceId);
703
- let hcoords = segHorizontals[instanceId];
704
- if (height != null && hcoords != null) {
705
- segEntries.push({
706
- index: i,
707
- seg,
708
- span: {
709
- start: hcoords.start,
710
- end: hcoords.start + hcoords.size,
711
- },
712
- thickness: height,
713
- });
667
+ segs, segHorizontals, // TODO: use Map
668
+ segHeights, // keyed by instanceId
669
+ hiddenGroupHeights, strictOrder, maxDepth) {
670
+ const segRanges = [];
671
+ // isn't it true that there will either be ALL hcoords or NONE? can optimize
672
+ for (const seg of segs) {
673
+ const hcoords = segHorizontals[internal$1.getEventKey(seg)];
674
+ if (hcoords) {
675
+ segRanges.push(Object.assign(Object.assign({}, seg), { start: hcoords.start, end: hcoords.start + hcoords.size }));
714
676
  }
715
677
  }
716
- let hierarchy = new internal$1.SegHierarchy();
717
- if (strictOrder != null) {
718
- hierarchy.strictOrder = strictOrder;
719
- }
720
- if (maxStackCnt != null) {
721
- hierarchy.maxStackCnt = maxStackCnt;
722
- }
723
- let hiddenEntries = hierarchy.addSegs(segEntries);
724
- let hiddenGroups = internal$1.groupIntersectingEntries(hiddenEntries);
725
- let hiddenGroupEntries = hiddenGroups.map((hiddenGroup, index) => ({
726
- index: segs.length + index,
727
- segGroup: hiddenGroup,
728
- span: hiddenGroup.span,
729
- thickness: 1, // HACK to ensure it's placed
730
- }));
731
- // add more-links into the hierarchy, but don't limit
732
- hierarchy.maxStackCnt = -1;
733
- hierarchy.addSegs(hiddenGroupEntries);
734
- let visibleRects = hierarchy.toRects();
735
- let segTops = {};
736
- let hiddenGroupTops = {};
737
- for (let rect of visibleRects) {
738
- const { seg, segGroup } = rect;
739
- if (seg) { // regular seg
740
- segTops[seg.eventRange.instance.instanceId] = rect.levelCoord;
741
- }
742
- else { // hiddenGroup
743
- hiddenGroupTops[segGroup.key] = rect.levelCoord;
678
+ const hierarchy = new internal$1.SegHierarchy(segRanges, (seg) => segHeights.get(internal$1.getEventKey(seg)), strictOrder, undefined, // maxCoord
679
+ maxDepth);
680
+ const segTops = new Map();
681
+ hierarchy.traverseSegs((seg, segTop) => {
682
+ segTops.set(internal$1.getEventKey(seg), segTop);
683
+ });
684
+ const { hiddenSegs } = hierarchy;
685
+ let totalHeight = 0;
686
+ for (const segRange of segRanges) {
687
+ const segKey = internal$1.getEventKey(segRange);
688
+ const segHeight = segHeights.get(segKey);
689
+ const segTop = segTops.get(segKey);
690
+ if (segHeight != null) {
691
+ if (segTop != null) {
692
+ totalHeight = Math.max(totalHeight, segTop + segHeight);
693
+ }
744
694
  }
745
695
  }
696
+ const hiddenGroups = internal$1.groupIntersectingSegs(hiddenSegs);
697
+ const hiddenGroupTops = new Map();
698
+ // HACK for hiddenGroup findInsertion() call
699
+ hierarchy.strictOrder = true;
700
+ for (const hiddenGroup of hiddenGroups) {
701
+ const { levelCoord: top } = hierarchy.findInsertion(hiddenGroup, 0);
702
+ const hiddenGroupHeight = hiddenGroupHeights.get(hiddenGroup.key) || 0;
703
+ hiddenGroupTops.set(hiddenGroup.key, top);
704
+ totalHeight = Math.max(totalHeight, top + hiddenGroupHeight);
705
+ }
746
706
  return [
747
707
  segTops,
748
- computeMaxBottom(segs, segTops, segHeights),
749
708
  hiddenGroups,
750
709
  hiddenGroupTops,
710
+ totalHeight,
751
711
  ];
752
712
  }
753
- function computeMaxBottom(segs, segTops, segHeights) {
754
- let max = 0;
755
- for (const seg of segs) {
756
- const { instanceId } = seg.eventRange.instance;
757
- const top = segTops[instanceId];
758
- const height = segHeights.get(instanceId);
759
- if (top != null && height != null) {
760
- max = Math.max(max, top + height);
761
- }
762
- }
763
- return max;
764
- }
765
- /*
766
- TODO: converge with computeMaxBottom, but keys are different
767
- */
768
- function computeMoreLinkMaxBottom(hiddenGroups, hiddenGroupTops, hiddenGroupHeights) {
769
- let max = 0;
770
- for (const hiddenGroup of hiddenGroups) {
771
- const top = hiddenGroupTops[hiddenGroup.key];
772
- const height = hiddenGroupHeights.get(hiddenGroup.key);
773
- if (top != null && height != null) {
774
- max = Math.max(max, top + height);
775
- }
776
- }
777
- return max;
778
- }
779
713
 
780
714
  class TimelineLaneBg extends internal$1.BaseComponent {
781
715
  render() {
782
716
  let { props } = this;
783
717
  let highlightSeg = [].concat(props.eventResizeSegs, props.dateSelectionSegs);
784
- return (preact.createElement("div", { className: "fc-timeline-bg" },
718
+ return (preact.createElement(preact.Fragment, null,
785
719
  this.renderSegs(props.businessHourSegs || [], 'non-business'),
786
720
  this.renderSegs(props.bgEventSegs || [], 'bg-event'),
787
721
  this.renderSegs(highlightSeg, 'highlight')));
@@ -795,9 +729,8 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
795
729
  let segHorizontal = computeSegHorizontals(seg, undefined, dateEnv, tDateProfile, slotWidth);
796
730
  hStyle = horizontalsToCss(segHorizontal, isRtl);
797
731
  }
798
- return (preact.createElement("div", { key: internal$1.buildEventRangeKey(seg.eventRange), className: "fc-timeline-bg-harness", style: hStyle }, fillType === 'bg-event' ?
799
- preact.createElement(internal$1.BgEvent, Object.assign({ seg: seg }, internal$1.getSegMeta(seg, todayRange, nowDate))) :
800
- internal$1.renderFill(fillType)));
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))));
801
734
  })));
802
735
  }
803
736
  }
@@ -813,8 +746,8 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
813
746
  let slicedRange = internal$1.intersectRanges(normalRange, tDateProfile.normalizedRange);
814
747
  if (slicedRange) {
815
748
  segs.push({
816
- start: slicedRange.start,
817
- end: slicedRange.end,
749
+ startDate: slicedRange.start,
750
+ endDate: slicedRange.end,
818
751
  isStart: slicedRange.start.valueOf() === normalRange.start.valueOf()
819
752
  && isValidDate(slicedRange.start, tDateProfile, dateProfile, dateProfileGenerator),
820
753
  isEnd: slicedRange.end.valueOf() === normalRange.end.valueOf()
@@ -836,13 +769,8 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
836
769
  render() {
837
770
  let { props, context } = this;
838
771
  let { options } = context;
839
- return (preact.createElement(internal$1.StandardEvent, Object.assign({}, props, { elClasses: [
840
- 'fc-timeline-event',
841
- 'fc-h-event',
842
- options.eventOverlap === false // TODO: fix bad default
843
- ? 'fc-timeline-event-spacious'
844
- : ''
845
- ], defaultTimeFormat: DEFAULT_TIME_FORMAT, defaultDisplayEventTime: !props.isTimeScale })));
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 })));
846
774
  }
847
775
  }
848
776
 
@@ -850,12 +778,13 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
850
778
  render() {
851
779
  let { props } = this;
852
780
  let { hiddenSegs, resourceId, forcedInvisibleMap } = props;
853
- let extraDateSpan = resourceId ? { resourceId } : {};
854
- return (preact.createElement(internal$1.MoreLinkContainer, { elClasses: ['fc-timeline-more-link'], allDayDate: null, segs: hiddenSegs, hiddenSegs: hiddenSegs, dateProfile: props.dateProfile, todayRange: props.todayRange, extraDateSpan: extraDateSpan, popoverContent: () => (preact.createElement(preact.Fragment, null, hiddenSegs.map((seg) => {
855
- let instanceId = seg.eventRange.instance.instanceId;
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;
856
785
  return (preact.createElement("div", { key: instanceId, style: { visibility: forcedInvisibleMap[instanceId] ? 'hidden' : '' } },
857
- preact.createElement(TimelineEvent, Object.assign({ isTimeScale: props.isTimeScale, seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection }, internal$1.getSegMeta(seg, props.todayRange, props.nowDate)))));
858
- }))) }, (InnerContent) => (preact.createElement(InnerContent, { elTag: "div", elClasses: ['fc-timeline-more-link-inner', 'fc-sticky-x'] }))));
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' }))));
859
788
  }
860
789
  }
861
790
 
@@ -874,12 +803,13 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
874
803
  }
875
804
  componentDidMount() {
876
805
  const rootEl = this.rootElRef.current; // TODO: make dynamic with useEffect
877
- this.detachHeight = internal$1.watchHeight(rootEl, (height) => {
806
+ this.disconnectHeight = internal$1.watchHeight(rootEl, (height) => {
878
807
  internal$1.setRef(this.props.heightRef, height);
879
808
  });
880
809
  }
881
810
  componentWillUnmount() {
882
- this.detachHeight();
811
+ this.disconnectHeight();
812
+ internal$1.setRef(this.props.heightRef, null);
883
813
  }
884
814
  }
885
815
 
@@ -911,7 +841,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
911
841
  TODO: lots of memoization needed here!
912
842
  */
913
843
  render() {
914
- let { props, context, segHeightRefMap } = this;
844
+ let { props, context, segHeightRefMap, moreLinkHeightRefMap } = this;
915
845
  let { options } = context;
916
846
  let { dateProfile, tDateProfile } = props;
917
847
  let slicedProps = this.slicer.sliceProps(props, dateProfile, tDateProfile.isTimeScale ? null : props.nextDayThreshold, context, // wish we didn't have to pass in the rest of the args...
@@ -923,10 +853,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
923
853
  let fgSegHorizontals = props.slotWidth != null
924
854
  ? computeManySegHorizontals(fgSegs, options.eventMinWidth, context.dateEnv, tDateProfile, props.slotWidth)
925
855
  : {};
926
- let [fgSegTops, fgSegsBottom, hiddenGroups, hiddenGroupTops] = computeFgSegPlacements(// verticals
927
- fgSegs, fgSegHorizontals, segHeightRefMap.current, options.eventOrderStrict, options.eventMaxStack);
928
- let moreLinksBottom = computeMoreLinkMaxBottom(hiddenGroups, hiddenGroupTops, this.moreLinkHeightRefMap.current);
929
- let innerHeight = Math.max(moreLinksBottom, fgSegsBottom);
856
+ let [fgSegTops, hiddenGroups, hiddenGroupTops, totalHeight] = computeFgSegPlacements(fgSegs, fgSegHorizontals, segHeightRefMap.current, moreLinkHeightRefMap.current, options.eventOrderStrict, options.eventMaxStack);
930
857
  let forcedInvisibleMap = // TODO: more convenient/DRY
931
858
  (slicedProps.eventDrag ? slicedProps.eventDrag.affectedInstances : null) ||
932
859
  (slicedProps.eventResize ? slicedProps.eventResize.affectedInstances : null) ||
@@ -937,39 +864,38 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
937
864
  bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventResizeSegs: slicedProps.eventResize ? slicedProps.eventResize.segs : [] /* bad new empty array? */,
938
865
  // dimensions
939
866
  slotWidth: props.slotWidth }),
940
- preact.createElement("div", { className: [
941
- 'fc-timeline-events',
942
- 'fc-content-box',
943
- options.eventOverlap === false // TODO: fix bad default
944
- ? 'fc-timeline-events-overlap-disabled'
945
- : 'fc-timeline-events-overlap-enabled'
946
- ].join(' '), style: { height: innerHeight } },
867
+ preact.createElement("div", { className: internal$1.joinClassNames('fc-timeline-events', options.eventOverlap === false // TODO: fix bad default
868
+ ? 'fc-timeline-events-overlap-disabled'
869
+ : 'fc-timeline-events-overlap-enabled', 'fc-content-box'), style: { height: totalHeight } },
947
870
  this.renderFgSegs(fgSegs, fgSegHorizontals, fgSegTops, forcedInvisibleMap, hiddenGroups, hiddenGroupTops, false, // isDragging
948
871
  false, // isResizing
949
872
  false),
950
873
  this.renderFgSegs(mirrorSegs, props.slotWidth // TODO: memoize
951
874
  ? computeManySegHorizontals(mirrorSegs, options.eventMinWidth, context.dateEnv, tDateProfile, props.slotWidth)
952
875
  : {}, fgSegTops, {}, // forcedInvisibleMap
953
- [], {}, Boolean(slicedProps.eventDrag), Boolean(slicedProps.eventResize), false))));
876
+ [], // hiddenGroups
877
+ new Map(), // hiddenGroupTops
878
+ Boolean(slicedProps.eventDrag), Boolean(slicedProps.eventResize), false))));
954
879
  }
955
880
  renderFgSegs(segs, segHorizontals, segTops, forcedInvisibleMap, hiddenGroups, hiddenGroupTops, isDragging, isResizing, isDateSelecting) {
956
881
  let { props, context, segHeightRefMap, moreLinkHeightRefMap } = this;
957
882
  let isMirror = isDragging || isResizing || isDateSelecting;
958
883
  return (preact.createElement(preact.Fragment, null,
959
884
  segs.map((seg) => {
960
- const { instanceId } = seg.eventRange.instance;
961
- const segTop = segTops[instanceId];
885
+ const { eventRange } = seg;
886
+ const { instanceId } = eventRange.instance;
887
+ const segTop = segTops.get(instanceId);
962
888
  const segHorizontal = segHorizontals[instanceId];
963
889
  const isVisible = isMirror ||
964
890
  (segHorizontal && segTop != null && !forcedInvisibleMap[instanceId]);
965
891
  return (preact.createElement(TimelineEventHarness, { key: instanceId, style: Object.assign({ visibility: isVisible ? '' : 'hidden', top: segTop || 0 }, horizontalsToCss(segHorizontal, context.isRtl)), heightRef: isMirror ? undefined : segHeightRefMap.createRef(instanceId) },
966
- preact.createElement(TimelineEvent, Object.assign({ isTimeScale: props.tDateProfile.isTimeScale, seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === props.eventSelection /* TODO: bad for mirror? */ }, internal$1.getSegMeta(seg, props.todayRange, props.nowDate)))));
892
+ preact.createElement(TimelineEvent, Object.assign({ isTimeScale: props.tDateProfile.isTimeScale, eventRange: eventRange, isStart: seg.isStart, isEnd: seg.isEnd, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === props.eventSelection /* TODO: bad for mirror? */ }, internal$1.getEventRangeMeta(eventRange, props.todayRange, props.nowDate)))));
967
893
  }),
968
- hiddenGroups.map((hiddenGroup) => (preact.createElement(TimelineEventHarness, { key: hiddenGroup.key, style: Object.assign({ top: hiddenGroupTops[hiddenGroup.key] || 0 }, horizontalsToCss({
969
- start: hiddenGroup.span.start,
970
- size: hiddenGroup.span.end - hiddenGroup.span.start
894
+ hiddenGroups.map((hiddenGroup) => (preact.createElement(TimelineEventHarness, { key: hiddenGroup.key, style: Object.assign({ top: hiddenGroupTops.get(hiddenGroup.key) || 0 }, horizontalsToCss({
895
+ start: hiddenGroup.start,
896
+ size: hiddenGroup.end - hiddenGroup.start
971
897
  }, context.isRtl)), heightRef: moreLinkHeightRefMap.createRef(hiddenGroup.key) },
972
- preact.createElement(TimelineLaneMoreLink, { hiddenSegs: hiddenGroup.segs /* TODO: make SegGroup generic! */, dateProfile: props.dateProfile, nowDate: props.nowDate, todayRange: props.todayRange, isTimeScale: props.tDateProfile.isTimeScale, eventSelection: props.eventSelection, resourceId: props.resourceId, forcedInvisibleMap: forcedInvisibleMap }))))));
898
+ 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 }))))));
973
899
  }
974
900
  }
975
901
 
@@ -981,7 +907,6 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
981
907
  this.buildCellNavLinkAttrs = internal$1.memoize(buildCellNavLinkAttrs);
982
908
  // ref
983
909
  this.innerElRef = preact.createRef();
984
- // TODO: unset width/height ref on unmount?
985
910
  }
986
911
  render() {
987
912
  let { props, context } = this;
@@ -998,36 +923,21 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
998
923
  dateEnv: context.dateEnv,
999
924
  viewApi: context.viewApi,
1000
925
  });
1001
- return (preact.createElement(internal$1.ContentContainer, { elTag: "div", elClasses: [
1002
- 'fc-timeline-slot-label',
1003
- 'fc-timeline-slot',
1004
- cell.isWeekStart ? 'fc-timeline-slot-em' : '',
1005
- 'fc-header-cell',
1006
- 'fc-cell',
1007
- 'fc-flex-column',
1008
- 'fc-justify-center',
1009
- props.isCentered ? 'fc-align-center' : 'fc-align-start',
1010
- ...( // TODO: so slot classnames for week/month/bigger. see note above about rowUnit
1011
- cell.rowUnit === 'time' ?
1012
- internal$1.getSlotClassNames(dateMeta, context.theme) :
1013
- internal$1.getDayClassNames(dateMeta, context.theme)),
1014
- ], elAttrs: {
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: {
1015
932
  'data-date': dateEnv.formatIso(cell.date, {
1016
933
  omitTime: !tDateProfile.isTimeScale,
1017
934
  omitTimeZoneOffset: true,
1018
935
  }),
1019
- }, elStyle: {
936
+ }, style: {
1020
937
  width: props.slotWidth != null
1021
938
  ? props.slotWidth * cell.colspan
1022
939
  : undefined,
1023
- }, renderProps: renderProps, generatorName: "slotLabelContent", customGenerator: options.slotLabelContent, defaultGenerator: renderInnerContent, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (preact.createElement("div", { ref: this.innerElRef, className: [
1024
- 'fc-flex-column',
1025
- props.isSticky ? 'fc-sticky-x' : '',
1026
- ].join(' ') },
1027
- preact.createElement(InnerContent, { elTag: "a", elClasses: [
1028
- 'fc-cell-inner',
1029
- 'fc-padding-md',
1030
- ], elAttrs: this.buildCellNavLinkAttrs(context, cell.date, cell.rowUnit) })))));
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 }))));
1031
941
  }
1032
942
  componentDidMount() {
1033
943
  const { props } = this;
@@ -1043,7 +953,10 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
1043
953
  });
1044
954
  }
1045
955
  componentWillUnmount() {
956
+ const { props } = this;
1046
957
  this.detachSize();
958
+ internal$1.setRef(props.innerWidthRef, null);
959
+ internal$1.setRef(props.innerHeightRef, null);
1047
960
  }
1048
961
  }
1049
962
  // Utils
@@ -1098,18 +1011,24 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
1098
1011
  const { props, innerWidthRefMap, innerHeightRefMap } = this;
1099
1012
  const isCentered = !(props.tDateProfile.isTimeScale && props.isLastRow);
1100
1013
  const isSticky = !props.isLastRow;
1101
- return (preact.createElement("div", { className: 'fc-row', style: { height: props.height } }, props.cells.map((cell) => {
1014
+ return (preact.createElement("div", { className: internal$1.joinClassNames('fc-flex-row fc-grow', // TODO: move fc-grow to parent?
1015
+ !props.isLastRow && 'fc-border-b') }, props.cells.map((cell, cellI) => {
1102
1016
  // TODO: make this part of the cell obj?
1103
1017
  // TODO: rowUnit seems wrong sometimes. says 'month' when it should be day
1104
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?
1105
1020
  const key = cell.rowUnit + ':' + cell.date.toISOString();
1106
- 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,
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),
1107
1022
  // refs
1108
1023
  innerWidthRef: innerWidthRefMap.createRef(key), innerHeightRef: innerHeightRefMap.createRef(key),
1109
1024
  // dimensions
1110
1025
  slotWidth: props.slotWidth }));
1111
1026
  })));
1112
1027
  }
1028
+ componentWillUnmount() {
1029
+ internal$1.setRef(this.props.innerWidthRef, null);
1030
+ internal$1.setRef(this.props.innerHeighRef, null);
1031
+ }
1113
1032
  }
1114
1033
 
1115
1034
  class TimelineNowIndicatorLine extends internal$1.BaseComponent {
@@ -1117,7 +1036,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
1117
1036
  const { props, context } = this;
1118
1037
  return (preact.createElement("div", { className: "fc-timeline-now-indicator-container" },
1119
1038
  preact.createElement(internal$1.NowIndicatorContainer // TODO: make separate component?
1120
- , { elClasses: ['fc-timeline-now-indicator-line'], elStyle: props.slotWidth != null
1039
+ , { className: 'fc-timeline-now-indicator-line', style: props.slotWidth != null
1121
1040
  ? horizontalCoordToCss(dateToCoord(props.nowDate, context.dateEnv, props.tDateProfile, props.slotWidth), context.isRtl)
1122
1041
  : {}, isAxis: false, date: props.nowDate })));
1123
1042
  }
@@ -1127,7 +1046,7 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
1127
1046
  render() {
1128
1047
  const { props, context } = this;
1129
1048
  return (preact.createElement("div", { className: "fc-timeline-now-indicator-container" },
1130
- preact.createElement(internal$1.NowIndicatorContainer, { elClasses: ['fc-timeline-now-indicator-arrow'], elStyle: props.slotWidth != null
1049
+ preact.createElement(internal$1.NowIndicatorContainer, { className: 'fc-timeline-now-indicator-arrow', style: props.slotWidth != null
1131
1050
  ? horizontalCoordToCss(dateToCoord(props.nowDate, context.dateEnv, props.tDateProfile, props.slotWidth), context.isRtl)
1132
1051
  : {}, isAxis: true, date: props.nowDate })));
1133
1052
  }
@@ -1143,48 +1062,50 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
1143
1062
  this.headerScrollerRef = preact.createRef();
1144
1063
  this.bodyScrollerRef = preact.createRef();
1145
1064
  this.footerScrollerRef = preact.createRef();
1065
+ this.headerRowInnerWidthMap = new internal$1.RefMap(() => {
1066
+ internal$1.afterSize(this.handleSlotInnerWidths);
1067
+ });
1068
+ this.scrollTime = null;
1146
1069
  // Sizing
1147
1070
  // -----------------------------------------------------------------------------------------------
1148
- this.handleHeaderSlotInnerWidth = (innerWidth) => {
1149
- this.headerSlotInnerWidth = innerWidth;
1150
- internal$1.afterSize(this.handleSlotInnerWidths);
1151
- };
1152
1071
  this.handleBodySlotInnerWidth = (innerWidth) => {
1153
1072
  this.bodySlotInnerWidth = innerWidth;
1154
1073
  internal$1.afterSize(this.handleSlotInnerWidths);
1155
1074
  };
1156
1075
  this.handleSlotInnerWidths = () => {
1157
1076
  const { state } = this;
1158
- const slotInnerWidth = Math.max(this.headerSlotInnerWidth, this.bodySlotInnerWidth);
1077
+ const slotInnerWidth = Math.max(this.headerRowInnerWidthMap.current.get(this.tDateProfile.cellRows.length - 1) || 0, this.bodySlotInnerWidth);
1159
1078
  if (state.slotInnerWidth !== slotInnerWidth) {
1160
1079
  this.setState({ slotInnerWidth });
1161
1080
  }
1162
1081
  };
1163
- this.handleScrollerWidth = (scrollerWidth) => {
1082
+ this.handleClientWidth = (clientWidth) => {
1164
1083
  this.setState({
1165
- scrollerWidth,
1084
+ clientWidth,
1166
1085
  });
1167
1086
  };
1168
- this.handleLeftScrollbarWidth = (leftScrollbarWidth) => {
1087
+ this.handleEndScrollbarWidth = (endScrollbarWidth) => {
1169
1088
  this.setState({
1170
- leftScrollbarWidth
1089
+ endScrollbarWidth
1171
1090
  });
1172
1091
  };
1173
- this.handleRightScrollbarWidth = (rightScrollbarWidth) => {
1174
- this.setState({
1175
- rightScrollbarWidth
1176
- });
1092
+ this.handleTimeScroll = (scrollTime) => {
1093
+ this.scrollTime = scrollTime;
1094
+ this.updateScroll();
1177
1095
  };
1178
- this.timeScrollResponder = new internal$1.ScrollResponder((time) => {
1179
- const { props, context, tDateProfile, slotWidth } = this;
1180
- if (slotWidth != null) {
1181
- const x = timeToCoord(time, context.dateEnv, props.dateProfile, tDateProfile, slotWidth) +
1182
- (context.isRtl ? -1 : 1); // overcome border. TODO: DRY this up
1096
+ this.updateScroll = () => {
1097
+ const { props, context, tDateProfile, scrollTime, slotWidth } = this;
1098
+ if (scrollTime != null && slotWidth != null) {
1099
+ let x = timeToCoord(scrollTime, context.dateEnv, props.dateProfile, tDateProfile, slotWidth);
1100
+ if (x) {
1101
+ x += 1; // overcome border. TODO: DRY this up
1102
+ }
1183
1103
  this.syncedScroller.scrollTo({ x });
1184
- return true;
1185
1104
  }
1186
- return false;
1187
- });
1105
+ };
1106
+ this.clearScroll = () => {
1107
+ this.scrollTime = null;
1108
+ };
1188
1109
  // Hit System
1189
1110
  // -----------------------------------------------------------------------------------------------
1190
1111
  this.handeBodyEl = (el) => {
@@ -1210,44 +1131,30 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
1210
1131
  const stickyFooterScrollbar = !props.forPrint && internal$1.getStickyFooterScrollbar(options);
1211
1132
  /* table positions */
1212
1133
  const [canvasWidth, slotWidth] = this.computeSlotWidth(tDateProfile.slotCnt, tDateProfile.slotsPerLabel, options.slotMinWidth, state.slotInnerWidth, // is ACTUALLY the label width. rename?
1213
- state.scrollerWidth);
1134
+ state.clientWidth);
1214
1135
  this.slotWidth = slotWidth;
1215
1136
  return (preact.createElement(internal$1.NowTimer, { unit: timerUnit }, (nowDate, todayRange) => {
1216
1137
  const enableNowIndicator = // TODO: DRY
1217
1138
  options.nowIndicator &&
1218
1139
  slotWidth != null &&
1219
1140
  internal$1.rangeContainsMarker(props.dateProfile.currentRange, nowDate);
1220
- return (preact.createElement(internal$1.ViewContainer, { viewSpec: context.viewSpec, elClasses: [
1221
- 'fc-timeline-view',
1222
- 'fc-flex-column',
1223
- 'fc-border',
1224
- ] },
1225
- preact.createElement(internal$1.Scroller, { horizontal: true, hideScrollbars: true, elClassNames: [
1226
- 'fc-timeline-header',
1227
- 'fc-rowgroup',
1228
- stickyHeaderDates ? 'fc-sticky-header' : '',
1229
- ], ref: this.headerScrollerRef },
1230
- preact.createElement("div", { className: 'fc-rel fc-content-box' // origin for now-indicator
1231
- , style: {
1232
- width: canvasWidth,
1233
- paddingLeft: state.leftScrollbarWidth,
1234
- paddingRight: state.rightScrollbarWidth,
1235
- } },
1236
- preact.createElement("div", null, cellRows.map((cells, rowLevel) => {
1141
+ return (preact.createElement(internal$1.ViewContainer, { viewSpec: context.viewSpec, className: internal$1.joinClassNames('fc-timeline fc-border',
1142
+ // HACK for Safari print-mode, where fc-scroller-no-bars won't take effect for
1143
+ // the below Scrollers if they have liquid flex height
1144
+ !props.forPrint && 'fc-flex-col') },
1145
+ preact.createElement(internal$1.Scroller, { horizontal: true, hideScrollbars: true, className: internal$1.joinClassNames('fc-timeline-header fc-flex-row fc-border-b', stickyHeaderDates && 'fc-table-header-sticky'), ref: this.headerScrollerRef },
1146
+ preact.createElement("div", {
1147
+ // TODO: DRY
1148
+ className: internal$1.joinClassNames('fc-rel', // origin for now-indicator
1149
+ canvasWidth == null && 'fc-liquid'), style: { width: canvasWidth } },
1150
+ cellRows.map((cells, rowLevel) => {
1237
1151
  const isLast = rowLevel === cellRows.length - 1;
1238
- return (preact.createElement(TimelineHeaderRow, { key: rowLevel, dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange, rowLevel: rowLevel, isLastRow: isLast, cells: cells, slotWidth: slotWidth, innerWidthRef: isLast ? this.handleHeaderSlotInnerWidth : undefined }));
1239
- })),
1240
- enableNowIndicator && (
1241
- // TODO: make this positioned WITHIN padding?
1242
- preact.createElement(TimelineNowIndicatorArrow, { tDateProfile: tDateProfile, nowDate: nowDate, slotWidth: slotWidth })))),
1243
- preact.createElement(internal$1.Scroller, { vertical: verticalScrolling, horizontal: true, elClassNames: [
1244
- 'fc-timeline-body',
1245
- 'fc-rowgroup',
1246
- verticalScrolling ? 'fc-liquid' : '',
1247
- ], ref: this.bodyScrollerRef, widthRef: this.handleScrollerWidth, leftScrollbarWidthRef: this.handleLeftScrollbarWidth, rightScrollbarWidthRef: this.handleRightScrollbarWidth },
1248
- preact.createElement("div", { className: "fc-rel fc-grow", style: {
1249
- width: canvasWidth,
1250
- }, ref: this.handeBodyEl },
1152
+ 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
+ }),
1154
+ enableNowIndicator && (preact.createElement(TimelineNowIndicatorArrow, { tDateProfile: tDateProfile, nowDate: nowDate, slotWidth: slotWidth }))),
1155
+ Boolean(state.endScrollbarWidth) && (preact.createElement("div", { className: 'fc-border-s fc-filler', style: { minWidth: state.endScrollbarWidth } }))),
1156
+ preact.createElement(internal$1.Scroller, { vertical: verticalScrolling, horizontal: true, hideScrollbars: props.forPrint, className: internal$1.joinClassNames('fc-timeline-body fc-flex-col', verticalScrolling && 'fc-liquid'), ref: this.bodyScrollerRef, clientWidthRef: this.handleClientWidth, endScrollbarWidthRef: this.handleEndScrollbarWidth },
1157
+ preact.createElement("div", { className: "fc-rel fc-grow", style: { width: canvasWidth }, ref: this.handeBodyEl },
1251
1158
  preact.createElement(TimelineSlats, { dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange,
1252
1159
  // ref
1253
1160
  innerWidthRef: this.handleBodySlotInnerWidth,
@@ -1262,27 +1169,26 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
1262
1169
  // Lifecycle
1263
1170
  // -----------------------------------------------------------------------------------------------
1264
1171
  componentDidMount() {
1265
- const { context } = this;
1266
- const { options } = context;
1267
- const ScrollerSyncer = internal$1.getScrollerSyncerClass(this.context.pluginHooks);
1268
- this.syncedScroller = new ScrollerSyncer(true); // horizontal=true
1172
+ this.syncedScroller = new internal$2.ScrollerSyncer(true); // horizontal=true
1269
1173
  this.updateSyncedScroller();
1270
- context.emitter.on('_timeScrollRequest', this.timeScrollResponder.handleScroll);
1271
- this.timeScrollResponder.handleScroll(options.scrollTime);
1174
+ this.resetScroll();
1175
+ this.context.emitter.on('_timeScrollRequest', this.handleTimeScroll);
1176
+ this.syncedScroller.addScrollEndListener(this.clearScroll);
1272
1177
  }
1273
1178
  componentDidUpdate(prevProps) {
1274
- const { options } = this.context;
1275
1179
  this.updateSyncedScroller();
1276
- if (prevProps.dateProfile !== this.props.dateProfile && options.scrollTimeReset) {
1277
- this.timeScrollResponder.handleScroll(options.scrollTime);
1180
+ if (prevProps.dateProfile !== this.props.dateProfile && this.context.options.scrollTimeReset) {
1181
+ this.resetScroll();
1278
1182
  }
1279
1183
  else {
1280
- this.timeScrollResponder.drain();
1184
+ // TODO: inefficient to update so often
1185
+ this.updateScroll();
1281
1186
  }
1282
1187
  }
1283
1188
  componentWillUnmount() {
1284
1189
  this.syncedScroller.destroy();
1285
- this.context.emitter.off('_timeScrollRequest', this.timeScrollResponder.handleScroll);
1190
+ this.context.emitter.off('_timeScrollRequest', this.handleTimeScroll);
1191
+ this.syncedScroller.removeScrollEndListener(this.clearScroll);
1286
1192
  }
1287
1193
  // Scrolling
1288
1194
  // -----------------------------------------------------------------------------------------------
@@ -1291,7 +1197,10 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
1291
1197
  this.headerScrollerRef.current,
1292
1198
  this.bodyScrollerRef.current,
1293
1199
  this.footerScrollerRef.current
1294
- ], this.context.isRtl);
1200
+ ]);
1201
+ }
1202
+ resetScroll() {
1203
+ this.handleTimeScroll(this.context.options.scrollTime);
1295
1204
  }
1296
1205
  queryHit(positionLeft, positionTop, elWidth, elHeight) {
1297
1206
  const { props, context, tDateProfile, slotWidth } = this;
@@ -1338,12 +1247,12 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
1338
1247
  }
1339
1248
  }
1340
1249
 
1341
- var css_248z = ".fc-timeline-slots{z-index:1}.fc-timeline-slot-minor{border-style:dotted}.fc-timeline-now-indicator-container{bottom:0;left:0;overflow:hidden;position:absolute;right:0;top:0;z-index:4}.fc-timeline-now-indicator-arrow,.fc-timeline-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;pointer-events:none;position:absolute;top:0}.fc-timeline-now-indicator-arrow{border-left-color:transparent;border-right-color:transparent;border-width:6px 5px 0;margin:0 -5px}.fc-timeline-now-indicator-line{border-width:0 0 0 1px;bottom:0}.fc-timeline-events{z-index:3}.fc-timeline-events-overlap-enabled{padding-bottom:10px}.fc-timeline-event{border-radius:0;font-size:var(--fc-small-font-size);margin-bottom:1px;z-index:1}.fc-timeline-event.fc-event-mirror{z-index:2}.fc-direction-ltr .fc-timeline-event.fc-event-end{margin-right:1px}.fc-direction-rtl .fc-timeline-event.fc-event-end{margin-left:1px}.fc-timeline-event-spacious{margin-bottom:0;padding-bottom:5px;padding-top:5px}.fc-timeline-event .fc-event-inner{align-items:center;display:flex;flex-direction:row;padding:2px 1px}.fc-timeline-event:not(.fc-event-end) .fc-event-inner:after,.fc-timeline-event:not(.fc-event-start) .fc-event-inner:before{border-color:transparent #000;border-style:solid;border-width:5px;content:\"\";flex-grow:0;flex-shrink:0;height:0;margin:0 1px;opacity:.5;width:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-start) .fc-event-inner:before,.fc-direction-rtl .fc-timeline-event:not(.fc-event-end) .fc-event-inner:after{border-left:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-end) .fc-event-inner:after,.fc-direction-rtl .fc-timeline-event:not(.fc-event-start) .fc-event-inner:before{border-right:0}.fc-timeline-event .fc-event-time{font-weight:700}.fc-timeline-event .fc-event-time,.fc-timeline-event .fc-event-title{padding:0 2px}.fc-timeline-more-link{align-items:flex-start;background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;display:flex;flex-direction:column;font-size:var(--fc-small-font-size);padding:1px}.fc-direction-ltr .fc-timeline-more-link{margin-right:1px}.fc-direction-rtl .fc-timeline-more-link{margin-left:1px}.fc-timeline-more-link-inner{padding:2px}.fc-timeline-bg{bottom:0;left:0;position:absolute;right:0;top:0;z-index:2}.fc-timeline-bg .fc-non-business{z-index:1}.fc-timeline-bg .fc-bg-event{z-index:2}.fc-timeline-bg .fc-highlight{z-index:3}.fc-timeline-bg-harness{bottom:0;position:absolute;top:0}";
1250
+ var css_248z = ".fc-timeline-slots{z-index:1}.fc-timeline-events{position:relative;z-index:2}.fc-timeline-slot-minor{border-style:dotted}.fc-timeline-events-overlap-enabled{padding-bottom:10px}.fc-timeline-event{border-radius:0;font-size:var(--fc-small-font-size);margin-bottom:1px}.fc-direction-ltr .fc-timeline-event.fc-event-end{margin-right:1px}.fc-direction-rtl .fc-timeline-event.fc-event-end{margin-left:1px}.fc-timeline-event .fc-event-inner{align-items:center;display:flex;flex-direction:row;padding:2px 1px}.fc-timeline-event-spacious .fc-event-inner{padding-bottom:5px;padding-top:5px}.fc-timeline-event .fc-event-time{font-weight:700}.fc-timeline-event .fc-event-time,.fc-timeline-event .fc-event-title{padding:0 2px}.fc-timeline-event:not(.fc-event-end) .fc-event-inner:after,.fc-timeline-event:not(.fc-event-start) .fc-event-inner:before{border-color:transparent #000;border-style:solid;border-width:5px;content:\"\";flex-grow:0;flex-shrink:0;height:0;margin:0 1px;opacity:.5;width:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-start) .fc-event-inner:before,.fc-direction-rtl .fc-timeline-event:not(.fc-event-end) .fc-event-inner:after{border-left:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-end) .fc-event-inner:after,.fc-direction-rtl .fc-timeline-event:not(.fc-event-start) .fc-event-inner:before{border-right:0}.fc-timeline-more-link{align-items:flex-start;background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;display:flex;flex-direction:column;font-size:var(--fc-small-font-size);padding:1px}.fc-direction-ltr .fc-timeline-more-link{margin-right:1px}.fc-direction-rtl .fc-timeline-more-link{margin-left:1px}.fc-timeline-more-link-inner{padding:2px}.fc-timeline-now-indicator-container{bottom:0;left:0;overflow:hidden;pointer-events:none;position:absolute;right:0;top:0;z-index:4}.fc-timeline-now-indicator-arrow{border-bottom-style:solid;border-bottom-width:0;border-color:var(--fc-now-indicator-color);border-left:5px solid transparent;border-right:5px solid transparent;border-top-style:solid;border-top-width:6px;height:0;margin:0 -5px;position:absolute;top:0;width:0}.fc-timeline-now-indicator-line{border-left:1px solid var(--fc-now-indicator-color);bottom:0;position:absolute;top:0}";
1342
1251
  internal$1.injectStyles(css_248z);
1343
1252
 
1344
1253
  var plugin = core.createPlugin({
1345
1254
  name: '@fullcalendar/timeline',
1346
- premiumReleaseDate: '2024-10-01',
1255
+ premiumReleaseDate: '2024-12-19',
1347
1256
  deps: [premiumCommonPlugin__default["default"]],
1348
1257
  initialView: 'timelineDay',
1349
1258
  views: {
@@ -1382,8 +1291,6 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
1382
1291
  createHorizontalStyle: createHorizontalStyle,
1383
1292
  computeSlotWidth: computeSlotWidth,
1384
1293
  timeToCoord: timeToCoord,
1385
- coordToCss: coordToCss,
1386
- coordsToCss: coordsToCss,
1387
1294
  TimelineLaneSlicer: TimelineLaneSlicer,
1388
1295
  TimelineHeaderRow: TimelineHeaderRow,
1389
1296
  TimelineNowIndicatorArrow: TimelineNowIndicatorArrow,
@@ -1399,4 +1306,4 @@ FullCalendar.Timeline = (function (exports, core, premiumCommonPlugin, internal$
1399
1306
 
1400
1307
  return exports;
1401
1308
 
1402
- })({}, FullCalendar, FullCalendar.PremiumCommon, FullCalendar.Internal, FullCalendar.Preact);
1309
+ })({}, FullCalendar, FullCalendar.PremiumCommon, FullCalendar.Internal, FullCalendar.Preact, FullCalendar.ScrollGrid.Internal);