@fullcalendar/multimonth 7.0.0-beta.3 → 7.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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,25 @@ 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, dayMaxEventRows: (forPrint && props.hasLateralSiblings)
47
+ ? 1 // for side-by-side multimonths, limit to one row
48
+ : true // otherwise, always do +more link, never expand rows
49
+ ,
50
+ // content
51
+ fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection,
52
+ // dimensions
53
+ visibleWidth: props.visibleWidth })))));
51
54
  }
52
55
  }
53
56
 
@@ -61,22 +64,11 @@ class MultiMonthView extends internal_cjs.DateComponent {
61
64
  this.scrollerRef = preact_cjs.createRef();
62
65
  this.innerElRef = preact_cjs.createRef(); // .fc-multimonth-inner
63
66
  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 });
67
+ this.handleScrollEnd = (isUser) => {
68
+ if (isUser) {
69
+ this.scrollDate = null;
75
70
  }
76
71
  };
77
- this.clearScroll = () => {
78
- this.scrollDate = null;
79
- };
80
72
  }
81
73
  render() {
82
74
  const { context, props, state } = this;
@@ -99,14 +91,14 @@ class MultiMonthView extends internal_cjs.DateComponent {
99
91
  cssMonthWidth = internal_cjs.fracToCssDim(1 / cols);
100
92
  hasLateralSiblings = cols > 1;
101
93
  }
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) ?
94
+ 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
95
  'fc-multimonth-singlecol' :
104
96
  'fc-multimonth-multicol',
105
97
  // HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
106
98
  // https://stackoverflow.com/a/60256345
107
- !props.forPrint && 'fc-flex-col'), viewSpec: context.viewSpec },
99
+ !props.forPrint && 'fc-flex-col') },
108
100
  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) => {
101
+ 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
102
  const monthStr = internal_cjs.formatIsoMonthStr(monthDateProfile.currentRange.start);
111
103
  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
104
  })))))));
@@ -115,7 +107,7 @@ class MultiMonthView extends internal_cjs.DateComponent {
115
107
  // -----------------------------------------------------------------------------------------------
116
108
  componentDidMount() {
117
109
  this.resetScroll();
118
- this.scrollerRef.current.addScrollEndListener(this.clearScroll);
110
+ this.scrollerRef.current.addScrollEndListener(this.handleScrollEnd);
119
111
  this.disconnectInnerWidth = internal_cjs.watchWidth(this.innerElRef.current, (innerWidth) => {
120
112
  internal_cjs.afterSize(() => {
121
113
  this.setState({ innerWidth });
@@ -129,18 +121,31 @@ class MultiMonthView extends internal_cjs.DateComponent {
129
121
  else {
130
122
  // NOT optimal to update so often
131
123
  // TODO: isolate dependencies of scroll coordinate
132
- this.updateScroll();
124
+ this.applyScroll();
133
125
  }
134
126
  }
135
127
  componentWillUnmount() {
136
- this.scrollerRef.current.removeScrollEndListener(this.clearScroll);
128
+ this.scrollerRef.current.removeScrollEndListener(this.handleScrollEnd);
137
129
  this.disconnectInnerWidth();
138
130
  }
139
131
  // Scrolling
140
132
  // -----------------------------------------------------------------------------------------------
141
133
  resetScroll() {
142
134
  this.scrollDate = this.props.dateProfile.currentDate;
143
- this.updateScroll();
135
+ this.applyScroll();
136
+ }
137
+ applyScroll() {
138
+ if (this.scrollDate != null &&
139
+ this.state.innerWidth != null // render completed?
140
+ ) {
141
+ const scroller = this.scrollerRef.current;
142
+ const innerEl = this.innerElRef.current;
143
+ const monthEl = innerEl.querySelector(`[data-date="${internal_cjs.formatIsoMonthStr(this.scrollDate)}"]`);
144
+ const scrollTop = Math.ceil(// for fractions, err on the side of scrolling further
145
+ monthEl.getBoundingClientRect().top -
146
+ innerEl.getBoundingClientRect().top);
147
+ scroller.scrollTo({ y: scrollTop });
148
+ }
144
149
  }
145
150
  }
146
151
  // date profile
@@ -206,7 +211,7 @@ const OPTION_REFINERS = {
206
211
  multiMonthMinWidth: Number,
207
212
  };
208
213
 
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}";
214
+ 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
215
  internal_cjs.injectStyles(css_248z);
211
216
 
212
217
  var index = index_cjs.createPlugin({
@@ -217,7 +222,7 @@ var index = index_cjs.createPlugin({
217
222
  multiMonth: {
218
223
  component: MultiMonthView,
219
224
  dateProfileGeneratorClass: internal_cjs$1.TableDateProfileGenerator,
220
- multiMonthMinWidth: 350,
225
+ multiMonthMinWidth: 375,
221
226
  multiMonthMaxColumns: 3,
222
227
  },
223
228
  multiMonthYear: {
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-rc.0
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,25 @@ 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, dayMaxEventRows: (forPrint && props.hasLateralSiblings)
46
+ ? 1 // for side-by-side multimonths, limit to one row
47
+ : true // otherwise, always do +more link, never expand rows
48
+ ,
49
+ // content
50
+ fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection,
51
+ // dimensions
52
+ visibleWidth: props.visibleWidth })))));
50
53
  }
51
54
  }
52
55
 
@@ -60,22 +63,11 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
60
63
  this.scrollerRef = preact.createRef();
61
64
  this.innerElRef = preact.createRef(); // .fc-multimonth-inner
62
65
  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 });
