@fullcalendar/multimonth 7.0.0-beta.3 → 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/index.js DELETED
@@ -1,228 +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, joinClassNames, fracToCssDim, formatIsoMonthStr, getIsHeightAuto, NowTimer, ViewContainer, Scroller, 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
- }
16
- render() {
17
- const { props, context } = this;
18
- const { dateProfile, forPrint } = props;
19
- const { options } = context;
20
- const dayTableModel = this.buildDayTableModel(dateProfile, context.dateProfileGenerator);
21
- const slicedProps = this.slicer.sliceProps(props, dateProfile, options.nextDayThreshold, context, dayTableModel);
22
- const dayHeaderFormat = this.createDayHeaderFormatter(options.dayHeaderFormat, false, // datesRepDistinctDays
23
- dayTableModel.colCnt);
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
- } },
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 }))));
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.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 });
71
- }
72
- };
73
- this.clearScroll = () => {
74
- this.scrollDate = null;
75
- };
76
- }
77
- render() {
78
- const { context, props, state } = this;
79
- const { options } = context;
80
- const verticalScrolling = !props.forPrint && !getIsHeightAuto(options);
81
- const monthDateProfiles = this.splitDateProfileByMonth(context.dateProfileGenerator, props.dateProfile, context.dateEnv, options.fixedWeekCount, options.showNonCurrentDates);
82
- const monthTitleFormat = this.buildMonthFormat(options.multiMonthTitleFormat, monthDateProfiles);
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) ?
99
- 'fc-multimonth-singlecol' :
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) => {
106
- const monthStr = formatIsoMonthStr(monthDateProfile.currentRange.start);
107
- return (createElement(SingleMonth, Object.assign({}, props, { key: monthStr, todayRange: todayRange, isoDateStr: monthStr, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width: cssMonthWidth, visibleWidth: computedMonthWidth, hasLateralSiblings: hasLateralSiblings })));
108
- })))))));
109
- }
110
- // Lifecycle
111
- // -----------------------------------------------------------------------------------------------
112
- componentDidMount() {
113
- this.resetScroll();
114
- this.scrollerRef.current.addScrollEndListener(this.clearScroll);
115
- this.disconnectInnerWidth = watchWidth(this.innerElRef.current, (innerWidth) => {
116
- afterSize(() => {
117
- this.setState({ innerWidth });
118
- });
119
- });
120
- }
121
- componentDidUpdate(prevProps) {
122
- if (prevProps.dateProfile !== this.props.dateProfile && this.context.options.scrollTimeReset) {
123
- this.resetScroll();
124
- }
125
- else {
126
- // NOT optimal to update so often
127
- // TODO: isolate dependencies of scroll coordinate
128
- this.updateScroll();
129
- }
130
- }
131
- componentWillUnmount() {
132
- this.scrollerRef.current.removeScrollEndListener(this.clearScroll);
133
- this.disconnectInnerWidth();
134
- }
135
- // Scrolling
136
- // -----------------------------------------------------------------------------------------------
137
- resetScroll() {
138
- this.scrollDate = this.props.dateProfile.currentDate;
139
- this.updateScroll();
140
- }
141
- }
142
- // date profile
143
- // -------------------------------------------------------------------------------------------------
144
- const oneMonthDuration = createDuration(1, 'month');
145
- function splitDateProfileByMonth(dateProfileGenerator, dateProfile, dateEnv, fixedWeekCount, showNonCurrentDates) {
146
- const { start, end } = dateProfile.currentRange;
147
- let monthStart = start;
148
- const monthDateProfiles = [];
149
- while (monthStart.valueOf() < end.valueOf()) {
150
- const monthEnd = dateEnv.add(monthStart, oneMonthDuration);
151
- const currentRange = {
152
- // yuck
153
- start: dateProfileGenerator.skipHiddenDays(monthStart),
154
- end: dateProfileGenerator.skipHiddenDays(monthEnd, -1, true),
155
- };
156
- let renderRange = buildDayTableRenderRange({
157
- currentRange,
158
- snapToWeek: true,
159
- fixedWeekCount,
160
- dateEnv,
161
- });
162
- renderRange = {
163
- // yuck
164
- start: dateProfileGenerator.skipHiddenDays(renderRange.start),
165
- end: dateProfileGenerator.skipHiddenDays(renderRange.end, -1, true),
166
- };
167
- const activeRange = dateProfile.activeRange ?
168
- intersectRanges(dateProfile.activeRange, showNonCurrentDates ? renderRange : currentRange) :
169
- null;
170
- monthDateProfiles.push({
171
- currentDate: dateProfile.currentDate,
172
- isValid: dateProfile.isValid,
173
- validRange: dateProfile.validRange,
174
- renderRange,
175
- activeRange,
176
- currentRange,
177
- currentRangeUnit: 'month',
178
- isRangeAllDay: true,
179
- dateIncrement: dateProfile.dateIncrement,
180
- slotMinTime: dateProfile.slotMaxTime,
181
- slotMaxTime: dateProfile.slotMinTime,
182
- });
183
- monthStart = monthEnd;
184
- }
185
- return monthDateProfiles;
186
- }
187
- // date formatting
188
- // -------------------------------------------------------------------------------------------------
189
- const YEAR_MONTH_FORMATTER = createFormatter({ year: 'numeric', month: 'long' });
190
- const YEAR_FORMATTER = createFormatter({ month: 'long' });
191
- function buildMonthFormat(formatOverride, monthDateProfiles) {
192
- return formatOverride ||
193
- ((monthDateProfiles[0].currentRange.start.getUTCFullYear() !==
194
- monthDateProfiles[monthDateProfiles.length - 1].currentRange.start.getUTCFullYear())
195
- ? YEAR_MONTH_FORMATTER
196
- : YEAR_FORMATTER);
197
- }
198
-
199
- const OPTION_REFINERS = {
200
- multiMonthTitleFormat: createFormatter,
201
- multiMonthMaxColumns: Number,
202
- multiMonthMinWidth: Number,
203
- };
204
-
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}";
206
- injectStyles(css_248z);
207
-
208
- var index = createPlugin({
209
- name: '@fullcalendar/multimonth',
210
- initialView: 'multiMonthYear',
211
- optionRefiners: OPTION_REFINERS,
212
- views: {
213
- multiMonth: {
214
- component: MultiMonthView,
215
- dateProfileGeneratorClass: TableDateProfileGenerator,
216
- multiMonthMinWidth: 350,
217
- multiMonthMaxColumns: 3,
218
- },
219
- multiMonthYear: {
220
- type: 'multiMonth',
221
- duration: { years: 1 },
222
- fixedWeekCount: true,
223
- showNonCurrentDates: false, // TODO: looks bad when single-col layout
224
- },
225
- },
226
- });
227
-
228
- export { index as default };