@fullcalendar/multimonth 7.0.0-beta.3 → 7.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs CHANGED
@@ -16,6 +16,7 @@ class SingleMonth extends internal_cjs.DateComponent {
16
16
  this.buildDateRowConfig = internal_cjs.memoize(internal_cjs$1.buildDateRowConfig);
17
17
  // internal
18
18
  this.slicer = new internal_cjs$1.DayTableSlicer();
19
+ this.titleId = internal_cjs.getUniqueDomId();
19
20
  }
20
21
  render() {
21
22
  const { props, context } = this;
@@ -31,23 +32,22 @@ class SingleMonth extends internal_cjs.DateComponent {
31
32
  const invRowAspectRatio = invAspectRatio / dayTableModel.rowCnt;
32
33
  const isHeaderSticky = !forPrint;
33
34
  const isAspectRatio = !forPrint || props.hasLateralSiblings;
34
- return (preact_cjs.createElement("div", { "data-date": props.isoDateStr, className: internal_cjs.joinClassNames('fc-multimonth-month', props.hasLateralSiblings && 'fc-break-inside-avoid'),
35
- // override fc-liquid's basis. fc-grow isn't sufficient because doesn't set min-width:0
36
- style: { width: props.width } },
37
- preact_cjs.createElement("div", { className: "fc-multimonth-header", style: {
38
- marginBottom: isHeaderSticky ? internal_cjs.fracToCssDim(invRowAspectRatio) : undefined,
39
- } },
40
- preact_cjs.createElement("div", { className: "fc-multimonth-title" }, context.dateEnv.format(props.dateProfile.currentRange.start, props.titleFormat)),
41
- preact_cjs.createElement(internal_cjs$1.DayGridHeaderRow, Object.assign({}, rowConfig, { className: 'fc-multimonth-header-row' }))),
42
- preact_cjs.createElement("div", { className: internal_cjs.joinClassNames('fc-multimonth-body', isAspectRatio && 'fc-rel'), style: {
43
- marginTop: isHeaderSticky ? internal_cjs.fracToCssDim(-invRowAspectRatio) : undefined,
44
- paddingBottom: isAspectRatio ? internal_cjs.fracToCssDim(invAspectRatio) : undefined,
45
- } },
46
- preact_cjs.createElement(internal_cjs$1.DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: dayTableModel.cellRows, className: isAspectRatio ? 'fc-fill' : '', forPrint: forPrint && !props.hasLateralSiblings, dayMaxEvents: forPrint ? undefined : options.dayMaxEvents, dayMaxEventRows: (forPrint && props.hasLateralSiblings) ? 1 : options.dayMaxEventRows,
47
- // content
48
- fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection,
49
- // dimensions
50
- visibleWidth: props.visibleWidth }))));
35
+ return (preact_cjs.createElement("div", { role: 'listitem', className: 'fc-multimonth-month-outer', style: { width: props.width } },
36
+ preact_cjs.createElement("div", { role: 'grid', "aria-labelledby": this.titleId, "data-date": props.isoDateStr, className: internal_cjs.joinClassNames('fc-multimonth-month', props.hasLateralSiblings && 'fc-break-inside-avoid') },
37
+ preact_cjs.createElement("div", { className: "fc-multimonth-header", style: {
38
+ marginBottom: isHeaderSticky ? internal_cjs.fracToCssDim(invRowAspectRatio) : undefined,
39
+ } },
40
+ preact_cjs.createElement("div", { id: this.titleId, className: 'fc-multimonth-title' }, context.dateEnv.format(props.dateProfile.currentRange.start, props.titleFormat)),
41
+ preact_cjs.createElement(internal_cjs$1.DayGridHeaderRow, Object.assign({}, rowConfig, { role: 'row', className: 'fc-multimonth-header-row' }))),
42
+ preact_cjs.createElement("div", { className: internal_cjs.joinClassNames('fc-multimonth-body', isAspectRatio && 'fc-rel'), style: {
43
+ marginTop: isHeaderSticky ? internal_cjs.fracToCssDim(-invRowAspectRatio) : undefined,
44
+ paddingBottom: isAspectRatio ? internal_cjs.fracToCssDim(invAspectRatio) : undefined,
45
+ } },
46
+ preact_cjs.createElement(internal_cjs$1.DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: dayTableModel.cellRows, className: isAspectRatio ? 'fc-fill' : '', forPrint: forPrint && !props.hasLateralSiblings, dayMaxEvents: forPrint ? undefined : options.dayMaxEvents, dayMaxEventRows: (forPrint && props.hasLateralSiblings) ? 1 : options.dayMaxEventRows,
47
+ // content
48
+ fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection,
49
+ // dimensions
50
+ visibleWidth: props.visibleWidth })))));
51
51
  }
52
52
  }
53
53
 