66
+ this.handleScrollEnd = (isUser) => {
67
+ if (isUser) {
68
+ this.scrollDate = null;
74
69
  }
75
70
  };
76
- this.clearScroll = () => {
77
- this.scrollDate = null;
78
- };
79
71
  }
80
72
  render() {
81
73
  const { context, props, state } = this;
@@ -98,14 +90,14 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
98
90
  cssMonthWidth = internal.fracToCssDim(1 / cols);
99
91
  hasLateralSiblings = cols > 1;
100
92
  }
101
- return (preact.createElement(internal.NowTimer, { unit: "day" }, (nowDate, todayRange) => (preact.createElement(internal.ViewContainer, { className: internal.joinClassNames('fc-multimonth fc-border', (cols === 1) ?
93
+ 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
94
  'fc-multimonth-singlecol' :
103
95
  'fc-multimonth-multicol',
104
96
  // HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
105
97
  // https://stackoverflow.com/a/60256345
106
- !props.forPrint && 'fc-flex-col'), viewSpec: context.viewSpec },
98
+ !props.forPrint && 'fc-flex-col') },
107
99
  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) => {
100
+ preact.createElement("div", { role: 'list', "aria-labelledby": props.labelId, "aria-label": props.labelStr, className: 'fc-multimonth-inner', ref: this.innerElRef }, monthDateProfiles.map((monthDateProfile) => {
109
101
  const monthStr = internal.formatIsoMonthStr(monthDateProfile.currentRange.start);
110
102
  return (preact.createElement(SingleMonth, Object.assign({}, props, { key: monthStr, todayRange: todayRange, isoDateStr: monthStr, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width: cssMonthWidth, visibleWidth: computedMonthWidth, hasLateralSiblings: hasLateralSiblings })));
111
103
  })))))));
@@ -114,7 +106,7 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
114
106
  // -----------------------------------------------------------------------------------------------
