index.global.js 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  1. /*!
  2. FullCalendar Day Grid Plugin v6.1.14
  3. Docs & License: https://fullcalendar.io/docs/month-view
  4. (c) 2024 Adam Shaw
  5. */
  6. FullCalendar.DayGrid = (function (exports, core, internal$1, preact) {
  7. 'use strict';
  8. /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.
  9. ----------------------------------------------------------------------------------------------------------------------*/
  10. // It is a manager for a Table subcomponent, which does most of the heavy lifting.
  11. // It is responsible for managing width/height.
  12. class TableView extends internal$1.DateComponent {
  13. constructor() {
  14. super(...arguments);
  15. this.headerElRef = preact.createRef();
  16. }
  17. renderSimpleLayout(headerRowContent, bodyContent) {
  18. let { props, context } = this;
  19. let sections = [];
  20. let stickyHeaderDates = internal$1.getStickyHeaderDates(context.options);
  21. if (headerRowContent) {
  22. sections.push({
  23. type: 'header',
  24. key: 'header',
  25. isSticky: stickyHeaderDates,
  26. chunk: {
  27. elRef: this.headerElRef,
  28. tableClassName: 'fc-col-header',
  29. rowContent: headerRowContent,
  30. },
  31. });
  32. }
  33. sections.push({
  34. type: 'body',
  35. key: 'body',
  36. liquid: true,
  37. chunk: { content: bodyContent },
  38. });
  39. return (preact.createElement(internal$1.ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
  40. preact.createElement(internal$1.SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [] /* TODO: make optional? */, sections: sections })));
  41. }
  42. renderHScrollLayout(headerRowContent, bodyContent, colCnt, dayMinWidth) {
  43. let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
  44. if (!ScrollGrid) {
  45. throw new Error('No ScrollGrid implementation');
  46. }
  47. let { props, context } = this;
  48. let stickyHeaderDates = !props.forPrint && internal$1.getStickyHeaderDates(context.options);
  49. let stickyFooterScrollbar = !props.forPrint && internal$1.getStickyFooterScrollbar(context.options);
  50. let sections = [];
  51. if (headerRowContent) {
  52. sections.push({
  53. type: 'header',
  54. key: 'header',
  55. isSticky: stickyHeaderDates,
  56. chunks: [{
  57. key: 'main',
  58. elRef: this.headerElRef,
  59. tableClassName: 'fc-col-header',
  60. rowContent: headerRowContent,
  61. }],
  62. });
  63. }
  64. sections.push({
  65. type: 'body',
  66. key: 'body',
  67. liquid: true,
  68. chunks: [{
  69. key: 'main',
  70. content: bodyContent,
  71. }],
  72. });
  73. if (stickyFooterScrollbar) {
  74. sections.push({
  75. type: 'footer',
  76. key: 'footer',
  77. isSticky: true,
  78. chunks: [{
  79. key: 'main',
  80. content: internal$1.renderScrollShim,
  81. }],
  82. });
  83. }
  84. return (preact.createElement(internal$1.ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
  85. preact.createElement(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: props.forPrint, colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }], sections: sections })));
  86. }
  87. }
  88. function splitSegsByRow(segs, rowCnt) {
  89. let byRow = [];
  90. for (let i = 0; i < rowCnt; i += 1) {
  91. byRow[i] = [];
  92. }
  93. for (let seg of segs) {
  94. byRow[seg.row].push(seg);
  95. }
  96. return byRow;
  97. }
  98. function splitSegsByFirstCol(segs, colCnt) {
  99. let byCol = [];
  100. for (let i = 0; i < colCnt; i += 1) {
  101. byCol[i] = [];
  102. }
  103. for (let seg of segs) {
  104. byCol[seg.firstCol].push(seg);
  105. }
  106. return byCol;
  107. }
  108. function splitInteractionByRow(ui, rowCnt) {
  109. let byRow = [];
  110. if (!ui) {
  111. for (let i = 0; i < rowCnt; i += 1) {
  112. byRow[i] = null;
  113. }
  114. }
  115. else {
  116. for (let i = 0; i < rowCnt; i += 1) {
  117. byRow[i] = {
  118. affectedInstances: ui.affectedInstances,
  119. isEvent: ui.isEvent,
  120. segs: [],
  121. };
  122. }
  123. for (let seg of ui.segs) {
  124. byRow[seg.row].segs.push(seg);
  125. }
  126. }
  127. return byRow;
  128. }
  129. const DEFAULT_TABLE_EVENT_TIME_FORMAT = internal$1.createFormatter({
  130. hour: 'numeric',
  131. minute: '2-digit',
  132. omitZeroMinute: true,
  133. meridiem: 'narrow',
  134. });
  135. function hasListItemDisplay(seg) {
  136. let { display } = seg.eventRange.ui;
  137. return display === 'list-item' || (display === 'auto' &&
  138. !seg.eventRange.def.allDay &&
  139. seg.firstCol === seg.lastCol && // can't be multi-day
  140. seg.isStart && // "
  141. seg.isEnd // "
  142. );
  143. }
  144. class TableBlockEvent extends internal$1.BaseComponent {
  145. render() {
  146. let { props } = this;
  147. return (preact.createElement(internal$1.StandardEvent, Object.assign({}, props, { elClasses: ['fc-daygrid-event', 'fc-daygrid-block-event', 'fc-h-event'], defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: props.defaultDisplayEventEnd, disableResizing: !props.seg.eventRange.def.allDay })));
  148. }
  149. }
  150. class TableListItemEvent extends internal$1.BaseComponent {
  151. render() {
  152. let { props, context } = this;
  153. let { options } = context;
  154. let { seg } = props;
  155. let timeFormat = options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT;
  156. let timeText = internal$1.buildSegTimeText(seg, timeFormat, context, true, props.defaultDisplayEventEnd);
  157. return (preact.createElement(internal$1.EventContainer, Object.assign({}, props, { elTag: "a", elClasses: ['fc-daygrid-event', 'fc-daygrid-dot-event'], elAttrs: internal$1.getSegAnchorAttrs(props.seg, context), defaultGenerator: renderInnerContent, timeText: timeText, isResizing: false, isDateSelecting: false })));
  158. }
  159. }
  160. function renderInnerContent(renderProps) {
  161. return (preact.createElement(preact.Fragment, null,
  162. preact.createElement("div", { className: "fc-daygrid-event-dot", style: { borderColor: renderProps.borderColor || renderProps.backgroundColor } }),
  163. renderProps.timeText && (preact.createElement("div", { className: "fc-event-time" }, renderProps.timeText)),
  164. preact.createElement("div", { className: "fc-event-title" }, renderProps.event.title || preact.createElement(preact.Fragment, null, "\u00A0"))));
  165. }
  166. class TableCellMoreLink extends internal$1.BaseComponent {
  167. constructor() {
  168. super(...arguments);
  169. this.compileSegs = internal$1.memoize(compileSegs);
  170. }
  171. render() {
  172. let { props } = this;
  173. let { allSegs, invisibleSegs } = this.compileSegs(props.singlePlacements);
  174. return (preact.createElement(internal$1.MoreLinkContainer, { elClasses: ['fc-daygrid-more-link'], dateProfile: props.dateProfile, todayRange: props.todayRange, allDayDate: props.allDayDate, moreCnt: props.moreCnt, allSegs: allSegs, hiddenSegs: invisibleSegs, alignmentElRef: props.alignmentElRef, alignGridTop: props.alignGridTop, extraDateSpan: props.extraDateSpan, popoverContent: () => {
  175. let isForcedInvisible = (props.eventDrag ? props.eventDrag.affectedInstances : null) ||
  176. (props.eventResize ? props.eventResize.affectedInstances : null) ||
  177. {};
  178. return (preact.createElement(preact.Fragment, null, allSegs.map((seg) => {
  179. let instanceId = seg.eventRange.instance.instanceId;
  180. return (preact.createElement("div", { className: "fc-daygrid-event-harness", key: instanceId, style: {
  181. visibility: isForcedInvisible[instanceId] ? 'hidden' : '',
  182. } }, hasListItemDisplay(seg) ? (preact.createElement(TableListItemEvent, Object.assign({ seg: seg, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, internal$1.getSegMeta(seg, props.todayRange)))) : (preact.createElement(TableBlockEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, internal$1.getSegMeta(seg, props.todayRange))))));
  183. })));
  184. } }));
  185. }
  186. }
  187. function compileSegs(singlePlacements) {
  188. let allSegs = [];
  189. let invisibleSegs = [];
  190. for (let placement of singlePlacements) {
  191. allSegs.push(placement.seg);
  192. if (!placement.isVisible) {
  193. invisibleSegs.push(placement.seg);
  194. }
  195. }
  196. return { allSegs, invisibleSegs };
  197. }
  198. const DEFAULT_WEEK_NUM_FORMAT = internal$1.createFormatter({ week: 'narrow' });
  199. class TableCell extends internal$1.DateComponent {
  200. constructor() {
  201. super(...arguments);
  202. this.rootElRef = preact.createRef();
  203. this.state = {
  204. dayNumberId: internal$1.getUniqueDomId(),
  205. };
  206. this.handleRootEl = (el) => {
  207. internal$1.setRef(this.rootElRef, el);
  208. internal$1.setRef(this.props.elRef, el);
  209. };
  210. }
  211. render() {
  212. let { context, props, state, rootElRef } = this;
  213. let { options, dateEnv } = context;
  214. let { date, dateProfile } = props;
  215. // TODO: memoize this?
  216. const isMonthStart = props.showDayNumber &&
  217. shouldDisplayMonthStart(date, dateProfile.currentRange, dateEnv);
  218. return (preact.createElement(internal$1.DayCellContainer, { elTag: "td", elRef: this.handleRootEl, elClasses: [
  219. 'fc-daygrid-day',
  220. ...(props.extraClassNames || []),
  221. ], elAttrs: Object.assign(Object.assign(Object.assign({}, props.extraDataAttrs), (props.showDayNumber ? { 'aria-labelledby': state.dayNumberId } : {})), { role: 'gridcell' }), defaultGenerator: renderTopInner, date: date, dateProfile: dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, isMonthStart: isMonthStart, extraRenderProps: props.extraRenderProps }, (InnerContent, renderProps) => (preact.createElement("div", { ref: props.innerElRef, className: "fc-daygrid-day-frame fc-scrollgrid-sync-inner", style: { minHeight: props.minHeight } },
  222. props.showWeekNumber && (preact.createElement(internal$1.WeekNumberContainer, { elTag: "a", elClasses: ['fc-daygrid-week-number'], elAttrs: internal$1.buildNavLinkAttrs(context, date, 'week'), date: date, defaultFormat: DEFAULT_WEEK_NUM_FORMAT })),
  223. !renderProps.isDisabled &&
  224. (props.showDayNumber || internal$1.hasCustomDayCellContent(options) || props.forceDayTop) ? (preact.createElement("div", { className: "fc-daygrid-day-top" },
  225. preact.createElement(InnerContent, { elTag: "a", elClasses: [
  226. 'fc-daygrid-day-number',
  227. isMonthStart && 'fc-daygrid-month-start',
  228. ], elAttrs: Object.assign(Object.assign({}, internal$1.buildNavLinkAttrs(context, date)), { id: state.dayNumberId }) }))) : props.showDayNumber ? (
  229. // for creating correct amount of space (see issue #7162)
  230. preact.createElement("div", { className: "fc-daygrid-day-top", style: { visibility: 'hidden' } },
  231. preact.createElement("a", { className: "fc-daygrid-day-number" }, "\u00A0"))) : undefined,
  232. preact.createElement("div", { className: "fc-daygrid-day-events", ref: props.fgContentElRef },
  233. props.fgContent,
  234. preact.createElement("div", { className: "fc-daygrid-day-bottom", style: { marginTop: props.moreMarginTop } },
  235. preact.createElement(TableCellMoreLink, { allDayDate: date, singlePlacements: props.singlePlacements, moreCnt: props.moreCnt, alignmentElRef: rootElRef, alignGridTop: !props.showDayNumber, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange }))),
  236. preact.createElement("div", { className: "fc-daygrid-day-bg" }, props.bgContent)))));
  237. }
  238. }
  239. function renderTopInner(props) {
  240. return props.dayNumberText || preact.createElement(preact.Fragment, null, "\u00A0");
  241. }
  242. function shouldDisplayMonthStart(date, currentRange, dateEnv) {
  243. const { start: currentStart, end: currentEnd } = currentRange;
  244. const currentEndIncl = internal$1.addMs(currentEnd, -1);
  245. const currentFirstYear = dateEnv.getYear(currentStart);
  246. const currentFirstMonth = dateEnv.getMonth(currentStart);
  247. const currentLastYear = dateEnv.getYear(currentEndIncl);
  248. const currentLastMonth = dateEnv.getMonth(currentEndIncl);
  249. // spans more than one month?
  250. return !(currentFirstYear === currentLastYear && currentFirstMonth === currentLastMonth) &&
  251. Boolean(
  252. // first date in current view?
  253. date.valueOf() === currentStart.valueOf() ||
  254. // a month-start that's within the current range?
  255. (dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf()));
  256. }
  257. function generateSegKey(seg) {
  258. return seg.eventRange.instance.instanceId + ':' + seg.firstCol;
  259. }
  260. function generateSegUid(seg) {
  261. return generateSegKey(seg) + ':' + seg.lastCol;
  262. }
  263. function computeFgSegPlacement(segs, // assumed already sorted
  264. dayMaxEvents, dayMaxEventRows, strictOrder, segHeights, maxContentHeight, cells) {
  265. let hierarchy = new DayGridSegHierarchy((segEntry) => {
  266. // TODO: more DRY with generateSegUid
  267. let segUid = segs[segEntry.index].eventRange.instance.instanceId +
  268. ':' + segEntry.span.start +
  269. ':' + (segEntry.span.end - 1);
  270. // if no thickness known, assume 1 (if 0, so small it always fits)
  271. return segHeights[segUid] || 1;
  272. });
  273. hierarchy.allowReslicing = true;
  274. hierarchy.strictOrder = strictOrder;
  275. if (dayMaxEvents === true || dayMaxEventRows === true) {
  276. hierarchy.maxCoord = maxContentHeight;
  277. hierarchy.hiddenConsumes = true;
  278. }
  279. else if (typeof dayMaxEvents === 'number') {
  280. hierarchy.maxStackCnt = dayMaxEvents;
  281. }
  282. else if (typeof dayMaxEventRows === 'number') {
  283. hierarchy.maxStackCnt = dayMaxEventRows;
  284. hierarchy.hiddenConsumes = true;
  285. }
  286. // create segInputs only for segs with known heights
  287. let segInputs = [];
  288. let unknownHeightSegs = [];
  289. for (let i = 0; i < segs.length; i += 1) {
  290. let seg = segs[i];
  291. let segUid = generateSegUid(seg);
  292. let eventHeight = segHeights[segUid];
  293. if (eventHeight != null) {
  294. segInputs.push({
  295. index: i,
  296. span: {
  297. start: seg.firstCol,
  298. end: seg.lastCol + 1,
  299. },
  300. });
  301. }
  302. else {
  303. unknownHeightSegs.push(seg);
  304. }
  305. }
  306. let hiddenEntries = hierarchy.addSegs(segInputs);
  307. let segRects = hierarchy.toRects();
  308. let { singleColPlacements, multiColPlacements, leftoverMargins } = placeRects(segRects, segs, cells);
  309. let moreCnts = [];
  310. let moreMarginTops = [];
  311. // add segs with unknown heights
  312. for (let seg of unknownHeightSegs) {
  313. multiColPlacements[seg.firstCol].push({
  314. seg,
  315. isVisible: false,
  316. isAbsolute: true,
  317. absoluteTop: 0,
  318. marginTop: 0,
  319. });
  320. for (let col = seg.firstCol; col <= seg.lastCol; col += 1) {
  321. singleColPlacements[col].push({
  322. seg: resliceSeg(seg, col, col + 1, cells),
  323. isVisible: false,
  324. isAbsolute: false,
  325. absoluteTop: 0,
  326. marginTop: 0,
  327. });
  328. }
  329. }
  330. // add the hidden entries
  331. for (let col = 0; col < cells.length; col += 1) {
  332. moreCnts.push(0);
  333. }
  334. for (let hiddenEntry of hiddenEntries) {
  335. let seg = segs[hiddenEntry.index];
  336. let hiddenSpan = hiddenEntry.span;
  337. multiColPlacements[hiddenSpan.start].push({
  338. seg: resliceSeg(seg, hiddenSpan.start, hiddenSpan.end, cells),
  339. isVisible: false,
  340. isAbsolute: true,
  341. absoluteTop: 0,
  342. marginTop: 0,
  343. });
  344. for (let col = hiddenSpan.start; col < hiddenSpan.end; col += 1) {
  345. moreCnts[col] += 1;
  346. singleColPlacements[col].push({
  347. seg: resliceSeg(seg, col, col + 1, cells),
  348. isVisible: false,
  349. isAbsolute: false,
  350. absoluteTop: 0,
  351. marginTop: 0,
  352. });
  353. }
  354. }
  355. // deal with leftover margins
  356. for (let col = 0; col < cells.length; col += 1) {
  357. moreMarginTops.push(leftoverMargins[col]);
  358. }
  359. return { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops };
  360. }
  361. // rects ordered by top coord, then left
  362. function placeRects(allRects, segs, cells) {
  363. let rectsByEachCol = groupRectsByEachCol(allRects, cells.length);
  364. let singleColPlacements = [];
  365. let multiColPlacements = [];
  366. let leftoverMargins = [];
  367. for (let col = 0; col < cells.length; col += 1) {
  368. let rects = rectsByEachCol[col];
  369. // compute all static segs in singlePlacements
  370. let singlePlacements = [];
  371. let currentHeight = 0;
  372. let currentMarginTop = 0;
  373. for (let rect of rects) {
  374. let seg = segs[rect.index];
  375. singlePlacements.push({
  376. seg: resliceSeg(seg, col, col + 1, cells),
  377. isVisible: true,
  378. isAbsolute: false,
  379. absoluteTop: rect.levelCoord,
  380. marginTop: rect.levelCoord - currentHeight,
  381. });
  382. currentHeight = rect.levelCoord + rect.thickness;
  383. }
  384. // compute mixed static/absolute segs in multiPlacements
  385. let multiPlacements = [];
  386. currentHeight = 0;
  387. currentMarginTop = 0;
  388. for (let rect of rects) {
  389. let seg = segs[rect.index];
  390. let isAbsolute = rect.span.end - rect.span.start > 1; // multi-column?
  391. let isFirstCol = rect.span.start === col;
  392. currentMarginTop += rect.levelCoord - currentHeight; // amount of space since bottom of previous seg
  393. currentHeight = rect.levelCoord + rect.thickness; // height will now be bottom of current seg
  394. if (isAbsolute) {
  395. currentMarginTop += rect.thickness;
  396. if (isFirstCol) {
  397. multiPlacements.push({
  398. seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
  399. isVisible: true,
  400. isAbsolute: true,
  401. absoluteTop: rect.levelCoord,
  402. marginTop: 0,
  403. });
  404. }
  405. }
  406. else if (isFirstCol) {
  407. multiPlacements.push({
  408. seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
  409. isVisible: true,
  410. isAbsolute: false,
  411. absoluteTop: rect.levelCoord,
  412. marginTop: currentMarginTop, // claim the margin
  413. });
  414. currentMarginTop = 0;
  415. }
  416. }
  417. singleColPlacements.push(singlePlacements);
  418. multiColPlacements.push(multiPlacements);
  419. leftoverMargins.push(currentMarginTop);
  420. }
  421. return { singleColPlacements, multiColPlacements, leftoverMargins };
  422. }
  423. function groupRectsByEachCol(rects, colCnt) {
  424. let rectsByEachCol = [];
  425. for (let col = 0; col < colCnt; col += 1) {
  426. rectsByEachCol.push([]);
  427. }
  428. for (let rect of rects) {
  429. for (let col = rect.span.start; col < rect.span.end; col += 1) {
  430. rectsByEachCol[col].push(rect);
  431. }
  432. }
  433. return rectsByEachCol;
  434. }
  435. function resliceSeg(seg, spanStart, spanEnd, cells) {
  436. if (seg.firstCol === spanStart && seg.lastCol === spanEnd - 1) {
  437. return seg;
  438. }
  439. let eventRange = seg.eventRange;
  440. let origRange = eventRange.range;
  441. let slicedRange = internal$1.intersectRanges(origRange, {
  442. start: cells[spanStart].date,
  443. end: internal$1.addDays(cells[spanEnd - 1].date, 1),
  444. });
  445. return Object.assign(Object.assign({}, seg), { firstCol: spanStart, lastCol: spanEnd - 1, eventRange: {
  446. def: eventRange.def,
  447. ui: Object.assign(Object.assign({}, eventRange.ui), { durationEditable: false }),
  448. instance: eventRange.instance,
  449. range: slicedRange,
  450. }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() });
  451. }
  452. class DayGridSegHierarchy extends internal$1.SegHierarchy {
  453. constructor() {
  454. super(...arguments);
  455. // config
  456. this.hiddenConsumes = false;
  457. // allows us to keep hidden entries in the hierarchy so they take up space
  458. this.forceHidden = {};
  459. }
  460. addSegs(segInputs) {
  461. const hiddenSegs = super.addSegs(segInputs);
  462. const { entriesByLevel } = this;
  463. const excludeHidden = (entry) => !this.forceHidden[internal$1.buildEntryKey(entry)];
  464. // remove the forced-hidden segs
  465. for (let level = 0; level < entriesByLevel.length; level += 1) {
  466. entriesByLevel[level] = entriesByLevel[level].filter(excludeHidden);
  467. }
  468. return hiddenSegs;
  469. }
  470. handleInvalidInsertion(insertion, entry, hiddenEntries) {
  471. const { entriesByLevel, forceHidden } = this;
  472. const { touchingEntry, touchingLevel, touchingLateral } = insertion;
  473. // the entry that the new insertion is touching must be hidden
  474. if (this.hiddenConsumes && touchingEntry) {
  475. const touchingEntryId = internal$1.buildEntryKey(touchingEntry);
  476. if (!forceHidden[touchingEntryId]) {
  477. if (this.allowReslicing) {
  478. // split up the touchingEntry, reinsert it
  479. const hiddenEntry = Object.assign(Object.assign({}, touchingEntry), { span: internal$1.intersectSpans(touchingEntry.span, entry.span) });
  480. // reinsert the area that turned into a "more" link (so no other entries try to
  481. // occupy the space) but mark it forced-hidden
  482. const hiddenEntryId = internal$1.buildEntryKey(hiddenEntry);
  483. forceHidden[hiddenEntryId] = true;
  484. entriesByLevel[touchingLevel][touchingLateral] = hiddenEntry;
  485. hiddenEntries.push(hiddenEntry);
  486. this.splitEntry(touchingEntry, entry, hiddenEntries);
  487. }
  488. else {
  489. forceHidden[touchingEntryId] = true;
  490. hiddenEntries.push(touchingEntry);
  491. }
  492. }
  493. }
  494. // will try to reslice...
  495. super.handleInvalidInsertion(insertion, entry, hiddenEntries);
  496. }
  497. }
  498. class TableRow extends internal$1.DateComponent {
  499. constructor() {
  500. super(...arguments);
  501. this.cellElRefs = new internal$1.RefMap(); // the <td>
  502. this.frameElRefs = new internal$1.RefMap(); // the fc-daygrid-day-frame
  503. this.fgElRefs = new internal$1.RefMap(); // the fc-daygrid-day-events
  504. this.segHarnessRefs = new internal$1.RefMap(); // indexed by "instanceId:firstCol"
  505. this.rootElRef = preact.createRef();
  506. this.state = {
  507. framePositions: null,
  508. maxContentHeight: null,
  509. segHeights: {},
  510. };
  511. this.handleResize = (isForced) => {
  512. if (isForced) {
  513. this.updateSizing(true); // isExternal=true
  514. }
  515. };
  516. }
  517. render() {
  518. let { props, state, context } = this;
  519. let { options } = context;
  520. let colCnt = props.cells.length;
  521. let businessHoursByCol = splitSegsByFirstCol(props.businessHourSegs, colCnt);
  522. let bgEventSegsByCol = splitSegsByFirstCol(props.bgEventSegs, colCnt);
  523. let highlightSegsByCol = splitSegsByFirstCol(this.getHighlightSegs(), colCnt);
  524. let mirrorSegsByCol = splitSegsByFirstCol(this.getMirrorSegs(), colCnt);
  525. let { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops } = computeFgSegPlacement(internal$1.sortEventSegs(props.fgEventSegs, options.eventOrder), props.dayMaxEvents, props.dayMaxEventRows, options.eventOrderStrict, state.segHeights, state.maxContentHeight, props.cells);
  526. let isForcedInvisible = // TODO: messy way to compute this
  527. (props.eventDrag && props.eventDrag.affectedInstances) ||
  528. (props.eventResize && props.eventResize.affectedInstances) ||
  529. {};
  530. return (preact.createElement("tr", { ref: this.rootElRef, role: "row" },
  531. props.renderIntro && props.renderIntro(),
  532. props.cells.map((cell, col) => {
  533. let normalFgNodes = this.renderFgSegs(col, props.forPrint ? singleColPlacements[col] : multiColPlacements[col], props.todayRange, isForcedInvisible);
  534. let mirrorFgNodes = this.renderFgSegs(col, buildMirrorPlacements(mirrorSegsByCol[col], multiColPlacements), props.todayRange, {}, Boolean(props.eventDrag), Boolean(props.eventResize), false);
  535. return (preact.createElement(TableCell, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), innerElRef: this.frameElRefs.createRef(cell.key) /* FF <td> problem, but okay to use for left/right. TODO: rename prop */, dateProfile: props.dateProfile, date: cell.date, showDayNumber: props.showDayNumbers, showWeekNumber: props.showWeekNumbers && col === 0, forceDayTop: props.showWeekNumbers /* even displaying weeknum for row, not necessarily day */, todayRange: props.todayRange, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, moreCnt: moreCnts[col], moreMarginTop: moreMarginTops[col], singlePlacements: singleColPlacements[col], fgContentElRef: this.fgElRefs.createRef(cell.key), fgContent: ( // Fragment scopes the keys
  536. preact.createElement(preact.Fragment, null,
  537. preact.createElement(preact.Fragment, null, normalFgNodes),
  538. preact.createElement(preact.Fragment, null, mirrorFgNodes))), bgContent: ( // Fragment scopes the keys
  539. preact.createElement(preact.Fragment, null,
  540. this.renderFillSegs(highlightSegsByCol[col], 'highlight'),
  541. this.renderFillSegs(businessHoursByCol[col], 'non-business'),
  542. this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))), minHeight: props.cellMinHeight }));
  543. })));
  544. }
  545. componentDidMount() {
  546. this.updateSizing(true);
  547. this.context.addResizeHandler(this.handleResize);
  548. }
  549. componentDidUpdate(prevProps, prevState) {
  550. let currentProps = this.props;
  551. this.updateSizing(!internal$1.isPropsEqual(prevProps, currentProps));
  552. }
  553. componentWillUnmount() {
  554. this.context.removeResizeHandler(this.handleResize);
  555. }
  556. getHighlightSegs() {
  557. let { props } = this;
  558. if (props.eventDrag && props.eventDrag.segs.length) { // messy check
  559. return props.eventDrag.segs;
  560. }
  561. if (props.eventResize && props.eventResize.segs.length) { // messy check
  562. return props.eventResize.segs;
  563. }
  564. return props.dateSelectionSegs;
  565. }
  566. getMirrorSegs() {
  567. let { props } = this;
  568. if (props.eventResize && props.eventResize.segs.length) { // messy check
  569. return props.eventResize.segs;
  570. }
  571. return [];
  572. }
  573. renderFgSegs(col, segPlacements, todayRange, isForcedInvisible, isDragging, isResizing, isDateSelecting) {
  574. let { context } = this;
  575. let { eventSelection } = this.props;
  576. let { framePositions } = this.state;
  577. let defaultDisplayEventEnd = this.props.cells.length === 1; // colCnt === 1
  578. let isMirror = isDragging || isResizing || isDateSelecting;
  579. let nodes = [];
  580. if (framePositions) {
  581. for (let placement of segPlacements) {
  582. let { seg } = placement;
  583. let { instanceId } = seg.eventRange.instance;
  584. let isVisible = placement.isVisible && !isForcedInvisible[instanceId];
  585. let isAbsolute = placement.isAbsolute;
  586. let left = '';
  587. let right = '';
  588. if (isAbsolute) {
  589. if (context.isRtl) {
  590. right = 0;
  591. left = framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol];
  592. }
  593. else {
  594. left = 0;
  595. right = framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol];
  596. }
  597. }
  598. /*
  599. known bug: events that are force to be list-item but span multiple days still take up space in later columns
  600. todo: in print view, for multi-day events, don't display title within non-start/end segs
  601. */
  602. nodes.push(preact.createElement("div", { className: 'fc-daygrid-event-harness' + (isAbsolute ? ' fc-daygrid-event-harness-abs' : ''), key: generateSegKey(seg), ref: isMirror ? null : this.segHarnessRefs.createRef(generateSegUid(seg)), style: {
  603. visibility: isVisible ? '' : 'hidden',
  604. marginTop: isAbsolute ? '' : placement.marginTop,
  605. top: isAbsolute ? placement.absoluteTop : '',
  606. left,
  607. right,
  608. } }, hasListItemDisplay(seg) ? (preact.createElement(TableListItemEvent, Object.assign({ seg: seg, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal$1.getSegMeta(seg, todayRange)))) : (preact.createElement(TableBlockEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal$1.getSegMeta(seg, todayRange))))));
  609. }
  610. }
  611. return nodes;
  612. }
  613. renderFillSegs(segs, fillType) {
  614. let { isRtl } = this.context;
  615. let { todayRange } = this.props;
  616. let { framePositions } = this.state;
  617. let nodes = [];
  618. if (framePositions) {
  619. for (let seg of segs) {
  620. let leftRightCss = isRtl ? {
  621. right: 0,
  622. left: framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol],
  623. } : {
  624. left: 0,
  625. right: framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol],
  626. };
  627. nodes.push(preact.createElement("div", { key: internal$1.buildEventRangeKey(seg.eventRange), className: "fc-daygrid-bg-harness", style: leftRightCss }, fillType === 'bg-event' ?
  628. preact.createElement(internal$1.BgEvent, Object.assign({ seg: seg }, internal$1.getSegMeta(seg, todayRange))) :
  629. internal$1.renderFill(fillType)));
  630. }
  631. }
  632. return preact.createElement(preact.Fragment, {}, ...nodes);
  633. }
  634. updateSizing(isExternalSizingChange) {
  635. let { props, state, frameElRefs } = this;
  636. if (!props.forPrint &&
  637. props.clientWidth !== null // positioning ready?
  638. ) {
  639. if (isExternalSizingChange) {
  640. let frameEls = props.cells.map((cell) => frameElRefs.currentMap[cell.key]);
  641. if (frameEls.length) {
  642. let originEl = this.rootElRef.current;
  643. let newPositionCache = new internal$1.PositionCache(originEl, frameEls, true, // isHorizontal
  644. false);
  645. if (!state.framePositions || !state.framePositions.similarTo(newPositionCache)) {
  646. this.setState({
  647. framePositions: new internal$1.PositionCache(originEl, frameEls, true, // isHorizontal
  648. false),
  649. });
  650. }
  651. }
  652. }
  653. const oldSegHeights = this.state.segHeights;
  654. const newSegHeights = this.querySegHeights();
  655. const limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
  656. this.safeSetState({
  657. // HACK to prevent oscillations of events being shown/hidden from max-event-rows
  658. // Essentially, once you compute an element's height, never null-out.
  659. // TODO: always display all events, as visibility:hidden?
  660. segHeights: Object.assign(Object.assign({}, oldSegHeights), newSegHeights),
  661. maxContentHeight: limitByContentHeight ? this.computeMaxContentHeight() : null,
  662. });
  663. }
  664. }
  665. querySegHeights() {
  666. let segElMap = this.segHarnessRefs.currentMap;
  667. let segHeights = {};
  668. // get the max height amongst instance segs
  669. for (let segUid in segElMap) {
  670. let height = Math.round(segElMap[segUid].getBoundingClientRect().height);
  671. segHeights[segUid] = Math.max(segHeights[segUid] || 0, height);
  672. }
  673. return segHeights;
  674. }
  675. computeMaxContentHeight() {
  676. let firstKey = this.props.cells[0].key;
  677. let cellEl = this.cellElRefs.currentMap[firstKey];
  678. let fcContainerEl = this.fgElRefs.currentMap[firstKey];
  679. return cellEl.getBoundingClientRect().bottom - fcContainerEl.getBoundingClientRect().top;
  680. }
  681. getCellEls() {
  682. let elMap = this.cellElRefs.currentMap;
  683. return this.props.cells.map((cell) => elMap[cell.key]);
  684. }
  685. }
  686. TableRow.addStateEquality({
  687. segHeights: internal$1.isPropsEqual,
  688. });
  689. function buildMirrorPlacements(mirrorSegs, colPlacements) {
  690. if (!mirrorSegs.length) {
  691. return [];
  692. }
  693. let topsByInstanceId = buildAbsoluteTopHash(colPlacements); // TODO: cache this at first render?
  694. return mirrorSegs.map((seg) => ({
  695. seg,
  696. isVisible: true,
  697. isAbsolute: true,
  698. absoluteTop: topsByInstanceId[seg.eventRange.instance.instanceId],
  699. marginTop: 0,
  700. }));
  701. }
  702. function buildAbsoluteTopHash(colPlacements) {
  703. let topsByInstanceId = {};
  704. for (let placements of colPlacements) {
  705. for (let placement of placements) {
  706. topsByInstanceId[placement.seg.eventRange.instance.instanceId] = placement.absoluteTop;
  707. }
  708. }
  709. return topsByInstanceId;
  710. }
  711. class TableRows extends internal$1.DateComponent {
  712. constructor() {
  713. super(...arguments);
  714. this.splitBusinessHourSegs = internal$1.memoize(splitSegsByRow);
  715. this.splitBgEventSegs = internal$1.memoize(splitSegsByRow);
  716. this.splitFgEventSegs = internal$1.memoize(splitSegsByRow);
  717. this.splitDateSelectionSegs = internal$1.memoize(splitSegsByRow);
  718. this.splitEventDrag = internal$1.memoize(splitInteractionByRow);
  719. this.splitEventResize = internal$1.memoize(splitInteractionByRow);
  720. this.rowRefs = new internal$1.RefMap();
  721. }
  722. render() {
  723. let { props, context } = this;
  724. let rowCnt = props.cells.length;
  725. let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt);
  726. let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);
  727. let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt);
  728. let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt);
  729. let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt);
  730. let eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt);
  731. // for DayGrid view with many rows, force a min-height on cells so doesn't appear squished
  732. // choose 7 because a month view will have max 6 rows
  733. let cellMinHeight = (rowCnt >= 7 && props.clientWidth) ?
  734. props.clientWidth / context.options.aspectRatio / 6 :
  735. null;
  736. return (preact.createElement(internal$1.NowTimer, { unit: "day" }, (nowDate, todayRange) => (preact.createElement(preact.Fragment, null, props.cells.map((cells, row) => (preact.createElement(TableRow, { ref: this.rowRefs.createRef(row), key: cells.length
  737. ? cells[0].date.toISOString() /* best? or put key on cell? or use diff formatter? */
  738. : row // in case there are no cells (like when resource view is loading)
  739. , showDayNumbers: rowCnt > 1, showWeekNumbers: props.showWeekNumbers, todayRange: todayRange, dateProfile: props.dateProfile, cells: cells, renderIntro: props.renderRowIntro, businessHourSegs: businessHourSegsByRow[row], eventSelection: props.eventSelection, bgEventSegs: bgEventSegsByRow[row].filter(isSegAllDay) /* hack */, fgEventSegs: fgEventSegsByRow[row], dateSelectionSegs: dateSelectionSegsByRow[row], eventDrag: eventDragByRow[row], eventResize: eventResizeByRow[row], dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, clientWidth: props.clientWidth, clientHeight: props.clientHeight, cellMinHeight: cellMinHeight, forPrint: props.forPrint })))))));
  740. }
  741. componentDidMount() {
  742. this.registerInteractiveComponent();
  743. }
  744. componentDidUpdate() {
  745. // for if started with zero cells
  746. this.registerInteractiveComponent();
  747. }
  748. registerInteractiveComponent() {
  749. if (!this.rootEl) {
  750. // HACK: need a daygrid wrapper parent to do positioning
  751. // NOTE: a daygrid resource view w/o resources can have zero cells
  752. const firstCellEl = this.rowRefs.currentMap[0].getCellEls()[0];
  753. const rootEl = firstCellEl ? firstCellEl.closest('.fc-daygrid-body') : null;
  754. if (rootEl) {
  755. this.rootEl = rootEl;
  756. this.context.registerInteractiveComponent(this, {
  757. el: rootEl,
  758. isHitComboAllowed: this.props.isHitComboAllowed,
  759. });
  760. }
  761. }
  762. }
  763. componentWillUnmount() {
  764. if (this.rootEl) {
  765. this.context.unregisterInteractiveComponent(this);
  766. this.rootEl = null;
  767. }
  768. }
  769. // Hit System
  770. // ----------------------------------------------------------------------------------------------------
  771. prepareHits() {
  772. this.rowPositions = new internal$1.PositionCache(this.rootEl, this.rowRefs.collect().map((rowObj) => rowObj.getCellEls()[0]), // first cell el in each row. TODO: not optimal
  773. false, true);
  774. this.colPositions = new internal$1.PositionCache(this.rootEl, this.rowRefs.currentMap[0].getCellEls(), // cell els in first row
  775. true, // horizontal
  776. false);
  777. }
  778. queryHit(positionLeft, positionTop) {
  779. let { colPositions, rowPositions } = this;
  780. let col = colPositions.leftToIndex(positionLeft);
  781. let row = rowPositions.topToIndex(positionTop);
  782. if (row != null && col != null) {
  783. let cell = this.props.cells[row][col];
  784. return {
  785. dateProfile: this.props.dateProfile,
  786. dateSpan: Object.assign({ range: this.getCellRange(row, col), allDay: true }, cell.extraDateSpan),
  787. dayEl: this.getCellEl(row, col),
  788. rect: {
  789. left: colPositions.lefts[col],
  790. right: colPositions.rights[col],
  791. top: rowPositions.tops[row],
  792. bottom: rowPositions.bottoms[row],
  793. },
  794. layer: 0,
  795. };
  796. }
  797. return null;
  798. }
  799. getCellEl(row, col) {
  800. return this.rowRefs.currentMap[row].getCellEls()[col]; // TODO: not optimal
  801. }
  802. getCellRange(row, col) {
  803. let start = this.props.cells[row][col].date;
  804. let end = internal$1.addDays(start, 1);
  805. return { start, end };
  806. }
  807. }
  808. function isSegAllDay(seg) {
  809. return seg.eventRange.def.allDay;
  810. }
  811. class Table extends internal$1.DateComponent {
  812. constructor() {
  813. super(...arguments);
  814. this.elRef = preact.createRef();
  815. this.needsScrollReset = false;
  816. }
  817. render() {
  818. let { props } = this;
  819. let { dayMaxEventRows, dayMaxEvents, expandRows } = props;
  820. let limitViaBalanced = dayMaxEvents === true || dayMaxEventRows === true;
  821. // if rows can't expand to fill fixed height, can't do balanced-height event limit
  822. // TODO: best place to normalize these options?
  823. if (limitViaBalanced && !expandRows) {
  824. limitViaBalanced = false;
  825. dayMaxEventRows = null;
  826. dayMaxEvents = null;
  827. }
  828. let classNames = [
  829. 'fc-daygrid-body',
  830. limitViaBalanced ? 'fc-daygrid-body-balanced' : 'fc-daygrid-body-unbalanced',
  831. expandRows ? '' : 'fc-daygrid-body-natural', // will height of one row depend on the others?
  832. ];
  833. return (preact.createElement("div", { ref: this.elRef, className: classNames.join(' '), style: {
  834. // these props are important to give this wrapper correct dimensions for interactions
  835. // TODO: if we set it here, can we avoid giving to inner tables?
  836. width: props.clientWidth,
  837. minWidth: props.tableMinWidth,
  838. } },
  839. preact.createElement("table", { role: "presentation", className: "fc-scrollgrid-sync-table", style: {
  840. width: props.clientWidth,
  841. minWidth: props.tableMinWidth,
  842. height: expandRows ? props.clientHeight : '',
  843. } },
  844. props.colGroupNode,
  845. preact.createElement("tbody", { role: "presentation" },
  846. preact.createElement(TableRows, { dateProfile: props.dateProfile, cells: props.cells, renderRowIntro: props.renderRowIntro, showWeekNumbers: props.showWeekNumbers, clientWidth: props.clientWidth, clientHeight: props.clientHeight, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, dayMaxEvents: dayMaxEvents, dayMaxEventRows: dayMaxEventRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed })))));
  847. }
  848. componentDidMount() {
  849. this.requestScrollReset();
  850. }
  851. componentDidUpdate(prevProps) {
  852. if (prevProps.dateProfile !== this.props.dateProfile) {
  853. this.requestScrollReset();
  854. }
  855. else {
  856. this.flushScrollReset();
  857. }
  858. }
  859. requestScrollReset() {
  860. this.needsScrollReset = true;
  861. this.flushScrollReset();
  862. }
  863. flushScrollReset() {
  864. if (this.needsScrollReset &&
  865. this.props.clientWidth // sizes computed?
  866. ) {
  867. const subjectEl = getScrollSubjectEl(this.elRef.current, this.props.dateProfile);
  868. if (subjectEl) {
  869. const originEl = subjectEl.closest('.fc-daygrid-body');
  870. const scrollEl = originEl.closest('.fc-scroller');
  871. const scrollTop = subjectEl.getBoundingClientRect().top -
  872. originEl.getBoundingClientRect().top;
  873. scrollEl.scrollTop = scrollTop ? (scrollTop + 1) : 0; // overcome border
  874. }
  875. this.needsScrollReset = false;
  876. }
  877. }
  878. }
  879. function getScrollSubjectEl(containerEl, dateProfile) {
  880. let el;
  881. if (dateProfile.currentRangeUnit.match(/year|month/)) {
  882. el = containerEl.querySelector(`[data-date="${internal$1.formatIsoMonthStr(dateProfile.currentDate)}-01"]`);
  883. // even if view is month-based, first-of-month might be hidden...
  884. }
  885. if (!el) {
  886. el = containerEl.querySelector(`[data-date="${internal$1.formatDayString(dateProfile.currentDate)}"]`);
  887. // could still be hidden if an interior-view hidden day
  888. }
  889. return el;
  890. }
  891. class DayTableSlicer extends internal$1.Slicer {
  892. constructor() {
  893. super(...arguments);
  894. this.forceDayIfListItem = true;
  895. }
  896. sliceRange(dateRange, dayTableModel) {
  897. return dayTableModel.sliceRange(dateRange);
  898. }
  899. }
  900. class DayTable extends internal$1.DateComponent {
  901. constructor() {
  902. super(...arguments);
  903. this.slicer = new DayTableSlicer();
  904. this.tableRef = preact.createRef();
  905. }
  906. render() {
  907. let { props, context } = this;
  908. return (preact.createElement(Table, Object.assign({ ref: this.tableRef }, this.slicer.sliceProps(props, props.dateProfile, props.nextDayThreshold, context, props.dayTableModel), { dateProfile: props.dateProfile, cells: props.dayTableModel.cells, colGroupNode: props.colGroupNode, tableMinWidth: props.tableMinWidth, renderRowIntro: props.renderRowIntro, dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, showWeekNumbers: props.showWeekNumbers, expandRows: props.expandRows, headerAlignElRef: props.headerAlignElRef, clientWidth: props.clientWidth, clientHeight: props.clientHeight, forPrint: props.forPrint })));
  909. }
  910. }
  911. class DayTableView extends TableView {
  912. constructor() {
  913. super(...arguments);
  914. this.buildDayTableModel = internal$1.memoize(buildDayTableModel);
  915. this.headerRef = preact.createRef();
  916. this.tableRef = preact.createRef();
  917. // can't override any lifecycle methods from parent
  918. }
  919. render() {
  920. let { options, dateProfileGenerator } = this.context;
  921. let { props } = this;
  922. let dayTableModel = this.buildDayTableModel(props.dateProfile, dateProfileGenerator);
  923. let headerContent = options.dayHeaders && (preact.createElement(internal$1.DayHeader, { ref: this.headerRef, dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: dayTableModel.rowCnt === 1 }));
  924. let bodyContent = (contentArg) => (preact.createElement(DayTable, { ref: this.tableRef, dateProfile: props.dateProfile, dayTableModel: dayTableModel, businessHours: props.businessHours, dateSelection: props.dateSelection, eventStore: props.eventStore, eventUiBases: props.eventUiBases, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, nextDayThreshold: options.nextDayThreshold, colGroupNode: contentArg.tableColGroupNode, tableMinWidth: contentArg.tableMinWidth, dayMaxEvents: options.dayMaxEvents, dayMaxEventRows: options.dayMaxEventRows, showWeekNumbers: options.weekNumbers, expandRows: !props.isHeightAuto, headerAlignElRef: this.headerElRef, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, forPrint: props.forPrint }));
  925. return options.dayMinWidth
  926. ? this.renderHScrollLayout(headerContent, bodyContent, dayTableModel.colCnt, options.dayMinWidth)
  927. : this.renderSimpleLayout(headerContent, bodyContent);
  928. }
  929. }
  930. function buildDayTableModel(dateProfile, dateProfileGenerator) {
  931. let daySeries = new internal$1.DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
  932. return new internal$1.DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
  933. }
  934. class TableDateProfileGenerator extends internal$1.DateProfileGenerator {
  935. // Computes the date range that will be rendered
  936. buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
  937. let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay);
  938. let { props } = this;
  939. return buildDayTableRenderRange({
  940. currentRange: renderRange,
  941. snapToWeek: /^(year|month)$/.test(currentRangeUnit),
  942. fixedWeekCount: props.fixedWeekCount,
  943. dateEnv: props.dateEnv,
  944. });
  945. }
  946. }
  947. function buildDayTableRenderRange(props) {
  948. let { dateEnv, currentRange } = props;
  949. let { start, end } = currentRange;
  950. let endOfWeek;
  951. // year and month views should be aligned with weeks. this is already done for week
  952. if (props.snapToWeek) {
  953. start = dateEnv.startOfWeek(start);
  954. // make end-of-week if not already
  955. endOfWeek = dateEnv.startOfWeek(end);
  956. if (endOfWeek.valueOf() !== end.valueOf()) {
  957. end = internal$1.addWeeks(endOfWeek, 1);
  958. }
  959. }
  960. // ensure 6 weeks
  961. if (props.fixedWeekCount) {
  962. // TODO: instead of these date-math gymnastics (for multimonth view),
  963. // compute dateprofiles of all months, then use start of first and end of last.
  964. let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth(internal$1.addDays(currentRange.end, -1)));
  965. let rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
  966. internal$1.diffWeeks(lastMonthRenderStart, end));
  967. end = internal$1.addWeeks(end, 6 - rowCnt);
  968. }
  969. return { start, end };
  970. }
  971. var css_248z = ":root{--fc-daygrid-event-dot-width:8px}.fc-daygrid-day-events:after,.fc-daygrid-day-events:before,.fc-daygrid-day-frame:after,.fc-daygrid-day-frame:before,.fc-daygrid-event-harness:after,.fc-daygrid-event-harness:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-body{position:relative;z-index:1}.fc .fc-daygrid-day.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-daygrid-day-frame{min-height:100%;position:relative}.fc .fc-daygrid-day-top{display:flex;flex-direction:row-reverse}.fc .fc-day-other .fc-daygrid-day-top{opacity:.3}.fc .fc-daygrid-day-number{padding:4px;position:relative;z-index:4}.fc .fc-daygrid-month-start{font-size:1.1em;font-weight:700}.fc .fc-daygrid-day-events{margin-top:1px}.fc .fc-daygrid-body-balanced .fc-daygrid-day-events{left:0;position:absolute;right:0}.fc .fc-daygrid-body-unbalanced .fc-daygrid-day-events{min-height:2em;position:relative}.fc .fc-daygrid-body-natural .fc-daygrid-day-events{margin-bottom:1em}.fc .fc-daygrid-event-harness{position:relative}.fc .fc-daygrid-event-harness-abs{left:0;position:absolute;right:0;top:0}.fc .fc-daygrid-bg-harness{bottom:0;position:absolute;top:0}.fc .fc-daygrid-day-bg .fc-non-business{z-index:1}.fc .fc-daygrid-day-bg .fc-bg-event{z-index:2}.fc .fc-daygrid-day-bg .fc-highlight{z-index:3}.fc .fc-daygrid-event{margin-top:1px;z-index:6}.fc .fc-daygrid-event.fc-event-mirror{z-index:7}.fc .fc-daygrid-day-bottom{font-size:.85em;margin:0 2px}.fc .fc-daygrid-day-bottom:after,.fc .fc-daygrid-day-bottom:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-more-link{border-radius:3px;cursor:pointer;line-height:1;margin-top:1px;max-width:100%;overflow:hidden;padding:2px;position:relative;white-space:nowrap;z-index:4}.fc .fc-daygrid-more-link:hover{background-color:rgba(0,0,0,.1)}.fc .fc-daygrid-week-number{background-color:var(--fc-neutral-bg-color);color:var(--fc-neutral-text-color);min-width:1.5em;padding:2px;position:absolute;text-align:center;top:0;z-index:5}.fc .fc-more-popover .fc-popover-body{min-width:220px;padding:10px}.fc-direction-ltr .fc-daygrid-event.fc-event-start,.fc-direction-rtl .fc-daygrid-event.fc-event-end{margin-left:2px}.fc-direction-ltr .fc-daygrid-event.fc-event-end,.fc-direction-rtl .fc-daygrid-event.fc-event-start{margin-right:2px}.fc-direction-ltr .fc-daygrid-more-link{float:left}.fc-direction-ltr .fc-daygrid-week-number{border-radius:0 0 3px 0;left:0}.fc-direction-rtl .fc-daygrid-more-link{float:right}.fc-direction-rtl .fc-daygrid-week-number{border-radius:0 0 0 3px;right:0}.fc-liquid-hack .fc-daygrid-day-frame{position:static}.fc-daygrid-event{border-radius:3px;font-size:var(--fc-small-font-size);position:relative;white-space:nowrap}.fc-daygrid-block-event .fc-event-time{font-weight:700}.fc-daygrid-block-event .fc-event-time,.fc-daygrid-block-event .fc-event-title{padding:1px}.fc-daygrid-dot-event{align-items:center;display:flex;padding:2px 0}.fc-daygrid-dot-event .fc-event-title{flex-grow:1;flex-shrink:1;font-weight:700;min-width:0;overflow:hidden}.fc-daygrid-dot-event.fc-event-mirror,.fc-daygrid-dot-event:hover{background:rgba(0,0,0,.1)}.fc-daygrid-dot-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-daygrid-event-dot{border:calc(var(--fc-daygrid-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-daygrid-event-dot-width)/2);box-sizing:content-box;height:0;margin:0 4px;width:0}.fc-direction-ltr .fc-daygrid-event .fc-event-time{margin-right:3px}.fc-direction-rtl .fc-daygrid-event .fc-event-time{margin-left:3px}";
  972. internal$1.injectStyles(css_248z);
  973. var plugin = core.createPlugin({
  974. name: '@fullcalendar/daygrid',
  975. initialView: 'dayGridMonth',
  976. views: {
  977. dayGrid: {
  978. component: DayTableView,
  979. dateProfileGeneratorClass: TableDateProfileGenerator,
  980. },
  981. dayGridDay: {
  982. type: 'dayGrid',
  983. duration: { days: 1 },
  984. },
  985. dayGridWeek: {
  986. type: 'dayGrid',
  987. duration: { weeks: 1 },
  988. },
  989. dayGridMonth: {
  990. type: 'dayGrid',
  991. duration: { months: 1 },
  992. fixedWeekCount: true,
  993. },
  994. dayGridYear: {
  995. type: 'dayGrid',
  996. duration: { years: 1 },
  997. },
  998. },
  999. });
  1000. var internal = {
  1001. __proto__: null,
  1002. DayTable: DayTable,
  1003. DayTableSlicer: DayTableSlicer,
  1004. TableDateProfileGenerator: TableDateProfileGenerator,
  1005. buildDayTableRenderRange: buildDayTableRenderRange,
  1006. Table: Table,
  1007. TableRows: TableRows,
  1008. TableView: TableView,
  1009. buildDayTableModel: buildDayTableModel,
  1010. DayGridView: DayTableView
  1011. };
  1012. core.globalPlugins.push(plugin);
  1013. exports.Internal = internal;
  1014. exports["default"] = plugin;
  1015. Object.defineProperty(exports, '__esModule', { value: true });
  1016. return exports;
  1017. })({}, FullCalendar, FullCalendar.Internal, FullCalendar.Preact);