@fullcalendar/multimonth 7.0.0-beta.1 → 7.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs +59 -66
- package/index.global.js +60 -67
- package/index.global.min.js +2 -2
- package/index.js +61 -68
- package/package.json +3 -3
package/index.cjs
CHANGED
@@ -10,10 +10,12 @@ var preact_cjs = require('@fullcalendar/core/preact.cjs');
|
|
10
10
|
class SingleMonth extends internal_cjs.DateComponent {
|
11
11
|
constructor() {
|
12
12
|
super(...arguments);
|
13
|
-
this.slicer = new internal_cjs$1.DayTableSlicer();
|
14
13
|
// memo
|
15
14
|
this.buildDayTableModel = internal_cjs.memoize(internal_cjs$1.buildDayTableModel);
|
16
15
|
this.createDayHeaderFormatter = internal_cjs.memoize(internal_cjs$1.createDayHeaderFormatter);
|
16
|
+
this.buildDateRowConfig = internal_cjs.memoize(internal_cjs$1.buildDateRowConfig);
|
17
|
+
// internal
|
18
|
+
this.slicer = new internal_cjs$1.DayTableSlicer();
|
17
19
|
}
|
18
20
|
render() {
|
19
21
|
const { props, context } = this;
|
@@ -21,27 +23,31 @@ class SingleMonth extends internal_cjs.DateComponent {
|
|
21
23
|
const { options } = context;
|
22
24
|
const dayTableModel = this.buildDayTableModel(dateProfile, context.dateProfileGenerator);
|
23
25
|
const slicedProps = this.slicer.sliceProps(props, dateProfile, options.nextDayThreshold, context, dayTableModel);
|
24
|
-
|
25
|
-
const tableHeight = typeof props.width === 'number'
|
26
|
-
? props.width / options.aspectRatio
|
27
|
-
: null;
|
28
|
-
const rowCnt = dayTableModel.cellRows.length;
|
29
|
-
const rowHeight = tableHeight != null ? tableHeight / rowCnt : null;
|
30
|
-
const dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, false, // datesRepDistinctDays
|
26
|
+
const dayHeaderFormat = this.createDayHeaderFormatter(options.dayHeaderFormat, false, // datesRepDistinctDays
|
31
27
|
dayTableModel.colCnt);
|
32
|
-
|
33
|
-
|
34
|
-
|
28
|
+
const rowConfig = this.buildDateRowConfig(dayTableModel.headerDates, false, // datesRepDistinctDays
|
29
|
+
dateProfile, props.todayRange, dayHeaderFormat, context);
|
30
|
+
const invAspectRatio = 1 / options.aspectRatio;
|
31
|
+
const invRowAspectRatio = invAspectRatio / dayTableModel.rowCnt;
|
32
|
+
const isHeaderSticky = !forPrint;
|
33
|
+
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
|
+
} },
|
35
40
|
preact_cjs.createElement("div", { className: "fc-multimonth-title" }, context.dateEnv.format(props.dateProfile.currentRange.start, props.titleFormat)),
|
36
|
-
preact_cjs.createElement(
|
37
|
-
preact_cjs.createElement("div", { className: 'fc-multimonth-body fc-
|
38
|
-
marginTop: -
|
39
|
-
|
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,
|
40
45
|
} },
|
41
|
-
preact_cjs.createElement(internal_cjs$1.DayGridRows
|
42
|
-
, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: dayTableModel.cellRows, forPrint: props.forPrint,
|
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,
|
43
47
|
// content
|
44
|
-
fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection
|
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 }))));
|
45
51
|
}
|
46
52
|
}
|
47
53
|
|
@@ -53,32 +59,12 @@ class MultiMonthView extends internal_cjs.DateComponent {
|
|
53
59
|
this.buildMonthFormat = internal_cjs.memoize(buildMonthFormat);
|
54
60
|
// ref
|
55
61
|
this.scrollerRef = preact_cjs.createRef();
|
56
|
-
this.innerElRef = preact_cjs.createRef();
|
57
|
-
// internal
|
62
|
+
this.innerElRef = preact_cjs.createRef(); // .fc-multimonth-inner
|
58
63
|
this.scrollDate = null;
|
59
|
-
// Sizing
|
60
|
-
// -----------------------------------------------------------------------------------------------
|
61
|
-
this.handleWidth = (width) => {
|
62
|
-
let { xGap, xPadding } = this.state;
|
63
|
-
// for first time, assume 2 columns and query gap/padding
|
64
|
-
if (xGap == null) {
|
65
|
-
const innerEl = this.innerElRef.current;
|
66
|
-
const children = innerEl.childNodes;
|
67
|
-
if (children.length > 1) {
|
68
|
-
const box0 = children[0].getBoundingClientRect();
|
69
|
-
const box1 = children[1].getBoundingClientRect();
|
70
|
-
let xSpan;
|
71
|
-
[xGap, xSpan] = [
|
72
|
-
Math.abs(box0.left - box1.right),
|
73
|
-
Math.abs(box0.right - box1.left),
|
74
|
-
].sort(internal_cjs.compareNumbers);
|
75
|
-
xPadding = width - xSpan;
|
76
|
-
}
|
77
|
-
}
|
78
|
-
this.setState({ width, xGap, xPadding });
|
79
|
-
};
|
80
64
|
this.updateScroll = () => {
|
81
|
-
if (this.scrollDate != null &&
|
65
|
+
if (this.scrollDate != null &&
|
66
|
+
this.state.innerWidth != null // render completed?
|
67
|
+
) {
|
82
68
|
const scroller = this.scrollerRef.current;
|
83
69
|
const innerEl = this.innerElRef.current;
|
84
70
|
const monthEl = innerEl.querySelector(`[data-date="${internal_cjs.formatIsoMonthStr(this.scrollDate)}"]`);
|
@@ -96,32 +82,33 @@ class MultiMonthView extends internal_cjs.DateComponent {
|
|
96
82
|
const { context, props, state } = this;
|
97
83
|
const { options } = context;
|
98
84
|
const verticalScrolling = !props.forPrint && !internal_cjs.getIsHeightAuto(options);
|
99
|
-
const colCount = state.width == null
|
100
|
-
? 2
|
101
|
-
: Math.min(options.multiMonthMaxColumns, Math.floor((state.width - state.xPadding + state.xGap) /
|
102
|
-
(options.multiMonthMinWidth + state.xGap)));
|
103
|
-
const monthWidth = state.width == null
|
104
|
-
? '34%' // will expand. now small enough to be 1/3. for allowing gap
|
105
|
-
: Math.floor(// exact values can cause expansion to other rows
|
106
|
-
(state.width - state.xPadding - (state.xGap * (colCount - 1))) /
|
107
|
-
colCount);
|
108
85
|
const monthDateProfiles = this.splitDateProfileByMonth(context.dateProfileGenerator, props.dateProfile, context.dateEnv, options.fixedWeekCount, options.showNonCurrentDates);
|
109
86
|
const monthTitleFormat = this.buildMonthFormat(options.multiMonthTitleFormat, monthDateProfiles);
|
110
|
-
const
|
111
|
-
|
112
|
-
|
87
|
+
const { multiMonthMinWidth, multiMonthMaxColumns } = options;
|
88
|
+
const { innerWidth } = state;
|
89
|
+
let cols;
|
90
|
+
let computedMonthWidth;
|
91
|
+
let cssMonthWidth;
|
92
|
+
let hasLateralSiblings = false;
|
93
|
+
if (innerWidth != null) {
|
94
|
+
cols = Math.max(1, Math.min(multiMonthMaxColumns, Math.floor(innerWidth / multiMonthMinWidth)));
|
95
|
+
if (props.forPrint) {
|
96
|
+
cols = Math.min(cols, 2);
|
97
|
+
}
|
98
|
+
computedMonthWidth = innerWidth / cols;
|
99
|
+
cssMonthWidth = internal_cjs.fracToCssDim(1 / cols);
|
100
|
+
hasLateralSiblings = cols > 1;
|
101
|
+
}
|
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) ?
|
113
103
|
'fc-multimonth-singlecol' :
|
114
|
-
'fc-multimonth-multicol',
|
115
|
-
'
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
verticalScrolling ? 'fc-liquid' : '',
|
121
|
-
], ref: this.scrollerRef, widthRef: this.handleWidth },
|
122
|
-
preact_cjs.createElement("div", { ref: this.innerElRef, className: 'fc-multimonth-inner' }, monthDateProfiles.map((monthDateProfile, i) => {
|
104
|
+
'fc-multimonth-multicol',
|
105
|
+
// HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
|
106
|
+
// https://stackoverflow.com/a/60256345
|
107
|
+
!props.forPrint && 'fc-flex-col'), viewSpec: context.viewSpec },
|
108
|
+
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) => {
|
123
110
|
const monthStr = internal_cjs.formatIsoMonthStr(monthDateProfile.currentRange.start);
|
124
|
-
return (preact_cjs.createElement(SingleMonth, Object.assign({}, props, { key: monthStr, todayRange: todayRange, isoDateStr: monthStr, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width:
|
111
|
+
return (preact_cjs.createElement(SingleMonth, Object.assign({}, props, { key: monthStr, todayRange: todayRange, isoDateStr: monthStr, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width: cssMonthWidth, visibleWidth: computedMonthWidth, hasLateralSiblings: hasLateralSiblings })));
|
125
112
|
})))))));
|
126
113
|
}
|
127
114
|
// Lifecycle
|
@@ -129,6 +116,11 @@ class MultiMonthView extends internal_cjs.DateComponent {
|
|
129
116
|
componentDidMount() {
|
130
117
|
this.resetScroll();
|
131
118
|
this.scrollerRef.current.addScrollEndListener(this.clearScroll);
|
119
|
+
this.disconnectInnerWidth = internal_cjs.watchWidth(this.innerElRef.current, (innerWidth) => {
|
120
|
+
internal_cjs.afterSize(() => {
|
121
|
+
this.setState({ innerWidth });
|
122
|
+
});
|
123
|
+
});
|
132
124
|
}
|
133
125
|
componentDidUpdate(prevProps) {
|
134
126
|
if (prevProps.dateProfile !== this.props.dateProfile && this.context.options.scrollTimeReset) {
|
@@ -142,6 +134,7 @@ class MultiMonthView extends internal_cjs.DateComponent {
|
|
142
134
|
}
|
143
135
|
componentWillUnmount() {
|
144
136
|
this.scrollerRef.current.removeScrollEndListener(this.clearScroll);
|
137
|
+
this.disconnectInnerWidth();
|
145
138
|
}
|
146
139
|
// Scrolling
|
147
140
|
// -----------------------------------------------------------------------------------------------
|
@@ -213,7 +206,7 @@ const OPTION_REFINERS = {
|
|
213
206
|
multiMonthMinWidth: Number,
|
214
207
|
};
|
215
208
|
|
216
|
-
var css_248z = ".fc-multimonth-inner{display:flex;flex-wrap:wrap}.fc-
|
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}";
|
217
210
|
internal_cjs.injectStyles(css_248z);
|
218
211
|
|
219
212
|
var index = index_cjs.createPlugin({
|
@@ -231,7 +224,7 @@ var index = index_cjs.createPlugin({
|
|
231
224
|
type: 'multiMonth',
|
232
225
|
duration: { years: 1 },
|
233
226
|
fixedWeekCount: true,
|
234
|
-
showNonCurrentDates: false,
|
227
|
+
showNonCurrentDates: false, // TODO: looks bad when single-col layout
|
235
228
|
},
|
236
229
|
},
|
237
230
|
});
|
package/index.global.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
FullCalendar Multi-Month Plugin v7.0.0-beta.
|
2
|
+
FullCalendar Multi-Month Plugin v7.0.0-beta.3
|
3
3
|
Docs & License: https://fullcalendar.io/docs/multimonth-grid
|
4
4
|
(c) 2024 Adam Shaw
|
5
5
|
*/
|
@@ -9,10 +9,12 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
|
|
9
9
|
class SingleMonth extends internal.DateComponent {
|
10
10
|
constructor() {
|
11
11
|
super(...arguments);
|
12
|
-
this.slicer = new internal$1.DayTableSlicer();
|
13
12
|
// memo
|
14
13
|
this.buildDayTableModel = internal.memoize(internal$1.buildDayTableModel);
|
15
14
|
this.createDayHeaderFormatter = internal.memoize(internal$1.createDayHeaderFormatter);
|
15
|
+
this.buildDateRowConfig = internal.memoize(internal$1.buildDateRowConfig);
|
16
|
+
// internal
|
17
|
+
this.slicer = new internal$1.DayTableSlicer();
|
16
18
|
}
|
17
19
|
render() {
|
18
20
|
const { props, context } = this;
|
@@ -20,27 +22,31 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
|
|
20
22
|
const { options } = context;
|
21
23
|
const dayTableModel = this.buildDayTableModel(dateProfile, context.dateProfileGenerator);
|
22
24
|
const slicedProps = this.slicer.sliceProps(props, dateProfile, options.nextDayThreshold, context, dayTableModel);
|
23
|
-
|
24
|
-
const tableHeight = typeof props.width === 'number'
|
25
|
-
? props.width / options.aspectRatio
|
26
|
-
: null;
|
27
|
-
const rowCnt = dayTableModel.cellRows.length;
|
28
|
-
const rowHeight = tableHeight != null ? tableHeight / rowCnt : null;
|
29
|
-
const dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, false, // datesRepDistinctDays
|
25
|
+
const dayHeaderFormat = this.createDayHeaderFormatter(options.dayHeaderFormat, false, // datesRepDistinctDays
|
30
26
|
dayTableModel.colCnt);
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
const rowConfig = this.buildDateRowConfig(dayTableModel.headerDates, false, // datesRepDistinctDays
|
28
|
+
dateProfile, props.todayRange, dayHeaderFormat, context);
|
29
|
+
const invAspectRatio = 1 / options.aspectRatio;
|
30
|
+
const invRowAspectRatio = invAspectRatio / dayTableModel.rowCnt;
|
31
|
+
const isHeaderSticky = !forPrint;
|
32
|
+
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
|
+
} },
|
34
39
|
preact.createElement("div", { className: "fc-multimonth-title" }, context.dateEnv.format(props.dateProfile.currentRange.start, props.titleFormat)),
|
35
|
-
preact.createElement(
|
36
|
-
preact.createElement("div", { className: 'fc-multimonth-body fc-
|
37
|
-
marginTop: -
|
38
|
-
|
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,
|
39
44
|
} },
|
40
|
-
preact.createElement(internal$1.DayGridRows
|
41
|
-
, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: dayTableModel.cellRows, forPrint: props.forPrint,
|
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,
|
42
46
|
// content
|
43
|
-
fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection
|
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 }))));
|
44
50
|
}
|
45
51
|
}
|
46
52
|
|
@@ -52,32 +58,12 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
|
|
52
58
|
this.buildMonthFormat = internal.memoize(buildMonthFormat);
|
53
59
|
// ref
|
54
60
|
this.scrollerRef = preact.createRef();
|
55
|
-
this.innerElRef = preact.createRef();
|
56
|
-
// internal
|
61
|
+
this.innerElRef = preact.createRef(); // .fc-multimonth-inner
|
57
62
|
this.scrollDate = null;
|
58
|
-
// Sizing
|
59
|
-
// -----------------------------------------------------------------------------------------------
|
60
|
-
this.handleWidth = (width) => {
|
61
|
-
let { xGap, xPadding } = this.state;
|
62
|
-
// for first time, assume 2 columns and query gap/padding
|
63
|
-
if (xGap == null) {
|
64
|
-
const innerEl = this.innerElRef.current;
|
65
|
-
const children = innerEl.childNodes;
|
66
|
-
if (children.length > 1) {
|
67
|
-
const box0 = children[0].getBoundingClientRect();
|
68
|
-
const box1 = children[1].getBoundingClientRect();
|
69
|
-
let xSpan;
|
70
|
-
[xGap, xSpan] = [
|
71
|
-
Math.abs(box0.left - box1.right),
|
72
|
-
Math.abs(box0.right - box1.left),
|
73
|
-
].sort(internal.compareNumbers);
|
74
|
-
xPadding = width - xSpan;
|
75
|
-
}
|
76
|
-
}
|
77
|
-
this.setState({ width, xGap, xPadding });
|
78
|
-
};
|
79
63
|
this.updateScroll = () => {
|
80
|
-
if (this.scrollDate != null &&
|
64
|
+
if (this.scrollDate != null &&
|
65
|
+
this.state.innerWidth != null // render completed?
|
66
|
+
) {
|
81
67
|
const scroller = this.scrollerRef.current;
|
82
68
|
const innerEl = this.innerElRef.current;
|
83
69
|
const monthEl = innerEl.querySelector(`[data-date="${internal.formatIsoMonthStr(this.scrollDate)}"]`);
|
@@ -95,32 +81,33 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
|
|
95
81
|
const { context, props, state } = this;
|
96
82
|
const { options } = context;
|
97
83
|
const verticalScrolling = !props.forPrint && !internal.getIsHeightAuto(options);
|
98
|
-
const colCount = state.width == null
|
99
|
-
? 2
|
100
|
-
: Math.min(options.multiMonthMaxColumns, Math.floor((state.width - state.xPadding + state.xGap) /
|
101
|
-
(options.multiMonthMinWidth + state.xGap)));
|
102
|
-
const monthWidth = state.width == null
|
103
|
-
? '34%' // will expand. now small enough to be 1/3. for allowing gap
|
104
|
-
: Math.floor(// exact values can cause expansion to other rows
|
105
|
-
(state.width - state.xPadding - (state.xGap * (colCount - 1))) /
|
106
|
-
colCount);
|
107
84
|
const monthDateProfiles = this.splitDateProfileByMonth(context.dateProfileGenerator, props.dateProfile, context.dateEnv, options.fixedWeekCount, options.showNonCurrentDates);
|
108
85
|
const monthTitleFormat = this.buildMonthFormat(options.multiMonthTitleFormat, monthDateProfiles);
|
109
|
-
const
|
110
|
-
|
111
|
-
|
86
|
+
const { multiMonthMinWidth, multiMonthMaxColumns } = options;
|
87
|
+
const { innerWidth } = state;
|
88
|
+
let cols;
|
89
|
+
let computedMonthWidth;
|
90
|
+
let cssMonthWidth;
|
91
|
+
let hasLateralSiblings = false;
|
92
|
+
if (innerWidth != null) {
|
93
|
+
cols = Math.max(1, Math.min(multiMonthMaxColumns, Math.floor(innerWidth / multiMonthMinWidth)));
|
94
|
+
if (props.forPrint) {
|
95
|
+
cols = Math.min(cols, 2);
|
96
|
+
}
|
97
|
+
computedMonthWidth = innerWidth / cols;
|
98
|
+
cssMonthWidth = internal.fracToCssDim(1 / cols);
|
99
|
+
hasLateralSiblings = cols > 1;
|
100
|
+
}
|
101
|
+
return (preact.createElement(internal.NowTimer, { unit: "day" }, (nowDate, todayRange) => (preact.createElement(internal.ViewContainer, { className: internal.joinClassNames('fc-multimonth fc-border', (cols === 1) ?
|
112
102
|
'fc-multimonth-singlecol' :
|
113
|
-
'fc-multimonth-multicol',
|
114
|
-
'
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
verticalScrolling ? 'fc-liquid' : '',
|
120
|
-
], ref: this.scrollerRef, widthRef: this.handleWidth },
|
121
|
-
preact.createElement("div", { ref: this.innerElRef, className: 'fc-multimonth-inner' }, monthDateProfiles.map((monthDateProfile, i) => {
|
103
|
+
'fc-multimonth-multicol',
|
104
|
+
// HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
|
105
|
+
// https://stackoverflow.com/a/60256345
|
106
|
+
!props.forPrint && 'fc-flex-col'), viewSpec: context.viewSpec },
|
107
|
+
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) => {
|
122
109
|
const monthStr = internal.formatIsoMonthStr(monthDateProfile.currentRange.start);
|
123
|
-
return (preact.createElement(SingleMonth, Object.assign({}, props, { key: monthStr, todayRange: todayRange, isoDateStr: monthStr, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width:
|
110
|
+
return (preact.createElement(SingleMonth, Object.assign({}, props, { key: monthStr, todayRange: todayRange, isoDateStr: monthStr, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width: cssMonthWidth, visibleWidth: computedMonthWidth, hasLateralSiblings: hasLateralSiblings })));
|
124
111
|
})))))));
|
125
112
|
}
|
126
113
|
// Lifecycle
|
@@ -128,6 +115,11 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
|
|
128
115
|
componentDidMount() {
|
129
116
|
this.resetScroll();
|
130
117
|
this.scrollerRef.current.addScrollEndListener(this.clearScroll);
|
118
|
+
this.disconnectInnerWidth = internal.watchWidth(this.innerElRef.current, (innerWidth) => {
|
119
|
+
internal.afterSize(() => {
|
120
|
+
this.setState({ innerWidth });
|
121
|
+
});
|
122
|
+
});
|
131
123
|
}
|
132
124
|
componentDidUpdate(prevProps) {
|
133
125
|
if (prevProps.dateProfile !== this.props.dateProfile && this.context.options.scrollTimeReset) {
|
@@ -141,6 +133,7 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
|
|
141
133
|
}
|
142
134
|
componentWillUnmount() {
|
143
135
|
this.scrollerRef.current.removeScrollEndListener(this.clearScroll);
|
136
|
+
this.disconnectInnerWidth();
|
144
137
|
}
|
145
138
|
// Scrolling
|
146
139
|
// -----------------------------------------------------------------------------------------------
|
@@ -212,7 +205,7 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
|
|
212
205
|
multiMonthMinWidth: Number,
|
213
206
|
};
|
214
207
|
|
215
|
-
var css_248z = ".fc-multimonth-inner{display:flex;flex-wrap:wrap}.fc-
|
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}";
|
216
209
|
internal.injectStyles(css_248z);
|
217
210
|
|
218
211
|
var plugin = core.createPlugin({
|
@@ -230,7 +223,7 @@ FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact
|
|
230
223
|
type: 'multiMonth',
|
231
224
|
duration: { years: 1 },
|
232
225
|
fixedWeekCount: true,
|
233
|
-
showNonCurrentDates: false,
|
226
|
+
showNonCurrentDates: false, // TODO: looks bad when single-col layout
|
234
227
|
},
|
235
228
|
},
|
236
229
|
});
|
package/index.global.min.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*!
|
2
|
-
FullCalendar Multi-Month Plugin v7.0.0-beta.
|
2
|
+
FullCalendar Multi-Month Plugin v7.0.0-beta.3
|
3
3
|
Docs & License: https://fullcalendar.io/docs/multimonth-grid
|
4
4
|
(c) 2024 Adam Shaw
|
5
5
|
*/
|
6
|
-
FullCalendar.MultiMonth=function(e,t,
|
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);
|
package/index.js
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
import { createPlugin } from '@fullcalendar/core/index.js';
|
2
|
-
import {
|
3
|
-
import { DateComponent, memoize,
|
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';
|
4
4
|
import { createElement, createRef } from '@fullcalendar/core/preact.js';
|
5
5
|
|
6
6
|
class SingleMonth extends DateComponent {
|
7
7
|
constructor() {
|
8
8
|
super(...arguments);
|
9
|
-
this.slicer = new DayTableSlicer();
|
10
9
|
// memo
|
11
10
|
this.buildDayTableModel = memoize(buildDayTableModel);
|
12
11
|
this.createDayHeaderFormatter = memoize(createDayHeaderFormatter);
|
12
|
+
this.buildDateRowConfig = memoize(buildDateRowConfig);
|
13
|
+
// internal
|
14
|
+
this.slicer = new DayTableSlicer();
|
13
15
|
}
|
14
16
|
render() {
|
15
17
|
const { props, context } = this;
|
@@ -17,27 +19,31 @@ class SingleMonth extends DateComponent {
|
|
17
19
|
const { options } = context;
|
18
20
|
const dayTableModel = this.buildDayTableModel(dateProfile, context.dateProfileGenerator);
|
19
21
|
const slicedProps = this.slicer.sliceProps(props, dateProfile, options.nextDayThreshold, context, dayTableModel);
|
20
|
-
|
21
|
-
const tableHeight = typeof props.width === 'number'
|
22
|
-
? props.width / options.aspectRatio
|
23
|
-
: null;
|
24
|
-
const rowCnt = dayTableModel.cellRows.length;
|
25
|
-
const rowHeight = tableHeight != null ? tableHeight / rowCnt : null;
|
26
|
-
const dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, false, // datesRepDistinctDays
|
22
|
+
const dayHeaderFormat = this.createDayHeaderFormatter(options.dayHeaderFormat, false, // datesRepDistinctDays
|
27
23
|
dayTableModel.colCnt);
|
28
|
-
|
29
|
-
|
30
|
-
|
24
|
+
const rowConfig = this.buildDateRowConfig(dayTableModel.headerDates, false, // datesRepDistinctDays
|
25
|
+
dateProfile, props.todayRange, dayHeaderFormat, context);
|
26
|
+
const invAspectRatio = 1 / options.aspectRatio;
|
27
|
+
const invRowAspectRatio = invAspectRatio / dayTableModel.rowCnt;
|
28
|
+
const isHeaderSticky = !forPrint;
|
29
|
+
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
|
+
} },
|
31
36
|
createElement("div", { className: "fc-multimonth-title" }, context.dateEnv.format(props.dateProfile.currentRange.start, props.titleFormat)),
|
32
|
-
createElement(
|
33
|
-
createElement("div", { className: 'fc-multimonth-body fc-
|
34
|
-
marginTop: -
|
35
|
-
|
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,
|
36
41
|
} },
|
37
|
-
createElement(DayGridRows
|
38
|
-
, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: dayTableModel.cellRows, forPrint: props.forPrint,
|
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,
|
39
43
|
// content
|
40
|
-
fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection
|
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 }))));
|
41
47
|
}
|
42
48
|
}
|
43
49
|
|
@@ -49,32 +55,12 @@ class MultiMonthView extends DateComponent {
|
|
49
55
|
this.buildMonthFormat = memoize(buildMonthFormat);
|
50
56
|
// ref
|
51
57
|
this.scrollerRef = createRef();
|
52
|
-
this.innerElRef = createRef();
|
53
|
-
// internal
|
58
|
+
this.innerElRef = createRef(); // .fc-multimonth-inner
|
54
59
|
this.scrollDate = null;
|
55
|
-
// Sizing
|
56
|
-
// -----------------------------------------------------------------------------------------------
|
57
|
-
this.handleWidth = (width) => {
|
58
|
-
let { xGap, xPadding } = this.state;
|
59
|
-
// for first time, assume 2 columns and query gap/padding
|
60
|
-
if (xGap == null) {
|
61
|
-
const innerEl = this.innerElRef.current;
|
62
|
-
const children = innerEl.childNodes;
|
63
|
-
if (children.length > 1) {
|
64
|
-
const box0 = children[0].getBoundingClientRect();
|
65
|
-
const box1 = children[1].getBoundingClientRect();
|
66
|
-
let xSpan;
|
67
|
-
[xGap, xSpan] = [
|
68
|
-
Math.abs(box0.left - box1.right),
|
69
|
-
Math.abs(box0.right - box1.left),
|
70
|
-
].sort(compareNumbers);
|
71
|
-
xPadding = width - xSpan;
|
72
|
-
}
|
73
|
-
}
|
74
|
-
this.setState({ width, xGap, xPadding });
|
75
|
-
};
|
76
60
|
this.updateScroll = () => {
|
77
|
-
if (this.scrollDate != null &&
|
61
|
+
if (this.scrollDate != null &&
|
62
|
+
this.state.innerWidth != null // render completed?
|
63
|
+
) {
|
78
64
|
const scroller = this.scrollerRef.current;
|
79
65
|
const innerEl = this.innerElRef.current;
|
80
66
|
const monthEl = innerEl.querySelector(`[data-date="${formatIsoMonthStr(this.scrollDate)}"]`);
|
@@ -92,32 +78,33 @@ class MultiMonthView extends DateComponent {
|
|
92
78
|
const { context, props, state } = this;
|
93
79
|
const { options } = context;
|
94
80
|
const verticalScrolling = !props.forPrint && !getIsHeightAuto(options);
|
95
|
-
const colCount = state.width == null
|
96
|
-
? 2
|
97
|
-
: Math.min(options.multiMonthMaxColumns, Math.floor((state.width - state.xPadding + state.xGap) /
|
98
|
-
(options.multiMonthMinWidth + state.xGap)));
|
99
|
-
const monthWidth = state.width == null
|
100
|
-
? '34%' // will expand. now small enough to be 1/3. for allowing gap
|
101
|
-
: Math.floor(// exact values can cause expansion to other rows
|
102
|
-
(state.width - state.xPadding - (state.xGap * (colCount - 1))) /
|
103
|
-
colCount);
|
104
81
|
const monthDateProfiles = this.splitDateProfileByMonth(context.dateProfileGenerator, props.dateProfile, context.dateEnv, options.fixedWeekCount, options.showNonCurrentDates);
|
105
82
|
const monthTitleFormat = this.buildMonthFormat(options.multiMonthTitleFormat, monthDateProfiles);
|
106
|
-
const
|
107
|
-
|
108
|
-
|
83
|
+
const { multiMonthMinWidth, multiMonthMaxColumns } = options;
|
84
|
+
const { innerWidth } = state;
|
85
|
+
let cols;
|
86
|
+
let computedMonthWidth;
|
87
|
+
let cssMonthWidth;
|
88
|
+
let hasLateralSiblings = false;
|
89
|
+
if (innerWidth != null) {
|
90
|
+
cols = Math.max(1, Math.min(multiMonthMaxColumns, Math.floor(innerWidth / multiMonthMinWidth)));
|
91
|
+
if (props.forPrint) {
|
92
|
+
cols = Math.min(cols, 2);
|
93
|
+
}
|
94
|
+
computedMonthWidth = innerWidth / cols;
|
95
|
+
cssMonthWidth = fracToCssDim(1 / cols);
|
96
|
+
hasLateralSiblings = cols > 1;
|
97
|
+
}
|
98
|
+
return (createElement(NowTimer, { unit: "day" }, (nowDate, todayRange) => (createElement(ViewContainer, { className: joinClassNames('fc-multimonth fc-border', (cols === 1) ?
|
109
99
|
'fc-multimonth-singlecol' :
|
110
|
-
'fc-multimonth-multicol',
|
111
|
-
'
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
verticalScrolling ? 'fc-liquid' : '',
|
117
|
-
], ref: this.scrollerRef, widthRef: this.handleWidth },
|
118
|
-
createElement("div", { ref: this.innerElRef, className: 'fc-multimonth-inner' }, monthDateProfiles.map((monthDateProfile, i) => {
|
100
|
+
'fc-multimonth-multicol',
|
101
|
+
// HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
|
102
|
+
// https://stackoverflow.com/a/60256345
|
103
|
+
!props.forPrint && 'fc-flex-col'), viewSpec: context.viewSpec },
|
104
|
+
createElement(Scroller, { vertical: verticalScrolling, className: verticalScrolling ? 'fc-liquid' : '', ref: this.scrollerRef },
|
105
|
+
createElement("div", { ref: this.innerElRef, className: 'fc-multimonth-inner' }, monthDateProfiles.map((monthDateProfile) => {
|
119
106
|
const monthStr = formatIsoMonthStr(monthDateProfile.currentRange.start);
|
120
|
-
return (createElement(SingleMonth, Object.assign({}, props, { key: monthStr, todayRange: todayRange, isoDateStr: monthStr, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width:
|
107
|
+
return (createElement(SingleMonth, Object.assign({}, props, { key: monthStr, todayRange: todayRange, isoDateStr: monthStr, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width: cssMonthWidth, visibleWidth: computedMonthWidth, hasLateralSiblings: hasLateralSiblings })));
|
121
108
|
})))))));
|
122
109
|
}
|
123
110
|
// Lifecycle
|
@@ -125,6 +112,11 @@ class MultiMonthView extends DateComponent {
|
|
125
112
|
componentDidMount() {
|
126
113
|
this.resetScroll();
|
127
114
|
this.scrollerRef.current.addScrollEndListener(this.clearScroll);
|
115
|
+
this.disconnectInnerWidth = watchWidth(this.innerElRef.current, (innerWidth) => {
|
116
|
+
afterSize(() => {
|
117
|
+
this.setState({ innerWidth });
|
118
|
+
});
|
119
|
+
});
|
128
120
|
}
|
129
121
|
componentDidUpdate(prevProps) {
|
130
122
|
if (prevProps.dateProfile !== this.props.dateProfile && this.context.options.scrollTimeReset) {
|
@@ -138,6 +130,7 @@ class MultiMonthView extends DateComponent {
|
|
138
130
|
}
|
139
131
|
componentWillUnmount() {
|
140
132
|
this.scrollerRef.current.removeScrollEndListener(this.clearScroll);
|
133
|
+
this.disconnectInnerWidth();
|
141
134
|
}
|
142
135
|
// Scrolling
|
143
136
|
// -----------------------------------------------------------------------------------------------
|
@@ -209,7 +202,7 @@ const OPTION_REFINERS = {
|
|
209
202
|
multiMonthMinWidth: Number,
|
210
203
|
};
|
211
204
|
|
212
|
-
var css_248z = ".fc-multimonth-inner{display:flex;flex-wrap:wrap}.fc-
|
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}";
|
213
206
|
injectStyles(css_248z);
|
214
207
|
|
215
208
|
var index = createPlugin({
|
@@ -227,7 +220,7 @@ var index = createPlugin({
|
|
227
220
|
type: 'multiMonth',
|
228
221
|
duration: { years: 1 },
|
229
222
|
fixedWeekCount: true,
|
230
|
-
showNonCurrentDates: false,
|
223
|
+
showNonCurrentDates: false, // TODO: looks bad when single-col layout
|
231
224
|
},
|
232
225
|
},
|
233
226
|
});
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@fullcalendar/multimonth",
|
3
|
-
"version": "7.0.0-beta.
|
3
|
+
"version": "7.0.0-beta.3",
|
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.
|
15
|
+
"@fullcalendar/daygrid": "7.0.0-beta.3"
|
16
16
|
},
|
17
17
|
"peerDependencies": {
|
18
|
-
"@fullcalendar/core": "7.0.0-beta.
|
18
|
+
"@fullcalendar/core": "7.0.0-beta.3"
|
19
19
|
},
|
20
20
|
"type": "module",
|
21
21
|
"bugs": "https://fullcalendar.io/reporting-bugs",
|