@fullcalendar/multimonth 7.0.0-beta.4 → 7.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +1 -1
- package/README.md +6 -1
- package/cjs/index.cjs +322 -0
- package/esm/index.d.ts +41 -0
- package/esm/index.js +314 -0
- package/global.js +328 -0
- package/global.min.js +6 -0
- package/package.json +18 -15
- package/index.cjs +0 -234
- package/index.d.ts +0 -20
- package/index.global.js +0 -241
- package/index.global.min.js +0 -6
- package/index.js +0 -230
package/index.js
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
import { createPlugin } from '@fullcalendar/core/index.js';
|
|
2
|
-
import { buildDayTableModel, createDayHeaderFormatter, buildDateRowConfig, DayTableSlicer, DayGridHeaderRow, DayGridRows, buildDayTableRenderRange, TableDateProfileGenerator } from '@fullcalendar/daygrid/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
|
-
import { createElement, createRef } from '@fullcalendar/core/preact.js';
|
|
5
|
-
|
|
6
|
-
class SingleMonth extends DateComponent {
|
|
7
|
-
constructor() {
|
|
8
|
-
super(...arguments);
|
|
9
|
-
// memo
|
|
10
|
-
this.buildDayTableModel = memoize(buildDayTableModel);
|
|
11
|
-
this.createDayHeaderFormatter = memoize(createDayHeaderFormatter);
|
|
12
|
-
this.buildDateRowConfig = memoize(buildDateRowConfig);
|
|
13
|
-
// internal
|
|
14
|
-
this.slicer = new DayTableSlicer();
|
|
15
|
-
this.titleId = getUniqueDomId();
|
|
16
|
-
}
|
|
17
|
-
render() {
|
|
18
|
-
const { props, context } = this;
|
|
19
|
-
const { dateProfile, forPrint } = props;
|
|
20
|
-
const { options } = context;
|
|
21
|
-
const dayTableModel = this.buildDayTableModel(dateProfile, context.dateProfileGenerator);
|
|
22
|
-
const slicedProps = this.slicer.sliceProps(props, dateProfile, options.nextDayThreshold, context, dayTableModel);
|
|
23
|
-
const dayHeaderFormat = this.createDayHeaderFormatter(options.dayHeaderFormat, false, // datesRepDistinctDays
|
|
24
|
-
dayTableModel.colCnt);
|
|
25
|
-
const rowConfig = this.buildDateRowConfig(dayTableModel.headerDates, false, // datesRepDistinctDays
|
|
26
|
-
dateProfile, props.todayRange, dayHeaderFormat, context);
|
|
27
|
-
const invAspectRatio = 1 / options.aspectRatio;
|
|
28
|
-
const invRowAspectRatio = invAspectRatio / dayTableModel.rowCnt;
|
|
29
|
-
const isHeaderSticky = !forPrint;
|
|
30
|
-
const isAspectRatio = !forPrint || props.hasLateralSiblings;
|
|
31
|
-
return (createElement("div", { role: 'listitem', className: 'fc-multimonth-month-outer', style: { width: props.width } },
|
|
32
|
-
createElement("div", { role: 'grid', "aria-labelledby": this.titleId, "data-date": props.isoDateStr, className: joinClassNames('fc-multimonth-month', props.hasLateralSiblings && 'fc-break-inside-avoid') },
|
|
33
|
-
createElement("div", { className: "fc-multimonth-header", style: {
|
|
34
|
-
marginBottom: isHeaderSticky ? fracToCssDim(invRowAspectRatio) : undefined,
|
|
35
|
-
} },
|
|
36
|
-
createElement("div", { id: this.titleId, className: 'fc-multimonth-title' }, context.dateEnv.format(props.dateProfile.currentRange.start, props.titleFormat)),
|
|
37
|
-
createElement(DayGridHeaderRow, Object.assign({}, rowConfig, { role: 'row', className: 'fc-multimonth-header-row' }))),
|
|
38
|
-
createElement("div", { className: joinClassNames('fc-multimonth-body', isAspectRatio && 'fc-rel'), style: {
|
|
39
|
-
marginTop: isHeaderSticky ? fracToCssDim(-invRowAspectRatio) : undefined,
|
|
40
|
-
paddingBottom: isAspectRatio ? fracToCssDim(invAspectRatio) : undefined,
|
|
41
|
-
} },
|
|
42
|
-
createElement(DayGridRows, { dateProfile: props.dateProfile, todayRange: props.todayRange, cellRows: dayTableModel.cellRows, className: isAspectRatio ? 'fc-fill' : '', forPrint: forPrint && !props.hasLateralSiblings, dayMaxEvents: forPrint ? undefined : options.dayMaxEvents, dayMaxEventRows: (forPrint && props.hasLateralSiblings) ? 1 : options.dayMaxEventRows,
|
|
43
|
-
// content
|
|
44
|
-
fgEventSegs: slicedProps.fgEventSegs, bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventDrag: slicedProps.eventDrag, eventResize: slicedProps.eventResize, eventSelection: slicedProps.eventSelection,
|
|
45
|
-
// dimensions
|
|
46
|
-
visibleWidth: props.visibleWidth })))));
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
class MultiMonthView extends DateComponent {
|
|
51
|
-
constructor() {
|
|
52
|
-
super(...arguments);
|
|
53
|
-
// memo
|
|
54
|
-
this.splitDateProfileByMonth = memoize(splitDateProfileByMonth);
|
|
55
|
-
this.buildMonthFormat = memoize(buildMonthFormat);
|
|
56
|
-
// ref
|
|
57
|
-
this.scrollerRef = createRef();
|
|
58
|
-
this.innerElRef = createRef(); // .fc-multimonth-inner
|
|
59
|
-
this.scrollDate = null;
|
|
60
|
-
this.handleScrollEnd = ({ isUser }) => {
|
|
61
|
-
if (isUser) {
|
|
62
|
-
this.scrollDate = null;
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
render() {
|
|
67
|
-
const { context, props, state } = this;
|
|
68
|
-
const { options } = context;
|
|
69
|
-
const verticalScrolling = !props.forPrint && !getIsHeightAuto(options);
|
|
70
|
-
const monthDateProfiles = this.splitDateProfileByMonth(context.dateProfileGenerator, props.dateProfile, context.dateEnv, options.fixedWeekCount, options.showNonCurrentDates);
|
|
71
|
-
const monthTitleFormat = this.buildMonthFormat(options.multiMonthTitleFormat, monthDateProfiles);
|
|
72
|
-
const { multiMonthMinWidth, multiMonthMaxColumns } = options;
|
|
73
|
-
const { innerWidth } = state;
|
|
74
|
-
let cols;
|
|
75
|
-
let computedMonthWidth;
|
|
76
|
-
let cssMonthWidth;
|
|
77
|
-
let hasLateralSiblings = false;
|
|
78
|
-
if (innerWidth != null) {
|
|
79
|
-
cols = Math.max(1, Math.min(multiMonthMaxColumns, Math.floor(innerWidth / multiMonthMinWidth)));
|
|
80
|
-
if (props.forPrint) {
|
|
81
|
-
cols = Math.min(cols, 2);
|
|
82
|
-
}
|
|
83
|
-
computedMonthWidth = innerWidth / cols;
|
|
84
|
-
cssMonthWidth = fracToCssDim(1 / cols);
|
|
85
|
-
hasLateralSiblings = cols > 1;
|
|
86
|
-
}
|
|
87
|
-
return (createElement(NowTimer, { unit: "day" }, (nowDate, todayRange) => (createElement(ViewContainer, { viewSpec: context.viewSpec, className: joinClassNames('fc-multimonth fc-border', (cols === 1) ?
|
|
88
|
-
'fc-multimonth-singlecol' :
|
|
89
|
-
'fc-multimonth-multicol',
|
|
90
|
-
// HACK for Safari. Can't do break-inside:avoid with flexbox items, likely b/c it's not standard:
|
|
91
|
-
// https://stackoverflow.com/a/60256345
|
|
92
|
-
!props.forPrint && 'fc-flex-col') },
|
|
93
|
-
createElement(Scroller, { vertical: verticalScrolling, className: verticalScrolling ? 'fc-liquid' : '', ref: this.scrollerRef },
|
|
94
|
-
createElement("div", { role: 'list', "aria-labelledby": props.labelId, "aria-label": props.labelStr, className: 'fc-multimonth-inner', ref: this.innerElRef }, monthDateProfiles.map((monthDateProfile) => {
|
|
95
|
-
const monthStr = formatIsoMonthStr(monthDateProfile.currentRange.start);
|
|
96
|
-
return (createElement(SingleMonth, Object.assign({}, props, { key: monthStr, todayRange: todayRange, isoDateStr: monthStr, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width: cssMonthWidth, visibleWidth: computedMonthWidth, hasLateralSiblings: hasLateralSiblings })));
|
|
97
|
-
})))))));
|
|
98
|
-
}
|
|
99
|
-
// Lifecycle
|
|
100
|
-
// -----------------------------------------------------------------------------------------------
|
|
101
|
-
componentDidMount() {
|
|
102
|
-
this.resetScroll();
|
|
103
|
-
this.scrollerRef.current.addScrollEndListener(this.handleScrollEnd);
|
|
104
|
-
this.disconnectInnerWidth = watchWidth(this.innerElRef.current, (innerWidth) => {
|
|
105
|
-
afterSize(() => {
|
|
106
|
-
this.setState({ innerWidth });
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
componentDidUpdate(prevProps) {
|
|
111
|
-
if (prevProps.dateProfile !== this.props.dateProfile && this.context.options.scrollTimeReset) {
|
|
112
|
-
this.resetScroll();
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
// NOT optimal to update so often
|
|
116
|
-
// TODO: isolate dependencies of scroll coordinate
|
|
117
|
-
this.applyScroll();
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
componentWillUnmount() {
|
|
121
|
-
this.scrollerRef.current.removeScrollEndListener(this.handleScrollEnd);
|
|
122
|
-
this.disconnectInnerWidth();
|
|
123
|
-
}
|
|
124
|
-
// Scrolling
|
|
125
|
-
// -----------------------------------------------------------------------------------------------
|
|
126
|
-
resetScroll() {
|
|
127
|
-
this.scrollDate = this.props.dateProfile.currentDate;
|
|
128
|
-
this.applyScroll();
|
|
129
|
-
}
|
|
130
|
-
applyScroll() {
|
|
131
|
-
if (this.scrollDate != null &&
|
|
132
|
-
this.state.innerWidth != null // render completed?
|
|
133
|
-
) {
|
|
134
|
-
const scroller = this.scrollerRef.current;
|
|
135
|
-
const innerEl = this.innerElRef.current;
|
|
136
|
-
const monthEl = innerEl.querySelector(`[data-date="${formatIsoMonthStr(this.scrollDate)}"]`);
|
|
137
|
-
const scrollTop = Math.ceil(// for fractions, err on the side of scrolling further
|
|
138
|
-
monthEl.getBoundingClientRect().top -
|
|
139
|
-
innerEl.getBoundingClientRect().top);
|
|
140
|
-
scroller.scrollTo({ y: scrollTop });
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
// date profile
|
|
145
|
-
// -------------------------------------------------------------------------------------------------
|
|
146
|
-
const oneMonthDuration = createDuration(1, 'month');
|
|
147
|
-
function splitDateProfileByMonth(dateProfileGenerator, dateProfile, dateEnv, fixedWeekCount, showNonCurrentDates) {
|
|
148
|
-
const { start, end } = dateProfile.currentRange;
|
|
149
|
-
let monthStart = start;
|
|
150
|
-
const monthDateProfiles = [];
|
|
151
|
-
while (monthStart.valueOf() < end.valueOf()) {
|
|
152
|
-
const monthEnd = dateEnv.add(monthStart, oneMonthDuration);
|
|
153
|
-
const currentRange = {
|
|
154
|
-
// yuck
|
|
155
|
-
start: dateProfileGenerator.skipHiddenDays(monthStart),
|
|
156
|
-
end: dateProfileGenerator.skipHiddenDays(monthEnd, -1, true),
|
|
157
|
-
};
|
|
158
|
-
let renderRange = buildDayTableRenderRange({
|
|
159
|
-
currentRange,
|
|
160
|
-
snapToWeek: true,
|
|
161
|
-
fixedWeekCount,
|
|
162
|
-
dateEnv,
|
|
163
|
-
});
|
|
164
|
-
renderRange = {
|
|
165
|
-
// yuck
|
|
166
|
-
start: dateProfileGenerator.skipHiddenDays(renderRange.start),
|
|
167
|
-
end: dateProfileGenerator.skipHiddenDays(renderRange.end, -1, true),
|
|
168
|
-
};
|
|
169
|
-
const activeRange = dateProfile.activeRange ?
|
|
170
|
-
intersectRanges(dateProfile.activeRange, showNonCurrentDates ? renderRange : currentRange) :
|
|
171
|
-
null;
|
|
172
|
-
monthDateProfiles.push({
|
|
173
|
-
currentDate: dateProfile.currentDate,
|
|
174
|
-
isValid: dateProfile.isValid,
|
|
175
|
-
validRange: dateProfile.validRange,
|
|
176
|
-
renderRange,
|
|
177
|
-
activeRange,
|
|
178
|
-
currentRange,
|
|
179
|
-
currentRangeUnit: 'month',
|
|
180
|
-
isRangeAllDay: true,
|
|
181
|
-
dateIncrement: dateProfile.dateIncrement,
|
|
182
|
-
slotMinTime: dateProfile.slotMaxTime,
|
|
183
|
-
slotMaxTime: dateProfile.slotMinTime,
|
|
184
|
-
});
|
|
185
|
-
monthStart = monthEnd;
|
|
186
|
-
}
|
|
187
|
-
return monthDateProfiles;
|
|
188
|
-
}
|
|
189
|
-
// date formatting
|
|
190
|
-
// -------------------------------------------------------------------------------------------------
|
|
191
|
-
const YEAR_MONTH_FORMATTER = createFormatter({ year: 'numeric', month: 'long' });
|
|
192
|
-
const YEAR_FORMATTER = createFormatter({ month: 'long' });
|
|
193
|
-
function buildMonthFormat(formatOverride, monthDateProfiles) {
|
|
194
|
-
return formatOverride ||
|
|
195
|
-
((monthDateProfiles[0].currentRange.start.getUTCFullYear() !==
|
|
196
|
-
monthDateProfiles[monthDateProfiles.length - 1].currentRange.start.getUTCFullYear())
|
|
197
|
-
? YEAR_MONTH_FORMATTER
|
|
198
|
-
: YEAR_FORMATTER);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const OPTION_REFINERS = {
|
|
202
|
-
multiMonthTitleFormat: createFormatter,
|
|
203
|
-
multiMonthMaxColumns: Number,
|
|
204
|
-
multiMonthMinWidth: Number,
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
var css_248z = ".fc-media-screen .fc-multimonth-inner{display:flex;flex-direction:row;flex-wrap:wrap}.fc-media-print.fc-direction-ltr .fc-multimonth-inner>*{float:left}.fc-media-print.fc-direction-rtl .fc-multimonth-inner>*{float:right}.fc-media-print .fc-multimonth-inner:after{clear:both;content:\"\";display:block}.fc-multimonth-multicol .fc-multimonth-month{padding:1.2em}.fc-multimonth-singlecol .fc-multimonth-title{padding:.5em 0}.fc-multimonth-multicol .fc-multimonth-title{padding-bottom:1em}.fc-multimonth-title{font-size:1.2em;font-weight:700;text-align:center}.fc-multimonth-header-row{border-top:1px solid var(--fc-border-color)}.fc-multimonth-body:not(.fc-multimonth-singlecol .fc-multimonth-month-outer:last-child .fc-multimonth-body),.fc-multimonth-header-row{border-bottom:1px solid var(--fc-border-color)}.fc-multimonth-multicol .fc-multimonth-body,.fc-multimonth-multicol .fc-multimonth-header-row{border-left:1px solid var(--fc-border-color);border-right:1px solid var(--fc-border-color);font-size:.9em;line-height:1}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:sticky;top:0;z-index:2}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-body{position:relative;z-index:1}";
|
|
208
|
-
injectStyles(css_248z);
|
|
209
|
-
|
|
210
|
-
var index = createPlugin({
|
|
211
|
-
name: '@fullcalendar/multimonth',
|
|
212
|
-
initialView: 'multiMonthYear',
|
|
213
|
-
optionRefiners: OPTION_REFINERS,
|
|
214
|
-
views: {
|
|
215
|
-
multiMonth: {
|
|
216
|
-
component: MultiMonthView,
|
|
217
|
-
dateProfileGeneratorClass: TableDateProfileGenerator,
|
|
218
|
-
multiMonthMinWidth: 350,
|
|
219
|
-
multiMonthMaxColumns: 3,
|
|
220
|
-
},
|
|
221
|
-
multiMonthYear: {
|
|
222
|
-
type: 'multiMonth',
|
|
223
|
-
duration: { years: 1 },
|
|
224
|
-
fixedWeekCount: true,
|
|
225
|
-
showNonCurrentDates: false, // TODO: looks bad when single-col layout
|
|
226
|
-
},
|
|
227
|
-
},
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
export { index as default };
|