1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | FullCalendar.TimeGrid = (function (exports, core, internal$1, preact, internal$2) {
|
7 | 'use strict';
|
8 |
|
9 | class AllDaySplitter extends internal$1.Splitter {
|
10 | getKeyInfo() {
|
11 | return {
|
12 | allDay: {},
|
13 | timed: {},
|
14 | };
|
15 | }
|
16 | getKeysForDateSpan(dateSpan) {
|
17 | if (dateSpan.allDay) {
|
18 | return ['allDay'];
|
19 | }
|
20 | return ['timed'];
|
21 | }
|
22 | getKeysForEventDef(eventDef) {
|
23 | if (!eventDef.allDay) {
|
24 | return ['timed'];
|
25 | }
|
26 | if (internal$1.hasBgRendering(eventDef)) {
|
27 | return ['timed', 'allDay'];
|
28 | }
|
29 | return ['allDay'];
|
30 | }
|
31 | }
|
32 |
|
33 | const DEFAULT_SLAT_LABEL_FORMAT = internal$1.createFormatter({
|
34 | hour: 'numeric',
|
35 | minute: '2-digit',
|
36 | omitZeroMinute: true,
|
37 | meridiem: 'short',
|
38 | });
|
39 | function TimeColsAxisCell(props) {
|
40 | let classNames = [
|
41 | 'fc-timegrid-slot',
|
42 | 'fc-timegrid-slot-label',
|
43 | props.isLabeled ? 'fc-scrollgrid-shrink' : 'fc-timegrid-slot-minor',
|
44 | ];
|
45 | return (preact.createElement(internal$1.ViewContextType.Consumer, null, (context) => {
|
46 | if (!props.isLabeled) {
|
47 | return (preact.createElement("td", { className: classNames.join(' '), "data-time": props.isoTimeStr }));
|
48 | }
|
49 | let { dateEnv, options, viewApi } = context;
|
50 | let labelFormat =
|
51 | options.slotLabelFormat == null ? DEFAULT_SLAT_LABEL_FORMAT :
|
52 | Array.isArray(options.slotLabelFormat) ? internal$1.createFormatter(options.slotLabelFormat[0]) :
|
53 | internal$1.createFormatter(options.slotLabelFormat);
|
54 | let renderProps = {
|
55 | level: 0,
|
56 | time: props.time,
|
57 | date: dateEnv.toDate(props.date),
|
58 | view: viewApi,
|
59 | text: dateEnv.format(props.date, labelFormat),
|
60 | };
|
61 | return (preact.createElement(internal$1.ContentContainer, { elTag: "td", elClasses: classNames, elAttrs: {
|
62 | 'data-time': props.isoTimeStr,
|
63 | }, renderProps: renderProps, generatorName: "slotLabelContent", customGenerator: options.slotLabelContent, defaultGenerator: renderInnerContent, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (preact.createElement("div", { className: "fc-timegrid-slot-label-frame fc-scrollgrid-shrink-frame" },
|
64 | preact.createElement(InnerContent, { elTag: "div", elClasses: [
|
65 | 'fc-timegrid-slot-label-cushion',
|
66 | 'fc-scrollgrid-shrink-cushion',
|
67 | ] })))));
|
68 | }));
|
69 | }
|
70 | function renderInnerContent(props) {
|
71 | return props.text;
|
72 | }
|
73 |
|
74 | class TimeBodyAxis extends internal$1.BaseComponent {
|
75 | render() {
|
76 | return this.props.slatMetas.map((slatMeta) => (preact.createElement("tr", { key: slatMeta.key },
|
77 | preact.createElement(TimeColsAxisCell, Object.assign({}, slatMeta)))));
|
78 | }
|
79 | }
|
80 |
|
81 | const DEFAULT_WEEK_NUM_FORMAT = internal$1.createFormatter({ week: 'short' });
|
82 | const AUTO_ALL_DAY_MAX_EVENT_ROWS = 5;
|
83 | class TimeColsView extends internal$1.DateComponent {
|
84 | constructor() {
|
85 | super(...arguments);
|
86 | this.allDaySplitter = new AllDaySplitter();
|
87 | this.headerElRef = preact.createRef();
|
88 | this.rootElRef = preact.createRef();
|
89 | this.scrollerElRef = preact.createRef();
|
90 | this.state = {
|
91 | slatCoords: null,
|
92 | };
|
93 | this.handleScrollTopRequest = (scrollTop) => {
|
94 | let scrollerEl = this.scrollerElRef.current;
|
95 | if (scrollerEl) {
|
96 | scrollerEl.scrollTop = scrollTop;
|
97 | }
|
98 | };
|
99 | |
100 |
|
101 | this.renderHeadAxis = (rowKey, frameHeight = '') => {
|
102 | let { options } = this.context;
|
103 | let { dateProfile } = this.props;
|
104 | let range = dateProfile.renderRange;
|
105 | let dayCnt = internal$1.diffDays(range.start, range.end);
|
106 |
|
107 | let navLinkAttrs = (dayCnt === 1)
|
108 | ? internal$1.buildNavLinkAttrs(this.context, range.start, 'week')
|
109 | : {};
|
110 | if (options.weekNumbers && rowKey === 'day') {
|
111 | return (preact.createElement(internal$1.WeekNumberContainer, { elTag: "th", elClasses: [
|
112 | 'fc-timegrid-axis',
|
113 | 'fc-scrollgrid-shrink',
|
114 | ], elAttrs: {
|
115 | 'aria-hidden': true,
|
116 | }, date: range.start, defaultFormat: DEFAULT_WEEK_NUM_FORMAT }, (InnerContent) => (preact.createElement("div", { className: [
|
117 | 'fc-timegrid-axis-frame',
|
118 | 'fc-scrollgrid-shrink-frame',
|
119 | 'fc-timegrid-axis-frame-liquid',
|
120 | ].join(' '), style: { height: frameHeight } },
|
121 | preact.createElement(InnerContent, { elTag: "a", elClasses: [
|
122 | 'fc-timegrid-axis-cushion',
|
123 | 'fc-scrollgrid-shrink-cushion',
|
124 | 'fc-scrollgrid-sync-inner',
|
125 | ], elAttrs: navLinkAttrs })))));
|
126 | }
|
127 | return (preact.createElement("th", { "aria-hidden": true, className: "fc-timegrid-axis" },
|
128 | preact.createElement("div", { className: "fc-timegrid-axis-frame", style: { height: frameHeight } })));
|
129 | };
|
130 | |
131 |
|
132 |
|
133 |
|
134 | this.renderTableRowAxis = (rowHeight) => {
|
135 | let { options, viewApi } = this.context;
|
136 | let renderProps = {
|
137 | text: options.allDayText,
|
138 | view: viewApi,
|
139 | };
|
140 | return (
|
141 |
|
142 | preact.createElement(internal$1.ContentContainer, { elTag: "td", elClasses: [
|
143 | 'fc-timegrid-axis',
|
144 | 'fc-scrollgrid-shrink',
|
145 | ], elAttrs: {
|
146 | 'aria-hidden': true,
|
147 | }, renderProps: renderProps, generatorName: "allDayContent", customGenerator: options.allDayContent, defaultGenerator: renderAllDayInner, classNameGenerator: options.allDayClassNames, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }, (InnerContent) => (preact.createElement("div", { className: [
|
148 | 'fc-timegrid-axis-frame',
|
149 | 'fc-scrollgrid-shrink-frame',
|
150 | rowHeight == null ? ' fc-timegrid-axis-frame-liquid' : '',
|
151 | ].join(' '), style: { height: rowHeight } },
|
152 | preact.createElement(InnerContent, { elTag: "span", elClasses: [
|
153 | 'fc-timegrid-axis-cushion',
|
154 | 'fc-scrollgrid-shrink-cushion',
|
155 | 'fc-scrollgrid-sync-inner',
|
156 | ] })))));
|
157 | };
|
158 | this.handleSlatCoords = (slatCoords) => {
|
159 | this.setState({ slatCoords });
|
160 | };
|
161 | }
|
162 |
|
163 |
|
164 | renderSimpleLayout(headerRowContent, allDayContent, timeContent) {
|
165 | let { context, props } = this;
|
166 | let sections = [];
|
167 | let stickyHeaderDates = internal$1.getStickyHeaderDates(context.options);
|
168 | if (headerRowContent) {
|
169 | sections.push({
|
170 | type: 'header',
|
171 | key: 'header',
|
172 | isSticky: stickyHeaderDates,
|
173 | chunk: {
|
174 | elRef: this.headerElRef,
|
175 | tableClassName: 'fc-col-header',
|
176 | rowContent: headerRowContent,
|
177 | },
|
178 | });
|
179 | }
|
180 | if (allDayContent) {
|
181 | sections.push({
|
182 | type: 'body',
|
183 | key: 'all-day',
|
184 | chunk: { content: allDayContent },
|
185 | });
|
186 | sections.push({
|
187 | type: 'body',
|
188 | key: 'all-day-divider',
|
189 | outerContent: (
|
190 | preact.createElement("tr", { role: "presentation", className: "fc-scrollgrid-section" },
|
191 | preact.createElement("td", { className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),
|
192 | });
|
193 | }
|
194 | sections.push({
|
195 | type: 'body',
|
196 | key: 'body',
|
197 | liquid: true,
|
198 | expandRows: Boolean(context.options.expandRows),
|
199 | chunk: {
|
200 | scrollerElRef: this.scrollerElRef,
|
201 | content: timeContent,
|
202 | },
|
203 | });
|
204 | return (preact.createElement(internal$1.ViewContainer, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },
|
205 | preact.createElement(internal$1.SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [{ width: 'shrink' }], sections: sections })));
|
206 | }
|
207 | renderHScrollLayout(headerRowContent, allDayContent, timeContent, colCnt, dayMinWidth, slatMetas, slatCoords) {
|
208 | let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
|
209 | if (!ScrollGrid) {
|
210 | throw new Error('No ScrollGrid implementation');
|
211 | }
|
212 | let { context, props } = this;
|
213 | let stickyHeaderDates = !props.forPrint && internal$1.getStickyHeaderDates(context.options);
|
214 | let stickyFooterScrollbar = !props.forPrint && internal$1.getStickyFooterScrollbar(context.options);
|
215 | let sections = [];
|
216 | if (headerRowContent) {
|
217 | sections.push({
|
218 | type: 'header',
|
219 | key: 'header',
|
220 | isSticky: stickyHeaderDates,
|
221 | syncRowHeights: true,
|
222 | chunks: [
|
223 | {
|
224 | key: 'axis',
|
225 | rowContent: (arg) => (preact.createElement("tr", { role: "presentation" }, this.renderHeadAxis('day', arg.rowSyncHeights[0]))),
|
226 | },
|
227 | {
|
228 | key: 'cols',
|
229 | elRef: this.headerElRef,
|
230 | tableClassName: 'fc-col-header',
|
231 | rowContent: headerRowContent,
|
232 | },
|
233 | ],
|
234 | });
|
235 | }
|
236 | if (allDayContent) {
|
237 | sections.push({
|
238 | type: 'body',
|
239 | key: 'all-day',
|
240 | syncRowHeights: true,
|
241 | chunks: [
|
242 | {
|
243 | key: 'axis',
|
244 | rowContent: (contentArg) => (preact.createElement("tr", { role: "presentation" }, this.renderTableRowAxis(contentArg.rowSyncHeights[0]))),
|
245 | },
|
246 | {
|
247 | key: 'cols',
|
248 | content: allDayContent,
|
249 | },
|
250 | ],
|
251 | });
|
252 | sections.push({
|
253 | key: 'all-day-divider',
|
254 | type: 'body',
|
255 | outerContent: (
|
256 | preact.createElement("tr", { role: "presentation", className: "fc-scrollgrid-section" },
|
257 | preact.createElement("td", { colSpan: 2, className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),
|
258 | });
|
259 | }
|
260 | let isNowIndicator = context.options.nowIndicator;
|
261 | sections.push({
|
262 | type: 'body',
|
263 | key: 'body',
|
264 | liquid: true,
|
265 | expandRows: Boolean(context.options.expandRows),
|
266 | chunks: [
|
267 | {
|
268 | key: 'axis',
|
269 | content: (arg) => (
|
270 |
|
271 | preact.createElement("div", { className: "fc-timegrid-axis-chunk" },
|
272 | preact.createElement("table", { "aria-hidden": true, style: { height: arg.expandRows ? arg.clientHeight : '' } },
|
273 | arg.tableColGroupNode,
|
274 | preact.createElement("tbody", null,
|
275 | preact.createElement(TimeBodyAxis, { slatMetas: slatMetas }))),
|
276 | preact.createElement("div", { className: "fc-timegrid-now-indicator-container" },
|
277 | preact.createElement(internal$1.NowTimer, { unit: isNowIndicator ? 'minute' : 'day' }, (nowDate) => {
|
278 | let nowIndicatorTop = isNowIndicator &&
|
279 | slatCoords &&
|
280 | slatCoords.safeComputeTop(nowDate);
|
281 | if (typeof nowIndicatorTop === 'number') {
|
282 | return (preact.createElement(internal$1.NowIndicatorContainer, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: nowDate }));
|
283 | }
|
284 | return null;
|
285 | })))),
|
286 | },
|
287 | {
|
288 | key: 'cols',
|
289 | scrollerElRef: this.scrollerElRef,
|
290 | content: timeContent,
|
291 | },
|
292 | ],
|
293 | });
|
294 | if (stickyFooterScrollbar) {
|
295 | sections.push({
|
296 | key: 'footer',
|
297 | type: 'footer',
|
298 | isSticky: true,
|
299 | chunks: [
|
300 | {
|
301 | key: 'axis',
|
302 | content: internal$1.renderScrollShim,
|
303 | },
|
304 | {
|
305 | key: 'cols',
|
306 | content: internal$1.renderScrollShim,
|
307 | },
|
308 | ],
|
309 | });
|
310 | }
|
311 | return (preact.createElement(internal$1.ViewContainer, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },
|
312 | preact.createElement(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: false, colGroups: [
|
313 | { width: 'shrink', cols: [{ width: 'shrink' }] },
|
314 | { cols: [{ span: colCnt, minWidth: dayMinWidth }] },
|
315 | ], sections: sections })));
|
316 | }
|
317 | |
318 |
|
319 | getAllDayMaxEventProps() {
|
320 | let { dayMaxEvents, dayMaxEventRows } = this.context.options;
|
321 | if (dayMaxEvents === true || dayMaxEventRows === true) {
|
322 | dayMaxEvents = undefined;
|
323 | dayMaxEventRows = AUTO_ALL_DAY_MAX_EVENT_ROWS;
|
324 | }
|
325 | return { dayMaxEvents, dayMaxEventRows };
|
326 | }
|
327 | }
|
328 | function renderAllDayInner(renderProps) {
|
329 | return renderProps.text;
|
330 | }
|
331 |
|
332 | class TimeColsSlatsCoords {
|
333 | constructor(positions, dateProfile, slotDuration) {
|
334 | this.positions = positions;
|
335 | this.dateProfile = dateProfile;
|
336 | this.slotDuration = slotDuration;
|
337 | }
|
338 | safeComputeTop(date) {
|
339 | let { dateProfile } = this;
|
340 | if (internal$1.rangeContainsMarker(dateProfile.currentRange, date)) {
|
341 | let startOfDayDate = internal$1.startOfDay(date);
|
342 | let timeMs = date.valueOf() - startOfDayDate.valueOf();
|
343 | if (timeMs >= internal$1.asRoughMs(dateProfile.slotMinTime) &&
|
344 | timeMs < internal$1.asRoughMs(dateProfile.slotMaxTime)) {
|
345 | return this.computeTimeTop(internal$1.createDuration(timeMs));
|
346 | }
|
347 | }
|
348 | return null;
|
349 | }
|
350 |
|
351 |
|
352 | computeDateTop(when, startOfDayDate) {
|
353 | if (!startOfDayDate) {
|
354 | startOfDayDate = internal$1.startOfDay(when);
|
355 | }
|
356 | return this.computeTimeTop(internal$1.createDuration(when.valueOf() - startOfDayDate.valueOf()));
|
357 | }
|
358 |
|
359 |
|
360 |
|
361 | computeTimeTop(duration) {
|
362 | let { positions, dateProfile } = this;
|
363 | let len = positions.els.length;
|
364 |
|
365 | let slatCoverage = (duration.milliseconds - internal$1.asRoughMs(dateProfile.slotMinTime)) / internal$1.asRoughMs(this.slotDuration);
|
366 | let slatIndex;
|
367 | let slatRemainder;
|
368 |
|
369 |
|
370 |
|
371 | slatCoverage = Math.max(0, slatCoverage);
|
372 | slatCoverage = Math.min(len, slatCoverage);
|
373 |
|
374 |
|
375 | slatIndex = Math.floor(slatCoverage);
|
376 | slatIndex = Math.min(slatIndex, len - 1);
|
377 |
|
378 |
|
379 | slatRemainder = slatCoverage - slatIndex;
|
380 | return positions.tops[slatIndex] +
|
381 | positions.getHeight(slatIndex) * slatRemainder;
|
382 | }
|
383 | }
|
384 |
|
385 | class TimeColsSlatsBody extends internal$1.BaseComponent {
|
386 | render() {
|
387 | let { props, context } = this;
|
388 | let { options } = context;
|
389 | let { slatElRefs } = props;
|
390 | return (preact.createElement("tbody", null, props.slatMetas.map((slatMeta, i) => {
|
391 | let renderProps = {
|
392 | time: slatMeta.time,
|
393 | date: context.dateEnv.toDate(slatMeta.date),
|
394 | view: context.viewApi,
|
395 | };
|
396 | return (preact.createElement("tr", { key: slatMeta.key, ref: slatElRefs.createRef(slatMeta.key) },
|
397 | props.axis && (preact.createElement(TimeColsAxisCell, Object.assign({}, slatMeta))),
|
398 | preact.createElement(internal$1.ContentContainer, { elTag: "td", elClasses: [
|
399 | 'fc-timegrid-slot',
|
400 | 'fc-timegrid-slot-lane',
|
401 | !slatMeta.isLabeled && 'fc-timegrid-slot-minor',
|
402 | ], elAttrs: {
|
403 | 'data-time': slatMeta.isoTimeStr,
|
404 | }, renderProps: renderProps, generatorName: "slotLaneContent", customGenerator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount })));
|
405 | })));
|
406 | }
|
407 | }
|
408 |
|
409 | |
410 |
|
411 |
|
412 | class TimeColsSlats extends internal$1.BaseComponent {
|
413 | constructor() {
|
414 | super(...arguments);
|
415 | this.rootElRef = preact.createRef();
|
416 | this.slatElRefs = new internal$1.RefMap();
|
417 | }
|
418 | render() {
|
419 | let { props, context } = this;
|
420 | return (preact.createElement("div", { ref: this.rootElRef, className: "fc-timegrid-slots" },
|
421 | preact.createElement("table", { "aria-hidden": true, className: context.theme.getClass('table'), style: {
|
422 | minWidth: props.tableMinWidth,
|
423 | width: props.clientWidth,
|
424 | height: props.minHeight,
|
425 | } },
|
426 | props.tableColGroupNode ,
|
427 | preact.createElement(TimeColsSlatsBody, { slatElRefs: this.slatElRefs, axis: props.axis, slatMetas: props.slatMetas }))));
|
428 | }
|
429 | componentDidMount() {
|
430 | this.updateSizing();
|
431 | }
|
432 | componentDidUpdate() {
|
433 | this.updateSizing();
|
434 | }
|
435 | componentWillUnmount() {
|
436 | if (this.props.onCoords) {
|
437 | this.props.onCoords(null);
|
438 | }
|
439 | }
|
440 | updateSizing() {
|
441 | let { context, props } = this;
|
442 | if (props.onCoords &&
|
443 | props.clientWidth !== null
|
444 | ) {
|
445 | let rootEl = this.rootElRef.current;
|
446 | if (rootEl.offsetHeight) {
|
447 | props.onCoords(new TimeColsSlatsCoords(new internal$1.PositionCache(this.rootElRef.current, collectSlatEls(this.slatElRefs.currentMap, props.slatMetas), false, true), this.props.dateProfile, context.options.slotDuration));
|
448 | }
|
449 | }
|
450 | }
|
451 | }
|
452 | function collectSlatEls(elMap, slatMetas) {
|
453 | return slatMetas.map((slatMeta) => elMap[slatMeta.key]);
|
454 | }
|
455 |
|
456 | function splitSegsByCol(segs, colCnt) {
|
457 | let segsByCol = [];
|
458 | let i;
|
459 | for (i = 0; i < colCnt; i += 1) {
|
460 | segsByCol.push([]);
|
461 | }
|
462 | if (segs) {
|
463 | for (i = 0; i < segs.length; i += 1) {
|
464 | segsByCol[segs[i].col].push(segs[i]);
|
465 | }
|
466 | }
|
467 | return segsByCol;
|
468 | }
|
469 | function splitInteractionByCol(ui, colCnt) {
|
470 | let byRow = [];
|
471 | if (!ui) {
|
472 | for (let i = 0; i < colCnt; i += 1) {
|
473 | byRow[i] = null;
|
474 | }
|
475 | }
|
476 | else {
|
477 | for (let i = 0; i < colCnt; i += 1) {
|
478 | byRow[i] = {
|
479 | affectedInstances: ui.affectedInstances,
|
480 | isEvent: ui.isEvent,
|
481 | segs: [],
|
482 | };
|
483 | }
|
484 | for (let seg of ui.segs) {
|
485 | byRow[seg.col].segs.push(seg);
|
486 | }
|
487 | }
|
488 | return byRow;
|
489 | }
|
490 |
|
491 | class TimeColMoreLink extends internal$1.BaseComponent {
|
492 | render() {
|
493 | let { props } = this;
|
494 | return (preact.createElement(internal$1.MoreLinkContainer, { elClasses: ['fc-timegrid-more-link'], elStyle: {
|
495 | top: props.top,
|
496 | bottom: props.bottom,
|
497 | }, allDayDate: null, moreCnt: props.hiddenSegs.length, allSegs: props.hiddenSegs, hiddenSegs: props.hiddenSegs, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, todayRange: props.todayRange, popoverContent: () => renderPlainFgSegs(props.hiddenSegs, props), defaultGenerator: renderMoreLinkInner }, (InnerContent) => (preact.createElement(InnerContent, { elTag: "div", elClasses: ['fc-timegrid-more-link-inner', 'fc-sticky'] }))));
|
498 | }
|
499 | }
|
500 | function renderMoreLinkInner(props) {
|
501 | return props.shortText;
|
502 | }
|
503 |
|
504 |
|
505 | function buildPositioning(segInputs, strictOrder, maxStackCnt) {
|
506 | let hierarchy = new internal$1.SegHierarchy();
|
507 | if (strictOrder != null) {
|
508 | hierarchy.strictOrder = strictOrder;
|
509 | }
|
510 | if (maxStackCnt != null) {
|
511 | hierarchy.maxStackCnt = maxStackCnt;
|
512 | }
|
513 | let hiddenEntries = hierarchy.addSegs(segInputs);
|
514 | let hiddenGroups = internal$1.groupIntersectingEntries(hiddenEntries);
|
515 | let web = buildWeb(hierarchy);
|
516 | web = stretchWeb(web, 1);
|
517 | let segRects = webToRects(web);
|
518 | return { segRects, hiddenGroups };
|
519 | }
|
520 | function buildWeb(hierarchy) {
|
521 | const { entriesByLevel } = hierarchy;
|
522 | const buildNode = cacheable((level, lateral) => level + ':' + lateral, (level, lateral) => {
|
523 | let siblingRange = findNextLevelSegs(hierarchy, level, lateral);
|
524 | let nextLevelRes = buildNodes(siblingRange, buildNode);
|
525 | let entry = entriesByLevel[level][lateral];
|
526 | return [
|
527 | Object.assign(Object.assign({}, entry), { nextLevelNodes: nextLevelRes[0] }),
|
528 | entry.thickness + nextLevelRes[1],
|
529 | ];
|
530 | });
|
531 | return buildNodes(entriesByLevel.length
|
532 | ? { level: 0, lateralStart: 0, lateralEnd: entriesByLevel[0].length }
|
533 | : null, buildNode)[0];
|
534 | }
|
535 | function buildNodes(siblingRange, buildNode) {
|
536 | if (!siblingRange) {
|
537 | return [[], 0];
|
538 | }
|
539 | let { level, lateralStart, lateralEnd } = siblingRange;
|
540 | let lateral = lateralStart;
|
541 | let pairs = [];
|
542 | while (lateral < lateralEnd) {
|
543 | pairs.push(buildNode(level, lateral));
|
544 | lateral += 1;
|
545 | }
|
546 | pairs.sort(cmpDescPressures);
|
547 | return [
|
548 | pairs.map(extractNode),
|
549 | pairs[0][1],
|
550 | ];
|
551 | }
|
552 | function cmpDescPressures(a, b) {
|
553 | return b[1] - a[1];
|
554 | }
|
555 | function extractNode(a) {
|
556 | return a[0];
|
557 | }
|
558 | function findNextLevelSegs(hierarchy, subjectLevel, subjectLateral) {
|
559 | let { levelCoords, entriesByLevel } = hierarchy;
|
560 | let subjectEntry = entriesByLevel[subjectLevel][subjectLateral];
|
561 | let afterSubject = levelCoords[subjectLevel] + subjectEntry.thickness;
|
562 | let levelCnt = levelCoords.length;
|
563 | let level = subjectLevel;
|
564 |
|
565 | for (; level < levelCnt && levelCoords[level] < afterSubject; level += 1)
|
566 | ;
|
567 | for (; level < levelCnt; level += 1) {
|
568 | let entries = entriesByLevel[level];
|
569 | let entry;
|
570 | let searchIndex = internal$1.binarySearch(entries, subjectEntry.span.start, internal$1.getEntrySpanEnd);
|
571 | let lateralStart = searchIndex[0] + searchIndex[1];
|
572 | let lateralEnd = lateralStart;
|
573 | while (
|
574 | (entry = entries[lateralEnd]) &&
|
575 | entry.span.start < subjectEntry.span.end) {
|
576 | lateralEnd += 1;
|
577 | }
|
578 | if (lateralStart < lateralEnd) {
|
579 | return { level, lateralStart, lateralEnd };
|
580 | }
|
581 | }
|
582 | return null;
|
583 | }
|
584 | function stretchWeb(topLevelNodes, totalThickness) {
|
585 | const stretchNode = cacheable((node, startCoord, prevThickness) => internal$1.buildEntryKey(node), (node, startCoord, prevThickness) => {
|
586 | let { nextLevelNodes, thickness } = node;
|
587 | let allThickness = thickness + prevThickness;
|
588 | let thicknessFraction = thickness / allThickness;
|
589 | let endCoord;
|
590 | let newChildren = [];
|
591 | if (!nextLevelNodes.length) {
|
592 | endCoord = totalThickness;
|
593 | }
|
594 | else {
|
595 | for (let childNode of nextLevelNodes) {
|
596 | if (endCoord === undefined) {
|
597 | let res = stretchNode(childNode, startCoord, allThickness);
|
598 | endCoord = res[0];
|
599 | newChildren.push(res[1]);
|
600 | }
|
601 | else {
|
602 | let res = stretchNode(childNode, endCoord, 0);
|
603 | newChildren.push(res[1]);
|
604 | }
|
605 | }
|
606 | }
|
607 | let newThickness = (endCoord - startCoord) * thicknessFraction;
|
608 | return [endCoord - newThickness, Object.assign(Object.assign({}, node), { thickness: newThickness, nextLevelNodes: newChildren })];
|
609 | });
|
610 | return topLevelNodes.map((node) => stretchNode(node, 0, 0)[1]);
|
611 | }
|
612 |
|
613 | function webToRects(topLevelNodes) {
|
614 | let rects = [];
|
615 | const processNode = cacheable((node, levelCoord, stackDepth) => internal$1.buildEntryKey(node), (node, levelCoord, stackDepth) => {
|
616 | let rect = Object.assign(Object.assign({}, node), { levelCoord,
|
617 | stackDepth, stackForward: 0 });
|
618 | rects.push(rect);
|
619 | return (rect.stackForward = processNodes(node.nextLevelNodes, levelCoord + node.thickness, stackDepth + 1) + 1);
|
620 | });
|
621 | function processNodes(nodes, levelCoord, stackDepth) {
|
622 | let stackForward = 0;
|
623 | for (let node of nodes) {
|
624 | stackForward = Math.max(processNode(node, levelCoord, stackDepth), stackForward);
|
625 | }
|
626 | return stackForward;
|
627 | }
|
628 | processNodes(topLevelNodes, 0, 0);
|
629 | return rects;
|
630 | }
|
631 |
|
632 | function cacheable(keyFunc, workFunc) {
|
633 | const cache = {};
|
634 | return (...args) => {
|
635 | let key = keyFunc(...args);
|
636 | return (key in cache)
|
637 | ? cache[key]
|
638 | : (cache[key] = workFunc(...args));
|
639 | };
|
640 | }
|
641 |
|
642 | function computeSegVCoords(segs, colDate, slatCoords = null, eventMinHeight = 0) {
|
643 | let vcoords = [];
|
644 | if (slatCoords) {
|
645 | for (let i = 0; i < segs.length; i += 1) {
|
646 | let seg = segs[i];
|
647 | let spanStart = slatCoords.computeDateTop(seg.start, colDate);
|
648 | let spanEnd = Math.max(spanStart + (eventMinHeight || 0),
|
649 | slatCoords.computeDateTop(seg.end, colDate));
|
650 | vcoords.push({
|
651 | start: Math.round(spanStart),
|
652 | end: Math.round(spanEnd),
|
653 | });
|
654 | }
|
655 | }
|
656 | return vcoords;
|
657 | }
|
658 | function computeFgSegPlacements(segs, segVCoords, // might not have for every seg
|
659 | eventOrderStrict, eventMaxStack) {
|
660 | let segInputs = [];
|
661 | let dumbSegs = [];
|
662 | for (let i = 0; i < segs.length; i += 1) {
|
663 | let vcoords = segVCoords[i];
|
664 | if (vcoords) {
|
665 | segInputs.push({
|
666 | index: i,
|
667 | thickness: 1,
|
668 | span: vcoords,
|
669 | });
|
670 | }
|
671 | else {
|
672 | dumbSegs.push(segs[i]);
|
673 | }
|
674 | }
|
675 | let { segRects, hiddenGroups } = buildPositioning(segInputs, eventOrderStrict, eventMaxStack);
|
676 | let segPlacements = [];
|
677 | for (let segRect of segRects) {
|
678 | segPlacements.push({
|
679 | seg: segs[segRect.index],
|
680 | rect: segRect,
|
681 | });
|
682 | }
|
683 | for (let dumbSeg of dumbSegs) {
|
684 | segPlacements.push({ seg: dumbSeg, rect: null });
|
685 | }
|
686 | return { segPlacements, hiddenGroups };
|
687 | }
|
688 |
|
689 | const DEFAULT_TIME_FORMAT = internal$1.createFormatter({
|
690 | hour: 'numeric',
|
691 | minute: '2-digit',
|
692 | meridiem: false,
|
693 | });
|
694 | class TimeColEvent extends internal$1.BaseComponent {
|
695 | render() {
|
696 | return (preact.createElement(internal$1.StandardEvent, Object.assign({}, this.props, { elClasses: [
|
697 | 'fc-timegrid-event',
|
698 | 'fc-v-event',
|
699 | this.props.isShort && 'fc-timegrid-event-short',
|
700 | ], defaultTimeFormat: DEFAULT_TIME_FORMAT })));
|
701 | }
|
702 | }
|
703 |
|
704 | class TimeCol extends internal$1.BaseComponent {
|
705 | constructor() {
|
706 | super(...arguments);
|
707 | this.sortEventSegs = internal$1.memoize(internal$1.sortEventSegs);
|
708 | }
|
709 |
|
710 | render() {
|
711 | let { props, context } = this;
|
712 | let { options } = context;
|
713 | let isSelectMirror = options.selectMirror;
|
714 | let mirrorSegs =
|
715 | (props.eventDrag && props.eventDrag.segs) ||
|
716 | (props.eventResize && props.eventResize.segs) ||
|
717 | (isSelectMirror && props.dateSelectionSegs) ||
|
718 | [];
|
719 | let interactionAffectedInstances =
|
720 | (props.eventDrag && props.eventDrag.affectedInstances) ||
|
721 | (props.eventResize && props.eventResize.affectedInstances) ||
|
722 | {};
|
723 | let sortedFgSegs = this.sortEventSegs(props.fgEventSegs, options.eventOrder);
|
724 | return (preact.createElement(internal$1.DayCellContainer, { elTag: "td", elRef: props.elRef, elClasses: [
|
725 | 'fc-timegrid-col',
|
726 | ...(props.extraClassNames || []),
|
727 | ], elAttrs: Object.assign({ role: 'gridcell' }, props.extraDataAttrs), date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, extraRenderProps: props.extraRenderProps }, (InnerContent) => (preact.createElement("div", { className: "fc-timegrid-col-frame" },
|
728 | preact.createElement("div", { className: "fc-timegrid-col-bg" },
|
729 | this.renderFillSegs(props.businessHourSegs, 'non-business'),
|
730 | this.renderFillSegs(props.bgEventSegs, 'bg-event'),
|
731 | this.renderFillSegs(props.dateSelectionSegs, 'highlight')),
|
732 | preact.createElement("div", { className: "fc-timegrid-col-events" }, this.renderFgSegs(sortedFgSegs, interactionAffectedInstances, false, false, false)),
|
733 | preact.createElement("div", { className: "fc-timegrid-col-events" }, this.renderFgSegs(mirrorSegs, {}, Boolean(props.eventDrag), Boolean(props.eventResize), Boolean(isSelectMirror))),
|
734 | preact.createElement("div", { className: "fc-timegrid-now-indicator-container" }, this.renderNowIndicator(props.nowIndicatorSegs)),
|
735 | internal$1.hasCustomDayCellContent(options) && (preact.createElement(InnerContent, { elTag: "div", elClasses: ['fc-timegrid-col-misc'] }))))));
|
736 | }
|
737 | renderFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting) {
|
738 | let { props } = this;
|
739 | if (props.forPrint) {
|
740 | return renderPlainFgSegs(sortedFgSegs, props);
|
741 | }
|
742 | return this.renderPositionedFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting);
|
743 | }
|
744 | renderPositionedFgSegs(segs,
|
745 | segIsInvisible, isDragging, isResizing, isDateSelecting) {
|
746 | let { eventMaxStack, eventShortHeight, eventOrderStrict, eventMinHeight } = this.context.options;
|
747 | let { date, slatCoords, eventSelection, todayRange, nowDate } = this.props;
|
748 | let isMirror = isDragging || isResizing || isDateSelecting;
|
749 | let segVCoords = computeSegVCoords(segs, date, slatCoords, eventMinHeight);
|
750 | let { segPlacements, hiddenGroups } = computeFgSegPlacements(segs, segVCoords, eventOrderStrict, eventMaxStack);
|
751 | return (preact.createElement(preact.Fragment, null,
|
752 | this.renderHiddenGroups(hiddenGroups, segs),
|
753 | segPlacements.map((segPlacement) => {
|
754 | let { seg, rect } = segPlacement;
|
755 | let instanceId = seg.eventRange.instance.instanceId;
|
756 | let isVisible = isMirror || Boolean(!segIsInvisible[instanceId] && rect);
|
757 | let vStyle = computeSegVStyle(rect && rect.span);
|
758 | let hStyle = (!isMirror && rect) ? this.computeSegHStyle(rect) : { left: 0, right: 0 };
|
759 | let isInset = Boolean(rect) && rect.stackForward > 0;
|
760 | let isShort = Boolean(rect) && (rect.span.end - rect.span.start) < eventShortHeight;
|
761 | return (preact.createElement("div", { className: 'fc-timegrid-event-harness' +
|
762 | (isInset ? ' fc-timegrid-event-harness-inset' : ''), key: instanceId, style: Object.assign(Object.assign({ visibility: isVisible ? '' : 'hidden' }, vStyle), hStyle) },
|
763 | preact.createElement(TimeColEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, isShort: isShort }, internal$1.getSegMeta(seg, todayRange, nowDate)))));
|
764 | })));
|
765 | }
|
766 |
|
767 | renderHiddenGroups(hiddenGroups, segs) {
|
768 | let { extraDateSpan, dateProfile, todayRange, nowDate, eventSelection, eventDrag, eventResize } = this.props;
|
769 | return (preact.createElement(preact.Fragment, null, hiddenGroups.map((hiddenGroup) => {
|
770 | let positionCss = computeSegVStyle(hiddenGroup.span);
|
771 | let hiddenSegs = compileSegsFromEntries(hiddenGroup.entries, segs);
|
772 | return (preact.createElement(TimeColMoreLink, { key: internal$1.buildIsoString(internal$1.computeEarliestSegStart(hiddenSegs)), hiddenSegs: hiddenSegs, top: positionCss.top, bottom: positionCss.bottom, extraDateSpan: extraDateSpan, dateProfile: dateProfile, todayRange: todayRange, nowDate: nowDate, eventSelection: eventSelection, eventDrag: eventDrag, eventResize: eventResize }));
|
773 | })));
|
774 | }
|
775 | renderFillSegs(segs, fillType) {
|
776 | let { props, context } = this;
|
777 | let segVCoords = computeSegVCoords(segs, props.date, props.slatCoords, context.options.eventMinHeight);
|
778 | let children = segVCoords.map((vcoords, i) => {
|
779 | let seg = segs[i];
|
780 | return (preact.createElement("div", { key: internal$1.buildEventRangeKey(seg.eventRange), className: "fc-timegrid-bg-harness", style: computeSegVStyle(vcoords) }, fillType === 'bg-event' ?
|
781 | preact.createElement(internal$1.BgEvent, Object.assign({ seg: seg }, internal$1.getSegMeta(seg, props.todayRange, props.nowDate))) :
|
782 | internal$1.renderFill(fillType)));
|
783 | });
|
784 | return preact.createElement(preact.Fragment, null, children);
|
785 | }
|
786 | renderNowIndicator(segs) {
|
787 | let { slatCoords, date } = this.props;
|
788 | if (!slatCoords) {
|
789 | return null;
|
790 | }
|
791 | return segs.map((seg, i) => (preact.createElement(internal$1.NowIndicatorContainer
|
792 |
|
793 | , {
|
794 |
|
795 | key: i, elClasses: ['fc-timegrid-now-indicator-line'], elStyle: {
|
796 | top: slatCoords.computeDateTop(seg.start, date),
|
797 | }, isAxis: false, date: date })));
|
798 | }
|
799 | computeSegHStyle(segHCoords) {
|
800 | let { isRtl, options } = this.context;
|
801 | let shouldOverlap = options.slotEventOverlap;
|
802 | let nearCoord = segHCoords.levelCoord;
|
803 | let farCoord = segHCoords.levelCoord + segHCoords.thickness;
|
804 | let left;
|
805 | let right;
|
806 | if (shouldOverlap) {
|
807 |
|
808 | farCoord = Math.min(1, nearCoord + (farCoord - nearCoord) * 2);
|
809 | }
|
810 | if (isRtl) {
|
811 | left = 1 - farCoord;
|
812 | right = nearCoord;
|
813 | }
|
814 | else {
|
815 | left = nearCoord;
|
816 | right = 1 - farCoord;
|
817 | }
|
818 | let props = {
|
819 | zIndex: segHCoords.stackDepth + 1,
|
820 | left: left * 100 + '%',
|
821 | right: right * 100 + '%',
|
822 | };
|
823 | if (shouldOverlap && !segHCoords.stackForward) {
|
824 |
|
825 | props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2;
|
826 | }
|
827 | return props;
|
828 | }
|
829 | }
|
830 | function renderPlainFgSegs(sortedFgSegs, { todayRange, nowDate, eventSelection, eventDrag, eventResize }) {
|
831 | let hiddenInstances = (eventDrag ? eventDrag.affectedInstances : null) ||
|
832 | (eventResize ? eventResize.affectedInstances : null) ||
|
833 | {};
|
834 | return (preact.createElement(preact.Fragment, null, sortedFgSegs.map((seg) => {
|
835 | let instanceId = seg.eventRange.instance.instanceId;
|
836 | return (preact.createElement("div", { key: instanceId, style: { visibility: hiddenInstances[instanceId] ? 'hidden' : '' } },
|
837 | preact.createElement(TimeColEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === eventSelection, isShort: false }, internal$1.getSegMeta(seg, todayRange, nowDate)))));
|
838 | })));
|
839 | }
|
840 | function computeSegVStyle(segVCoords) {
|
841 | if (!segVCoords) {
|
842 | return { top: '', bottom: '' };
|
843 | }
|
844 | return {
|
845 | top: segVCoords.start,
|
846 | bottom: -segVCoords.end,
|
847 | };
|
848 | }
|
849 | function compileSegsFromEntries(segEntries, allSegs) {
|
850 | return segEntries.map((segEntry) => allSegs[segEntry.index]);
|
851 | }
|
852 |
|
853 | class TimeColsContent extends internal$1.BaseComponent {
|
854 | constructor() {
|
855 | super(...arguments);
|
856 | this.splitFgEventSegs = internal$1.memoize(splitSegsByCol);
|
857 | this.splitBgEventSegs = internal$1.memoize(splitSegsByCol);
|
858 | this.splitBusinessHourSegs = internal$1.memoize(splitSegsByCol);
|
859 | this.splitNowIndicatorSegs = internal$1.memoize(splitSegsByCol);
|
860 | this.splitDateSelectionSegs = internal$1.memoize(splitSegsByCol);
|
861 | this.splitEventDrag = internal$1.memoize(splitInteractionByCol);
|
862 | this.splitEventResize = internal$1.memoize(splitInteractionByCol);
|
863 | this.rootElRef = preact.createRef();
|
864 | this.cellElRefs = new internal$1.RefMap();
|
865 | }
|
866 | render() {
|
867 | let { props, context } = this;
|
868 | let nowIndicatorTop = context.options.nowIndicator &&
|
869 | props.slatCoords &&
|
870 | props.slatCoords.safeComputeTop(props.nowDate);
|
871 | let colCnt = props.cells.length;
|
872 | let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, colCnt);
|
873 | let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, colCnt);
|
874 | let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, colCnt);
|
875 | let nowIndicatorSegsByRow = this.splitNowIndicatorSegs(props.nowIndicatorSegs, colCnt);
|
876 | let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, colCnt);
|
877 | let eventDragByRow = this.splitEventDrag(props.eventDrag, colCnt);
|
878 | let eventResizeByRow = this.splitEventResize(props.eventResize, colCnt);
|
879 | return (preact.createElement("div", { className: "fc-timegrid-cols", ref: this.rootElRef },
|
880 | preact.createElement("table", { role: "presentation", style: {
|
881 | minWidth: props.tableMinWidth,
|
882 | width: props.clientWidth,
|
883 | } },
|
884 | props.tableColGroupNode,
|
885 | preact.createElement("tbody", { role: "presentation" },
|
886 | preact.createElement("tr", { role: "row" },
|
887 | props.axis && (preact.createElement("td", { "aria-hidden": true, className: "fc-timegrid-col fc-timegrid-axis" },
|
888 | preact.createElement("div", { className: "fc-timegrid-col-frame" },
|
889 | preact.createElement("div", { className: "fc-timegrid-now-indicator-container" }, typeof nowIndicatorTop === 'number' && (preact.createElement(internal$1.NowIndicatorContainer, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: props.nowDate })))))),
|
890 | props.cells.map((cell, i) => (preact.createElement(TimeCol, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), dateProfile: props.dateProfile, date: cell.date, nowDate: props.nowDate, todayRange: props.todayRange, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, fgEventSegs: fgEventSegsByRow[i], bgEventSegs: bgEventSegsByRow[i], businessHourSegs: businessHourSegsByRow[i], nowIndicatorSegs: nowIndicatorSegsByRow[i], dateSelectionSegs: dateSelectionSegsByRow[i], eventDrag: eventDragByRow[i], eventResize: eventResizeByRow[i], slatCoords: props.slatCoords, eventSelection: props.eventSelection, forPrint: props.forPrint }))))))));
|
891 | }
|
892 | componentDidMount() {
|
893 | this.updateCoords();
|
894 | }
|
895 | componentDidUpdate() {
|
896 | this.updateCoords();
|
897 | }
|
898 | updateCoords() {
|
899 | let { props } = this;
|
900 | if (props.onColCoords &&
|
901 | props.clientWidth !== null
|
902 | ) {
|
903 | props.onColCoords(new internal$1.PositionCache(this.rootElRef.current, collectCellEls(this.cellElRefs.currentMap, props.cells), true,
|
904 | false));
|
905 | }
|
906 | }
|
907 | }
|
908 | function collectCellEls(elMap, cells) {
|
909 | return cells.map((cell) => elMap[cell.key]);
|
910 | }
|
911 |
|
912 | |
913 |
|
914 | class TimeCols extends internal$1.DateComponent {
|
915 | constructor() {
|
916 | super(...arguments);
|
917 | this.processSlotOptions = internal$1.memoize(processSlotOptions);
|
918 | this.state = {
|
919 | slatCoords: null,
|
920 | };
|
921 | this.handleRootEl = (el) => {
|
922 | if (el) {
|
923 | this.context.registerInteractiveComponent(this, {
|
924 | el,
|
925 | isHitComboAllowed: this.props.isHitComboAllowed,
|
926 | });
|
927 | }
|
928 | else {
|
929 | this.context.unregisterInteractiveComponent(this);
|
930 | }
|
931 | };
|
932 | this.handleScrollRequest = (request) => {
|
933 | let { onScrollTopRequest } = this.props;
|
934 | let { slatCoords } = this.state;
|
935 | if (onScrollTopRequest && slatCoords) {
|
936 | if (request.time) {
|
937 | let top = slatCoords.computeTimeTop(request.time);
|
938 | top = Math.ceil(top);
|
939 | if (top) {
|
940 | top += 1;
|
941 | }
|
942 | onScrollTopRequest(top);
|
943 | }
|
944 | return true;
|
945 | }
|
946 | return false;
|
947 | };
|
948 | this.handleColCoords = (colCoords) => {
|
949 | this.colCoords = colCoords;
|
950 | };
|
951 | this.handleSlatCoords = (slatCoords) => {
|
952 | this.setState({ slatCoords });
|
953 | if (this.props.onSlatCoords) {
|
954 | this.props.onSlatCoords(slatCoords);
|
955 | }
|
956 | };
|
957 | }
|
958 | render() {
|
959 | let { props, state } = this;
|
960 | return (preact.createElement("div", { className: "fc-timegrid-body", ref: this.handleRootEl, style: {
|
961 |
|
962 |
|
963 | width: props.clientWidth,
|
964 | minWidth: props.tableMinWidth,
|
965 | } },
|
966 | preact.createElement(TimeColsSlats, { axis: props.axis, dateProfile: props.dateProfile, slatMetas: props.slatMetas, clientWidth: props.clientWidth, minHeight: props.expandRows ? props.clientHeight : '', tableMinWidth: props.tableMinWidth, tableColGroupNode: props.axis ? props.tableColGroupNode : null , onCoords: this.handleSlatCoords }),
|
967 | preact.createElement(TimeColsContent, { cells: props.cells, axis: props.axis, dateProfile: props.dateProfile, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange, nowDate: props.nowDate, nowIndicatorSegs: props.nowIndicatorSegs, clientWidth: props.clientWidth, tableMinWidth: props.tableMinWidth, tableColGroupNode: props.tableColGroupNode, slatCoords: state.slatCoords, onColCoords: this.handleColCoords, forPrint: props.forPrint })));
|
968 | }
|
969 | componentDidMount() {
|
970 | this.scrollResponder = this.context.createScrollResponder(this.handleScrollRequest);
|
971 | }
|
972 | componentDidUpdate(prevProps) {
|
973 | this.scrollResponder.update(prevProps.dateProfile !== this.props.dateProfile);
|
974 | }
|
975 | componentWillUnmount() {
|
976 | this.scrollResponder.detach();
|
977 | }
|
978 | queryHit(positionLeft, positionTop) {
|
979 | let { dateEnv, options } = this.context;
|
980 | let { colCoords } = this;
|
981 | let { dateProfile } = this.props;
|
982 | let { slatCoords } = this.state;
|
983 | let { snapDuration, snapsPerSlot } = this.processSlotOptions(this.props.slotDuration, options.snapDuration);
|
984 | let colIndex = colCoords.leftToIndex(positionLeft);
|
985 | let slatIndex = slatCoords.positions.topToIndex(positionTop);
|
986 | if (colIndex != null && slatIndex != null) {
|
987 | let cell = this.props.cells[colIndex];
|
988 | let slatTop = slatCoords.positions.tops[slatIndex];
|
989 | let slatHeight = slatCoords.positions.getHeight(slatIndex);
|
990 | let partial = (positionTop - slatTop) / slatHeight;
|
991 | let localSnapIndex = Math.floor(partial * snapsPerSlot);
|
992 | let snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
|
993 | let dayDate = this.props.cells[colIndex].date;
|
994 | let time = internal$1.addDurations(dateProfile.slotMinTime, internal$1.multiplyDuration(snapDuration, snapIndex));
|
995 | let start = dateEnv.add(dayDate, time);
|
996 | let end = dateEnv.add(start, snapDuration);
|
997 | return {
|
998 | dateProfile,
|
999 | dateSpan: Object.assign({ range: { start, end }, allDay: false }, cell.extraDateSpan),
|
1000 | dayEl: colCoords.els[colIndex],
|
1001 | rect: {
|
1002 | left: colCoords.lefts[colIndex],
|
1003 | right: colCoords.rights[colIndex],
|
1004 | top: slatTop,
|
1005 | bottom: slatTop + slatHeight,
|
1006 | },
|
1007 | layer: 0,
|
1008 | };
|
1009 | }
|
1010 | return null;
|
1011 | }
|
1012 | }
|
1013 | function processSlotOptions(slotDuration, snapDurationOverride) {
|
1014 | let snapDuration = snapDurationOverride || slotDuration;
|
1015 | let snapsPerSlot = internal$1.wholeDivideDurations(slotDuration, snapDuration);
|
1016 | if (snapsPerSlot === null) {
|
1017 | snapDuration = slotDuration;
|
1018 | snapsPerSlot = 1;
|
1019 |
|
1020 | }
|
1021 | return { snapDuration, snapsPerSlot };
|
1022 | }
|
1023 |
|
1024 | class DayTimeColsSlicer extends internal$1.Slicer {
|
1025 | sliceRange(range, dayRanges) {
|
1026 | let segs = [];
|
1027 | for (let col = 0; col < dayRanges.length; col += 1) {
|
1028 | let segRange = internal$1.intersectRanges(range, dayRanges[col]);
|
1029 | if (segRange) {
|
1030 | segs.push({
|
1031 | start: segRange.start,
|
1032 | end: segRange.end,
|
1033 | isStart: segRange.start.valueOf() === range.start.valueOf(),
|
1034 | isEnd: segRange.end.valueOf() === range.end.valueOf(),
|
1035 | col,
|
1036 | });
|
1037 | }
|
1038 | }
|
1039 | return segs;
|
1040 | }
|
1041 | }
|
1042 |
|
1043 | class DayTimeCols extends internal$1.DateComponent {
|
1044 | constructor() {
|
1045 | super(...arguments);
|
1046 | this.buildDayRanges = internal$1.memoize(buildDayRanges);
|
1047 | this.slicer = new DayTimeColsSlicer();
|
1048 | this.timeColsRef = preact.createRef();
|
1049 | }
|
1050 | render() {
|
1051 | let { props, context } = this;
|
1052 | let { dateProfile, dayTableModel } = props;
|
1053 | let { nowIndicator, nextDayThreshold } = context.options;
|
1054 | let dayRanges = this.buildDayRanges(dayTableModel, dateProfile, context.dateEnv);
|
1055 |
|
1056 |
|
1057 | return (preact.createElement(internal$1.NowTimer, { unit: nowIndicator ? 'minute' : 'day' }, (nowDate, todayRange) => (preact.createElement(TimeCols, Object.assign({ ref: this.timeColsRef }, this.slicer.sliceProps(props, dateProfile, null, context, dayRanges), { forPrint: props.forPrint, axis: props.axis, dateProfile: dateProfile, slatMetas: props.slatMetas, slotDuration: props.slotDuration, cells: dayTableModel.cells[0], tableColGroupNode: props.tableColGroupNode, tableMinWidth: props.tableMinWidth, clientWidth: props.clientWidth, clientHeight: props.clientHeight, expandRows: props.expandRows, nowDate: nowDate, nowIndicatorSegs: nowIndicator && this.slicer.sliceNowDate(nowDate, dateProfile, nextDayThreshold, context, dayRanges), todayRange: todayRange, onScrollTopRequest: props.onScrollTopRequest, onSlatCoords: props.onSlatCoords })))));
|
1058 | }
|
1059 | }
|
1060 | function buildDayRanges(dayTableModel, dateProfile, dateEnv) {
|
1061 | let ranges = [];
|
1062 | for (let date of dayTableModel.headerDates) {
|
1063 | ranges.push({
|
1064 | start: dateEnv.add(date, dateProfile.slotMinTime),
|
1065 | end: dateEnv.add(date, dateProfile.slotMaxTime),
|
1066 | });
|
1067 | }
|
1068 | return ranges;
|
1069 | }
|
1070 |
|
1071 |
|
1072 |
|
1073 | const STOCK_SUB_DURATIONS = [
|
1074 | { hours: 1 },
|
1075 | { minutes: 30 },
|
1076 | { minutes: 15 },
|
1077 | { seconds: 30 },
|
1078 | { seconds: 15 },
|
1079 | ];
|
1080 | function buildSlatMetas(slotMinTime, slotMaxTime, explicitLabelInterval, slotDuration, dateEnv) {
|
1081 | let dayStart = new Date(0);
|
1082 | let slatTime = slotMinTime;
|
1083 | let slatIterator = internal$1.createDuration(0);
|
1084 | let labelInterval = explicitLabelInterval || computeLabelInterval(slotDuration);
|
1085 | let metas = [];
|
1086 | while (internal$1.asRoughMs(slatTime) < internal$1.asRoughMs(slotMaxTime)) {
|
1087 | let date = dateEnv.add(dayStart, slatTime);
|
1088 | let isLabeled = internal$1.wholeDivideDurations(slatIterator, labelInterval) !== null;
|
1089 | metas.push({
|
1090 | date,
|
1091 | time: slatTime,
|
1092 | key: date.toISOString(),
|
1093 | isoTimeStr: internal$1.formatIsoTimeString(date),
|
1094 | isLabeled,
|
1095 | });
|
1096 | slatTime = internal$1.addDurations(slatTime, slotDuration);
|
1097 | slatIterator = internal$1.addDurations(slatIterator, slotDuration);
|
1098 | }
|
1099 | return metas;
|
1100 | }
|
1101 |
|
1102 | function computeLabelInterval(slotDuration) {
|
1103 | let i;
|
1104 | let labelInterval;
|
1105 | let slotsPerLabel;
|
1106 |
|
1107 | for (i = STOCK_SUB_DURATIONS.length - 1; i >= 0; i -= 1) {
|
1108 | labelInterval = internal$1.createDuration(STOCK_SUB_DURATIONS[i]);
|
1109 | slotsPerLabel = internal$1.wholeDivideDurations(labelInterval, slotDuration);
|
1110 | if (slotsPerLabel !== null && slotsPerLabel > 1) {
|
1111 | return labelInterval;
|
1112 | }
|
1113 | }
|
1114 | return slotDuration;
|
1115 | }
|
1116 |
|
1117 | class DayTimeColsView extends TimeColsView {
|
1118 | constructor() {
|
1119 | super(...arguments);
|
1120 | this.buildTimeColsModel = internal$1.memoize(buildTimeColsModel);
|
1121 | this.buildSlatMetas = internal$1.memoize(buildSlatMetas);
|
1122 | }
|
1123 | render() {
|
1124 | let { options, dateEnv, dateProfileGenerator } = this.context;
|
1125 | let { props } = this;
|
1126 | let { dateProfile } = props;
|
1127 | let dayTableModel = this.buildTimeColsModel(dateProfile, dateProfileGenerator);
|
1128 | let splitProps = this.allDaySplitter.splitProps(props);
|
1129 | let slatMetas = this.buildSlatMetas(dateProfile.slotMinTime, dateProfile.slotMaxTime, options.slotLabelInterval, options.slotDuration, dateEnv);
|
1130 | let { dayMinWidth } = options;
|
1131 | let hasAttachedAxis = !dayMinWidth;
|
1132 | let hasDetachedAxis = dayMinWidth;
|
1133 | let headerContent = options.dayHeaders && (preact.createElement(internal$1.DayHeader, { dates: dayTableModel.headerDates, dateProfile: dateProfile, datesRepDistinctDays: true, renderIntro: hasAttachedAxis ? this.renderHeadAxis : null }));
|
1134 | let allDayContent = (options.allDaySlot !== false) && ((contentArg) => (preact.createElement(internal$2.DayTable, Object.assign({}, splitProps.allDay, { dateProfile: dateProfile, dayTableModel: dayTableModel, nextDayThreshold: options.nextDayThreshold, tableMinWidth: contentArg.tableMinWidth, colGroupNode: contentArg.tableColGroupNode, renderRowIntro: hasAttachedAxis ? this.renderTableRowAxis : null, showWeekNumbers: false, expandRows: false, headerAlignElRef: this.headerElRef, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, forPrint: props.forPrint }, this.getAllDayMaxEventProps()))));
|
1135 | let timeGridContent = (contentArg) => (preact.createElement(DayTimeCols, Object.assign({}, splitProps.timed, { dayTableModel: dayTableModel, dateProfile: dateProfile, axis: hasAttachedAxis, slotDuration: options.slotDuration, slatMetas: slatMetas, forPrint: props.forPrint, tableColGroupNode: contentArg.tableColGroupNode, tableMinWidth: contentArg.tableMinWidth, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, onSlatCoords: this.handleSlatCoords, expandRows: contentArg.expandRows, onScrollTopRequest: this.handleScrollTopRequest })));
|
1136 | return hasDetachedAxis
|
1137 | ? this.renderHScrollLayout(headerContent, allDayContent, timeGridContent, dayTableModel.colCnt, dayMinWidth, slatMetas, this.state.slatCoords)
|
1138 | : this.renderSimpleLayout(headerContent, allDayContent, timeGridContent);
|
1139 | }
|
1140 | }
|
1141 | function buildTimeColsModel(dateProfile, dateProfileGenerator) {
|
1142 | let daySeries = new internal$1.DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
|
1143 | return new internal$1.DayTableModel(daySeries, false);
|
1144 | }
|
1145 |
|
1146 | const OPTION_REFINERS = {
|
1147 | allDaySlot: Boolean,
|
1148 | };
|
1149 |
|
1150 | var css_248z = ".fc-v-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-v-event .fc-event-main{color:var(--fc-event-text-color);height:100%}.fc-v-event .fc-event-main-frame{display:flex;flex-direction:column;height:100%}.fc-v-event .fc-event-time{flex-grow:0;flex-shrink:0;max-height:100%;overflow:hidden}.fc-v-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-height:0}.fc-v-event .fc-event-title{bottom:0;max-height:100%;overflow:hidden;top:0}.fc-v-event:not(.fc-event-start){border-top-left-radius:0;border-top-right-radius:0;border-top-width:0}.fc-v-event:not(.fc-event-end){border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-width:0}.fc-v-event.fc-event-selected:before{left:-10px;right:-10px}.fc-v-event .fc-event-resizer-start{cursor:n-resize}.fc-v-event .fc-event-resizer-end{cursor:s-resize}.fc-v-event:not(.fc-event-selected) .fc-event-resizer{height:var(--fc-event-resizer-thickness);left:0;right:0}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-start{top:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer{left:50%;margin-left:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-start{top:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc .fc-timegrid .fc-daygrid-body{z-index:2}.fc .fc-timegrid-divider{padding:0 0 2px}.fc .fc-timegrid-body{min-height:100%;position:relative;z-index:1}.fc .fc-timegrid-axis-chunk{position:relative}.fc .fc-timegrid-axis-chunk>table,.fc .fc-timegrid-slots{position:relative;z-index:1}.fc .fc-timegrid-slot{border-bottom:0;height:1.5em}.fc .fc-timegrid-slot:empty:before{content:\"\\00a0\"}.fc .fc-timegrid-slot-minor{border-top-style:dotted}.fc .fc-timegrid-slot-label-cushion{display:inline-block;white-space:nowrap}.fc .fc-timegrid-slot-label{vertical-align:middle}.fc .fc-timegrid-axis-cushion,.fc .fc-timegrid-slot-label-cushion{padding:0 4px}.fc .fc-timegrid-axis-frame-liquid{height:100%}.fc .fc-timegrid-axis-frame{align-items:center;display:flex;justify-content:flex-end;overflow:hidden}.fc .fc-timegrid-axis-cushion{flex-shrink:0;max-width:60px}.fc-direction-ltr .fc-timegrid-slot-label-frame{text-align:right}.fc-direction-rtl .fc-timegrid-slot-label-frame{text-align:left}.fc-liquid-hack .fc-timegrid-axis-frame-liquid{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-timegrid-col-frame{min-height:100%;position:relative}.fc-media-screen.fc-liquid-hack .fc-timegrid-col-frame{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols{bottom:0;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols>table{height:100%}.fc-media-screen .fc-timegrid-col-bg,.fc-media-screen .fc-timegrid-col-events,.fc-media-screen .fc-timegrid-now-indicator-container{left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col-bg{z-index:2}.fc .fc-timegrid-col-bg .fc-non-business{z-index:1}.fc .fc-timegrid-col-bg .fc-bg-event{z-index:2}.fc .fc-timegrid-col-bg .fc-highlight{z-index:3}.fc .fc-timegrid-bg-harness{left:0;position:absolute;right:0}.fc .fc-timegrid-col-events{z-index:3}.fc .fc-timegrid-now-indicator-container{bottom:0;overflow:hidden}.fc-direction-ltr .fc-timegrid-col-events{margin:0 2.5% 0 2px}.fc-direction-rtl .fc-timegrid-col-events{margin:0 2px 0 2.5%}.fc-timegrid-event-harness{position:absolute}.fc-timegrid-event-harness>.fc-timegrid-event{bottom:0;left:0;position:absolute;right:0;top:0}.fc-timegrid-event-harness-inset .fc-timegrid-event,.fc-timegrid-event.fc-event-mirror,.fc-timegrid-more-link{box-shadow:0 0 0 1px var(--fc-page-bg-color)}.fc-timegrid-event,.fc-timegrid-more-link{border-radius:3px;font-size:var(--fc-small-font-size)}.fc-timegrid-event{margin-bottom:1px}.fc-timegrid-event .fc-event-main{padding:1px 1px 0}.fc-timegrid-event .fc-event-time{font-size:var(--fc-small-font-size);margin-bottom:1px;white-space:nowrap}.fc-timegrid-event-short .fc-event-main-frame{flex-direction:row;overflow:hidden}.fc-timegrid-event-short .fc-event-time:after{content:\"\\00a0-\\00a0\"}.fc-timegrid-event-short .fc-event-title{font-size:var(--fc-small-font-size)}.fc-timegrid-more-link{background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;margin-bottom:1px;position:absolute;z-index:9999}.fc-timegrid-more-link-inner{padding:3px 2px;top:0}.fc-direction-ltr .fc-timegrid-more-link{right:0}.fc-direction-rtl .fc-timegrid-more-link{left:0}.fc .fc-timegrid-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;border-width:1px 0 0;left:0;position:absolute;right:0;z-index:4}.fc .fc-timegrid-now-indicator-arrow{border-color:var(--fc-now-indicator-color);border-style:solid;margin-top:-5px;position:absolute;z-index:4}.fc-direction-ltr .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 0 5px 6px;left:0}.fc-direction-rtl .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 6px 5px 0;right:0}";
|
1151 | internal$1.injectStyles(css_248z);
|
1152 |
|
1153 | var plugin = core.createPlugin({
|
1154 | name: '@fullcalendar/timegrid',
|
1155 | initialView: 'timeGridWeek',
|
1156 | optionRefiners: OPTION_REFINERS,
|
1157 | views: {
|
1158 | timeGrid: {
|
1159 | component: DayTimeColsView,
|
1160 | usesMinMaxTime: true,
|
1161 | allDaySlot: true,
|
1162 | slotDuration: '00:30:00',
|
1163 | slotEventOverlap: true,
|
1164 | },
|
1165 | timeGridDay: {
|
1166 | type: 'timeGrid',
|
1167 | duration: { days: 1 },
|
1168 | },
|
1169 | timeGridWeek: {
|
1170 | type: 'timeGrid',
|
1171 | duration: { weeks: 1 },
|
1172 | },
|
1173 | },
|
1174 | });
|
1175 |
|
1176 | var internal = {
|
1177 | __proto__: null,
|
1178 | TimeColsView: TimeColsView,
|
1179 | DayTimeColsView: DayTimeColsView,
|
1180 | buildTimeColsModel: buildTimeColsModel,
|
1181 | DayTimeCols: DayTimeCols,
|
1182 | buildDayRanges: buildDayRanges,
|
1183 | DayTimeColsSlicer: DayTimeColsSlicer,
|
1184 | TimeCols: TimeCols,
|
1185 | buildSlatMetas: buildSlatMetas,
|
1186 | TimeColsSlatsCoords: TimeColsSlatsCoords
|
1187 | };
|
1188 |
|
1189 | core.globalPlugins.push(plugin);
|
1190 |
|
1191 | exports.Internal = internal;
|
1192 | exports["default"] = plugin;
|
1193 |
|
1194 | Object.defineProperty(exports, '__esModule', { value: true });
|
1195 |
|
1196 | return exports;
|
1197 |
|
1198 | })({}, FullCalendar, FullCalendar.Internal, FullCalendar.Preact, FullCalendar.DayGrid.Internal);
|