@@ -61,22 +61,11 @@ class MultiMonthView extends internal_cjs.DateComponent {
61
61
  this.scrollerRef = preact_cjs.createRef();
62
62
  this.innerElRef = preact_cjs.createRef(); // .fc-multimonth-inner
63
63
  this.scrollDate = null;
64
- this.updateScroll = () => {
65
- if (this.scrollDate != null &&
66
- this.state.innerWidth != null // render completed?
67
- ) {
68
- const scroller = this.scrollerRef.current;
69
- const innerEl = this.innerElRef.current;
70
- const monthEl = innerEl.querySelector(`[data-date="${internal_cjs.formatIsoMonthStr(this.scrollDate)}"]`);
71
- const scrollTop = Math.ceil(// for fractions, err on the side of scrolling further
72
- monthEl.getBoundingClientRect().top -
73
- innerEl.getBoundingClientRect().top);
74
- scroller.scrollTo({ y: scrollTop });
64
+ this.handleScrollEnd = ({ isUser }) => {
65
+ if (isUser) {
66
+ this.scrollDate = null;
75
67
  }
76
68
  };
77
- this.clearScroll = () => {
78
- this.scrollDate = null;
79
- };
80
69
  }
81
70
  render() {
82
71
  const { context, props, state } = this;
@@ -99,14 +88,14 @@ class MultiMonthView extends internal_cjs.DateComponent {
99
88
  cssMonthWidth = internal_cjs.fracToCssDim(1 / cols);
100
89
  hasLateralSiblings = cols > 1;
101
90
  }
102
- return (preact_cjs.createElement(internal_cjs.NowTimer, { unit: "day" }, (nowDate, todayRange) => (preact_cjs.createElement(internal_cjs.ViewContainer, { className: internal_cjs.joinClassNames('fc-multimonth fc-border', (cols === 1) ?
91
+ return (preact_cjs.createElement(internal_cjs.NowTimer, { unit: "day" }, (nowDate, todayRange) => (preact_cjs.createElement(internal_cjs.ViewContainer, { viewSpec: context.viewSpec, className: internal_cjs.joinClassNames('fc-multimonth fc-border', (cols === 1) ?
103
92
  'fc-multimonth-singlecol' :
104
93
  'fc-multimonth-multicol',
105
94
  // HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
106
95
  // https://stackoverflow.com/a/60256345
107
- !props.forPrint && 'fc-flex-col'), viewSpec: context.viewSpec },
96
+ !props.forPrint && 'fc-flex-col') },
108
97
  preact_cjs.createElement(internal_cjs.Scroller, { vertical: verticalScrolling, className: verticalScrolling ? 'fc-liquid' : '', ref: this.scrollerRef },
109
- preact_cjs.createElement("div", { ref: this.innerElRef, className: 'fc-multimonth-inner' }, monthDateProfiles.map((monthDateProfile) => {
98
+ preact_cjs.createElement("div", { role: 'list', "aria-labelledby": props.labelId, "aria-label": props.labelStr, className: 'fc-multimonth-inner', ref: this.innerElRef }, monthDateProfiles.map((monthDateProfile) => {
110
99
  const monthStr = internal_cjs.formatIsoMonthStr(monthDateProfile.currentRange.start);
111
100
  return (preact_cjs.createElement(SingleMonth, Object.assign({}, props, { key: monthStr, todayRange: todayRange, isoDateStr: monthStr, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width: cssMonthWidth, visibleWidth: computedMonthWidth, hasLateralSiblings: hasLateralSiblings })));
112
101
  })))))));
@@ -115,7 +104,7 @@ class MultiMonthView extends internal_cjs.DateComponent {
115
104
  // -----------------------------------------------------------------------------------------------
116
105
  componentDidMount() {
117
106
  this.resetScroll();
118
- this.scrollerRef.current.addScrollEndListener(this.clearScroll);
107
+ this.scrollerRef.current.addScrollEndListener(this.handleScrollEnd);
119
108
  this.disconnectInnerWidth = internal_cjs.watchWidth(this.innerElRef.current, (innerWidth) => {
120
109
  internal_cjs.afterSize(() => {
121
110
  this.setState({ innerWidth });
@@ -129,18 +118,31 @@ class MultiMonthView extends internal_cjs.DateComponent {
129
118
  else {
130
119
  // NOT optimal to update so often
131
120
  // TODO: isolate dependencies of scroll coordinate
132
- this.updateScroll();
121
+ this.applyScroll();
133
122
  }
134
123
  }
135
124
  componentWillUnmount() {
136
- this.scrollerRef.current.removeScrollEndListener(this.clearScroll);
125
+ this.scrollerRef.current.removeScrollEndListener(this.handleScrollEnd);
137
126
  this.disconnectInnerWidth();
138
127
  }
139
128
  // Scrolling
140
129
  // -----------------------------------------------------------------------------------------------
141
130
  resetScroll() {
142
131
  this.scrollDate = this.props.dateProfile.currentDate;
143
- this.updateScroll();
132
+ this.applyScroll();
133
+ }
134
+ applyScroll() {
135
+ if (this.scrollDate != null &&
136
+ this.state.innerWidth != null // render completed?
137
+ ) {
138
+ const scroller = this.scrollerRef.current;
139
+ const innerEl = this.innerElRef.current;
140
+ const monthEl = innerEl.querySelector(`[data-date="${internal_cjs.formatIsoMonthStr(this.scrollDate)}"]`);
141
+ const scrollTop = Math.ceil(// for fractions, err on the side of scrolling further
142
+ monthEl.getBoundingClientRect().top -
143
+ innerEl.getBoundingClientRect().top);
144
+ scroller.scrollTo({ y: scrollTop });
145
+ }
144
146
  }
145
147
  }
146
148
  // date profile
@@ -206,7 +208,7 @@ const OPTION_REFINERS = {
206
208
  multiMonthMinWidth: Number,
207
209
  };
208
210
 
209
- var css_248z = ".fc-media-screen .fc-multimonth-inner{display:flex;flex-direction:row;flex-wrap:wrap}.fc-media-print.fc-direction-ltr .fc-multimonth-inner>*{float:left}.fc-media-print.fc-direction-rtl .fc-multimonth-inner>*{float:right}.fc-media-print .fc-multimonth-inner:after{clear:both;content:\"\";display:block}.fc-multimonth-multicol .fc-multimonth-month{padding:1.2em}.fc-multimonth-singlecol .fc-multimonth-title{padding:.5em 0}.fc-multimonth-multicol .fc-multimonth-title{padding-bottom:1em}.fc-multimonth-title{font-size:1.2em;font-weight:700;text-align:center}.fc-multimonth-header-row{border-top:1px solid var(--fc-border-color)}.fc-multimonth-body:not(.fc-multimonth-singlecol .fc-multimonth-month:last-child .fc-multimonth-body),.fc-multimonth-header-row{border-bottom:1px solid var(--fc-border-color)}.fc-multimonth-multicol .fc-multimonth-body,.fc-multimonth-multicol .fc-multimonth-header-row{border-left:1px solid var(--fc-border-color);border-right:1px solid var(--fc-border-color);font-size:.9em;line-height:1}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:sticky;top:0;z-index:2}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-body{position:relative;z-index:1}";
211
+ var css_248z = ".fc-media-screen .fc-multimonth-inner{display:flex;flex-direction:row;flex-wrap:wrap}.fc-media-print.fc-direction-ltr .fc-multimonth-inner>*{float:left}.fc-media-print.fc-direction-rtl .fc-multimonth-inner>*{float:right}.fc-media-print .fc-multimonth-inner:after{clear:both;content:\"\";display:block}.fc-multimonth-multicol .fc-multimonth-month{padding:1.2em}.fc-multimonth-singlecol .fc-multimonth-title{padding:.5em 0}.fc-multimonth-multicol .fc-multimonth-title{padding-bottom:1em}.fc-multimonth-title{font-size:1.2em;font-weight:700;text-align:center}.fc-multimonth-header-row{border-top:1px solid var(--fc-border-color)}.fc-multimonth-body:not(.fc-multimonth-singlecol .fc-multimonth-month-outer:last-child .fc-multimonth-body),.fc-multimonth-header-row{border-bottom:1px solid var(--fc-border-color)}.fc-multimonth-multicol .fc-multimonth-body,.fc-multimonth-multicol .fc-multimonth-header-row{border-left:1px solid var(--fc-border-color);border-right:1px solid var(--fc-border-color);font-size:.9em;line-height:1}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:sticky;top:0;z-index:2}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-body{position:relative;z-index:1}";
210
212
  internal_cjs.injectStyles(css_248z);
211
213
 
212
214
  var index = index_cjs.createPlugin({
package/index.global.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- FullCalendar Multi-Month Plugin v7.0.0-beta.3
2
+ FullCalendar Multi-Month Plugin v7.0.0-beta.4
3
3
  Docs & License: https://fullcalendar.io/docs/multimonth-grid
4
4
  (c) 2024 Adam Shaw
5
5
  */
@@ -15,6 +15,7 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
15
15
  this.buildDateRowConfig = internal.memoize(internal$1.buildDateRowConfig);
16
16
  // internal
17
17
  this.slicer = new internal$1.DayTableSlicer();
18
+ this.titleId = internal.getUniqueDomId();
18
19
  }
19
20
  render() {
20
21
  const { props, context } = this;
@@ -30,23 +31,22 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
30
31
  const invRowAspectRatio = invAspectRatio / dayTableModel.rowCnt;
31
32
  const isHeaderSticky = !forPrint;
32
33
  const isAspectRatio = !forPrint || props.hasLateralSiblings;
33
- return (preact.createElement("div", { "data-date": props.isoDateStr, className: internal.joinClassNames('fc-multimonth-month', props.hasLateralSiblings && 'fc-break-inside-avoid'),
34
- // override fc-liquid's basis. fc-grow isn't sufficient because doesn't set min-width:0
35
- style: { width: props.width } },
36
- preact.createElement("div", { className: "fc-multimonth-header", style: {
37
- marginBottom: isHeaderSticky ? internal.fracToCssDim(invRowAspectRatio) : undefined,
38
- } },
39
- preact.createElement("div", { className: "fc-multimonth-title" }, context.dateEnv.format(props.dateProfile.currentRange.start, props.titleFormat)),
40
- preact.createElement(internal$1.DayGridHeaderRow, Object.assign({}, rowConfig, { className: 'fc-multimonth-header-row' }))),
41
- preact.createElement("div", { className: internal.joinClassNames('fc-multimonth-body', isAspectRatio && 'fc-rel'), style: {
42
- marginTop: isHeaderSticky ? internal.fracToCssDim(-invRowAspectRatio) : undefined,
43
- paddingBottom: isAspectRatio ? internal.fracToCssDim(invAspectRatio) : undefined,
44
- } },
45
- preact.createElement(internal$1.DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: dayTableModel.cellRows, className: isAspectRatio ? 'fc-fill' : '', forPrint: forPrint && !props.hasLateralSiblings, dayMaxEvents: forPrint ? undefined : options.dayMaxEvents, dayMaxEventRows: (forPrint && props.hasLateralSiblings) ? 1 : options.dayMaxEventRows,
46
- // content
47
- fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection,
48
- // dimensions
49
- visibleWidth: props.visibleWidth }))));
34
+ return (preact.createElement("div", { role: 'listitem', className: 'fc-multimonth-month-outer', style: { width: props.width } },
35
+ preact.createElement("div", { role: 'grid', "aria-labelledby": this.titleId, "data-date": props.isoDateStr, className: internal.joinClassNames('fc-multimonth-month', props.hasLateralSiblings && 'fc-break-inside-avoid') },
36
+ preact.createElement("div", { className: "fc-multimonth-header", style: {
37
+ marginBottom: isHeaderSticky ? internal.fracToCssDim(invRowAspectRatio) : undefined,
38
+ } },
39
+ preact.createElement("div", { id: this.titleId, className: 'fc-multimonth-title' }, context.dateEnv.format(props.dateProfile.currentRange.start, props.titleFormat)),
40
+ preact.createElement(internal$1.DayGridHeaderRow, Object.assign({}, rowConfig, { role: 'row', className: 'fc-multimonth-header-row' }))),
41
+ preact.createElement("div", { className: internal.joinClassNames('fc-multimonth-body', isAspectRatio && 'fc-rel'), style: {
42
+ marginTop: isHeaderSticky ? internal.fracToCssDim(-invRowAspectRatio) : undefined,
43
+ paddingBottom: isAspectRatio ? internal.fracToCssDim(invAspectRatio) : undefined,
44
+ } },
45
+ preact.createElement(internal$1.DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: dayTableModel.cellRows, className: isAspectRatio ? 'fc-fill' : '', forPrint: forPrint && !props.hasLateralSiblings, dayMaxEvents: forPrint ? undefined : options.dayMaxEvents, dayMaxEventRows: (forPrint && props.hasLateralSiblings) ? 1 : options.dayMaxEventRows,
46
+ // content
47
+ fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection,
48
+ // dimensions
49
+ visibleWidth: props.visibleWidth })))));
50
50
  }
51
51
  }
52
52
 
@@ -60,22 +60,11 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
60
60
  this.scrollerRef = preact.createRef();
61
61
  this.innerElRef = preact.createRef(); // .fc-multimonth-inner
62
62
  this.scrollDate = null;
63
- this.updateScroll = () => {
64
- if (this.scrollDate != null &&
65
- this.state.innerWidth != null // render completed?
66
- ) {
67
- const scroller = this.scrollerRef.current;
68
- const innerEl = this.innerElRef.current;
69
- const monthEl = innerEl.querySelector(`[data-date="${internal.formatIsoMonthStr(this.scrollDate)}"]`);
70
- const scrollTop = Math.ceil(// for fractions, err on the side of scrolling further
71
- monthEl.getBoundingClientRect().top -
72
- innerEl.getBoundingClientRect().top);
73
- scroller.scrollTo({ y: scrollTop });
63
+ this.handleScrollEnd = ({ isUser }) => {
64
+ if (isUser) {
65
+ this.scrollDate = null;
74
66
  }
75
67
  };
76
- this.clearScroll = () => {
77
- this.scrollDate = null;
78
- };
79
68
  }
80
69
  render() {
81
70
  const { context, props, state } = this;
@@ -98,14 +87,14 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
98
87
  cssMonthWidth = internal.fracToCssDim(1 / cols);
99
88
  hasLateralSiblings = cols > 1;
100
89
  }
101
- return (preact.createElement(internal.NowTimer, { unit: "day" }, (nowDate, todayRange) => (preact.createElement(internal.ViewContainer, { className: internal.joinClassNames('fc-multimonth fc-border', (cols === 1) ?
90
+ return (preact.createElement(internal.NowTimer, { unit: "day" }, (nowDate, todayRange) => (preact.createElement(internal.ViewContainer, { viewSpec: context.viewSpec, className: internal.joinClassNames('fc-multimonth fc-border', (cols === 1) ?
102
91
  'fc-multimonth-singlecol' :
103
92
  'fc-multimonth-multicol',
104
93
  // HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
105
94
  // https://stackoverflow.com/a/60256345
106
- !props.forPrint && 'fc-flex-col'), viewSpec: context.viewSpec },
95
+ !props.forPrint && 'fc-flex-col') },
107
96
  preact.createElement(internal.Scroller, { vertical: verticalScrolling, className: verticalScrolling ? 'fc-liquid' : '', ref: this.scrollerRef },
108
- preact.createElement("div", { ref: this.innerElRef, className: 'fc-multimonth-inner' }, monthDateProfiles.map((monthDateProfile) => {
97
+ preact.createElement("div", { role: 'list', "aria-labelledby": props.labelId, "aria-label": props.labelStr, className: 'fc-multimonth-inner', ref: this.innerElRef }, monthDateProfiles.map((monthDateProfile) => {
109
98
  const monthStr = internal.formatIsoMonthStr(monthDateProfile.currentRange.start);
110
99
  return (preact.createElement(SingleMonth, Object.assign({}, props, { key: monthStr, todayRange: todayRange, isoDateStr: monthStr, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width: cssMonthWidth, visibleWidth: computedMonthWidth, hasLateralSiblings: hasLateralSiblings })));
111
100
  })))))));
@@ -114,7 +103,7 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
114
103
  // -----------------------------------------------------------------------------------------------
115
104
  componentDidMount() {
116
105
  this.resetScroll();
117
- this.scrollerRef.current.addScrollEndListener(this.clearScroll);
106
+ this.scrollerRef.current.addScrollEndListener(this.handleScrollEnd);
118
107
  this.disconnectInnerWidth = internal.watchWidth(this.innerElRef.current, (innerWidth) => {
119
108
  internal.afterSize(() => {
120
109
  this.setState({ innerWidth });
@@ -128,18 +117,31 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
128
117
  else {
129
118
  // NOT optimal to update so often
130
119
  // TODO: isolate dependencies of scroll coordinate
131
- this.updateScroll();
120
+ this.applyScroll();
132
121
  }
133
122
  }
134
123
  componentWillUnmount() {
135
- this.scrollerRef.current.removeScrollEndListener(this.clearScroll);
124
+ this.scrollerRef.current.removeScrollEndListener(this.handleScrollEnd);
136
125
  this.disconnectInnerWidth();
137
126
  }
138
127
  // Scrolling
139
128
  // -----------------------------------------------------------------------------------------------
140
129
  resetScroll() {
141
130
  this.scrollDate = this.props.dateProfile.currentDate;
142
- this.updateScroll();
131
+ this.applyScroll();
132
+ }
133
+ applyScroll() {
134
+ if (this.scrollDate != null &&
135
+ this.state.innerWidth != null // render completed?
136
+ ) {
137
+ const scroller = this.scrollerRef.current;
138
+ const innerEl = this.innerElRef.current;
139
+ const monthEl = innerEl.querySelector(`[data-date="${internal.formatIsoMonthStr(this.scrollDate)}"]`);
140
+ const scrollTop = Math.ceil(// for fractions, err on the side of scrolling further
141
+ monthEl.getBoundingClientRect().top -
142
+ innerEl.getBoundingClientRect().top);
143
+ scroller.scrollTo({ y: scrollTop });
144
+ }
143
145
  }
144
146
  }
145
147
  // date profile
@@ -205,7 +207,7 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
205
207
  multiMonthMinWidth: Number,
206
208
  };
207
209
 
208
- var css_248z = ".fc-media-screen .fc-multimonth-inner{display:flex;flex-direction:row;flex-wrap:wrap}.fc-media-print.fc-direction-ltr .fc-multimonth-inner>*{float:left}.fc-media-print.fc-direction-rtl .fc-multimonth-inner>*{float:right}.fc-media-print .fc-multimonth-inner:after{clear:both;content:\"\";display:block}.fc-multimonth-multicol .fc-multimonth-month{padding:1.2em}.fc-multimonth-singlecol .fc-multimonth-title{padding:.5em 0}.fc-multimonth-multicol .fc-multimonth-title{padding-bottom:1em}.fc-multimonth-title{font-size:1.2em;font-weight:700;text-align:center}.fc-multimonth-header-row{border-top:1px solid var(--fc-border-color)}.fc-multimonth-body:not(.fc-multimonth-singlecol .fc-multimonth-month:last-child .fc-multimonth-body),.fc-multimonth-header-row{border-bottom:1px solid var(--fc-border-color)}.fc-multimonth-multicol .fc-multimonth-body,.fc-multimonth-multicol .fc-multimonth-header-row{border-left:1px solid var(--fc-border-color);border-right:1px solid var(--fc-border-color);font-size:.9em;line-height:1}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:sticky;top:0;z-index:2}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-body{position:relative;z-index:1}";
210
+ var css_248z = ".fc-media-screen .fc-multimonth-inner{display:flex;flex-direction:row;flex-wrap:wrap}.fc-media-print.fc-direction-ltr .fc-multimonth-inner>*{float:left}.fc-media-print.fc-direction-rtl .fc-multimonth-inner>*{float:right}.fc-media-print .fc-multimonth-inner:after{clear:both;content:\"\";display:block}.fc-multimonth-multicol .fc-multimonth-month{padding:1.2em}.fc-multimonth-singlecol .fc-multimonth-title{padding:.5em 0}.fc-multimonth-multicol .fc-multimonth-title{padding-bottom:1em}.fc-multimonth-title{font-size:1.2em;font-weight:700;text-align:center}.fc-multimonth-header-row{border-top:1px solid var(--fc-border-color)}.fc-multimonth-body:not(.fc-multimonth-singlecol .fc-multimonth-month-outer:last-child .fc-multimonth-body),.fc-multimonth-header-row{border-bottom:1px solid var(--fc-border-color)}.fc-multimonth-multicol .fc-multimonth-body,.fc-multimonth-multicol .fc-multimonth-header-row{border-left:1px solid var(--fc-border-color);border-right:1px solid var(--fc-border-color);font-size:.9em;line-height:1}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:sticky;top:0;z-index:2}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-body{position:relative;z-index:1}";
209
211
  internal.injectStyles(css_248z);
210
212
 
211
213
  var plugin = core.createPlugin({
@@ -1,6 +1,6 @@
1
1
  /*!
2
- FullCalendar Multi-Month Plugin v7.0.0-beta.3
2
+ FullCalendar Multi-Month Plugin v7.0.0-beta.4
3
3
  Docs & License: https://fullcalendar.io/docs/multimonth-grid
4
4
  (c) 2024 Adam Shaw
5
5
  */
6
- FullCalendar.MultiMonth=function(e,t,i,n,r){"use strict";class o extends n.DateComponent{constructor(){super(...arguments),this.buildDayTableModel=n.memoize(i.buildDayTableModel),this.createDayHeaderFormatter=n.memoize(i.createDayHeaderFormatter),this.buildDateRowConfig=n.memoize(i.buildDateRowConfig),this.slicer=new i.DayTableSlicer}render(){const{props:e,context:t}=this,{dateProfile:o,forPrint:l}=e,{options:a}=t,s=this.buildDayTableModel(o,t.dateProfileGenerator),c=this.slicer.sliceProps(e,o,a.nextDayThreshold,t,s),m=this.createDayHeaderFormatter(a.dayHeaderFormat,!1,s.colCnt),d=this.buildDateRowConfig(s.headerDates,!1,o,e.todayRange,m,t),h=1/a.aspectRatio,u=h/s.rowCnt,f=!l,g=!l||e.hasLateralSiblings;return r.createElement("div",{"data-date":e.isoDateStr,className:n.joinClassNames("fc-multimonth-month",e.hasLateralSiblings&&"fc-break-inside-avoid"),style:{width:e.width}},r.createElement("div",{className:"fc-multimonth-header",style:{marginBottom:f?n.fracToCssDim(u):void 0}},r.createElement("div",{className:"fc-multimonth-title"},t.dateEnv.format(e.dateProfile.currentRange.start,e.titleFormat)),r.createElement(i.DayGridHeaderRow,Object.assign({},d,{className:"fc-multimonth-header-row"}))),r.createElement("div",{className:n.joinClassNames("fc-multimonth-body",g&&"fc-rel"),style:{marginTop:f?n.fracToCssDim(-u):void 0,paddingBottom:g?n.fracToCssDim(h):void 0}},r.createElement(i.DayGridRows,{dateProfile:e.dateProfile,todayRange:e.todayRange,cellRows:s.cellRows,className:g?"fc-fill":"",forPrint:l&&!e.hasLateralSiblings,dayMaxEvents:l?void 0:a.dayMaxEvents,dayMaxEventRows:l&&e.hasLateralSiblings?1:a.dayMaxEventRows,fgEventSegs:c.fgEventSegs,bgEventSegs:c.bgEventSegs,businessHourSegs:c.businessHourSegs,dateSelectionSegs:c.dateSelectionSegs,eventDrag:c.eventDrag,eventResize:c.eventResize,eventSelection:c.eventSelection,visibleWidth:e.visibleWidth})))}}class l extends n.DateComponent{constructor(){super(...arguments),this.splitDateProfileByMonth=n.memoize(s),this.buildMonthFormat=n.memoize(d),this.scrollerRef=r.createRef(),this.innerElRef=r.createRef(),this.scrollDate=null,this.updateScroll=()=>{if(null!=this.scrollDate&&null!=this.state.innerWidth){const e=this.scrollerRef.current,t=this.innerElRef.current,i=t.querySelector(`[data-date="${n.formatIsoMonthStr(this.scrollDate)}"]`),r=Math.ceil(i.getBoundingClientRect().top-t.getBoundingClientRect().top);e.scrollTo({y:r})}},this.clearScroll=()=>{this.scrollDate=null}}render(){const{context:e,props:t,state:i}=this,{options:l}=e,a=!t.forPrint&&!n.getIsHeightAuto(l),s=this.splitDateProfileByMonth(e.dateProfileGenerator,t.dateProfile,e.dateEnv,l.fixedWeekCount,l.showNonCurrentDates),c=this.buildMonthFormat(l.multiMonthTitleFormat,s),{multiMonthMinWidth:m,multiMonthMaxColumns:d}=l,{innerWidth:h}=i;let u,f,g,p=!1;return null!=h&&(u=Math.max(1,Math.min(d,Math.floor(h/m))),t.forPrint&&(u=Math.min(u,2)),f=h/u,g=n.fracToCssDim(1/u),p=u>1),r.createElement(n.NowTimer,{unit:"day"},(i,l)=>r.createElement(n.ViewContainer,{className:n.joinClassNames("fc-multimonth fc-border",1===u?"fc-multimonth-singlecol":"fc-multimonth-multicol",!t.forPrint&&"fc-flex-col"),viewSpec:e.viewSpec},r.createElement(n.Scroller,{vertical:a,className:a?"fc-liquid":"",ref:this.scrollerRef},r.createElement("div",{ref:this.innerElRef,className:"fc-multimonth-inner"},s.map(e=>{const i=n.formatIsoMonthStr(e.currentRange.start);return r.createElement(o,Object.assign({},t,{key:i,todayRange:l,isoDateStr:i,titleFormat:c,dateProfile:e,width:g,visibleWidth:f,hasLateralSiblings:p}))})))))}componentDidMount(){this.resetScroll(),this.scrollerRef.current.addScrollEndListener(this.clearScroll),this.disconnectInnerWidth=n.watchWidth(this.innerElRef.current,e=>{n.afterSize(()=>{this.setState({innerWidth:e})})})}componentDidUpdate(e){e.dateProfile!==this.props.dateProfile&&this.context.options.scrollTimeReset?this.resetScroll():this.updateScroll()}componentWillUnmount(){this.scrollerRef.current.removeScrollEndListener(this.clearScroll),this.disconnectInnerWidth()}resetScroll(){this.scrollDate=this.props.dateProfile.currentDate,this.updateScroll()}}const a=n.createDuration(1,"month");function s(e,t,r,o,l){const{start:s,end:c}=t.currentRange;let m=s;const d=[];for(;m.valueOf()<c.valueOf();){const s=r.add(m,a),c={start:e.skipHiddenDays(m),end:e.skipHiddenDays(s,-1,!0)};let h=i.buildDayTableRenderRange({currentRange:c,snapToWeek:!0,fixedWeekCount:o,dateEnv:r});h={start:e.skipHiddenDays(h.start),end:e.skipHiddenDays(h.end,-1,!0)};const u=t.activeRange?n.intersectRanges(t.activeRange,l?h:c):null;d.push({currentDate:t.currentDate,isValid:t.isValid,validRange:t.validRange,renderRange:h,activeRange:u,currentRange:c,currentRangeUnit:"month",isRangeAllDay:!0,dateIncrement:t.dateIncrement,slotMinTime:t.slotMaxTime,slotMaxTime:t.slotMinTime}),m=s}return d}const c=n.createFormatter({year:"numeric",month:"long"}),m=n.createFormatter({month:"long"});function d(e,t){return e||(t[0].currentRange.start.getUTCFullYear()!==t[t.length-1].currentRange.start.getUTCFullYear()?c:m)}const h={multiMonthTitleFormat:n.createFormatter,multiMonthMaxColumns:Number,multiMonthMinWidth:Number};n.injectStyles('.fc-media-screen .fc-multimonth-inner{display:flex;flex-direction:row;flex-wrap:wrap}.fc-media-print.fc-direction-ltr .fc-multimonth-inner>*{float:left}.fc-media-print.fc-direction-rtl .fc-multimonth-inner>*{float:right}.fc-media-print .fc-multimonth-inner:after{clear:both;content:"";display:block}.fc-multimonth-multicol .fc-multimonth-month{padding:1.2em}.fc-multimonth-singlecol .fc-multimonth-title{padding:.5em 0}.fc-multimonth-multicol .fc-multimonth-title{padding-bottom:1em}.fc-multimonth-title{font-size:1.2em;font-weight:700;text-align:center}.fc-multimonth-header-row{border-top:1px solid var(--fc-border-color)}.fc-multimonth-body:not(.fc-multimonth-singlecol .fc-multimonth-month:last-child .fc-multimonth-body),.fc-multimonth-header-row{border-bottom:1px solid var(--fc-border-color)}.fc-multimonth-multicol .fc-multimonth-body,.fc-multimonth-multicol .fc-multimonth-header-row{border-left:1px solid var(--fc-border-color);border-right:1px solid var(--fc-border-color);font-size:.9em;line-height:1}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:sticky;top:0;z-index:2}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-body{position:relative;z-index:1}');var u=t.createPlugin({name:"@fullcalendar/multimonth",initialView:"multiMonthYear",optionRefiners:h,views:{multiMonth:{component:l,dateProfileGeneratorClass:i.TableDateProfileGenerator,multiMonthMinWidth:350,multiMonthMaxColumns:3},multiMonthYear:{type:"multiMonth",duration:{years:1},fixedWeekCount:!0,showNonCurrentDates:!1}}});return t.globalPlugins.push(u),e.default=u,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,FullCalendar.DayGrid.Internal,FullCalendar.Internal,FullCalendar.Preact);
6
+ FullCalendar.MultiMonth=function(e,t,i,n,l){"use strict";class r extends n.DateComponent{constructor(){super(...arguments),this.buildDayTableModel=n.memoize(i.buildDayTableModel),this.createDayHeaderFormatter=n.memoize(i.createDayHeaderFormatter),this.buildDateRowConfig=n.memoize(i.buildDateRowConfig),this.slicer=new i.DayTableSlicer,this.titleId=n.getUniqueDomId()}render(){const{props:e,context:t}=this,{dateProfile:r,forPrint:o}=e,{options:a}=t,s=this.buildDayTableModel(r,t.dateProfileGenerator),c=this.slicer.sliceProps(e,r,a.nextDayThreshold,t,s),m=this.createDayHeaderFormatter(a.dayHeaderFormat,!1,s.colCnt),d=this.buildDateRowConfig(s.headerDates,!1,r,e.todayRange,m,t),h=1/a.aspectRatio,u=h/s.rowCnt,f=!o,g=!o||e.hasLateralSiblings;return l.createElement("div",{role:"listitem",className:"fc-multimonth-month-outer",style:{width:e.width}},l.createElement("div",{role:"grid","aria-labelledby":this.titleId,"data-date":e.isoDateStr,className:n.joinClassNames("fc-multimonth-month",e.hasLateralSiblings&&"fc-break-inside-avoid")},l.createElement("div",{className:"fc-multimonth-header",style:{marginBottom:f?n.fracToCssDim(u):void 0}},l.createElement("div",{id:this.titleId,className:"fc-multimonth-title"},t.dateEnv.format(e.dateProfile.currentRange.start,e.titleFormat)),l.createElement(i.DayGridHeaderRow,Object.assign({},d,{role:"row",className:"fc-multimonth-header-row"}))),l.createElement("div",{className:n.joinClassNames("fc-multimonth-body",g&&"fc-rel"),style:{marginTop:f?n.fracToCssDim(-u):void 0,paddingBottom:g?n.fracToCssDim(h):void 0}},l.createElement(i.DayGridRows,{dateProfile:e.dateProfile,todayRange:e.todayRange,cellRows:s.cellRows,className:g?"fc-fill":"",forPrint:o&&!e.hasLateralSiblings,dayMaxEvents:o?void 0:a.dayMaxEvents,dayMaxEventRows:o&&e.hasLateralSiblings?1:a.dayMaxEventRows,fgEventSegs:c.fgEventSegs,bgEventSegs:c.bgEventSegs,businessHourSegs:c.businessHourSegs,dateSelectionSegs:c.dateSelectionSegs,eventDrag:c.eventDrag,eventResize:c.eventResize,eventSelection:c.eventSelection,visibleWidth:e.visibleWidth}))))}}class o extends n.DateComponent{constructor(){super(...arguments),this.splitDateProfileByMonth=n.memoize(s),this.buildMonthFormat=n.memoize(d),this.scrollerRef=l.createRef(),this.innerElRef=l.createRef(),this.scrollDate=null,this.handleScrollEnd=({isUser:e})=>{e&&(this.scrollDate=null)}}render(){const{context:e,props:t,state:i}=this,{options:o}=e,a=!t.forPrint&&!n.getIsHeightAuto(o),s=this.splitDateProfileByMonth(e.dateProfileGenerator,t.dateProfile,e.dateEnv,o.fixedWeekCount,o.showNonCurrentDates),c=this.buildMonthFormat(o.multiMonthTitleFormat,s),{multiMonthMinWidth:m,multiMonthMaxColumns:d}=o,{innerWidth:h}=i;let u,f,g,p=!1;return null!=h&&(u=Math.max(1,Math.min(d,Math.floor(h/m))),t.forPrint&&(u=Math.min(u,2)),f=h/u,g=n.fracToCssDim(1/u),p=u>1),l.createElement(n.NowTimer,{unit:"day"},(i,o)=>l.createElement(n.ViewContainer,{viewSpec:e.viewSpec,className:n.joinClassNames("fc-multimonth fc-border",1===u?"fc-multimonth-singlecol":"fc-multimonth-multicol",!t.forPrint&&"fc-flex-col")},l.createElement(n.Scroller,{vertical:a,className:a?"fc-liquid":"",ref:this.scrollerRef},l.createElement("div",{role:"list","aria-labelledby":t.labelId,"aria-label":t.labelStr,className:"fc-multimonth-inner",ref:this.innerElRef},s.map(e=>{const i=n.formatIsoMonthStr(e.currentRange.start);return l.createElement(r,Object.assign({},t,{key:i,todayRange:o,isoDateStr:i,titleFormat:c,dateProfile:e,width:g,visibleWidth:f,hasLateralSiblings:p}))})))))}componentDidMount(){this.resetScroll(),this.scrollerRef.current.addScrollEndListener(this.handleScrollEnd),this.disconnectInnerWidth=n.watchWidth(this.innerElRef.current,e=>{n.afterSize(()=>{this.setState({innerWidth:e})})})}componentDidUpdate(e){e.dateProfile!==this.props.dateProfile&&this.context.options.scrollTimeReset?this.resetScroll():this.applyScroll()}componentWillUnmount(){this.scrollerRef.current.removeScrollEndListener(this.handleScrollEnd),this.disconnectInnerWidth()}resetScroll(){this.scrollDate=this.props.dateProfile.currentDate,this.applyScroll()}applyScroll(){if(null!=this.scrollDate&&null!=this.state.innerWidth){const e=this.scrollerRef.current,t=this.innerElRef.current,i=t.querySelector(`[data-date="${n.formatIsoMonthStr(this.scrollDate)}"]`),l=Math.ceil(i.getBoundingClientRect().top-t.getBoundingClientRect().top);e.scrollTo({y:l})}}}const a=n.createDuration(1,"month");function s(e,t,l,r,o){const{start:s,end:c}=t.currentRange;let m=s;const d=[];for(;m.valueOf()<c.valueOf();){const s=l.add(m,a),c={start:e.skipHiddenDays(m),end:e.skipHiddenDays(s,-1,!0)};let h=i.buildDayTableRenderRange({currentRange:c,snapToWeek:!0,fixedWeekCount:r,dateEnv:l});h={start:e.skipHiddenDays(h.start),end:e.skipHiddenDays(h.end,-1,!0)};const u=t.activeRange?n.intersectRanges(t.activeRange,o?h:c):null;d.push({currentDate:t.currentDate,isValid:t.isValid,validRange:t.validRange,renderRange:h,activeRange:u,currentRange:c,currentRangeUnit:"month",isRangeAllDay:!0,dateIncrement:t.dateIncrement,slotMinTime:t.slotMaxTime,slotMaxTime:t.slotMinTime}),m=s}return d}const c=n.createFormatter({year:"numeric",month:"long"}),m=n.createFormatter({month:"long"});function d(e,t){return e||(t[0].currentRange.start.getUTCFullYear()!==t[t.length-1].currentRange.start.getUTCFullYear()?c:m)}const h={multiMonthTitleFormat:n.createFormatter,multiMonthMaxColumns:Number,multiMonthMinWidth:Number};n.injectStyles('.fc-media-screen .fc-multimonth-inner{display:flex;flex-direction:row;flex-wrap:wrap}.fc-media-print.fc-direction-ltr .fc-multimonth-inner>*{float:left}.fc-media-print.fc-direction-rtl .fc-multimonth-inner>*{float:right}.fc-media-print .fc-multimonth-inner:after{clear:both;content:"";display:block}.fc-multimonth-multicol .fc-multimonth-month{padding:1.2em}.fc-multimonth-singlecol .fc-multimonth-title{padding:.5em 0}.fc-multimonth-multicol .fc-multimonth-title{padding-bottom:1em}.fc-multimonth-title{font-size:1.2em;font-weight:700;text-align:center}.fc-multimonth-header-row{border-top:1px solid var(--fc-border-color)}.fc-multimonth-body:not(.fc-multimonth-singlecol .fc-multimonth-month-outer:last-child .fc-multimonth-body),.fc-multimonth-header-row{border-bottom:1px solid var(--fc-border-color)}.fc-multimonth-multicol .fc-multimonth-body,.fc-multimonth-multicol .fc-multimonth-header-row{border-left:1px solid var(--fc-border-color);border-right:1px solid var(--fc-border-color);font-size:.9em;line-height:1}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:sticky;top:0;z-index:2}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-body{position:relative;z-index:1}');var u=t.createPlugin({name:"@fullcalendar/multimonth",initialView:"multiMonthYear",optionRefiners:h,views:{multiMonth:{component:o,dateProfileGeneratorClass:i.TableDateProfileGenerator,multiMonthMinWidth:350,multiMonthMaxColumns:3},multiMonthYear:{type:"multiMonth",duration:{years:1},fixedWeekCount:!0,showNonCurrentDates:!1}}});return t.globalPlugins.push(u),e.default=u,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,FullCalendar.DayGrid.Internal,FullCalendar.Internal,FullCalendar.Preact);
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createPlugin } from '@fullcalendar/core/index.js';
2
2
  import { buildDayTableModel, createDayHeaderFormatter, buildDateRowConfig, DayTableSlicer, DayGridHeaderRow, DayGridRows, buildDayTableRenderRange, TableDateProfileGenerator } from '@fullcalendar/daygrid/internal.js';
3
- import { DateComponent, memoize, joinClassNames, fracToCssDim, formatIsoMonthStr, getIsHeightAuto, NowTimer, ViewContainer, Scroller, watchWidth, afterSize, createDuration, intersectRanges, createFormatter, injectStyles } from '@fullcalendar/core/internal.js';
3
+ import { DateComponent, memoize, getUniqueDomId, joinClassNames, fracToCssDim, getIsHeightAuto, NowTimer, ViewContainer, Scroller, formatIsoMonthStr, watchWidth, afterSize, createDuration, intersectRanges, createFormatter, injectStyles } from '@fullcalendar/core/internal.js';
4
4
  import { createElement, createRef } from '@fullcalendar/core/preact.js';
5
5
 
6
6
  class SingleMonth extends DateComponent {
@@ -12,6 +12,7 @@ class SingleMonth extends DateComponent {
12
12
  this.buildDateRowConfig = memoize(buildDateRowConfig);
13
13
  // internal
14
14
  this.slicer = new DayTableSlicer();
15
+ this.titleId = getUniqueDomId();
15
16
  }
16
17
  render() {
17
18
  const { props, context } = this;
@@ -27,23 +28,22 @@ class SingleMonth extends DateComponent {
27
28
  const invRowAspectRatio = invAspectRatio / dayTableModel.rowCnt;
28
29
  const isHeaderSticky = !forPrint;
29
30
  const isAspectRatio = !forPrint || props.hasLateralSiblings;
30
- return (createElement("div", { "data-date": props.isoDateStr, className: joinClassNames('fc-multimonth-month', props.hasLateralSiblings && 'fc-break-inside-avoid'),
31
- // override fc-liquid's basis. fc-grow isn't sufficient because doesn't set min-width:0
32
- style: { width: props.width } },
33
- createElement("div", { className: "fc-multimonth-header", style: {
34
- marginBottom: isHeaderSticky ? fracToCssDim(invRowAspectRatio) : undefined,
35
- } },
36
- createElement("div", { className: "fc-multimonth-title" }, context.dateEnv.format(props.dateProfile.currentRange.start, props.titleFormat)),
37
- createElement(DayGridHeaderRow, Object.assign({}, rowConfig, { className: 'fc-multimonth-header-row' }))),
38
- createElement("div", { className: joinClassNames('fc-multimonth-body', isAspectRatio && 'fc-rel'), style: {
39
- marginTop: isHeaderSticky ? fracToCssDim(-invRowAspectRatio) : undefined,
40
- paddingBottom: isAspectRatio ? fracToCssDim(invAspectRatio) : undefined,
41
- } },
42
- createElement(DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: dayTableModel.cellRows, className: isAspectRatio ? 'fc-fill' : '', forPrint: forPrint && !props.hasLateralSiblings, dayMaxEvents: forPrint ? undefined : options.dayMaxEvents, dayMaxEventRows: (forPrint && props.hasLateralSiblings) ? 1 : options.dayMaxEventRows,
43
- // content
44
- fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection,
45
- // dimensions
46
- visibleWidth: props.visibleWidth }))));
31
+ return (createElement("div", { role: 'listitem', className: 'fc-multimonth-month-outer', style: { width: props.width } },
32
+ createElement("div", { role: 'grid', "aria-labelledby": this.titleId, "data-date": props.isoDateStr, className: joinClassNames('fc-multimonth-month', props.hasLateralSiblings && 'fc-break-inside-avoid') },
33
+ createElement("div", { className: "fc-multimonth-header", style: {
34
+ marginBottom: isHeaderSticky ? fracToCssDim(invRowAspectRatio) : undefined,
35
+ } },
36
+ createElement("div", { id: this.titleId, className: 'fc-multimonth-title' }, context.dateEnv.format(props.dateProfile.currentRange.start, props.titleFormat)),
37
+ createElement(DayGridHeaderRow, Object.assign({}, rowConfig, { role: 'row', className: 'fc-multimonth-header-row' }))),
38
+ createElement("div", { className: joinClassNames('fc-multimonth-body', isAspectRatio && 'fc-rel'), style: {
39
+ marginTop: isHeaderSticky ? fracToCssDim(-invRowAspectRatio) : undefined,
40
+ paddingBottom: isAspectRatio ? fracToCssDim(invAspectRatio) : undefined,
41
+ } },
42
+ createElement(DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: dayTableModel.cellRows, className: isAspectRatio ? 'fc-fill' : '', forPrint: forPrint && !props.hasLateralSiblings, dayMaxEvents: forPrint ? undefined : options.dayMaxEvents, dayMaxEventRows: (forPrint && props.hasLateralSiblings) ? 1 : options.dayMaxEventRows,
43
+ // content
44
+ fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection,
45
+ // dimensions
46
+ visibleWidth: props.visibleWidth })))));
47
47
  }
48
48
  }
49
49
 
@@ -57,22 +57,11 @@ class MultiMonthView extends DateComponent {
57
57
  this.scrollerRef = createRef();
58
58
  this.innerElRef = createRef(); // .fc-multimonth-inner
59
59
  this.scrollDate = null;
60
- this.updateScroll = () => {
61
- if (this.scrollDate != null &&
62
- this.state.innerWidth != null // render completed?
63
- ) {
64
- const scroller = this.scrollerRef.current;
65
- const innerEl = this.innerElRef.current;
66
- const monthEl = innerEl.querySelector(`[data-date="${formatIsoMonthStr(this.scrollDate)}"]`);
67
- const scrollTop = Math.ceil(// for fractions, err on the side of scrolling further
68
- monthEl.getBoundingClientRect().top -
69
- innerEl.getBoundingClientRect().top);
70
- scroller.scrollTo({ y: scrollTop });
60
+ this.handleScrollEnd = ({ isUser }) => {
61
+ if (isUser) {
62
+ this.scrollDate = null;
71
63
  }
72
64
  };
73
- this.clearScroll = () => {
74
- this.scrollDate = null;
75
- };
76
65
  }
77
66
  render() {
78
67
  const { context, props, state } = this;
@@ -95,14 +84,14 @@ class MultiMonthView extends DateComponent {
95
84
  cssMonthWidth = fracToCssDim(1 / cols);
96
85
  hasLateralSiblings = cols > 1;
97
86
  }
98
- return (createElement(NowTimer, { unit: "day" }, (nowDate, todayRange) => (createElement(ViewContainer, { className: joinClassNames('fc-multimonth fc-border', (cols === 1) ?
87
+ return (createElement(NowTimer, { unit: "day" }, (nowDate, todayRange) => (createElement(ViewContainer, { viewSpec: context.viewSpec, className: joinClassNames('fc-multimonth fc-border', (cols === 1) ?
99
88
  'fc-multimonth-singlecol' :
100
89
  'fc-multimonth-multicol',
101
90
  // HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
102
91
  // https://stackoverflow.com/a/60256345
103
- !props.forPrint && 'fc-flex-col'), viewSpec: context.viewSpec },
92
+ !props.forPrint && 'fc-flex-col') },
104
93
  createElement(Scroller, { vertical: verticalScrolling, className: verticalScrolling ? 'fc-liquid' : '', ref: this.scrollerRef },
105
- createElement("div", { ref: this.innerElRef, className: 'fc-multimonth-inner' }, monthDateProfiles.map((monthDateProfile) => {
94
+ createElement("div", { role: 'list', "aria-labelledby": props.labelId, "aria-label": props.labelStr, className: 'fc-multimonth-inner', ref: this.innerElRef }, monthDateProfiles.map((monthDateProfile) => {
106
95
  const monthStr = formatIsoMonthStr(monthDateProfile.currentRange.start);
107
96
  return (createElement(SingleMonth, Object.assign({}, props, { key: monthStr, todayRange: todayRange, isoDateStr: monthStr, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width: cssMonthWidth, visibleWidth: computedMonthWidth, hasLateralSiblings: hasLateralSiblings })));
108
97
  })))))));
@@ -111,7 +100,7 @@ class MultiMonthView extends DateComponent {
111
100
  // -----------------------------------------------------------------------------------------------
112
101
  componentDidMount() {
113
102
  this.resetScroll();
114
- this.scrollerRef.current.addScrollEndListener(this.clearScroll);
103
+ this.scrollerRef.current.addScrollEndListener(this.handleScrollEnd);
115
104
  this.disconnectInnerWidth = watchWidth(this.innerElRef.current, (innerWidth) => {
116
105
  afterSize(() => {
117
106
  this.setState({ innerWidth });
@@ -125,18 +114,31 @@ class MultiMonthView extends DateComponent {
125
114
  else {
126
115
  // NOT optimal to update so often
127
116
  // TODO: isolate dependencies of scroll coordinate
128
- this.updateScroll();
117
+ this.applyScroll();
129
118
  }
130
119
  }
131
120
  componentWillUnmount() {
132
- this.scrollerRef.current.removeScrollEndListener(this.clearScroll);
121
+ this.scrollerRef.current.removeScrollEndListener(this.handleScrollEnd);
133
122
  this.disconnectInnerWidth();
134
123
  }
135
124
  // Scrolling
136
125
  // -----------------------------------------------------------------------------------------------
137
126
  resetScroll() {
138
127
  this.scrollDate = this.props.dateProfile.currentDate;
139
- this.updateScroll();
128
+ this.applyScroll();
129
+ }
130
+ applyScroll() {
131
+ if (this.scrollDate != null &&
132
+ this.state.innerWidth != null // render completed?
133
+ ) {
134
+ const scroller = this.scrollerRef.current;
135
+ const innerEl = this.innerElRef.current;
136
+ const monthEl = innerEl.querySelector(`[data-date="${formatIsoMonthStr(this.scrollDate)}"]`);
137
+ const scrollTop = Math.ceil(// for fractions, err on the side of scrolling further
138
+ monthEl.getBoundingClientRect().top -
139
+ innerEl.getBoundingClientRect().top);
140
+ scroller.scrollTo({ y: scrollTop });
141
+ }
140
142
  }
141
143
  }
142
144
  // date profile
@@ -202,7 +204,7 @@ const OPTION_REFINERS = {
202
204
  multiMonthMinWidth: Number,
203
205
  };
204
206
 
205
- var css_248z = ".fc-media-screen .fc-multimonth-inner{display:flex;flex-direction:row;flex-wrap:wrap}.fc-media-print.fc-direction-ltr .fc-multimonth-inner>*{float:left}.fc-media-print.fc-direction-rtl .fc-multimonth-inner>*{float:right}.fc-media-print .fc-multimonth-inner:after{clear:both;content:\"\";display:block}.fc-multimonth-multicol .fc-multimonth-month{padding:1.2em}.fc-multimonth-singlecol .fc-multimonth-title{padding:.5em 0}.fc-multimonth-multicol .fc-multimonth-title{padding-bottom:1em}.fc-multimonth-title{font-size:1.2em;font-weight:700;text-align:center}.fc-multimonth-header-row{border-top:1px solid var(--fc-border-color)}.fc-multimonth-body:not(.fc-multimonth-singlecol .fc-multimonth-month:last-child .fc-multimonth-body),.fc-multimonth-header-row{border-bottom:1px solid var(--fc-border-color)}.fc-multimonth-multicol .fc-multimonth-body,.fc-multimonth-multicol .fc-multimonth-header-row{border-left:1px solid var(--fc-border-color);border-right:1px solid var(--fc-border-color);font-size:.9em;line-height:1}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:sticky;top:0;z-index:2}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-body{position:relative;z-index:1}";
207
+ var css_248z = ".fc-media-screen .fc-multimonth-inner{display:flex;flex-direction:row;flex-wrap:wrap}.fc-media-print.fc-direction-ltr .fc-multimonth-inner>*{float:left}.fc-media-print.fc-direction-rtl .fc-multimonth-inner>*{float:right}.fc-media-print .fc-multimonth-inner:after{clear:both;content:\"\";display:block}.fc-multimonth-multicol .fc-multimonth-month{padding:1.2em}.fc-multimonth-singlecol .fc-multimonth-title{padding:.5em 0}.fc-multimonth-multicol .fc-multimonth-title{padding-bottom:1em}.fc-multimonth-title{font-size:1.2em;font-weight:700;text-align:center}.fc-multimonth-header-row{border-top:1px solid var(--fc-border-color)}.fc-multimonth-body:not(.fc-multimonth-singlecol .fc-multimonth-month-outer:last-child .fc-multimonth-body),.fc-multimonth-header-row{border-bottom:1px solid var(--fc-border-color)}.fc-multimonth-multicol .fc-multimonth-body,.fc-multimonth-multicol .fc-multimonth-header-row{border-left:1px solid var(--fc-border-color);border-right:1px solid var(--fc-border-color);font-size:.9em;line-height:1}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:sticky;top:0;z-index:2}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-body{position:relative;z-index:1}";
206
208
  injectStyles(css_248z);
207
209
 
208
210
  var index = createPlugin({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fullcalendar/multimonth",
3
- "version": "7.0.0-beta.3",
3
+ "version": "7.0.0-beta.4",
4
4
  "title": "FullCalendar Multi-Month Plugin",
5
5
  "description": "Display a sequence or grid of multiple months",
6
6
  "keywords": [
@@ -12,10 +12,10 @@
12
12
  ],
13
13
  "homepage": "https://fullcalendar.io/docs/multimonth-grid",
14
14
  "dependencies": {
15
- "@fullcalendar/daygrid": "7.0.0-beta.3"
15
+ "@fullcalendar/daygrid": "7.0.0-beta.4"
16
16
  },
17
17
  "peerDependencies": {
18
- "@fullcalendar/core": "7.0.0-beta.3"
18
+ "@fullcalendar/core": "7.0.0-beta.4"
19
19
  },
20
20
  "type": "module",
21
21
  "bugs": "https://fullcalendar.io/reporting-bugs",