115
107
  componentDidMount() {
116
108
  this.resetScroll();
117
- this.scrollerRef.current.addScrollEndListener(this.clearScroll);
109
+ this.scrollerRef.current.addScrollEndListener(this.handleScrollEnd);
118
110
  this.disconnectInnerWidth = internal.watchWidth(this.innerElRef.current, (innerWidth) => {
119
111
  internal.afterSize(() => {
120
112
  this.setState({ innerWidth });
@@ -128,18 +120,31 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
128
120
  else {
129
121
  // NOT optimal to update so often
130
122
  // TODO: isolate dependencies of scroll coordinate
131
- this.updateScroll();
123
+ this.applyScroll();
132
124
  }
133
125
  }
134
126
  componentWillUnmount() {
135
- this.scrollerRef.current.removeScrollEndListener(this.clearScroll);
127
+ this.scrollerRef.current.removeScrollEndListener(this.handleScrollEnd);
136
128
  this.disconnectInnerWidth();
137
129
  }
138
130
  // Scrolling
139
131
  // -----------------------------------------------------------------------------------------------
140
132
  resetScroll() {
141
133
  this.scrollDate = this.props.dateProfile.currentDate;
142
- this.updateScroll();
134
+ this.applyScroll();
135
+ }
136
+ applyScroll() {
137
+ if (this.scrollDate != null &&
138
+ this.state.innerWidth != null // render completed?
139
+ ) {
140
+ const scroller = this.scrollerRef.current;
141
+ const innerEl = this.innerElRef.current;
142
+ const monthEl = innerEl.querySelector(`[data-date="${internal.formatIsoMonthStr(this.scrollDate)}"]`);
143
+ const scrollTop = Math.ceil(// for fractions, err on the side of scrolling further
144
+ monthEl.getBoundingClientRect().top -
145
+ innerEl.getBoundingClientRect().top);
146
+ scroller.scrollTo({ y: scrollTop });
147
+ }
143
148
  }
144
149
  }
145
150
  // date profile
@@ -205,7 +210,7 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
205
210
  multiMonthMinWidth: Number,
206
211
  };
207
212
 
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}";
213
+ 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
214
  internal.injectStyles(css_248z);
210
215
 
211
216
  var plugin = core.createPlugin({
@@ -216,7 +221,7 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
216
221
  multiMonth: {
217
222
  component: MultiMonthView,
218
223
  dateProfileGeneratorClass: internal$1.TableDateProfileGenerator,
219
- multiMonthMinWidth: 350,
224
+ multiMonthMinWidth: 375,
220
225
  multiMonthMaxColumns: 3,
221
226
  },
222
227
  multiMonthYear: {
@@ -1,6 +1,6 @@
1
1
  /*!
2
- FullCalendar Multi-Month Plugin v7.0.0-beta.3
2
+ FullCalendar Multi-Month Plugin v7.0.0-rc.0
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,dayMaxEventRows:!o||!e.hasLateralSiblings||1,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=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:375,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,25 @@ 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, dayMaxEventRows: (forPrint && props.hasLateralSiblings)
43
+ ? 1 // for side-by-side multimonths, limit to one row
44
+ : true // otherwise, always do +more link, never expand rows
45
+ ,
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 })))));
47
50
  }
48
51
  }
49
52
 
@@ -57,22 +60,11 @@ class MultiMonthView extends DateComponent {
57
60
  this.scrollerRef = createRef();
58
61
  this.innerElRef = createRef(); // .fc-multimonth-inner
59
62
  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 });
63
+ this.handleScrollEnd = (isUser) => {
64
+ if (isUser) {
65
+ this.scrollDate = null;
71
66
  }
72
67
  };
73
- this.clearScroll = () => {
74
- this.scrollDate = null;
75
- };
76
68
  }
77
69
  render() {
78
70
  const { context, props, state } = this;
@@ -95,14 +87,14 @@ class MultiMonthView extends DateComponent {
95
87
  cssMonthWidth = fracToCssDim(1 / cols);
96
88
  hasLateralSiblings = cols > 1;
97
89
  }
98
- return (createElement(NowTimer, { unit: "day" }, (nowDate, todayRange) => (createElement(ViewContainer, { className: joinClassNames('fc-multimonth fc-border', (cols === 1) ?
90
+ return (createElement(NowTimer, { unit: "day" }, (nowDate, todayRange) => (createElement(ViewContainer, { viewSpec: context.viewSpec, className: joinClassNames('fc-multimonth fc-border', (cols === 1) ?
99
91
  'fc-multimonth-singlecol' :
100
92
  'fc-multimonth-multicol',
101
93
  // HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
102
94
  // https://stackoverflow.com/a/60256345
103
- !props.forPrint && 'fc-flex-col'), viewSpec: context.viewSpec },
95
+ !props.forPrint && 'fc-flex-col') },
104
96
  createElement(Scroller, { vertical: verticalScrolling, className: verticalScrolling ? 'fc-liquid' : '', ref: this.scrollerRef },
105
- createElement("div", { ref: this.innerElRef, className: 'fc-multimonth-inner' }, monthDateProfiles.map((monthDateProfile) => {
97
+ createElement("div", { role: 'list', "aria-labelledby": props.labelId, "aria-label": props.labelStr, className: 'fc-multimonth-inner', ref: this.innerElRef }, monthDateProfiles.map((monthDateProfile) => {
106
98
  const monthStr = formatIsoMonthStr(monthDateProfile.currentRange.start);
107
99
  return (createElement(SingleMonth, Object.assign({}, props, { key: monthStr, todayRange: todayRange, isoDateStr: monthStr, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width: cssMonthWidth, visibleWidth: computedMonthWidth, hasLateralSiblings: hasLateralSiblings })));
108
100
  })))))));
@@ -111,7 +103,7 @@ class MultiMonthView extends DateComponent {
111
103
  // -----------------------------------------------------------------------------------------------
112
104
  componentDidMount() {
113
105
  this.resetScroll();
114
- this.scrollerRef.current.addScrollEndListener(this.clearScroll);
106
+ this.scrollerRef.current.addScrollEndListener(this.handleScrollEnd);
115
107
  this.disconnectInnerWidth = watchWidth(this.innerElRef.current, (innerWidth) => {
116
108
  afterSize(() => {
117
109
  this.setState({ innerWidth });
@@ -125,18 +117,31 @@ class MultiMonthView extends DateComponent {
125
117
  else {
126
118
  // NOT optimal to update so often
127
119
  // TODO: isolate dependencies of scroll coordinate
128
- this.updateScroll();
120
+ this.applyScroll();
129
121
  }
130
122
  }
131
123
  componentWillUnmount() {
132
- this.scrollerRef.current.removeScrollEndListener(this.clearScroll);
124
+ this.scrollerRef.current.removeScrollEndListener(this.handleScrollEnd);
133
125
  this.disconnectInnerWidth();
134
126
  }
135
127
  // Scrolling
136
128
  // -----------------------------------------------------------------------------------------------
137
129
  resetScroll() {
138
130
  this.scrollDate = this.props.dateProfile.currentDate;
139
- 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="${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
+ }
140
145
  }
141
146
  }
142
147
  // date profile
@@ -202,7 +207,7 @@ const OPTION_REFINERS = {
202
207
  multiMonthMinWidth: Number,
203
208
  };
204
209
 
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}";
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}";
206
211
  injectStyles(css_248z);
207
212
 
208
213
  var index = createPlugin({
@@ -213,7 +218,7 @@ var index = createPlugin({
213
218
  multiMonth: {
214
219
  component: MultiMonthView,
215
220
  dateProfileGeneratorClass: TableDateProfileGenerator,
216
- multiMonthMinWidth: 350,
221
+ multiMonthMinWidth: 375,
217
222
  multiMonthMaxColumns: 3,
218
223
  },
219
224
  multiMonthYear: {
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-rc.0",
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-rc.0"
16
16
  },
17
17
  "peerDependencies": {
18
- "@fullcalendar/core": "7.0.0-beta.3"
18
+ "@fullcalendar/core": "7.0.0-rc.0"
19
19
  },
20
20
  "type": "module",
21
21
  "bugs": "https://fullcalendar.io/reporting-bugs",