vendor: 11,323 bytes, lines 1-57
1/*! 2FullCalendar v5.3.0 3Docs & License: https://fullcalendar.io/ 4(c) 2020 Adam Shaw 5*/ 6var FullCalendar = (function (exports) { 7 'use strict'; 8 9 /*! ***************************************************************************** 10 Copyright (c) Microsoft Corporation. 11 12 Permission to use, copy, modify, and/or distribute this software for any 13 purpose with or without fee is hereby granted. 14 15 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 16 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 17 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 18 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 19 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 20 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 PERFORMANCE OF THIS SOFTWARE. 22 ***************************************************************************** */ 23 /* global Reflect, Promise */ 24 25 var extendStatics = function(d, b) { 26 extendStatics = Object.setPrototypeOf || 27 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 28 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 29 return extendStatics(d, b); 30 }; 31 32 function __extends(d, b) { 33 extendStatics(d, b); 34 function __() { this.constructor = d; } 35 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 36 } 37 38 var __assign = function() { 39 __assign = Object.assign || function __assign(t) { 40 for (var s, i = 1, n = arguments.length; i < n; i++) { 41 s = arguments[i]; 42 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 43 } 44 return t; 45 }; 46 return __assign.apply(this, arguments); 47 }; 48 49 function __spreadArrays() { 50 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; 51 for (var r = Array(s), k = 0, i = 0; i < il; i++) 52 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) 53 r[k] = a[j]; 54 return r; 55 } 56 57 var n,u,i,t,r,o,f,e={},c=[],s=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord/i;function a(n,l){for(var u in l)n[u]=l[u];return n}function v(n){var l=n.parentNode;l&&l.removeChild(n);}function h(n,l,u){var i,t=arguments,r={};for(i in l)"key"!==i&&"ref"!==i&&(r[i]=l[i]);if(arguments.length>3)for(u=[u],i=3;i<arguments.length;i++)u.push(t[i]);if(null!=u&&(r.children=u),"function"==typeof n&&null!=n.defaultProps)for(i in n.defaultProps)void 0===r[i]&&(r[i]=n.defaultProps[i]);return p(n,r,l&&l.key,l&&l.ref,null)}function p(l,u,i,t,r){var o={type:l,props:u,key:i,ref:t,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,constructor:void 0,__v:r};return null==r&&(o.__v=o),n.vnode&&n.vnode(o),o}function y(){return {}}function d(n){return n.children}function m(n,l){this.props=n,this.context=l;}function w(n,l){if(null==l)return n.__?w(n.__,n.__.__k.indexOf(n)+1):null;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e;return "function"==typeof n.type?w(n):null}function k(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return k(n)}}function g(l){(!l.__d&&(l.__d=!0)&&u.push(l)&&!i++||r!==n.debounceRendering)&&((r=n.debounceRendering)||t)(_);}function _(){for(var n;i=u.length;)n=u.sort(function(n,l){return n.__v.__b-l.__v.__b}),u=[],n.some(function(n){var l,u,i,t,r,o,f;n.__d&&(o=(r=(l=n).__v).__e,(f=l.__P)&&(u=[],(i=a({},r)).__v=i,t=A(f,r,i,l.__n,void 0!==f.ownerSVGElement,null,u,null==o?w(r):o),T(u,r),t!=o&&k(r)));});}function b(n,l,u,i,t,r,o,f,s){var a,h,p,y,d,m,k,g=u&&u.__k||c,_=g.length;if(f==e&&(f=null!=r?r[0]:_?w(u,0):null),a=0,l.__k=x(l.__k,function(u){if(null!=u){if(u.__=l,u.__b=l.__b+1,null===(p=g[a])||p&&u.key==p.key&&u.type===p.type)g[a]=void 0;else for(h=0;h<_;h++){if((p=g[h])&&u.key==p.key&&u.type===p.type){g[h]=void 0;break}p=null;}if(y=A(n,u,p=p||e,i,t,r,o,f,s),(h=u.ref)&&p.ref!=h&&(k||(k=[]),p.ref&&k.push(p.ref,null,u),k.push(h,u.__c||y,u)),null!=y){var c;if(null==m&&(m=y),void 0!==u.__d)c=u.__d,u.__d=void 0;else if(r==p||y!=f||null==y.parentNode){n:if(null==f||f.parentNode!==n)n.appendChild(y),c=null;else {for(d=f,h=0;(d=d.nextSibling)&&h<_;h+=2)if(d==y)break n;n.insertBefore(y,f),c=f;}"option"==l.type&&(n.value="");}f=void 0!==c?c:y.nextSibling,"function"==typeof l.type&&(l.__d=f);}else f&&p.__e==f&&f.parentNode!=n&&(f=w(p));}return a++,u}),l.__e=m,null!=r&&"function"!=typeof l.type)for(a=r.length;a--;)null!=r[a]&&v(r[a]);for(a=_;a--;)null!=g[a]&&D(g[a],g[a]);if(k)for(a=0;a<k.length;a++)j(k[a],k[++a],k[++a]);}function x(n,l,u){if(null==u&&(u=[]),null==n||"boolean"==typeof n)l&&u.push(l(null));else if(Array.isArray(n))for(var i=0;i<n.length;i++)x(n[i],l,u);else u.push(l?l("string"==typeof n||"number"==typeof n?p(null,n,null,null,n):null!=n.__e||null!=n.__c?p(n.type,n.props,n.key,null,n.__v):n):n);return u}function P(n,l,u,i,t){var r;for(r in u)"children"===r||"key"===r||r in l||N(n,r,null,u[r],i);for(r in l)t&&"function"!=typeof l[r]||"children"===r||"key"===r||"value"===r||"checked"===r||u[r]===l[r]||N(n,r,l[r],u[r],i);}function C(n,l,u){"-"===l[0]?n.setProperty(l,u):n[l]="number"==typeof u&&!1===s.test(l)?u+"px":null==u?"":u;}function N(n,l,u,i,t){var r,o,f,e,c;if(t?"className"===l&&(l="class"):"class"===l&&(l="className"),"style"===l)if(r=n.style,"string"==typeof u)r.cssText=u;else {if("string"==typeof i&&(r.cssText="",i=null),i)for(e in i)u&&e in u||C(r,e,"");if(u)for(c in u)i&&u[c]===i[c]||C(r,c,u[c]);}else "o"===l[0]&&"n"===l[1]?(o=l!==(l=l.replace(/Capture$/,"")),f=l.toLowerCase(),l=(f in n?f:l).slice(2),u?(i||n.addEventListener(l,z,o),(n.l||(n.l={}))[l]=u):n.removeEventListener(l,z,o)):"list"!==l&&"tagName"!==l&&"form"!==l&&"type"!==l&&"size"!==l&&!t&&l in n?n[l]=null==u?"":u:"function"!=typeof u&&"dangerouslySetInnerHTML"!==l&&(l!==(l=l.replace(/^xlink:?/,""))?null==u||!1===u?n.removeAttributeNS("http://www.w3.org/1999/xlink",l.toLowerCase()):n.setAttributeNS("http://www.w3.org/1999/xlink",l.toLowerCase(),u):null==u||!1===u&&!/^ar/.test(l)?n.removeAttribute(l):n.setAttribute(l,u));}function z(l){this.l[l.type](n.event?n.event(l):l);}function A(l,u,i,t,r,o,f,e,c){var s,v,h,p,y,w,k,g,_,x,P=u.type;if(void 0!==u.constructor)return null;(s=n.__b)&&s(u);try{n:if("function"==typeof P){if(g=u.props,_=(s=P.contextType)&&t[s.__c],x=s?_?_.props.value:s.__:t,i.__c?k=(v=u.__c=i.__c).__=v.__E:("prototype"in P&&P.prototype.render?u.__c=v=new P(g,x):(u.__c=v=new m(g,x),v.constructor=P,v.render=E),_&&_.sub(v),v.props=g,v.state||(v.state={}),v.context=x,v.__n=t,h=v.__d=!0,v.__h=[]),null==v.__s&&(v.__s=v.state),null!=P.getDerivedStateFromProps&&(v.__s==v.state&&(v.__s=a({},v.__s)),a(v.__s,P.getDerivedStateFromProps(g,v.__s))),p=v.props,y=v.state,h)null==P.getDerivedStateFromProps&&null!=v.componentWillMount&&v.componentWillMount(),null!=v.componentDidMount&&v.__h.push(v.componentDidMount);else {if(null==P.getDerivedStateFromProps&&g!==p&&null!=v.componentWillReceiveProps&&v.componentWillReceiveProps(g,x),!v.__e&&null!=v.shouldComponentUpdate&&!1===v.shouldComponentUpdate(g,v.__s,x)||u.__v===i.__v&&!v.__){for(v.props=g,v.state=v.__s,u.__v!==i.__v&&(v.__d=!1),v.__v=u,u.__e=i.__e,u.__k=i.__k,v.__h.length&&f.push(v),s=0;s<u.__k.length;s++)u.__k[s]&&(u.__k[s].__=u);break n}null!=v.componentWillUpdate&&v.componentWillUpdate(g,v.__s,x),null!=v.componentDidUpdate&&v.__h.push(function(){v.componentDidUpdate(p,y,w);});}v.context=x,v.props=g,v.state=v.__s,(s=n.__r)&&s(u),v.__d=!1,v.__v=u,v.__P=l,s=v.render(v.props,v.state,v.context),u.__k=null!=s&&s.type==d&&null==s.key?s.props.children:Array.isArray(s)?s:[s],null!=v.getChildContext&&(t=a(a({},t),v.getChildContext())),h||null==v.getSnapshotBeforeUpdate||(w=v.getSnapshotBeforeUpdate(p,y)),b(l,u,i,t,r,o,f,e,c),v.base=u.__e,v.__h.length&&f.push(v),k&&(v.__E=v.__=null),v.__e=!1;}else null==o&&u.__v===i.__v?(u.__k=i.__k,u.__e=i.__e):u.__e=$(i.__e,u,i,t,r,o,f,c);(s=n.diffed)&&s(u);}catch(l){u.__v=null,n.__e(l,u,i);}return u.__e}function T(l,u){n.__c&&n.__c(u,l),l.some(function(u){try{l=u.__h,u.__h=[],l.some(function(n){n.call(u);});}catch(l){n.__e(l,u.__v);}});}function $(n,l,u,i,t,r,o,f){var s,a,v,h,p,y=u.props,d=l.props;if(t="svg"===l.type||t,null!=r)for(s=0;s<r.length;s++)if(null!=(a=r[s])&&((null===l.type?3===a.nodeType:a.localName===l.type)||n==a)){n=a,r[s]=null;break}if(null==n){if(null===l.type)return document.createTextNode(d);n=t?document.createElementNS("http://www.w3.org/2000/svg",l.type):document.createElement(l.type,d.is&&{is:d.is}),r=null,f=!1;}if(null===l.type)y!==d&&n.data!=d&&(n.data=d);else {if(null!=r&&(r=c.slice.call(n.childNodes)),v=(y=u.props||e).dangerouslySetInnerHTML,h=d.dangerouslySetInnerHTML,!f){if(y===e)for(y={},p=0;p<n.attributes.length;p++)y[n.attributes[p].name]=n.attributes[p].value;(h||v)&&(h&&v&&h.__html==v.__html||(n.innerHTML=h&&h.__html||""));}P(n,d,y,t,f),h?l.__k=[]:(l.__k=l.props.children,b(n,l,u,i,"foreignObject"!==l.type&&t,r,o,e,f)),f||("value"in d&&void 0!==(s=d.value)&&s!==n.value&&N(n,"value",s,y.value,!1),"checked"in d&&void 0!==(s=d.checked)&&s!==n.checked&&N(n,"checked",s,y.checked,!1));}return n}function j(l,u,i){try{"function"==typeof l?l(u):l.current=u;}catch(l){n.__e(l,i);}}function D(l,u,i){var t,r,o;if(n.unmount&&n.unmount(l),(t=l.ref)&&(t.current&&t.current!==l.__e||j(t,null,u)),i||"function"==typeof l.type||(i=null!=(r=l.__e)),l.__e=l.__d=void 0,null!=(t=l.__c)){if(t.componentWillUnmount)try{t.componentWillUnmount();}catch(l){n.__e(l,u);}t.base=t.__P=null;}if(t=l.__k)for(o=0;o<t.length;o++)t[o]&&D(t[o],u,i);null!=r&&v(r);}function E(n,l,u){return this.constructor(n,u)}function H(l,u,i){var t,r,f;n.__&&n.__(l,u),r=(t=i===o)?null:i&&i.__k||u.__k,l=h(d,null,[l]),f=[],A(u,(t?u:i||u).__k=l,r||e,e,void 0!==u.ownerSVGElement,i&&!t?[i]:r?null:c.slice.call(u.childNodes),f,i||e,t),T(f,l);}function M(n){var l={},u={__c:"__cC"+f++,__:n,Consumer:function(n,l){return n.children(l)},Provider:function(n){var i,t=this;return this.getChildContext||(i=[],this.getChildContext=function(){return l[u.__c]=t,l},this.shouldComponentUpdate=function(n){t.props.value!==n.value&&i.some(function(l){l.context=n.value,g(l);});},this.sub=function(n){i.push(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){i.splice(i.indexOf(n),1),l&&l.call(n);};}),n.children}};return u.Consumer.contextType=u,u.Provider.__=u,u}n={__e:function(n,l){for(var u,i;l=l.__;)if((u=l.__c)&&!u.__)try{if(u.constructor&&null!=u.constructor.getDerivedStateFromError&&(i=!0,u.setState(u.constructor.getDerivedStateFromError(n))),null!=u.componentDidCatch&&(i=!0,u.componentDidCatch(n)),i)return g(u.__E=u)}catch(l){n=l;}throw n}},m.prototype.setState=function(n,l){var u;u=this.__s!==this.state?this.__s:this.__s=a({},this.state),"function"==typeof n&&(n=n(u,this.props)),n&&a(u,n),null!=n&&this.__v&&(l&&this.__h.push(l),g(this));},m.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),g(this));},m.prototype.render=d,u=[],i=0,t="function"==typeof Promise?Promise.prototype.then.bind(Prom
57ise.resolve()):setTimeout,o=e,f=0; 58 59 (typeof globalThis !== 'undefined' ? globalThis : window).FullCalendarVDom = { 60 Component: m, 61 createElement: h, 62 render: H, 63 createRef: y, 64 Fragment: d, 65 createContext: createContext, 66 flushToDom: flushToDom 67 }; 68 // HACKS... 69 // TODO: lock version 70 // TODO: link gh issues 71 function flushToDom() { 72 var oldDebounceRendering = n.debounceRendering; // orig 73 var callbackQ = []; 74 function execCallbackSync(callback) { 75 callbackQ.push(callback); 76 } 77 n.debounceRendering = execCallbackSync; 78 H(h(FakeComponent, {}), document.createElement('div')); 79 while (callbackQ.length) { 80 callbackQ.shift()(); 81 } 82 n.debounceRendering = oldDebounceRendering; 83 } 84 var FakeComponent = /** @class */ (function (_super) { 85 __extends(FakeComponent, _super); 86 function FakeComponent() { 87 return _super !== null && _super.apply(this, arguments) || this; 88 } 89 FakeComponent.prototype.render = function () { return h('div', {}); }; 90 FakeComponent.prototype.componentDidMount = function () { this.setState({}); }; 91 return FakeComponent; 92 }(m)); 93 function createContext(defaultValue) { 94 var ContextType = M(defaultValue); 95 var origProvider = ContextType.Provider; 96 ContextType.Provider = function () { 97 var _this = this; 98 var isNew = !this.getChildContext; 99 var children = origProvider.apply(this, arguments); 100 if (isNew) { 101 var subs_1 = []; 102 this.shouldComponentUpdate = function (_props) { 103 if (_this.props.value !== _props.value) { 104 subs_1.some(function (c) { 105 c.context = _props.value; 106 c.forceUpdate(); 107 }); 108 } 109 }; 110 this.sub = function (c) { 111 subs_1.push(c); 112 var old = c.componentWillUnmount; 113 c.componentWillUnmount = function () { 114 subs_1.splice(subs_1.indexOf(c), 1); 115 old && old.call(c); 116 }; 117 }; 118 } 119 return children; 120 }; 121 return ContextType; 122 } 123 124 // no public types yet. when there are, export from: 125 // import {} from './api-type-deps' 126 var EventSourceApi = /** @class */ (function () { 127 function EventSourceApi(context, internalEventSource // rename? 128 ) { 129 this.context = context; 130 this.internalEventSource = internalEventSource; 131 } 132 EventSourceApi.prototype.remove = function () { 133 this.context.dispatch({ 134 type: 'REMOVE_EVENT_SOURCE', 135 sourceId: this.internalEventSource.sourceId 136 }); 137 }; 138 EventSourceApi.prototype.refetch = function () { 139 this.context.dispatch({ 140 type: 'FETCH_EVENT_SOURCES', 141 sourceIds: [this.internalEventSource.sourceId] 142 }); 143 }; 144 Object.defineProperty(EventSourceApi.prototype, "id", { 145 get: function () { 146 return this.internalEventSource.publicId; 147 }, 148 enumerable: false, 149 configurable: true 150 }); 151 Object.defineProperty(EventSourceApi.prototype, "url", { 152 // only relevant to json-feed event sources 153 get: function () { 154 return this.internalEventSource.meta.url; 155 }, 156 enumerable: false, 157 configurable: true 158 }); 159 return EventSourceApi; 160 }()); 161 162 function removeElement(el) { 163 if (el.parentNode) { 164 el.parentNode.removeChild(el); 165 } 166 } 167 // Querying 168 // ---------------------------------------------------------------------------------------------------------------- 169 function elementClosest(el, selector) { 170 if (el.closest) { 171 return el.closest(selector); 172 // really bad fallback for IE 173 // from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest 174 } 175 else { 176 if (!document.documentElement.contains(el)) { 177 return null; 178 } 179 do { 180 if (elementMatches(el, selector)) { 181 return el; 182 } 183 el = (el.parentElement || el.parentNode); 184 } while (el !== null && el.nodeType === 1); 185 return null; 186 } 187 } 188 function elementMatches(el, selector) { 189 var method = el.matches || el.matchesSelector || el.msMatchesSelector; 190 return method.call(el, selector); 191 } 192 // accepts multiple subject els 193 // returns a real array. good for methods like forEach 194 // TODO: accept the document 195 function findElements(container, selector) { 196 var containers = container instanceof HTMLElement ? [container] : container; 197 var allMatches = []; 198 for (var i = 0; i < containers.length; i++) { 199 var matches = containers[i].querySelectorAll(selector); 200 for (var j = 0; j < matches.length; j++) { 201 allMatches.push(matches[j]); 202 } 203 } 204 return allMatches; 205 } 206 // accepts multiple subject els 207 // only queries direct child elements // TODO: rename to findDirectChildren! 208 function findDirectChildren(parent, selector) { 209 var parents = parent instanceof HTMLElement ? [parent] : parent; 210 var allMatches = []; 211 for (var i = 0; i < parents.length; i++) { 212 var childNodes = parents[i].children; // only ever elements 213 for (var j = 0; j < childNodes.length; j++) { 214 var childNode = childNodes[j]; 215 if (!selector || elementMatches(childNode, selector)) { 216 allMatches.push(childNode); 217 } 218 } 219 } 220 return allMatches; 221 } 222 // Style 223 // ---------------------------------------------------------------------------------------------------------------- 224 var PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i; 225 function applyStyle(el, props) { 226 for (var propName in props) { 227 applyStyleProp(el, propName, props[propName]); 228 } 229 } 230 function applyStyleProp(el, name, val) { 231 if (val == null) { 232 el.style[name] = ''; 233 } 234 else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) { 235 el.style[name] = val + 'px'; 236 } 237 else { 238 el.style[name] = val; 239 } 240 } 241 242 // Stops a mouse/touch event from doing it's native browser action 243 function preventDefault(ev) { 244 ev.preventDefault(); 245 } 246 // Event Delegation 247 // ---------------------------------------------------------------------------------------------------------------- 248 function buildDelegationHandler(selector, handler) { 249 return function (ev) {
vendor: 15,049 bytes, lines 250-680
250 var matchedChild = elementClosest(ev.target, selector); 251 if (matchedChild) { 252 handler.call(matchedChild, ev, matchedChild); 253 } 254 }; 255 } 256 function listenBySelector(container, eventType, selector, handler) { 257 var attachedHandler = buildDelegationHandler(selector, handler); 258 container.addEventListener(eventType, attachedHandler); 259 return function () { 260 container.removeEventListener(eventType, attachedHandler); 261 }; 262 } 263 function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) { 264 var currentMatchedChild; 265 return listenBySelector(container, 'mouseover', selector, function (ev, matchedChild) { 266 if (matchedChild !== currentMatchedChild) { 267 currentMatchedChild = matchedChild; 268 onMouseEnter(ev, matchedChild); 269 var realOnMouseLeave_1 = function (ev) { 270 currentMatchedChild = null; 271 onMouseLeave(ev, matchedChild); 272 matchedChild.removeEventListener('mouseleave', realOnMouseLeave_1); 273 }; 274 // listen to the next mouseleave, and then unattach 275 matchedChild.addEventListener('mouseleave', realOnMouseLeave_1); 276 } 277 }); 278 } 279 // Animation 280 // ---------------------------------------------------------------------------------------------------------------- 281 var transitionEventNames = [ 282 'webkitTransitionEnd', 283 'otransitionend', 284 'oTransitionEnd', 285 'msTransitionEnd', 286 'transitionend' 287 ]; 288 // triggered only when the next single subsequent transition finishes 289 function whenTransitionDone(el, callback) { 290 var realCallback = function (ev) { 291 callback(ev); 292 transitionEventNames.forEach(function (eventName) { 293 el.removeEventListener(eventName, realCallback); 294 }); 295 }; 296 transitionEventNames.forEach(function (eventName) { 297 el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes 298 }); 299 } 300 301 var guidNumber = 0; 302 function guid() { 303 return String(guidNumber++); 304 } 305 /* FullCalendar-specific DOM Utilities 306 ----------------------------------------------------------------------------------------------------------------------*/ 307 // Make the mouse cursor express that an event is not allowed in the current area 308 function disableCursor() { 309 document.body.classList.add('fc-not-allowed'); 310 } 311 // Returns the mouse cursor to its original look 312 function enableCursor() { 313 document.body.classList.remove('fc-not-allowed'); 314 } 315 /* Selection 316 ----------------------------------------------------------------------------------------------------------------------*/ 317 function preventSelection(el) { 318 el.classList.add('fc-unselectable'); 319 el.addEventListener('selectstart', preventDefault); 320 } 321 function allowSelection(el) { 322 el.classList.remove('fc-unselectable'); 323 el.removeEventListener('selectstart', preventDefault); 324 } 325 /* Context Menu 326 ----------------------------------------------------------------------------------------------------------------------*/ 327 function preventContextMenu(el) { 328 el.addEventListener('contextmenu', preventDefault); 329 } 330 function allowContextMenu(el) { 331 el.removeEventListener('contextmenu', preventDefault); 332 } 333 function parseFieldSpecs(input) { 334 var specs = []; 335 var tokens = []; 336 var i; 337 var token; 338 if (typeof input === 'string') { 339 tokens = input.split(/\s*,\s*/); 340 } 341 else if (typeof input === 'function') { 342 tokens = [input]; 343 } 344 else if (Array.isArray(input)) { 345 tokens = input; 346 } 347 for (i = 0; i < tokens.length; i++) { 348 token = tokens[i]; 349 if (typeof token === 'string') { 350 specs.push(token.charAt(0) === '-' ? 351 { field: token.substring(1), order: -1 } : 352 { field: token, order: 1 }); 353 } 354 else if (typeof token === 'function') { 355 specs.push({ func: token }); 356 } 357 } 358 return specs; 359 } 360 function compareByFieldSpecs(obj0, obj1, fieldSpecs) { 361 var i; 362 var cmp; 363 for (i = 0; i < fieldSpecs.length; i++) { 364 cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]); 365 if (cmp) { 366 return cmp; 367 } 368 } 369 return 0; 370 } 371 function compareByFieldSpec(obj0, obj1, fieldSpec) { 372 if (fieldSpec.func) { 373 return fieldSpec.func(obj0, obj1); 374 } 375 return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field]) 376 * (fieldSpec.order || 1); 377 } 378 function flexibleCompare(a, b) { 379 if (!a && !b) { 380 return 0; 381 } 382 if (b == null) { 383 return -1; 384 } 385 if (a == null) { 386 return 1; 387 } 388 if (typeof a === 'string' || typeof b === 'string') { 389 return String(a).localeCompare(String(b)); 390 } 391 return a - b; 392 } 393 /* String Utilities 394 ----------------------------------------------------------------------------------------------------------------------*/ 395 function padStart(val, len) { 396 var s = String(val); 397 return '000'.substr(0, len - s.length) + s; 398 } 399 /* Number Utilities 400 ----------------------------------------------------------------------------------------------------------------------*/ 401 function compareNumbers(a, b) { 402 return a - b; 403 } 404 function isInt(n) { 405 return n % 1 === 0; 406 } 407 /* FC-specific DOM dimension stuff 408 ----------------------------------------------------------------------------------------------------------------------*/ 409 function computeSmallestCellWidth(cellEl) { 410 var allWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-frame'); 411 var contentWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-cushion'); 412 if (!allWidthEl) { 413 throw new Error('needs fc-scrollgrid-shrink-frame className'); // TODO: use const 414 } 415 if (!contentWidthEl) { 416 throw new Error('needs fc-scrollgrid-shrink-cushion className'); 417 } 418 return cellEl.getBoundingClientRect().width - allWidthEl.getBoundingClientRect().width + // the cell padding+border 419 contentWidthEl.getBoundingClientRect().width; 420 } 421 422 var DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; 423 // Adding 424 function addWeeks(m, n) { 425 var a = dateToUtcArray(m); 426 a[2] += n * 7; 427 return arrayToUtcDate(a); 428 } 429 function addDays(m, n) { 430 var a = dateToUtcArray(m); 431 a[2] += n; 432 return arrayToUtcDate(a); 433 } 434 function addMs(m, n) { 435 var a = dateToUtcArray(m); 436 a[6] += n; 437 return arrayToUtcDate(a); 438 } 439 // Diffing (all return floats) 440 // TODO: why not use ranges? 441 function diffWeeks(m0, m1) { 442 return diffDays(m0, m1) / 7; 443 } 444 function diffDays(m0, m1) { 445 return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24); 446 } 447 function diffHours(m0, m1) { 448 return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60); 449 } 450 function diffMinutes(m0, m1) { 451 return (m1.valueOf() - m0.valueOf()) / (1000 * 60); 452 } 453 function diffSeconds(m0, m1) { 454 return (m1.valueOf() - m0.valueOf()) / 1000; 455 } 456 function diffDayAndTime(m0, m1) { 457 var m0day = startOfDay(m0); 458 var m1day = startOfDay(m1); 459 return { 460 years: 0, 461 months: 0, 462 days: Math.round(diffDays(m0day, m1day)), 463 milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()) 464 }; 465 } 466 // Diffing Whole Units 467 function diffWholeWeeks(m0, m1) { 468 var d = diffWholeDays(m0, m1); 469 if (d !== null && d % 7 === 0) { 470 return d / 7; 471 } 472 return null; 473 } 474 function diffWholeDays(m0, m1) { 475 if (timeAsMs(m0) === timeAsMs(m1)) { 476 return Math.round(diffDays(m0, m1)); 477 } 478 return null; 479 } 480 // Start-Of 481 function startOfDay(m) { 482 return arrayToUtcDate([ 483 m.getUTCFullYear(), 484 m.getUTCMonth(), 485 m.getUTCDate() 486 ]); 487 } 488 function startOfHour(m) { 489 return arrayToUtcDate([ 490 m.getUTCFullYear(), 491 m.getUTCMonth(), 492 m.getUTCDate(), 493 m.getUTCHours() 494 ]); 495 } 496 function startOfMinute(m) { 497 return arrayToUtcDate([ 498 m.getUTCFullYear(), 499 m.getUTCMonth(), 500 m.getUTCDate(), 501 m.getUTCHours(), 502 m.getUTCMinutes() 503 ]); 504 } 505 function startOfSecond(m) { 506 return arrayToUtcDate([ 507 m.getUTCFullYear(), 508 m.getUTCMonth(), 509 m.getUTCDate(), 510 m.getUTCHours(), 511 m.getUTCMinutes(), 512 m.getUTCSeconds() 513 ]); 514 } 515 // Week Computation 516 function weekOfYear(marker, dow, doy) { 517 var y = marker.getUTCFullYear(); 518 var w = weekOfGivenYear(marker, y, dow, doy); 519 if (w < 1) { 520 return weekOfGivenYear(marker, y - 1, dow, doy); 521 } 522 var nextW = weekOfGivenYear(marker, y + 1, dow, doy); 523 if (nextW >= 1) { 524 return Math.min(w, nextW); 525 } 526 return w; 527 } 528 function weekOfGivenYear(marker, year, dow, doy) { 529 var firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]); 530 var dayStart = startOfDay(marker); 531 var days = Math.round(diffDays(firstWeekStart, dayStart)); 532 return Math.floor(days / 7) + 1; // zero-indexed 533 } 534 // start-of-first-week - start-of-year 535 function firstWeekOffset(year, dow, doy) { 536 // first-week day -- which january is always in the first week (4 for iso, 1 for other) 537 var fwd = 7 + dow - doy; 538 // first-week day local weekday -- which local weekday is fwd 539 var fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7; 540 return -fwdlw + fwd - 1; 541 } 542 // Array Conversion 543 function dateToLocalArray(date) { 544 return [ 545 date.getFullYear(), 546 date.getMonth(), 547 date.getDate(), 548 date.getHours(), 549 date.getMinutes(), 550 date.getSeconds(), 551 date.getMilliseconds() 552 ]; 553 } 554 function arrayToLocalDate(a) { 555 return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month 556 a[3] || 0, a[4] || 0, a[5] || 0); 557 } 558 function dateToUtcArray(date) { 559 return [ 560 date.getUTCFullYear(), 561 date.getUTCMonth(), 562 date.getUTCDate(), 563 date.getUTCHours(), 564 date.getUTCMinutes(), 565 date.getUTCSeconds(), 566 date.getUTCMilliseconds() 567 ]; 568 } 569 function arrayToUtcDate(a) { 570 // according to web standards (and Safari), a month index is required. 571 // massage if only given a year. 572 if (a.length === 1) { 573 a = a.concat([0]); 574 } 575 return new Date(Date.UTC.apply(Date, a)); 576 } 577 // Other Utils 578 function isValidDate(m) { 579 return !isNaN(m.valueOf()); 580 } 581 function timeAsMs(m) { 582 return m.getUTCHours() * 1000 * 60 * 60 + 583 m.getUTCMinutes() * 1000 * 60 + 584 m.getUTCSeconds() * 1000 + 585 m.getUTCMilliseconds(); 586 } 587 588 function createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) { 589 return { 590 instanceId: guid(), 591 defId: defId, 592 range: range, 593 forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo, 594 forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo 595 }; 596 } 597 598 var hasOwnProperty = Object.prototype.hasOwnProperty; 599 // Merges an array of objects into a single object. 600 // The second argument allows for an array of property names who's object values will be merged together. 601 function mergeProps(propObjs, complexPropsMap) { 602 var dest = {}; 603 if (complexPropsMap) { 604 for (var name_1 in complexPropsMap) { 605 var complexObjs = []; 606 // collect the trailing object values, stopping when a non-object is discovered 607 for (var i = propObjs.length - 1; i >= 0; i--) { 608 var val = propObjs[i][name_1]; 609 if (typeof val === 'object' && val) { // non-null object 610 complexObjs.unshift(val); 611 } 612 else if (val !== undefined) { 613 dest[name_1] = val; // if there were no objects, this value will be used 614 break; 615 } 616 } 617 // if the trailing values were objects, use the merged value 618 if (complexObjs.length) { 619 dest[name_1] = mergeProps(complexObjs); 620 } 621 } 622 } 623 // copy values into the destination, going from last to first 624 for (var i = propObjs.length - 1; i >= 0; i--) { 625 var props = propObjs[i]; 626 for (var name_2 in props) { 627 if (!(name_2 in dest)) { // if already assigned by previous props or complex props, don't reassign 628 dest[name_2] = props[name_2]; 629 } 630 } 631 } 632 return dest; 633 } 634 function filterHash(hash, func) { 635 var filtered = {}; 636 for (var key in hash) { 637 if (func(hash[key], key)) { 638 filtered[key] = hash[key]; 639 } 640 } 641 return filtered; 642 } 643 function mapHash(hash, func) { 644 var newHash = {}; 645 for (var key in hash) { 646 newHash[key] = func(hash[key], key); 647 } 648 return newHash; 649 } 650 function arrayToHash(a) { 651 var hash = {}; 652 for (var _i = 0, a_1 = a; _i < a_1.length; _i++) { 653 var item = a_1[_i]; 654 hash[item] = true; 655 } 656 return hash; 657 } 658 function buildHashFromArray(a, func) { 659 var hash = {}; 660 for (var i = 0; i < a.length; i++) { 661 var tuple = func(a[i], i); 662 hash[tuple[0]] = tuple[1]; 663 } 664 return hash; 665 } 666 function hashValuesToArray(obj) { 667 var a = []; 668 for (var key in obj) { 669 a.push(obj[key]); 670 } 671 return a; 672 } 673 function isPropsEqual(obj0, obj1) { 674 if (obj0 === obj1) { 675 return true; 676 } 677 for (var key in obj0) { 678 if (hasOwnProperty.call(obj0, key)) { 679 if (!(key in obj1)) { 680 return false;
681 } 682 } 683 } 684 for (var key in obj1) { 685 if (hasOwnProperty.call(obj1, key)) { 686 if (obj0[key] !== obj1[key]) { 687 return false; 688 } 689 } 690 } 691 return true; 692 } 693 function getUnequalProps(obj0, obj1) { 694 var keys = []; 695 for (var key in obj0) { 696 if (hasOwnProperty.call(obj0, key)) { 697 if (!(key in obj1)) { 698 keys.push(key); 699 } 700 } 701 } 702 for (var key in obj1) { 703 if (hasOwnProperty.call(obj1, key)) { 704 if (obj0[key] !== obj1[key]) { 705 keys.push(key); 706 } 707 } 708 } 709 return keys; 710 } 711 function compareObjs(oldProps, newProps, equalityFuncs) { 712 if (equalityFuncs === void 0) { equalityFuncs = {}; } 713 if (oldProps === newProps) { 714 return true; 715 } 716 for (var key in newProps) { 717 if (key in oldProps && isObjValsEqual(oldProps[key], newProps[key], equalityFuncs[key])) ; 718 else { 719 return false; 720 } 721 } 722 // check for props that were omitted in the new 723 for (var key in oldProps) { 724 if (!(key in newProps)) { 725 return false; 726 } 727 } 728 return true; 729 } 730 /* 731 assumed "true" equality for handler names like "onReceiveSomething" 732 */ 733 function isObjValsEqual(val0, val1, comparator) { 734 if (val0 === val1 || comparator === true) { 735 return true; 736 } 737 if (comparator) { 738 return comparator(val0, val1); 739 } 740 return false; 741 } 742 function collectFromHash(hash, startIndex, endIndex, step) { 743 if (startIndex === void 0) { startIndex = 0; } 744 if (step === void 0) { step = 1; } 745 var res = []; 746 if (endIndex == null) { 747 endIndex = Object.keys(hash).length; 748 } 749 for (var i = startIndex; i < endIndex; i += step) { 750 var val = hash[i]; 751 if (val !== undefined) { // will disregard undefined for sparse arrays 752 res.push(val); 753 } 754 } 755 return res; 756 } 757 758 function parseRecurring(refined, defaultAllDay, dateEnv, recurringTypes) { 759 for (var i = 0; i < recurringTypes.length; i++) { 760 var parsed = recurringTypes[i].parse(refined, dateEnv); 761 if (parsed) { 762 var allDay = refined.allDay; 763 if (allDay == null) { 764 allDay = defaultAllDay; 765 if (allDay == null) { 766 allDay = parsed.allDayGuess; 767 if (allDay == null) { 768 allDay = false; 769 } 770 } 771 } 772 return { 773 allDay: allDay, 774 duration: parsed.duration, 775 typeData: parsed.typeData, 776 typeId: i 777 }; 778 } 779 } 780 return null; 781 } 782 function expandRecurring(eventStore, framingRange, context) { 783 var dateEnv = context.dateEnv, pluginHooks = context.pluginHooks, options = context.options; 784 var defs = eventStore.defs, instances = eventStore.instances; 785 // remove existing recurring instances 786 // TODO: bad. always expand events as a second step 787 instances = filterHash(instances, function (instance) { 788 return !defs[instance.defId].recurringDef; 789 }); 790 for (var defId in defs) { 791 var def = defs[defId]; 792 if (def.recurringDef) { 793 var duration = def.recurringDef.duration; 794 if (!duration) { 795 duration = def.allDay ? 796 options.defaultAllDayEventDuration : 797 options.defaultTimedEventDuration; 798 } 799 var starts = expandRecurringRanges(def, duration, framingRange, dateEnv, pluginHooks.recurringTypes); 800 for (var _i = 0, starts_1 = starts; _i < starts_1.length; _i++) { 801 var start = starts_1[_i]; 802 var instance = createEventInstance(defId, { 803 start: start, 804 end: dateEnv.add(start, duration) 805 }); 806 instances[instance.instanceId] = instance; 807 } 808 } 809 } 810 return { defs: defs, instances: instances }; 811 } 812 /* 813 Event MUST have a recurringDef 814 */ 815 function expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) { 816 var typeDef = recurringTypes[eventDef.recurringDef.typeId]; 817 var markers = typeDef.expand(eventDef.recurringDef.typeData, { 818 start: dateEnv.subtract(framingRange.start, duration), 819 end: framingRange.end 820 }, dateEnv); 821 // the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to 822 if (eventDef.allDay) { 823 markers = markers.map(startOfDay); 824 } 825 return markers; 826 } 827 828 var INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];
829 var PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/; 830 // Parsing and Creation 831 function createDuration(input, unit) { 832 var _a; 833 if (typeof input === 'string') { 834 return parseString(input); 835 } 836 else if (typeof input === 'object' && input) { // non-null object 837 return parseObject(input); 838 } 839 else if (typeof input === 'number') { 840 return parseObject((_a = {}, _a[unit || 'milliseconds'] = input, _a)); 841 } 842 else { 843 return null; 844 } 845 } 846 function parseString(s) { 847 var m = PARSE_RE.exec(s); 848 if (m) { 849 var sign = m[1] ? -1 : 1; 850 return { 851 years: 0, 852 months: 0, 853 days: sign * (m[2] ? parseInt(m[2], 10) : 0), 854 milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours 855 (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes 856 (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds 857 (m[6] ? parseInt(m[6], 10) : 0) // ms 858 ) 859 }; 860 } 861 return null; 862 } 863 function parseObject(obj) { 864 var duration = { 865 years: obj.years || obj.year || 0, 866 months: obj.months || obj.month || 0, 867 days: obj.days || obj.day || 0, 868 milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours 869 (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes 870 (obj.seconds || obj.second || 0) * 1000 + // seconds 871 (obj.milliseconds || obj.millisecond || obj.ms || 0) // ms 872 }; 873 var weeks = obj.weeks || obj.week; 874 if (weeks) { 875 duration.days += weeks * 7; 876 duration.specifiedWeeks = true; 877 } 878 return duration; 879 } 880 // Equality 881 function durationsEqual(d0, d1) { 882 return d0.years === d1.years && 883 d0.months === d1.months && 884 d0.days === d1.days && 885 d0.milliseconds === d1.milliseconds; 886 } 887 function asCleanDays(dur) { 888 if (!dur.years && !dur.months && !dur.milliseconds) { 889 return dur.days; 890 } 891 return 0; 892 } 893 // Simple Math 894 function addDurations(d0, d1) { 895 return { 896 years: d0.years + d1.years, 897 months: d0.months + d1.months, 898 days: d0.days + d1.days, 899 milliseconds: d0.milliseconds + d1.milliseconds 900 }; 901 } 902 function subtractDurations(d1, d0) { 903 return { 904 years: d1.years - d0.years, 905 months: d1.months - d0.months, 906 days: d1.days - d0.days, 907 milliseconds: d1.milliseconds - d0.milliseconds 908 }; 909 } 910 function multiplyDuration(d, n) { 911 return { 912 years: d.years * n, 913 months: d.months * n, 914 days: d.days * n, 915 milliseconds: d.milliseconds * n 916 }; 917 } 918 // Conversions 919 // "Rough" because they are based on average-case Gregorian months/years 920 function asRoughYears(dur) { 921 return asRoughDays(dur) / 365; 922 } 923 function asRoughMonths(dur) { 924 return asRoughDays(dur) / 30; 925 } 926 function asRoughDays(dur) { 927 return asRoughMs(dur) / 864e5; 928 } 929 function asRoughMinutes(dur) { 930 return asRoughMs(dur) / (1000 * 60); 931 } 932 function asRoughSeconds(dur) { 933 return asRoughMs(dur) / 1000; 934 } 935 function asRoughMs(dur) { 936 return dur.years * (365 * 864e5) + 937 dur.months * (30 * 864e5) + 938 dur.days * 864e5 + 939 dur.milliseconds; 940 } 941 // Advanced Math 942 function wholeDivideDurations(numerator, denominator) { 943 var res = null; 944 for (var i = 0; i < INTERNAL_UNITS.length; i++) { 945 var unit = INTERNAL_UNITS[i]; 946 if (denominator[unit]) { 947 var localRes = numerator[unit] / denominator[unit]; 948 if (!isInt(localRes) || (res !== null && res !== localRes)) { 949 return null; 950 } 951 res = localRes; 952 } 953 else if (numerator[unit]) { 954 // needs to divide by something but can't! 955 return null; 956 } 957 } 958 return res; 959 } 960 function greatestDurationDenominator(dur) { 961 var ms = dur.milliseconds; 962 if (ms) { 963 if (ms % 1000 !== 0) { 964 return { unit: 'millisecond', value: ms }; 965 } 966 if (ms % (1000 * 60) !== 0) { 967 return { unit: 'second', value: ms / 1000 }; 968 } 969 if (ms % (1000 * 60 * 60) !== 0) { 970 return { unit: 'minute', value: ms / (1000 * 60) }; 971 } 972 if (ms) { 973 return { unit: 'hour', value: ms / (1000 * 60 * 60) }; 974 } 975 } 976 if (dur.days) { 977 if (dur.specifiedWeeks && dur.days % 7 === 0) { 978 return { unit: 'week', value: dur.days / 7 }; 979 } 980 return { unit: 'day', value: dur.days }; 981 } 982 if (dur.months) { 983 return { unit: 'month', value: dur.months }; 984 } 985 if (dur.years) { 986 return { unit: 'year', value: dur.years }; 987 } 988 return { unit: 'millisecond', value: 0 }; 989 } 990 991 // timeZoneOffset is in minutes 992 function buildIsoString(marker, timeZoneOffset, stripZeroTime) { 993 if (stripZeroTime === void 0) { stripZeroTime = false; } 994 var s = marker.toISOString(); 995 s = s.replace('.000', ''); 996 if (stripZeroTime) { 997 s = s.replace('T00:00:00Z', ''); 998 } 999 if (s.length > 10) { // time part wasn't stripped, can add timezone info 1000 if (timeZoneOffset == null) { 1001 s = s.replace('Z', ''); 1002 } 1003 else if (timeZoneOffset !== 0) { 1004 s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true)); 1005 } 1006 // otherwise, its UTC-0 and we want to keep the Z 1007 } 1008 return s; 1009 } 1010 // formats the date, but with no time part 1011 // TODO: somehow merge with buildIsoString and stripZeroTime 1012 // TODO: rename. omit "string" 1013 function formatDayString(marker) { 1014 return marker.toISOString().replace(/T.*$/, ''); 1015 } 1016 // TODO: use Date::toISOString and use everything after the T? 1017 function formatIsoTimeString(marker) { 1018 return padStart(marker.getUTCHours(), 2) + ':' + 1019 padStart(marker.getUTCMinutes(), 2) + ':' + 1020 padStart(marker.getUTCSeconds(), 2); 1021 } 1022 function formatTimeZoneOffset(minutes, doIso) { 1023 if (doIso === void 0) { doIso = false; } 1024 var sign = minutes < 0 ? '-' : '+'; 1025 var abs = Math.abs(minutes); 1026 var hours = Math.floor(abs / 60); 1027 var mins = Math.round(abs % 60); 1028 if (doIso) { 1029 return sign + padStart(hours, 2) + ':' + padStart(mins, 2); 1030 } 1031 else { 1032 return 'GMT' + sign + hours + (mins ? ':' + padStart(mins, 2) : ''); 1033 } 1034 } 1035 1036 // TODO: new util arrayify? 1037 function removeExact(array, exactVal) { 1038 var removeCnt = 0; 1039 var i = 0; 1040 while (i < array.length) { 1041 if (array[i] === exactVal) { 1042 array.splice(i, 1); 1043 removeCnt++; 1044 } 1045 else { 1046 i++; 1047 } 1048 } 1049 return removeCnt; 1050 } 1051 function isArraysEqual(a0, a1, equalityFunc) { 1052 if (a0 === a1) { 1053 return true; 1054 } 1055 var len = a0.length; 1056 var i; 1057 if (len !== a1.length) { // not array? or not same length? 1058 return false;
1059 } 1060 for (i = 0; i < len; i++) { 1061 if (!(equalityFunc ? equalityFunc(a0[i], a1[i]) : a0[i] === a1[i])) { 1062 return false; 1063 } 1064 } 1065 return true; 1066 } 1067 1068 function memoize(workerFunc, resEquality, teardownFunc) { 1069 var currentArgs; 1070 var currentRes; 1071 return function () { 1072 var newArgs = []; 1073 for (var _i = 0; _i < arguments.length; _i++) { 1074 newArgs[_i] = arguments[_i]; 1075 } 1076 if (!currentArgs) { 1077 currentRes = workerFunc.apply(this, newArgs); 1078 } 1079 else if (!isArraysEqual(currentArgs, newArgs)) { 1080 if (teardownFunc) { 1081 teardownFunc(currentRes); 1082 } 1083 var res = workerFunc.apply(this, newArgs); 1084 if (!resEquality || !resEquality(res, currentRes)) { 1085 currentRes = res; 1086 } 1087 } 1088 currentArgs = newArgs; 1089 return currentRes; 1090 }; 1091 } 1092 function memoizeObjArg(workerFunc, resEquality, teardownFunc) { 1093 var currentArg; 1094 var currentRes; 1095 return function (newArg) { 1096 if (!currentArg) { 1097 currentRes = workerFunc.call(this, newArg); 1098 } 1099 else if (!isPropsEqual(currentArg, newArg)) { 1100 if (teardownFunc) { 1101 teardownFunc(currentRes); 1102 } 1103 var res = workerFunc.call(this, newArg); 1104 if (!resEquality || !resEquality(res, currentRes)) { 1105 currentRes = res; 1106 } 1107 } 1108 currentArg = newArg; 1109 return currentRes; 1110 }; 1111 } 1112 function memoizeArraylike(// used at all? 1113 workerFunc, resEquality, teardownFunc) { 1114 var currentArgSets = []; 1115 var currentResults = []; 1116 return function (newArgSets) { 1117 var currentLen = currentArgSets.length; 1118 var newLen = newArgSets.length; 1119 var i = 0; 1120 for (; i < currentLen; i++) { 1121 if (!newArgSets[i]) { // one of the old sets no longer exists 1122 if (teardownFunc) { 1123 teardownFunc(currentResults[i]); 1124 } 1125 } 1126 else if (!isArraysEqual(currentArgSets[i], newArgSets[i])) { 1127 if (teardownFunc) { 1128 teardownFunc(currentResults[i]); 1129 } 1130 var res = workerFunc.apply(this, newArgSets[i]); 1131 if (!resEquality || !resEquality(res, currentResults[i])) { 1132 currentResults[i] = res; 1133 } 1134 } 1135 } 1136 for (; i < newLen; i++) { 1137 currentResults[i] = workerFunc.apply(this, newArgSets[i]); 1138 } 1139 currentArgSets = newArgSets; 1140 currentResults.splice(newLen); // remove excess 1141 return currentResults; 1142 }; 1143 } 1144 function memoizeHashlike(// used? 1145 workerFunc, resEquality, teardownFunc // TODO: change arg order 1146 ) { 1147 var currentArgHash = {}; 1148 var currentResHash = {}; 1149 return function (newArgHash) { 1150 var newResHash = {}; 1151 for (var key in newArgHash) { 1152 if (!currentResHash[key]) { 1153 newResHash[key] = workerFunc.apply(this, newArgHash[key]); 1154 } 1155 else if (!isArraysEqual(currentArgHash[key], newArgHash[key])) { 1156 if (teardownFunc) { 1157 teardownFunc(currentResHash[key]); 1158 } 1159 var res = workerFunc.apply(this, newArgHash[key]); 1160 newResHash[key] = (resEquality && resEquality(res, currentResHash[key])) 1161 ? currentResHash[key] 1162 : res; 1163 } 1164 else { 1165 newResHash[key] = currentResHash[key]; 1166 } 1167 } 1168 currentArgHash = newArgHash; 1169 currentResHash = newResHash; 1170 return newResHash; 1171 }; 1172 } 1173 1174 var EXTENDED_SETTINGS_AND_SEVERITIES = { 1175 week: 3, 1176 separator: 0, 1177 omitZeroMinute: 0, 1178 meridiem: 0, 1179 omitCommas: 0 1180 }; 1181 var STANDARD_DATE_PROP_SEVERITIES = { 1182 timeZoneName: 7, 1183 era: 6, 1184 year: 5, 1185 month: 4, 1186 day: 2, 1187 weekday: 2, 1188 hour: 1, 1189 minute: 1, 1190 second: 1 1191 }; 1192 var MERIDIEM_RE = /\s*([ap])\.?m\.?/i;
1192 // eats up leading spaces too 1193 var COMMA_RE = /,/g; // we need re for globalness 1194 var MULTI_SPACE_RE = /\s+/g; 1195 var LTR_RE = /\u200e/g; // control character 1196 var UTC_RE = /UTC|GMT/; 1197 var NativeFormatter = /** @class */ (function () { 1198 function NativeFormatter(formatSettings) { 1199 var standardDateProps = {}; 1200 var extendedSettings = {}; 1201 var severity = 0; 1202 for (var name_1 in formatSettings) { 1203 if (name_1 in EXTENDED_SETTINGS_AND_SEVERITIES) { 1204 extendedSettings[name_1] = formatSettings[name_1]; 1205 severity = Math.max(EXTENDED_SETTINGS_AND_SEVERITIES[name_1], severity); 1206 } 1207 else { 1208 standardDateProps[name_1] = formatSettings[name_1]; 1209 if (name_1 in STANDARD_DATE_PROP_SEVERITIES) { // TODO: what about hour12? no severity 1210 severity = Math.max(STANDARD_DATE_PROP_SEVERITIES[name_1], severity); 1211 } 1212 } 1213 } 1214 this.standardDateProps = standardDateProps; 1215 this.extendedSettings = extendedSettings; 1216 this.severity = severity; 1217 this.buildFormattingFunc = memoize(buildFormattingFunc); 1218 } 1219 NativeFormatter.prototype.format = function (date, context) { 1220 return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date); 1221 }; 1222 NativeFormatter.prototype.formatRange = function (start, end, context, betterDefaultSeparator) { 1223 var _a = this, standardDateProps = _a.standardDateProps, extendedSettings = _a.extendedSettings; 1224 var diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem); 1225 if (!diffSeverity) { 1226 return this.format(start, context); 1227 } 1228 var biggestUnitForPartial = diffSeverity; 1229 if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time 1230 (standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') && 1231 (standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') && 1232 (standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) { 1233 biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time 1234 } 1235 var full0 = this.format(start, context); 1236 var full1 = this.format(end, context); 1237 if (full0 === full1) { 1238 return full0; 1239 } 1240 var partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForPartial); 1241 var partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context); 1242 var partial0 = partialFormattingFunc(start); 1243 var partial1 = partialFormattingFunc(end); 1244 var insertion = findCommonInsertion(full0, partial0, full1, partial1); 1245 var separator = extendedSettings.separator || betterDefaultSeparator || context.defaultSeparator || ''; 1246 if (insertion) { 1247 return insertion.before + partial0 + separator + partial1 + insertion.after; 1248 } 1249 return full0 + separator + full1; 1250 }; 1251 NativeFormatter.prototype.getLargestUnit = function () { 1252 switch (this.severity) { 1253 case 7: 1254 case 6: 1255 case 5: 1256 return 'year'; 1257 case 4: 1258 return 'month'; 1259 case 3: 1260 return 'week'; 1261 case 2: 1262 return 'day'; 1263 default: 1264 return 'time'; // really? 1265 } 1266 }; 1267 return NativeFormatter; 1268 }()); 1269 function buildFormattingFunc(standardDateProps, extendedSettings, context) { 1270 var standardDatePropCnt = Object.keys(standardDateProps).length; 1271 if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') { 1272 return function (date) { 1273 return formatTimeZoneOffset(date.timeZoneOffset); 1274 }; 1275 } 1276 if (standardDatePropCnt === 0 && extendedSettings.week) { 1277 return function (date) { 1278 return formatWeekNumber(context.computeWeekNumber(date.marker), context.weekText, context.locale, extendedSettings.week); 1279 }; 1280 } 1281 return buildNativeFormattingFunc(standardDateProps, extendedSettings, context); 1282 } 1283 function buildNativeFormattingFunc(standardDateProps, extendedSettings, context) { 1284 standardDateProps = __assign({}, standardDateProps); // copy 1285 extendedSettings = __assign({}, extendedSettings); // copy 1286 sanitizeSettings(standardDateProps, extendedSettings); 1287 standardDateProps.timeZone = 'UTC';
1287 // we leverage the only guaranteed timeZone for our UTC markers 1288 var normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps); 1289 var zeroFormat; // needed? 1290 if (extendedSettings.omitZeroMinute) { 1291 var zeroProps = __assign({}, standardDateProps); 1292 delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings 1293 zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps); 1294 } 1295 return function (date) { 1296 var marker = date.marker; 1297 var format; 1298 if (zeroFormat && !marker.getUTCMinutes()) { 1299 format = zeroFormat; 1300 } 1301 else { 1302 format = normalFormat; 1303 } 1304 var s = format.format(marker); 1305 return postProcess(s, date, standardDateProps, extendedSettings, context); 1306 }; 1307 } 1308 function sanitizeSettings(standardDateProps, extendedSettings) { 1309 // deal with a browser inconsistency where formatting the timezone 1310 // requires that the hour/minute be present. 1311 if (standardDateProps.timeZoneName) { 1312 if (!standardDateProps.hour) { 1313 standardDateProps.hour = '2-digit'; 1314 } 1315 if (!standardDateProps.minute) { 1316 standardDateProps.minute = '2-digit'; 1317 } 1318 } 1319 // only support short timezone names 1320 if (standardDateProps.timeZoneName === 'long') { 1321 standardDateProps.timeZoneName = 'short'; 1322 } 1323 // if requesting to display seconds, MUST display minutes 1324 if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) { 1325 delete extendedSettings.omitZeroMinute; 1326 } 1327 } 1328 function postProcess(s, date, standardDateProps, extendedSettings, context) { 1329 s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes 1330 if (standardDateProps.timeZoneName === 'short') { 1331 s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ? 1332 'UTC' : // important to normalize for IE, which does "GMT" 1333 formatTimeZoneOffset(date.timeZoneOffset)); 1334 } 1335 if (extendedSettings.omitCommas) { 1336 s = s.replace(COMMA_RE, '').trim(); 1337 } 1338 if (extendedSettings.omitZeroMinute) { 1339 s = s.replace(':00', ''); // zeroFormat doesn't always achieve this 1340 } 1341 // ^ do anything that might create adjacent spaces before this point, 1342 // because MERIDIEM_RE likes to eat up loading spaces 1343 if (extendedSettings.meridiem === false) { 1344 s = s.replace(MERIDIEM_RE, '').trim(); 1345 } 1346 else if (extendedSettings.meridiem === 'narrow') { // a/p 1347 s = s.replace(MERIDIEM_RE, function (m0, m1) { 1348 return m1.toLocaleLowerCase(); 1349 }); 1350 } 1351 else if (extendedSettings.meridiem === 'short') { // am/pm 1352 s = s.replace(MERIDIEM_RE, function (m0, m1) { 1353 return m1.toLocaleLowerCase() + 'm'; 1354 }); 1355 } 1356 else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase 1357 s = s.replace(MERIDIEM_RE, function (m0) { 1358 return m0.toLocaleLowerCase(); 1359 }); 1360 } 1361 s = s.replace(MULTI_SPACE_RE, ' '); 1362 s = s.trim(); 1363 return s; 1364 } 1365 function injectTzoStr(s, tzoStr) { 1366 var replaced = false; 1367 s = s.replace(UTC_RE, function () { 1368 replaced = true; 1369 return tzoStr; 1370 }); 1371 // IE11 doesn't include UTC/GMT in the original string, so append to end 1372 if (!replaced) { 1373 s += ' ' + tzoStr; 1374 } 1375 return s; 1376 } 1377 function formatWeekNumber(num, weekText, locale, display) { 1378 var parts = []; 1379 if (display === 'narrow') { 1380 parts.push(weekText); 1381 } 1382 else if (display === 'short') { 1383 parts.push(weekText, ' '); 1384 } 1385 // otherwise, considered 'numeric' 1386 parts.push(locale.simpleNumberFormat.format(num)); 1387 if (locale.options.direction === 'rtl') { // TODO: use control characters instead? 1388 parts.reverse(); 1389 } 1390 return parts.join(''); 1391 } 1392 // Range Formatting Utils 1393 // 0 = exactly the same 1394 // 1 = different by time 1395 // and bigger 1396 function computeMarkerDiffSeverity(d0, d1, ca) { 1397 if (ca.getMarkerYear(d0) !== ca.getMarkerYear(d1)) { 1398 return 5; 1399 } 1400 if (ca.getMarkerMonth(d0) !== ca.getMarkerMonth(d1)) { 1401 return 4; 1402 } 1403 if (ca.getMarkerDay(d0) !== ca.getMarkerDay(d1)) { 1404 return 2; 1405 } 1406 if (timeAsMs(d0) !== timeAsMs(d1)) { 1407 return 1; 1408 } 1409 return 0; 1410 } 1411 function computePartialFormattingOptions(options, biggestUnit) { 1412 var partialOptions = {}; 1413 for (var name_2 in options) { 1414 if (!(name_2 in STANDARD_DATE_PROP_SEVERITIES) || // not a date part prop (like timeZone) 1415 STANDARD_DATE_PROP_SEVERITIES[name_2] <= biggestUnit) { 1416 partialOptions[name_2] = options[name_2]; 1417 } 1418 } 1419 return partialOptions; 1420 } 1421 function findCommonInsertion(full0, partial0, full1, partial1) { 1422 var i0 = 0; 1423 while (i0 < full0.length) { 1424 var found0 = full0.indexOf(partial0, i0); 1425 if (found0 === -1) { 1426 break; 1427 } 1428 var before0 = full0.substr(0, found0); 1429 i0 = found0 + partial0.length; 1430 var after0 = full0.substr(i0); 1431 var i1 = 0; 1432 while (i1 < full1.length) { 1433 var found1 = full1.indexOf(partial1, i1);
1434 if (found1 === -1) { 1435 break; 1436 } 1437 var before1 = full1.substr(0, found1); 1438 i1 = found1 + partial1.length; 1439 var after1 = full1.substr(i1); 1440 if (before0 === before1 && after0 === after1) { 1441 return { 1442 before: before0, 1443 after: after0 1444 }; 1445 } 1446 } 1447 } 1448 return null; 1449 } 1450 1451 function expandZonedMarker(dateInfo, calendarSystem) { 1452 var a = calendarSystem.markerToArray(dateInfo.marker); 1453 return { 1454 marker: dateInfo.marker, 1455 timeZoneOffset: dateInfo.timeZoneOffset, 1456 array: a, 1457 year: a[0], 1458 month: a[1], 1459 day: a[2], 1460 hour: a[3], 1461 minute: a[4], 1462 second: a[5], 1463 millisecond: a[6] 1464 }; 1465 } 1466 1467 function createVerboseFormattingArg(start, end, context, betterDefaultSeparator) { 1468 var startInfo = expandZonedMarker(start, context.calendarSystem); 1469 var endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null; 1470 return { 1471 date: startInfo, 1472 start: startInfo, 1473 end: endInfo, 1474 timeZone: context.timeZone, 1475 localeCodes: context.locale.codes, 1476 defaultSeparator: betterDefaultSeparator || context.defaultSeparator 1477 }; 1478 } 1479 1480 /* 1481 TODO: fix the terminology of "formatter" vs "formatting func" 1482 */ 1483 /* 1484 At the time of instantiation, this object does not know which cmd-formatting system it will use. 1485 It receives this at the time of formatting, as a setting. 1486 */ 1487 var CmdFormatter = /** @class */ (function () { 1488 function CmdFormatter(cmdStr) { 1489 this.cmdStr = cmdStr; 1490 } 1491 CmdFormatter.prototype.format = function (date, context, betterDefaultSeparator) { 1492 return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, betterDefaultSeparator)); 1493 }; 1494 CmdFormatter.prototype.formatRange = function (start, end, context, betterDefaultSeparator) { 1495 return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, betterDefaultSeparator)); 1496 }; 1497 return CmdFormatter; 1498 }()); 1499 1500 var FuncFormatter = /** @class */ (function () { 1501 function FuncFormatter(func) { 1502 this.func = func; 1503 } 1504 FuncFormatter.prototype.format = function (date, context, betterDefaultSeparator) { 1505 return this.func(createVerboseFormattingArg(date, null, context, betterDefaultSeparator)); 1506 }; 1507 FuncFormatter.prototype.formatRange = function (start, end, context, betterDefaultSeparator) { 1508 return this.func(createVerboseFormattingArg(start, end, context, betterDefaultSeparator)); 1509 }; 1510 return FuncFormatter; 1511 }()); 1512 1513 function createFormatter(input) { 1514 if (typeof input === 'object' && input) { // non-null object 1515 return new NativeFormatter(input); 1516 } 1517 else if (typeof input === 'string') { 1518 return new CmdFormatter(input); 1519 } 1520 else if (typeof input === 'function') { 1521 return new FuncFormatter(input); 1522 } 1523 } 1524 1525 // base options 1526 // ------------ 1527 var BASE_OPTION_REFINERS = { 1528 navLinkDayClick: identity, 1529 navLinkWeekClick: identity, 1530 duration: createDuration, 1531 bootstrapFontAwesome: identity, 1532 buttonIcons: identity, 1533 customButtons: identity, 1534 defaultAllDayEventDuration: createDuration, 1535 defaultTimedEventDuration: createDuration, 1536 nextDayThreshold: createDuration, 1537 scrollTime: createDuration, 1538 slotMinTime: createDuration, 1539 slotMaxTime: createDuration, 1540 dayPopoverFormat: createFormatter, 1541 slotDuration: createDuration, 1542 snapDuration: createDuration, 1543 headerToolbar: identity, 1544 footerToolbar: identity, 1545 defaultRangeSeparator: String, 1546 titleRangeSeparator: String, 1547 forceEventDuration: Boolean, 1548 dayHeaders: Boolean, 1549 dayHeaderFormat: createFormatter, 1550 dayHeaderClassNames: identity, 1551 dayHeaderContent: identity, 1552 dayHeaderDidMount: identity, 1553 dayHeaderWillUnmount: identity, 1554 dayCellClassNames: identity, 1555 dayCellContent: identity, 1556 dayCellDidMount: identity, 1557 dayCellWillUnmount: identity, 1558 initialView: String, 1559 aspectRatio: Number, 1560 weekends: Boolean, 1561 weekNumberCalculation: identity, 1562 weekNumbers: Boolean, 1563 weekNumberClassNames: identity, 1564 weekNumberContent: identity, 1565 weekNumberDidMount: identity, 1566 weekNumberWillUnmount: identity, 1567 editable: Boolean, 1568 viewClassNames: identity, 1569 viewDidMount: identity, 1570 viewWillUnmount: identity, 1571 nowIndicator: Boolean, 1572 nowIndicatorClassNames: identity, 1573 nowIndicatorContent: identity, 1574 nowIndicatorDidMount: identity, 1575 nowIndicatorWillUnmount: identity, 1576 showNonCurrentDates: Boolean, 1577 lazyFetching: Boolean, 1578 startParam: String, 1579 endParam: String, 1580 timeZoneParam: String, 1581 timeZone: String, 1582 locales: identity, 1583 locale: identity, 1584 themeSystem: String, 1585 dragRevertDuration: Number, 1586 dragScroll: Boolean, 1587 allDayMaintainDuration: Boolean, 1588 unselectAuto: Boolean, 1589 dropAccept: identity, 1590 eventOrder: parseFieldSpecs, 1591 handleWindowResize: Boolean, 1592 windowResizeDelay: Number, 1593 longPressDelay: Number, 1594 eventDragMinDistance: Number, 1595 expandRows: Boolean, 1596 height: identity, 1597 contentHeight: identity, 1598 direction: String, 1599 weekNumberFormat: createFormatter, 1600 eventResizableFromStart: Boolean, 1601 displayEventTime: Boolean, 1602 displayEventEnd: Boolean, 1603 weekText: String, 1604 progressiveEventRendering: Boolean, 1605 businessHours: identity, 1606 initialDate: identity, 1607 now: identity, 1608 eventDataTransform: identity, 1609 stickyHeaderDates: identity, 1610 stickyFooterScrollbar: identity, 1611 viewHeight: identity, 1612 defaultAllDay: Boolean, 1613 eventSourceFailure: identity, 1614 eventSourceSuccess: identity, 1615 eventDisplay: String, 1616 eventStartEditable: Boolean, 1617 eventDurationEditable: Boolean, 1618 eventOverlap: identity, 1619 eventConstraint: identity, 1620 eventAllow: identity,
1621 eventBackgroundColor: String, 1622 eventBorderColor: String, 1623 eventTextColor: String, 1624 eventColor: String, 1625 eventClassNames: identity, 1626 eventContent: identity, 1627 eventDidMount: identity, 1628 eventWillUnmount: identity, 1629 selectConstraint: identity, 1630 selectOverlap: identity, 1631 selectAllow: identity, 1632 droppable: Boolean, 1633 unselectCancel: String, 1634 slotLabelFormat: identity, 1635 slotLaneClassNames: identity, 1636 slotLaneContent: identity, 1637 slotLaneDidMount: identity, 1638 slotLaneWillUnmount: identity, 1639 slotLabelClassNames: identity, 1640 slotLabelContent: identity, 1641 slotLabelDidMount: identity, 1642 slotLabelWillUnmount: identity, 1643 dayMaxEvents: identity, 1644 dayMaxEventRows: identity, 1645 dayMinWidth: Number, 1646 slotLabelInterval: createDuration, 1647 allDayText: String, 1648 allDayClassNames: identity, 1649 allDayContent: identity, 1650 allDayDidMount: identity, 1651 allDayWillUnmount: identity, 1652 slotMinWidth: Number, 1653 navLinks: Boolean, 1654 eventTimeFormat: createFormatter, 1655 rerenderDelay: Number, 1656 moreLinkText: identity, 1657 selectMinDistance: Number, 1658 selectable: Boolean, 1659 selectLongPressDelay: Number, 1660 eventLongPressDelay: Number, 1661 selectMirror: Boolean, 1662 eventMinHeight: Number, 1663 slotEventOverlap: Boolean, 1664 plugins: identity, 1665 firstDay: Number, 1666 dayCount: Number, 1667 dateAlignment: String, 1668 dateIncrement: createDuration, 1669 hiddenDays: identity, 1670 monthMode: Boolean, 1671 fixedWeekCount: Boolean, 1672 validRange: identity, 1673 visibleRange: identity, 1674 titleFormat: identity, 1675 // only used by list-view, but languages define the value, so we need it in base options 1676 noEventsText: String 1677 }; 1678 // do NOT give a type here. need `typeof BASE_OPTION_DEFAULTS` to give real results. 1679 // raw values. 1680 var BASE_OPTION_DEFAULTS = { 1681 eventDisplay: 'auto', 1682 defaultRangeSeparator: ' - ', 1683 titleRangeSeparator: ' \u2013 ', 1684 defaultTimedEventDuration: '01:00:00', 1685 defaultAllDayEventDuration: { day: 1 }, 1686 forceEventDuration: false, 1687 nextDayThreshold: '00:00:00', 1688 dayHeaders: true, 1689 initialView: '', 1690 aspectRatio: 1.35, 1691 headerToolbar: { 1692 start: 'title', 1693 center: '', 1694 end: 'today prev,next' 1695 }, 1696 weekends: true, 1697 weekNumbers: false, 1698 weekNumberCalculation: 'local', 1699 editable: false, 1700 nowIndicator: false, 1701 scrollTime: '06:00:00', 1702 slotMinTime: '00:00:00', 1703 slotMaxTime: '24:00:00', 1704 showNonCurrentDates: true, 1705 lazyFetching: true, 1706 startParam: 'start', 1707 endParam: 'end', 1708 timeZoneParam: 'timeZone', 1709 timeZone: 'local', 1710 locales: [], 1711 locale: '', 1712 themeSystem: 'standard', 1713 dragRevertDuration: 500, 1714 dragScroll: true, 1715 allDayMaintainDuration: false, 1716 unselectAuto: true, 1717 dropAccept: '*', 1718 eventOrder: 'start,-duration,allDay,title', 1719 dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' }, 1720 handleWindowResize: true, 1721 windowResizeDelay: 100, 1722 longPressDelay: 1000, 1723 eventDragMinDistance: 5, 1724 expandRows: false, 1725 navLinks: false, 1726 selectable: false 1727 }; 1728 // calendar listeners 1729 // ------------------ 1730 var CALENDAR_LISTENER_REFINERS = { 1731 datesSet: identity, 1732 eventsSet: identity, 1733 eventAdd: identity, 1734 eventChange: identity, 1735 eventRemove: identity, 1736 windowResize: identity, 1737 eventClick: identity, 1738 eventMouseEnter: identity, 1739 eventMouseLeave: identity, 1740 select: identity, 1741 unselect: identity, 1742 loading: identity, 1743 // internal 1744 _unmount: identity, 1745 _beforeprint: identity, 1746 _afterprint: identity, 1747 _noEventDrop: identity, 1748 _noEventResize: identity, 1749 _resize: identity, 1750 _scrollRequest: identity 1751 }; 1752 // calendar-specific options 1753 // ------------------------- 1754 var CALENDAR_OPTION_REFINERS = { 1755 buttonText: identity, 1756 views: identity, 1757 plugins: identity, 1758 initialEvents: identity,
1759 events: identity, 1760 eventSources: identity 1761 }; 1762 var COMPLEX_OPTION_COMPARATORS = { 1763 headerToolbar: isBoolComplexEqual, 1764 footerToolbar: isBoolComplexEqual, 1765 buttonText: isBoolComplexEqual, 1766 buttonIcons: isBoolComplexEqual 1767 }; 1768 function isBoolComplexEqual(a, b) { 1769 if (typeof a === 'object' && typeof b === 'object' && a && b) { // both non-null objects 1770 return isPropsEqual(a, b); 1771 } 1772 else { 1773 return a === b; 1774 } 1775 } 1776 // view-specific options 1777 // --------------------- 1778 var VIEW_OPTION_REFINERS = { 1779 type: String, 1780 component: identity, 1781 buttonText: String, 1782 buttonTextKey: String, 1783 dateProfileGeneratorClass: identity, 1784 usesMinMaxTime: Boolean, 1785 classNames: identity, 1786 content: identity, 1787 didMount: identity, 1788 willUnmount: identity 1789 }; 1790 // util funcs 1791 // ---------------------------------------------------------------------------------------------------- 1792 function mergeRawOptions(optionSets) { 1793 return mergeProps(optionSets, COMPLEX_OPTION_COMPARATORS); 1794 } 1795 function refineProps(input, refiners) { 1796 var refined = {}; 1797 var extra = {}; 1798 for (var propName in refiners) { 1799 if (propName in input) { 1800 refined[propName] = refiners[propName](input[propName]); 1801 } 1802 } 1803 for (var propName in input) { 1804 if (!(propName in refiners)) { 1805 extra[propName] = input[propName]; 1806 } 1807 } 1808 return { refined: refined, extra: extra }; 1809 } 1810 function identity(raw) { 1811 return raw; 1812 } 1813 1814 function parseEvents(rawEvents, eventSource, context, allowOpenRange) { 1815 var eventStore = createEmptyEventStore(); 1816 var eventRefiners = buildEventRefiners(context); 1817 for (var _i = 0, rawEvents_1 = rawEvents; _i < rawEvents_1.length; _i++) { 1818 var rawEvent = rawEvents_1[_i]; 1819 var tuple = parseEvent(rawEvent, eventSource, context, allowOpenRange, eventRefiners); 1820 if (tuple) { 1821 eventTupleToStore(tuple, eventStore); 1822 } 1823 } 1824 return eventStore; 1825 } 1826 function eventTupleToStore(tuple, eventStore) { 1827 if (eventStore === void 0) { eventStore = createEmptyEventStore(); } 1828 eventStore.defs[tuple.def.defId] = tuple.def; 1829 if (tuple.instance) { 1830 eventStore.instances[tuple.instance.instanceId] = tuple.instance; 1831 } 1832 return eventStore; 1833 } 1834 // retrieves events that have the same groupId as the instance specified by `instanceId` 1835 // or they are the same as the instance. 1836 // why might instanceId not be in the store? an event from another calendar? 1837 function getRelevantEvents(eventStore, instanceId) { 1838 var instance = eventStore.instances[instanceId]; 1839 if (instance) { 1840 var def_1 = eventStore.defs[instance.defId]; 1841 // get events/instances with same group 1842 var newStore = filterEventStoreDefs(eventStore, function (lookDef) { 1843 return isEventDefsGrouped(def_1, lookDef); 1844 }); 1845 // add the original 1846 // TODO: wish we could use eventTupleToStore or something like it 1847 newStore.defs[def_1.defId] = def_1; 1848 newStore.instances[instance.instanceId] = instance; 1849 return newStore; 1850 } 1851 return createEmptyEventStore(); 1852 } 1853 function isEventDefsGrouped(def0, def1) { 1854 return Boolean(def0.groupId && def0.groupId === def1.groupId); 1855 } 1856 function createEmptyEventStore() { 1857 return { defs: {}, instances: {} }; 1858 } 1859 function mergeEventStores(store0, store1) { 1860 return { 1861 defs: __assign(__assign({}, store0.defs), store1.defs), 1862 instances: __assign(__assign({}, store0.instances), store1.instances) 1863 }; 1864 } 1865 function filterEventStoreDefs(eventStore, filterFunc) { 1866 var defs = filterHash(eventStore.defs, filterFunc); 1867 var instances = filterHash(eventStore.instances, function (instance) { 1868 return defs[instance.defId]; // still exists? 1869 }); 1870 return { defs: defs, instances: instances }; 1871 } 1872 function excludeSubEventStore(master, sub) { 1873 var defs = master.defs, instances = master.instances; 1874 var filteredDefs = {}; 1875 var filteredInstances = {}; 1876 for (var defId in defs) { 1877 if (!sub.defs[defId]) { // not explicitly excluded
1878 filteredDefs[defId] = defs[defId]; 1879 } 1880 } 1881 for (var instanceId in instances) { 1882 if (!sub.instances[instanceId] && // not explicitly excluded 1883 filteredDefs[instances[instanceId].defId] // def wasn't filtered away 1884 ) { 1885 filteredInstances[instanceId] = instances[instanceId]; 1886 } 1887 } 1888 return { 1889 defs: filteredDefs, 1890 instances: filteredInstances 1891 }; 1892 } 1893 1894 function normalizeConstraint(input, context) { 1895 if (Array.isArray(input)) { 1896 return parseEvents(input, null, context, true); // allowOpenRange=true 1897 } 1898 else if (typeof input === 'object' && input) { // non-null object 1899 return parseEvents([input], null, context, true); // allowOpenRange=true 1900 } 1901 else if (input != null) { 1902 return String(input); 1903 } 1904 else { 1905 return null; 1906 } 1907 } 1908 1909 function parseClassNames(raw) { 1910 if (Array.isArray(raw)) { 1911 return raw; 1912 } 1913 else if (typeof raw === 'string') { 1914 return raw.split(/\s+/); 1915 } 1916 else { 1917 return []; 1918 } 1919 } 1920 1921 // TODO: better called "EventSettings" or "EventConfig" 1922 // TODO: move this file into structs 1923 // TODO: separate constraint/overlap/allow, because selection uses only that, not other props 1924 var EVENT_UI_REFINERS = { 1925 display: String, 1926 editable: Boolean, 1927 startEditable: Boolean, 1928 durationEditable: Boolean, 1929 constraint: identity, 1930 overlap: identity, 1931 allow: identity, 1932 className: parseClassNames, 1933 classNames: parseClassNames, 1934 color: String, 1935 backgroundColor: String, 1936 borderColor: String, 1937 textColor: String 1938 }; 1939 function createEventUi(refined, context) { 1940 var constraint = normalizeConstraint(refined.constraint, context); 1941 return { 1942 display: refined.display || null, 1943 startEditable: refined.startEditable != null ? refined.startEditable : refined.editable, 1944 durationEditable: refined.durationEditable != null ? refined.durationEditable : refined.editable, 1945 constraints: constraint != null ? [constraint] : [], 1946 overlap: refined.overlap != null ? refined.overlap : null, 1947 allows: refined.allow != null ? [refined.allow] : [], 1948 backgroundColor: refined.backgroundColor || refined.color || '', 1949 borderColor: refined.borderColor || refined.color || '', 1950 textColor: refined.textColor || '', 1951 classNames: (refined.className || []).concat(refined.classNames || []) // join singular and plural 1952 }; 1953 } 1954 // TODO: prevent against problems with <2 args! 1955 function combineEventUis(uis) { 1956 return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI); 1957 } 1958 function combineTwoEventUis(item0, item1) { 1959 return { 1960 display: item1.display != null ? item1.display : item0.display, 1961 startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable, 1962 durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable, 1963 constraints: item0.constraints.concat(item1.constraints), 1964 overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap, 1965 allows: item0.allows.concat(item1.allows), 1966 backgroundColor: item1.backgroundColor || item0.backgroundColor, 1967 borderColor: item1.borderColor || item0.borderColor, 1968 textColor: item1.textColor || item0.textColor, 1969 classNames: item0.classNames.concat(item1.classNames) 1970 }; 1971 } 1972 var EMPTY_EVENT_UI = { 1973 display: null, 1974 startEditable: null, 1975 durationEditable: null, 1976 constraints: [], 1977 overlap: null, 1978 allows: [], 1979 backgroundColor: '', 1980 borderColor: '', 1981 textColor: '', 1982 classNames: [] 1983 }; 1984 1985 var EVENT_NON_DATE_REFINERS = { 1986 id: String, 1987 groupId: String, 1988 title: String, 1989 url: String 1990 }; 1991 var EVENT_DATE_REFINERS = { 1992 start: identity, 1993 end: identity, 1994 date: identity, 1995 allDay: Boolean 1996 }; 1997 var EVENT_REFINERS = __assign(__assign(__assign({}, EVENT_NON_DATE_REFINERS), EVENT_DATE_REFINERS), { extendedProps: identity }); 1998 function parseEvent(raw, eventSource, context, allowOpenRange, refiners) { 1999 if (refiners === void 0) { refiners = buildEventRefiners(context); } 2000 var _a = refineEventDef(raw, context, refiners), refined
2000= _a.refined, extra = _a.extra; 2001 var defaultAllDay = computeIsDefaultAllDay(eventSource, context); 2002 var recurringRes = parseRecurring(refined, defaultAllDay, context.dateEnv, context.pluginHooks.recurringTypes); 2003 if (recurringRes) { 2004 var def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', recurringRes.allDay, Boolean(recurringRes.duration), context); 2005 def.recurringDef = { 2006 typeId: recurringRes.typeId, 2007 typeData: recurringRes.typeData, 2008 duration: recurringRes.duration 2009 }; 2010 return { def: def, instance: null }; 2011 } 2012 else { 2013 var singleRes = parseSingle(refined, defaultAllDay, context, allowOpenRange); 2014 if (singleRes) { 2015 var def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', singleRes.allDay, singleRes.hasEnd, context); 2016 var instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo); 2017 return { def: def, instance: instance }; 2018 } 2019 } 2020 return null; 2021 } 2022 function refineEventDef(raw, context, refiners) { 2023 if (refiners === void 0) { refiners = buildEventRefiners(context); } 2024 return refineProps(raw, refiners); 2025 } 2026 function buildEventRefiners(context) { 2027 return __assign(__assign(__assign({}, EVENT_UI_REFINERS), EVENT_REFINERS), context.pluginHooks.eventRefiners); 2028 } 2029 /* 2030 Will NOT populate extendedProps with the leftover properties. 2031 Will NOT populate date-related props. 2032 */ 2033 function parseEventDef(refined, extra, sourceId, allDay, hasEnd, context) { 2034 var def = { 2035 title: refined.title || '', 2036 groupId: refined.groupId || '', 2037 publicId: refined.id || '', 2038 url: refined.url || '', 2039 recurringDef: null, 2040 defId: guid(), 2041 sourceId: sourceId, 2042 allDay: allDay, 2043 hasEnd: hasEnd, 2044 ui: createEventUi(refined, context), 2045 extendedProps: __assign(__assign({}, (refined.extendedProps || {})), extra) 2046 }; 2047 for (var _i = 0, _a = context.pluginHooks.eventDefMemberAdders; _i < _a.length; _i++) { 2048 var memberAdder = _a[_i]; 2049 __assign(def, memberAdder(refined)); 2050 } 2051 // help out EventApi from having user modify props 2052 Object.freeze(def.ui.classNames); 2053 Object.freeze(def.extendedProps); 2054 return def; 2055 } 2056 function parseSingle(refined, defaultAllDay, context, allowOpenRange) { 2057 var allDay = refined.allDay; 2058 var startMeta; 2059 var startMarker = null; 2060 var hasEnd = false; 2061 var endMeta; 2062 var endMarker = null; 2063 var startInput = refined.start != null ? refined.start : refined.date; 2064 startMeta = context.dateEnv.createMarkerMeta(startInput); 2065 if (startMeta) { 2066 startMarker = startMeta.marker; 2067 } 2068 else if (!allowOpenRange) { 2069 return null; 2070 } 2071 if (refined.end != null) { 2072 endMeta = context.dateEnv.createMarkerMeta(refined.end); 2073 } 2074 if (allDay == null) { 2075 if (defaultAllDay != null) { 2076 allDay = defaultAllDay; 2077 } 2078 else { 2079 // fall back to the date props LAST 2080 allDay = (!startMeta || startMeta.isTimeUnspecified) && 2081 (!endMeta || endMeta.isTimeUnspecified); 2082 } 2083 } 2084 if (allDay && startMarker) { 2085 startMarker = startOfDay(startMarker); 2086 } 2087 if (endMeta) { 2088 endMarker = endMeta.marker; 2089 if (allDay) { 2090 endMarker = startOfDay(endMarker); 2091 } 2092 if (startMarker && endMarker <= startMarker) { 2093 endMarker = null; 2094 } 2095 } 2096 if (endMarker) { 2097 hasEnd = true; 2098 } 2099 else if (!allowOpenRange) { 2100 hasEnd = context.options.forceEventDuration || false; 2101 endMarker = context.dateEnv.add(startMarker, allDay ? 2102 context.options.defaultAllDayEventDuration : 2103 context.options.defaultTimedEventDuration); 2104 } 2105 return { 2106 allDay: allDay, 2107 hasEnd: hasEnd, 2108 range: { start: startMarker, end: endMarker }, 2109 forcedStartTzo: startMeta ? startMeta.forcedTzo : null, 2110 forcedEndTzo: endMeta ? endMeta.forcedTzo : null 2111 }; 2112 } 2113 function computeIsDefaultAllDay(eventSource, context) { 2114 var res = null; 2115 if (eventSource) { 2116 res = eventSource.defaultAllDay; 2117 } 2118 if (res == null) { 2119 res = context.options.defaultAllDay; 2120 } 2121 return res; 2122 } 2123 2124 /* Date stuff that doesn't belong in datelib core 2125 ----------------------------------------------------------------------------------------------------------------------*/ 2126 // given a timed range, computes an all-day range that has the same exact duration, 2127 // but whose start time is aligned with the start of the day. 2128 function computeAlignedDayRange(timedRange) { 2129 var dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1; 2130 var start = startOfDay(timedRange.start); 2131 var end = addDays(start, dayCnt); 2132 return { start: start, end: end }; 2133 } 2134 // given a timed range, computes an all-day range based on how for the end date bleeds into the next day 2135 // TODO: give nextDayThreshold a default arg 2136 function computeVisibleDayRange(timedRange, nextDayThreshold) { 2137 if (nextDayThreshold === void 0) { nextDayThreshold = createDuration(0); } 2138 var startDay = null; 2139 var endDay = null; 2140 if (timedRange.end) { 2141 endDay = startOfDay(timedRange.end); 2142 var endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay` 2143 // If the end time is actually inclusively part of the next day and is equal to or
vendor: 15,865 bytes, lines 2144-2533
2144 // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`. 2145 // Otherwise, leaving it as inclusive will cause it to exclude `endDay`. 2146 if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) { 2147 endDay = addDays(endDay, 1); 2148 } 2149 } 2150 if (timedRange.start) { 2151 startDay = startOfDay(timedRange.start); // the beginning of the day the range starts 2152 // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day. 2153 if (endDay && endDay <= startDay) { 2154 endDay = addDays(startDay, 1); 2155 } 2156 } 2157 return { start: startDay, end: endDay }; 2158 } 2159 // spans from one day into another? 2160 function isMultiDayRange(range) { 2161 var visibleRange = computeVisibleDayRange(range); 2162 return diffDays(visibleRange.start, visibleRange.end) > 1; 2163 } 2164 function diffDates(date0, date1, dateEnv, largeUnit) { 2165 if (largeUnit === 'year') { 2166 return createDuration(dateEnv.diffWholeYears(date0, date1), 'year'); 2167 } 2168 else if (largeUnit === 'month') { 2169 return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month'); 2170 } 2171 else { 2172 return diffDayAndTime(date0, date1); // returns a duration 2173 } 2174 } 2175 2176 function parseRange(input, dateEnv) { 2177 var start = null; 2178 var end = null; 2179 if (input.start) { 2180 start = dateEnv.createMarker(input.start); 2181 } 2182 if (input.end) { 2183 end = dateEnv.createMarker(input.end); 2184 } 2185 if (!start && !end) { 2186 return null; 2187 } 2188 if (start && end && end < start) { 2189 return null; 2190 } 2191 return { start: start, end: end }; 2192 } 2193 // SIDE-EFFECT: will mutate ranges. 2194 // Will return a new array result. 2195 function invertRanges(ranges, constraintRange) { 2196 var invertedRanges = []; 2197 var start = constraintRange.start; // the end of the previous range. the start of the new range 2198 var i; 2199 var dateRange; 2200 // ranges need to be in order. required for our date-walking algorithm 2201 ranges.sort(compareRanges); 2202 for (i = 0; i < ranges.length; i++) { 2203 dateRange = ranges[i]; 2204 // add the span of time before the event (if there is any) 2205 if (dateRange.start > start) { // compare millisecond time (skip any ambig logic) 2206 invertedRanges.push({ start: start, end: dateRange.start }); 2207 } 2208 if (dateRange.end > start) { 2209 start = dateRange.end; 2210 } 2211 } 2212 // add the span of time after the last event (if there is any) 2213 if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic) 2214 invertedRanges.push({ start: start, end: constraintRange.end }); 2215 } 2216 return invertedRanges; 2217 } 2218 function compareRanges(range0, range1) { 2219 return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first 2220 } 2221 function intersectRanges(range0, range1) { 2222 var start = range0.start; 2223 var end = range0.end; 2224 var newRange = null; 2225 if (range1.start !== null) { 2226 if (start === null) { 2227 start = range1.start; 2228 } 2229 else { 2230 start = new Date(Math.max(start.valueOf(), range1.start.valueOf())); 2231 } 2232 } 2233 if (range1.end != null) { 2234 if (end === null) { 2235 end = range1.end; 2236 } 2237 else { 2238 end = new Date(Math.min(end.valueOf(), range1.end.valueOf())); 2239 } 2240 } 2241 if (start === null || end === null || start < end) { 2242 newRange = { start: start, end: end }; 2243 } 2244 return newRange; 2245 } 2246 function rangesEqual(range0, range1) { 2247 return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) && 2248 (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf()); 2249 } 2250 function rangesIntersect(range0, range1) { 2251 return (range0.end === null || range1.start === null || range0.end > range1.start) && 2252 (range0.start === null || range1.end === null || range0.start < range1.end); 2253 } 2254 function rangeContainsRange(outerRange, innerRange) { 2255 return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) && 2256 (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end)); 2257 } 2258 function rangeContainsMarker(range, date) { 2259 return (range.start === null || date >= range.start) && 2260 (range.end === null || date < range.end); 2261 } 2262 // If the given date is not within the given range, move it inside. 2263 // (If it's past the end, make it one millisecond before the end). 2264 function constrainMarkerToRange(date, range) { 2265 if (range.start != null && date < range.start) { 2266 return range.start; 2267 } 2268 if (range.end != null && date >= range.end) { 2269 return new Date(range.end.valueOf() - 1); 2270 } 2271 return date; 2272 } 2273 2274 /* 2275 Specifying nextDayThreshold signals that all-day ranges should be sliced. 2276 */ 2277 function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) { 2278 var inverseBgByGroupId = {}; 2279 var inverseBgByDefId = {}; 2280 var defByGroupId = {}; 2281 var bgRanges = []; 2282 var fgRanges = []; 2283 var eventUis = compileEventUis(eventStore.defs, eventUiBases); 2284 for (var defId in eventStore.defs) { 2285 var def = eventStore.defs[defId]; 2286 var ui = eventUis[def.defId]; 2287 if (ui.display === 'inverse-background') { 2288 if (def.groupId) { 2289 inverseBgByGroupId[def.groupId] = []; 2290 if (!defByGroupId[def.groupId]) { 2291 defByGroupId[def.groupId] = def; 2292 } 2293 } 2294 else { 2295 inverseBgByDefId[defId] = []; 2296 } 2297 } 2298 } 2299 for (var instanceId in eventStore.instances) { 2300 var instance = eventStore.instances[instanceId]; 2301 var def = eventStore.defs[instance.defId]; 2302 var ui = eventUis[def.defId]; 2303 var origRange = instance.range; 2304 var normalRange = (!def.allDay && nextDayThreshold) ? 2305 computeVisibleDayRange(origRange, nextDayThreshold) : 2306 origRange; 2307 var slicedRange = intersectRanges(normalRange, framingRange); 2308 if (slicedRange) { 2309 if (ui.display === 'inverse-background') { 2310 if (def.groupId) { 2311 inverseBgByGroupId[def.groupId].push(slicedRange); 2312 } 2313 else { 2314 inverseBgByDefId[instance.defId].push(slicedRange); 2315 } 2316 } 2317 else if (ui.display !== 'none') { 2318 (ui.display === 'background' ? bgRanges : fgRanges).push({ 2319 def: def, 2320 ui: ui, 2321 instance: instance, 2322 range: slicedRange, 2323 isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(), 2324 isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf() 2325 }); 2326 } 2327 } 2328 } 2329 for (var groupId in inverseBgByGroupId) { // BY GROUP 2330 var ranges = inverseBgByGroupId[groupId]; 2331 var invertedRanges = invertRanges(ranges, framingRange); 2332 for (var _i = 0, invertedRanges_1 = invertedRanges; _i < invertedRanges_1.length; _i++) { 2333 var invertedRange = invertedRanges_1[_i]; 2334 var def = defByGroupId[groupId]; 2335 var ui = eventUis[def.defId]; 2336 bgRanges.push({ 2337 def: def, 2338 ui: ui, 2339 instance: null, 2340 range: invertedRange, 2341 isStart: false, 2342 isEnd: false 2343 }); 2344 } 2345 } 2346 for (var defId in inverseBgByDefId) { 2347 var ranges = inverseBgByDefId[defId]; 2348 var invertedRanges = invertRanges(ranges, framingRange); 2349 for (var _a = 0, invertedRanges_2 = invertedRanges; _a < invertedRanges_2.length; _a++) { 2350 var invertedRange = invertedRanges_2[_a]; 2351 bgRanges.push({ 2352 def: eventStore.defs[defId], 2353 ui: eventUis[defId], 2354 instance: null, 2355 range: invertedRange, 2356 isStart: false, 2357 isEnd: false 2358 }); 2359 } 2360 } 2361 return { bg: bgRanges, fg: fgRanges }; 2362 } 2363 function hasBgRendering(def) { 2364 return def.ui.display === 'background' || def.ui.display === 'inverse-background'; 2365 } 2366 function setElSeg(el, seg) { 2367 el.fcSeg = seg; 2368 } 2369 function getElSeg(el) { 2370 return el.fcSeg || 2371 el.parentNode.fcSeg || // for the harness 2372 null; 2373 } 2374 // event ui computation 2375 function compileEventUis(eventDefs, eventUiBases) { 2376 return mapHash(eventDefs, function (eventDef) { 2377 return compileEventUi(eventDef, eventUiBases); 2378 }); 2379 } 2380 function compileEventUi(eventDef, eventUiBases) { 2381 var uis = []; 2382 if (eventUiBases['']) { 2383 uis.push(eventUiBases['']); 2384 } 2385 if (eventUiBases[eventDef.defId]) { 2386 uis.push(eventUiBases[eventDef.defId]); 2387 } 2388 uis.push(eventDef.ui); 2389 return combineEventUis(uis); 2390 } 2391 function sortEventSegs(segs, eventOrderSpecs) { 2392 var objs = segs.map(buildSegCompareObj); 2393 objs.sort(function (obj0, obj1) { 2394 return compareByFieldSpecs(obj0, obj1, eventOrderSpecs); 2395 }); 2396 return objs.map(function (c) { 2397 return c._seg; 2398 }); 2399 } 2400 // returns a object with all primitive props that can be compared 2401 function buildSegCompareObj(seg) { 2402 var eventRange = seg.eventRange; 2403 var eventDef = eventRange.def; 2404 var range = eventRange.instance ? eventRange.instance.range : eventRange.range; 2405 var start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events 2406 var end = range.end ? range.end.valueOf() : 0; // " 2407 return __assign(__assign(__assign({}, eventDef.extendedProps), eventDef), { id: eventDef.publicId, start: start, 2408 end: end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg // for later retrieval 2409 }); 2410 } 2411 function computeSegDraggable(seg, context) { 2412 var pluginHooks = context.pluginHooks; 2413 var transformers = pluginHooks.isDraggableTransformers; 2414 var _a = seg.eventRange, def = _a.def, ui = _a.ui; 2415 var val = ui.startEditable; 2416 for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) { 2417 var transformer = transformers_1[_i]; 2418 val = transformer(val, def, ui, context); 2419 } 2420 return val; 2421 } 2422 function computeSegStartResizable(seg, context) { 2423 return seg.isStart && seg.eventRange.ui.durationEditable && context.options.eventResizableFromStart; 2424 } 2425 function computeSegEndResizable(seg, context) { 2426 return seg.isEnd && seg.eventRange.ui.durationEditable; 2427 } 2428 function buildSegTimeText(seg, timeFormat, context, defaultDisplayEventTime, // defaults to true 2429 defaultDisplayEventEnd, // defaults to true 2430 startOverride, endOverride) { 2431 var dateEnv = context.dateEnv, options = context.options; 2432 var displayEventTime = options.displayEventTime, displayEventEnd = options.displayEventEnd; 2433 var eventDef = seg.eventRange.def; 2434 var eventInstance = seg.eventRange.instance; 2435 if (displayEventTime == null) { 2436 displayEventTime = defaultDisplayEventTime !== false; 2437 } 2438 if (displayEventEnd == null) { 2439 displayEventEnd = defaultDisplayEventEnd !== false; 2440 } 2441 if (displayEventTime && !eventDef.allDay && (seg.isStart || seg.isEnd)) { 2442 var segStart = startOverride || (seg.isStart ? eventInstance.range.start : (seg.start || seg.eventRange.range.start)); 2443 var segEnd = endOverride || (seg.isEnd ? eventInstance.range.end : (seg.end || seg.eventRange.range.end)); 2444 if (displayEventEnd && eventDef.hasEnd) { 2445 return dateEnv.formatRange(segStart, segEnd, timeFormat, { 2446 forcedStartTzo: startOverride ? null : eventInstance.forcedStartTzo, 2447 forcedEndTzo: endOverride ? null : eventInstance.forcedEndTzo 2448 }); 2449 } 2450 else { 2451 return dateEnv.format(segStart, timeFormat, { 2452 forcedTzo: startOverride ? null : eventInstance.forcedStartTzo // nooooo, same 2453 }); 2454 } 2455 } 2456 return ''; 2457 } 2458 function getSegMeta(seg, todayRange, nowDate) { 2459 var segRange = seg.eventRange.range; 2460 return { 2461 isPast: segRange.end < (nowDate || todayRange.start), 2462 isFuture: segRange.start >= (nowDate || todayRange.end), 2463 isToday: todayRange && rangeContainsMarker(todayRange, segRange.start) 2464 }; 2465 } 2466 function getEventClassNames(props) { 2467 var classNames = ['fc-event']; 2468 if (props.isMirror) { 2469 classNames.push('fc-event-mirror'); 2470 } 2471 if (props.isDraggable) { 2472 classNames.push('fc-event-draggable'); 2473 } 2474 if (props.isStartResizable || props.isEndResizable) { 2475 classNames.push('fc-event-resizable'); 2476 } 2477 if (props.isDragging) { 2478 classNames.push('fc-event-dragging'); 2479 } 2480 if (props.isResizing) { 2481 classNames.push('fc-event-resizing'); 2482 } 2483 if (props.isSelected) { 2484 classNames.push('fc-event-selected'); 2485 } 2486 if (props.isStart) { 2487 classNames.push('fc-event-start'); 2488 } 2489 if (props.isEnd) { 2490 classNames.push('fc-event-end'); 2491 } 2492 if (props.isPast) { 2493 classNames.push('fc-event-past'); 2494 } 2495 if (props.isToday) { 2496 classNames.push('fc-event-today'); 2497 } 2498 if (props.isFuture) { 2499 classNames.push('fc-event-future'); 2500 } 2501 return classNames; 2502 } 2503 function buildEventRangeKey(eventRange) { 2504 return eventRange.instance 2505 ? eventRange.instance.instanceId 2506 : eventRange.def.defId + ':' + eventRange.range.start.toISOString(); 2507 // inverse-background events don't have specific instances. TODO: better solution 2508 } 2509 2510 var STANDARD_PROPS = { 2511 start: identity, 2512 end: identity, 2513 allDay: Boolean 2514 }; 2515 function parseDateSpan(raw, dateEnv, defaultDuration) { 2516 var span = parseOpenDateSpan(raw, dateEnv); 2517 var range = span.range; 2518 if (!range.start) { 2519 return null; 2520 } 2521 if (!range.end) { 2522 if (defaultDuration == null) { 2523 return null; 2524 } 2525 else { 2526 range.end = dateEnv.add(range.start, defaultDuration); 2527 } 2528 } 2529 return span; 2530 } 2531 /* 2532 TODO: somehow combine with parseRange? 2533 Will return null if the start/end props were present but parsed invali
2533dly. 2534 */ 2535 function parseOpenDateSpan(raw, dateEnv) { 2536 var _a = refineProps(raw, STANDARD_PROPS), standardProps = _a.refined, extra = _a.extra; 2537 var startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null; 2538 var endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null; 2539 var allDay = standardProps.allDay; 2540 if (allDay == null) { 2541 allDay = (startMeta && startMeta.isTimeUnspecified) && 2542 (!endMeta || endMeta.isTimeUnspecified); 2543 } 2544 return __assign({ range: { 2545 start: startMeta ? startMeta.marker : null, 2546 end: endMeta ? endMeta.marker : null, 2547 }, allDay: allDay }, extra); 2548 } 2549 function isDateSpansEqual(span0, span1) { 2550 return rangesEqual(span0.range, span1.range) && 2551 span0.allDay === span1.allDay && 2552 isSpanPropsEqual(span0, span1); 2553 } 2554 // the NON-DATE-RELATED props 2555 function isSpanPropsEqual(span0, span1) { 2556 for (var propName in span1) { 2557 if (propName !== 'range' && propName !== 'allDay') { 2558 if (span0[propName] !== span1[propName]) { 2559 return false; 2560 } 2561 } 2562 } 2563 // are there any props that span0 has that span1 DOESN'T have? 2564 // both have range/allDay, so no need to special-case. 2565 for (var propName in span0) { 2566 if (!(propName in span1)) { 2567 return false; 2568 } 2569 } 2570 return true; 2571 } 2572 function buildDateSpanApi(span, dateEnv) { 2573 return __assign(__assign({}, buildRangeApi(span.range, dateEnv, span.allDay)), { allDay: span.allDay }); 2574 } 2575 function buildRangeApiWithTimeZone(range, dateEnv, omitTime) { 2576 return __assign(__assign({}, buildRangeApi(range, dateEnv, omitTime)), { timeZone: dateEnv.timeZone }); 2577 } 2578 function buildRangeApi(range, dateEnv, omitTime) { 2579 return { 2580 start: dateEnv.toDate(range.start), 2581 end: dateEnv.toDate(range.end), 2582 startStr: dateEnv.formatIso(range.start, { omitTime: omitTime }), 2583 endStr: dateEnv.formatIso(range.end, { omitTime: omitTime }) 2584 }; 2585 } 2586 function fabricateEventRange(dateSpan, eventUiBases, context) { 2587 var res = refineEventDef({ editable: false }, context); 2588 var def = parseEventDef(res.refined, res.extra, '', // sourceId 2589 dateSpan.allDay, true, // hasEnd 2590 context); 2591 return { 2592 def: def, 2593 ui: compileEventUi(def, eventUiBases), 2594 instance: createEventInstance(def.defId, dateSpan.range), 2595 range: dateSpan.range, 2596 isStart: true, 2597 isEnd: true 2598 }; 2599 } 2600 2601 function triggerDateSelect(selection, pev, context) { 2602 context.emitter.trigger('select', __assign(__assign({}, buildDateSpanApiWithContext(selection, context)), { jsEvent: pev ? pev.origEvent : null, view: context.viewApi || context.calendarApi.view })); 2603 } 2604 function triggerDateUnselect(pev, context) { 2605 context.emitter.trigger('unselect', { 2606 jsEvent: pev ? pev.origEvent : null, 2607 view: context.viewApi || context.calendarApi.view 2608 }); 2609 } 2610 function buildDateSpanApiWithContext(dateSpan, context) { 2611 var props = {}; 2612 for (var _i = 0, _a = context.pluginHooks.dateSpanTransforms; _i < _a.length; _i++) { 2613 var transform = _a[_i]; 2614 __assign(props, transform(dateSpan, context)); 2615 } 2616 __assign(props, buildDateSpanApi(dateSpan, context.dateEnv)); 2617 return props; 2618 } 2619 // Given an event's allDay status and start date, return what its fallback end date should be. 2620 // TODO: rename to computeDefaultEventEnd 2621 function getDefaultEventEnd(allDay, marker, context) { 2622 var dateEnv = context.dateEnv, options = context.options; 2623 var end = marker; 2624 if (allDay) { 2625 end = startOfDay(end); 2626 end = dateEnv.add(end, options.defaultAllDayEventDuration); 2627 } 2628 else { 2629 end = dateEnv.add(end, options.defaultTimedEventDuration); 2630 } 2631 return end; 2632 } 2633 2634 // applies the mutation to ALL defs/instances within the event store 2635 function applyMutationToEventStore(eventStore, eventConfigBase, mutation, context) { 2636 var eventConfigs = compileEventUis(eventStore.defs, eventConfigBase); 2637 var dest = createEmptyEventStore(); 2638 for (var defId in eventStore.defs) { 2639 var def = eventStore.defs[defId]; 2640 dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, context); 2641 } 2642 for (var instanceId in eventStore.instances) { 2643 var instance = eventStore.instances[instanceId]; 2644 var def = dest.defs[instance.defId]; // important to grab the newly modified def 2645 dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, context); 2646 } 2647 return dest; 2648 } 2649 function applyMutationToEventDef(eventDef, eventConfig, mutation, context) { 2650 var standardProps = mutation.standardProps || {}; 2651 // if hasEnd has not been specified, guess a good value based on deltas. 2652 // if duration will change, there's no way the default duration will persist, 2653 // and thus, we need to mark the event as having a real end 2654 if (standardProps.hasEnd == null && 2655 eventConfig.durationEditable && 2656 (mutation.startDelta || mutation.endDelta)) { 2657 standardProps.hasEnd = true; // TODO: is this mutation okay? 2658 } 2659 var copy = __assign(__assign(__assign({}, eventDef), standardProps), { ui: __assign(__assign({}, eventDef.ui), standardProps.ui) }); 2660 if (mutation.extendedProps) { 2661 copy.extendedProps = __assign(__assign({}, copy.extendedProps), mutation.extendedProps); 2662 } 2663 for (var _i = 0, _a = context.pluginHooks.eventDefMutationAppliers; _i < _a.length; _i++) { 2664 var applier = _a[_i]; 2665 applier(copy, mutation, context); 2666 } 2667 if (!copy.hasEnd && context.options.forceEventDuration) { 2668 copy.hasEnd = true; 2669 } 2670 return copy; 2671 } 2672 function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef 2673 eventConfig, mutation, context) { 2674 var dateEnv = context.dateEnv; 2675 var forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true; 2676 var clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false; 2677 var copy = __assign({}, eventInstance); 2678 if (forceAllDay) { 2679 copy.range = computeAlignedDayRange(copy.range); 2680 } 2681 if (mutation.datesDelta && eventConfig.startEditable) { 2682 copy.range = { 2683 start: dateEnv.add(copy.range.start, mutation.datesDelta), 2684 end: dateEnv.add(copy.range.end, mutation.datesDelta) 2685 }; 2686 } 2687 if (mutation.startDelta && eventConfig.durationEditable) { 2688 copy.range = { 2689 start: dateEnv.add(copy.range.start, mutation.startDelta), 2690 end: copy.range.end 2691 }; 2692 } 2693 if (mutation.endDelta && eventConfig.durationEditable) { 2694 copy.range = { 2695 start: copy.range.start, 2696 end: dateEnv.add(copy.range.end, mutation.endDelta) 2697 }; 2698 } 2699 if (clearEnd) { 2700 copy.range = { 2701 start: copy.range.start, 2702 end: getDefaultEventEnd(eventDef.allDay, copy.range.start, context) 2703 }; 2704 } 2705 // in case event was all-day but the supplied deltas were not 2706 // better util for this? 2707 if (eventDef.allDay) { 2708 copy.range = { 2709 start: startOfDay(copy.range.start), 2710 end: startOfDay(copy.range.end) 2711 }; 2712 } 2713 // handle invalid durations 2714 if (copy.range.end < copy.range.start) { 2715 copy.range.end = getDefaultEventEnd(eventDef.allDay, copy.range.start, context); 2716 } 2717 return copy; 2718 } 2719 2720 // no public types yet. when there are, export from: 2721 // import {} from './api-type-deps' 2722 var ViewApi = /** @class */ (function () { 2723 function ViewApi(type, getCurrentData, dateEnv) { 2724 this.type = type; 2725 this.getCurrentData = getCurrentData; 2726 this.dateEnv = dateEnv; 2727 } 2728 Object.defineProperty(ViewApi.prototype, "calendar", { 2729 get: function () { 2730 return this.getCurrentData().calendarApi; 2731 }, 2732 enumerable: false, 2733 configurable: true 2734 }); 2735 Object.defineProperty(ViewApi.prototype, "title", { 2736 get: function () { 2737 return this.getCurrentData().viewTitle; 2738 }, 2739 enumerable: false, 2740 configurable: true 2741 }); 2742 Object.defineProperty(ViewApi.prototype, "activeStart", { 2743 get: function () { 2744 return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.start); 2745 }, 2746 enumerable: false, 2747 configurable: true 2748 }); 2749 Object.defineProperty(ViewApi.prototype, "activeEnd", { 2750 get: function () { 2751 return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.end); 2752 }, 2753 enumerable: false, 2754 configurable: true 2755 }); 2756 Object.defineProperty(ViewApi.prototype, "currentStart", { 2757 get: function () { 2758 return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.start); 2759 }, 2760 enumerable: false, 2761 configurable: true 2762 }); 2763 Object.defineProperty(ViewApi.prototype, "currentEnd", { 2764 get: function () { 2765 return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.end); 2766 }, 2767 enumerable: false, 2768 configurable: true 2769 }); 2770 ViewApi.prototype.getOption = function (name) { 2771 return this.getCurrentData().options[name]; // are the view-specific options 2772 }; 2773 return ViewApi; 2774 }()); 2775 2776 var EVENT_SOURCE_REFINERS = { 2777 id: String, 2778 defaultAllDay: Boolean, 2779 url: String,
2780 events: identity, 2781 eventDataTransform: identity, 2782 // for any network-related sources 2783 success: identity, 2784 failure: identity, 2785 }; 2786 function parseEventSource(raw, context, refiners) { 2787 if (refiners === void 0) { refiners = buildEventSourceRefiners(context); } 2788 var rawObj; 2789 if (typeof raw === 'string') { 2790 rawObj = { url: raw }; 2791 } 2792 else if (typeof raw === 'function' || Array.isArray(raw)) { 2793 rawObj = { events: raw }; 2794 } 2795 else if (typeof raw === 'object' && raw) { // not null 2796 rawObj = raw; 2797 } 2798 if (rawObj) { 2799 var _a = refineProps(rawObj, refiners), refined = _a.refined, extra = _a.extra; 2800 var metaRes = buildEventSourceMeta(refined, context); 2801 if (metaRes) { 2802 return { 2803 _raw: raw, 2804 isFetching: false, 2805 latestFetchId: '', 2806 fetchRange: null, 2807 defaultAllDay: refined.defaultAllDay, 2808 eventDataTransform: refined.eventDataTransform, 2809 success: refined.success, 2810 failure: refined.failure, 2811 publicId: refined.id || '', 2812 sourceId: guid(), 2813 sourceDefId: metaRes.sourceDefId, 2814 meta: metaRes.meta, 2815 ui: createEventUi(refined, context), 2816 extendedProps: extra 2817 }; 2818 } 2819 } 2820 return null; 2821 } 2822 function buildEventSourceRefiners(context) { 2823 return __assign(__assign(__assign({}, EVENT_UI_REFINERS), EVENT_SOURCE_REFINERS), context.pluginHooks.eventSourceRefiners); 2824 } 2825 function buildEventSourceMeta(raw, context) { 2826 var defs = context.pluginHooks.eventSourceDefs; 2827 for (var i = defs.length - 1; i >= 0; i--) { // later-added plugins take precedence 2828 var def = defs[i]; 2829 var meta = def.parseMeta(raw); 2830 if (meta) { 2831 return { sourceDefId: i, meta: meta }; 2832 } 2833 } 2834 return null; 2835 } 2836 2837 function reduceCurrentDate(currentDate, action) { 2838 switch (action.type) { 2839 case 'CHANGE_DATE': 2840 return action.dateMarker; 2841 default: 2842 return currentDate; 2843 } 2844 } 2845 function getInitialDate(options, dateEnv) { 2846 var initialDateInput = options.initialDate; 2847 // compute the initial ambig-timezone date 2848 if (initialDateInput != null) { 2849 return dateEnv.createMarker(initialDateInput); 2850 } 2851 else { 2852 return getNow(options.now, dateEnv); // getNow already returns unzoned 2853 } 2854 } 2855 function getNow(nowInput, dateEnv) { 2856 if (typeof nowInput === 'function') { 2857 nowInput = nowInput(); 2858 } 2859 if (nowInput == null) { 2860 return dateEnv.createNowMarker(); 2861 } 2862 return dateEnv.createMarker(nowInput); 2863 } 2864 2865 var CalendarApi = /** @class */ (function () { 2866 function CalendarApi() { 2867 } 2868 CalendarApi.prototype.getCurrentData = function () { 2869 return this.currentDataManager.getCurrentData(); 2870 }; 2871 CalendarApi.prototype.dispatch = function (action) { 2872 return this.currentDataManager.dispatch(action); 2873 }; 2874 Object.defineProperty(CalendarApi.prototype, "view", { 2875 get: function () { return this.getCurrentData().viewApi; } // for public API 2876 , 2877 enumerable: false, 2878 configurable: true 2879 }); 2880 CalendarApi.prototype.batchRendering = function (callback) { 2881 callback(); 2882 }; 2883 CalendarApi.prototype.updateSize = function () { 2884 this.trigger('_resize', true); 2885 }; 2886 // Options 2887 // ----------------------------------------------------------------------------------------------------------------- 2888 CalendarApi.prototype.setOption = function (name, val) { 2889 this.dispatch({ 2890 type: 'SET_OPTION', 2891 optionName: name, 2892 rawOptionValue: val 2893 }); 2894 }; 2895 CalendarApi.prototype.getOption = function (name) { 2896 return this.currentDataManager.currentCalendarOptionsInput[name]; 2897 }; 2898 CalendarApi.prototype.getAvailableLocaleCodes = function () { 2899 return Object.keys(this.getCurrentData().availableRawLocales); 2900 }; 2901 // Trigger 2902 // ----------------------------------------------------------------------------------------------------------------- 2903 CalendarApi.prototype.on = function (handlerName, handler) { 2904 var currentDataManager = this.currentDataManager; 2905 if (currentDataManager.currentCalendarOptionsRefiners[handlerName]) { 2906 currentDataManager.emitter.on(handlerName, handler); 2907 } 2908 else { 2909 console.warn("Unknown listener name '" + handlerName + "'"); 2910 } 2911 }; 2912 CalendarApi.prototype.off = function (handlerName, handler) { 2913 this.currentDataManager.emitter.off(handlerName, handler); 2914 }; 2915 // not meant for public use 2916 CalendarApi.prototype.trigger = function (handlerName) { 2917 var _a; 2918 var args = []; 2919 for (var _i = 1; _i < arguments.length; _i++) { 2920 args[_i - 1] = arguments[_i]; 2921 } 2922 (_a = this.currentDataManager.emitter).trigger.apply(_a, __spreadArrays([handlerName], args)); 2923 }; 2924 // View 2925 // ----------------------------------------------------------------------------------------------------------------- 2926 CalendarApi.prototype.changeView = function (viewType, dateOrRange) { 2927 var _this = this; 2928 this.batchRendering(function () { 2929 _this.unselect(); 2930 if (dateOrRange) { 2931 if (dateOrRange.start && dateOrRange.end) { // a range 2932 _this.dispatch({ 2933 type: 'CHANGE_VIEW_TYPE', 2934 viewType: viewType, 2935 }); 2936 _this.dispatch({ 2937 type: 'SET_OPTION', 2938 optionName: 'visibleRange', 2939 rawOptionValue: dateOrRange 2940 }); 2941 } 2942 else { 2943 var dateEnv = _this.getCurrentData().dateEnv; 2944 _this.dispatch({ 2945 type: 'CHANGE_VIEW_TYPE', 2946 viewType: viewType, 2947 dateMarker: dateEnv.createMarker(dateOrRange) 2948 }); 2949 } 2950 } 2951 else { 2952 _this.dispatch({ 2953 type: 'CHANGE_VIEW_TYPE', 2954 viewType: viewType 2955 }); 2956 } 2957 }); 2958 };
2959 // Forces navigation to a view for the given date. 2960 // `viewType` can be a specific view name or a generic one like "week" or "day". 2961 // needs to change 2962 CalendarApi.prototype.zoomTo = function (dateMarker, viewType) { 2963 var state = this.getCurrentData(); 2964 var spec; 2965 viewType = viewType || 'day'; // day is default zoom 2966 spec = state.viewSpecs[viewType] || this.getUnitViewSpec(viewType); 2967 this.unselect(); 2968 if (spec) { 2969 this.dispatch({ 2970 type: 'CHANGE_VIEW_TYPE', 2971 viewType: spec.type, 2972 dateMarker: dateMarker 2973 }); 2974 } 2975 else { 2976 this.dispatch({ 2977 type: 'CHANGE_DATE', 2978 dateMarker: dateMarker 2979 }); 2980 } 2981 }; 2982 // Given a duration singular unit, like "week" or "day", finds a matching view spec. 2983 // Preference is given to views that have corresponding buttons. 2984 CalendarApi.prototype.getUnitViewSpec = function (unit) { 2985 var _a = this.getCurrentData(), viewSpecs = _a.viewSpecs, toolbarConfig = _a.toolbarConfig; 2986 var viewTypes = [].concat(toolbarConfig.viewsWithButtons); 2987 var i; 2988 var spec; 2989 for (var viewType in viewSpecs) { 2990 viewTypes.push(viewType); 2991 } 2992 for (i = 0; i < viewTypes.length; i++) { 2993 spec = viewSpecs[viewTypes[i]]; 2994 if (spec) { 2995 if (spec.singleUnit === unit) { 2996 return spec; 2997 } 2998 } 2999 } 3000 }; 3001 // Current Date 3002 // ----------------------------------------------------------------------------------------------------------------- 3003 CalendarApi.prototype.prev = function () { 3004 this.unselect(); 3005 this.dispatch({ type: 'PREV' }); 3006 }; 3007 CalendarApi.prototype.next = function () { 3008 this.unselect(); 3009 this.dispatch({ type: 'NEXT' }); 3010 }; 3011 CalendarApi.prototype.prevYear = function () { 3012 var state = this.getCurrentData(); 3013 this.unselect(); 3014 this.dispatch({ 3015 type: 'CHANGE_DATE', 3016 dateMarker: state.dateEnv.addYears(state.currentDate, -1) 3017 }); 3018 }; 3019 CalendarApi.prototype.nextYear = function () { 3020 var state = this.getCurrentData(); 3021 this.unselect(); 3022 this.dispatch({ 3023 type: 'CHANGE_DATE', 3024 dateMarker: state.dateEnv.addYears(state.currentDate, 1) 3025 }); 3026 }; 3027 CalendarApi.prototype.today = function () { 3028 var state = this.getCurrentData(); 3029 this.unselect(); 3030 this.dispatch({ 3031 type: 'CHANGE_DATE', 3032 dateMarker: getNow(state.calendarOptions.now, state.dateEnv) 3033 }); 3034 }; 3035 CalendarApi.prototype.gotoDate = function (zonedDateInput) { 3036 var state = this.getCurrentData(); 3037 this.unselect(); 3038 this.dispatch({ 3039 type: 'CHANGE_DATE', 3040 dateMarker: state.dateEnv.createMarker(zonedDateInput) 3041 }); 3042 }; 3043 CalendarApi.prototype.incrementDate = function (deltaInput) { 3044 var state = this.getCurrentData(); 3045 var delta = createDuration(deltaInput); 3046 if (delta) { // else, warn about invalid input? 3047 this.unselect(); 3048 this.dispatch({ 3049 type: 'CHANGE_DATE', 3050 dateMarker: state.dateEnv.add(state.currentDate, delta) 3051 }); 3052 } 3053 }; 3054 // for external API 3055 CalendarApi.prototype.getDate = function () { 3056 var state = this.getCurrentData(); 3057 return state.dateEnv.toDate(state.currentDate); 3058 }; 3059 // Date Formatting Utils 3060 // ----------------------------------------------------------------------------------------------------------------- 3061 CalendarApi.prototype.formatDate = function (d, formatter) { 3062 var dateEnv = this.getCurrentData().dateEnv; 3063 return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter)); 3064 }; 3065 // `settings` is for formatter AND isEndExclusive 3066 CalendarApi.prototype.formatRange = function (d0, d1, settings) { 3067 var dateEnv = this.getCurrentData().dateEnv; 3068 return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings), settings); 3069 }; 3070 CalendarApi.prototype.formatIso = function (d, omitTime) { 3071 var dateEnv = this.getCurrentData().dateEnv; 3072 return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime: omitTime }); 3073 }; 3074 // Date Selection / Event Selection / DayClick 3075 // ----------------------------------------------------------------------------------------------------------------- 3076 // this public method receives start/end dates in any format, with any timezone 3077 // NOTE: args were changed from v3 3078 CalendarApi.prototype.select = function (dateOrObj, endDate) { 3079 var selectionInput; 3080 if (endDate == null) { 3081 if (dateOrObj.start != null) { 3082 selectionInput = dateOrObj; 3083 } 3084 else { 3085 selectionInput = { 3086 start: dateOrObj, 3087 end: null 3088 }; 3089 } 3090 } 3091 else { 3092 selectionInput = { 3093 start: dateOrObj, 3094 end: endDate 3095 }; 3096 } 3097 var state = this.getCurrentData(); 3098 var selection = parseDateSpan(selectionInput, state.dateEnv, createDuration({ days: 1 }) // TODO: cache this? 3099 ); 3100 if (selection) { // throw parse error otherwise? 3101 this.dispatch({ type: 'SELECT_DATES', selection: selection }); 3102 triggerDateSelect(selection, null, state); 3103 } 3104 }; 3105 // public method 3106 CalendarApi.prototype.unselect = function (pev) { 3107 var state = this.getCurrentData(); 3108 if (state.dateSelection) { 3109 this.dispatch({ type: 'UNSELECT_DATES' }); 3110 triggerDateUnselect(pev, state); 3111 } 3112 }; 3113 // Public Events API 3114 // ----------------------------------------------------------------------------------------------------------------- 3115 CalendarApi.prototype.addEvent = function (eventInput, sourceIn
3115put) { 3116 if (eventInput instanceof EventApi) { 3117 var def = eventInput._def; 3118 var instance = eventInput._instance; 3119 var currentData = this.getCurrentData(); 3120 // not already present? don't want to add an old snapshot 3121 if (!currentData.eventStore.defs[def.defId]) { 3122 this.dispatch({ 3123 type: 'ADD_EVENTS', 3124 eventStore: eventTupleToStore({ def: def, instance: instance }) // TODO: better util for two args? 3125 }); 3126 this.triggerEventAdd(eventInput); 3127 } 3128 return eventInput; 3129 } 3130 var state = this.getCurrentData(); 3131 var eventSource; 3132 if (sourceInput instanceof EventSourceApi) { 3133 eventSource = sourceInput.internalEventSource; 3134 } 3135 else if (typeof sourceInput === 'boolean') { 3136 if (sourceInput) { // true. part of the first event source 3137 eventSource = hashValuesToArray(state.eventSources)[0]; 3138 } 3139 } 3140 else if (sourceInput != null) { // an ID. accepts a number too 3141 var sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function 3142 if (!sourceApi) { 3143 console.warn('Could not find an event source with ID "' + sourceInput + '"'); // TODO: test 3144 return null; 3145 } 3146 else { 3147 eventSource = sourceApi.internalEventSource; 3148 } 3149 } 3150 var tuple = parseEvent(eventInput, eventSource, state, false); 3151 if (tuple) { 3152 var newEventApi = new EventApi(state, tuple.def, tuple.def.recurringDef ? null : tuple.instance); 3153 this.dispatch({ 3154 type: 'ADD_EVENTS', 3155 eventStore: eventTupleToStore(tuple) 3156 }); 3157 this.triggerEventAdd(newEventApi); 3158 return newEventApi; 3159 } 3160 return null; 3161 }; 3162 CalendarApi.prototype.triggerEventAdd = function (eventApi) { 3163 var _this = this; 3164 var emitter = this.getCurrentData().emitter; 3165 emitter.trigger('eventAdd', { 3166 event: eventApi, 3167 relatedEvents: [], 3168 revert: function () { 3169 _this.dispatch({ 3170 type: 'REMOVE_EVENTS', 3171 eventStore: eventApiToStore(eventApi) 3172 }); 3173 } 3174 }); 3175 }; 3176 // TODO: optimize 3177 CalendarApi.prototype.getEventById = function (id) { 3178 var state = this.getCurrentData(); 3179 var _a = state.eventStore, defs = _a.defs, instances = _a.instances; 3180 id = String(id); 3181 for (var defId in defs) { 3182 var def = defs[defId]; 3183 if (def.publicId === id) { 3184 if (def.recurringDef) { 3185 return new EventApi(state, def, null); 3186 } 3187 else { 3188 for (var instanceId in instances) { 3189 var instance = instances[instanceId]; 3190 if (instance.defId === def.defId) { 3191 return new EventApi(state, def, instance); 3192 } 3193 } 3194 } 3195 } 3196 } 3197 return null; 3198 }; 3199 CalendarApi.prototype.getEvents = function () { 3200 var currentData = this.getCurrentData(); 3201 return buildEventApis(currentData.eventStore, currentData); 3202 }; 3203 CalendarApi.prototype.removeAllEvents = function () { 3204 this.dispatch({ type: 'REMOVE_ALL_EVENTS' }); 3205 }; 3206 // Public Event Sources API 3207 // ----------------------------------------------------------------------------------------------------------------- 3208 CalendarApi.prototype.getEventSources = function () { 3209 var state = this.getCurrentData(); 3210 var sourceHash = state.eventSources; 3211 var sourceApis = []; 3212 for (var internalId in sourceHash) { 3213 sourceApis.push(new EventSourceApi(state, sourceHash[internalId])); 3214 } 3215 return sourceApis; 3216 }; 3217 CalendarApi.prototype.getEventSourceById = function (id) { 3218 var state = this.getCurrentData(); 3219 var sourceHash = state.eventSources; 3220 id = String(id); 3221 for (var sourceId in sourceHash) { 3222 if (sourceHash[sourceId].publicId === id) { 3223 return new EventSourceApi(state, sourceHash[sourceId]); 3224 } 3225 } 3226 return null; 3227 }; 3228 CalendarApi.prototype.addEventSource = function (sourceInput) { 3229 var state = this.getCurrentData(); 3230 if (sourceInput instanceof EventSourceApi) { 3231 // not already present? don't want to add an old snapshot
3232 if (!state.eventSources[sourceInput.internalEventSource.sourceId]) { 3233 this.dispatch({ 3234 type: 'ADD_EVENT_SOURCES', 3235 sources: [sourceInput.internalEventSource] 3236 }); 3237 } 3238 return sourceInput; 3239 } 3240 var eventSource = parseEventSource(sourceInput, state); 3241 if (eventSource) { // TODO: error otherwise? 3242 this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] }); 3243 return new EventSourceApi(state, eventSource); 3244 } 3245 return null; 3246 }; 3247 CalendarApi.prototype.removeAllEventSources = function () { 3248 this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' }); 3249 }; 3250 CalendarApi.prototype.refetchEvents = function () { 3251 this.dispatch({ type: 'FETCH_EVENT_SOURCES' }); 3252 }; 3253 // Scroll 3254 // ----------------------------------------------------------------------------------------------------------------- 3255 CalendarApi.prototype.scrollToTime = function (timeInput) { 3256 var time = createDuration(timeInput); 3257 if (time) { 3258 this.trigger('_scrollRequest', { time: time }); 3259 } 3260 }; 3261 return CalendarApi; 3262 }()); 3263 3264 var EventApi = /** @class */ (function () { 3265 // instance will be null if expressing a recurring event that has no current instances, 3266 // OR if trying to validate an incoming external event that has no dates assigned 3267 function EventApi(context, def, instance) { 3268 this._context = context; 3269 this._def = def; 3270 this._instance = instance || null; 3271 } 3272 /* 3273 TODO: make event struct more responsible for this 3274 */ 3275 EventApi.prototype.setProp = function (name, val) { 3276 var _a, _b; 3277 if (name in EVENT_DATE_REFINERS) { 3278 console.warn("Could not set date-related prop 'name'. Use one of the date-related methods instead."); 3279 } 3280 else if (name in EVENT_NON_DATE_REFINERS) { 3281 val = EVENT_NON_DATE_REFINERS[name](val); 3282 this.mutate({ 3283 standardProps: (_a = {}, _a[name] = val, _a) 3284 }); 3285 } 3286 else if (name in EVENT_UI_REFINERS) { 3287 var ui = EVENT_UI_REFINERS[name](val); 3288 if (name === 'color') { 3289 ui = { backgroundColor: val, borderColor: val }; 3290 } 3291 else if (name === 'editable') { 3292 ui = { startEditable: val, durationEditable: val }; 3293 } 3294 else { 3295 ui = (_b = {}, _b[name] = val, _b); 3296 } 3297 this.mutate({ 3298 standardProps: { ui: ui } 3299 }); 3300 } 3301 else { 3302 console.warn("Could not set prop '" + name + "'. Use setExtendedProp instead."); 3303 } 3304 }; 3305 EventApi.prototype.setExtendedProp = function (name, val) { 3306 var _a; 3307 this.mutate({ 3308 extendedProps: (_a = {}, _a[name] = val, _a) 3309 }); 3310 }; 3311 EventApi.prototype.setStart = function (startInput, options) { 3312 if (options === void 0) { options = {}; } 3313 var dateEnv = this._context.dateEnv; 3314 var start = dateEnv.createMarker(startInput); 3315 if (start && this._instance) { // TODO: warning if parsed bad 3316 var instanceRange = this._instance.range; 3317 var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!? 3318 if (options.maintainDuration) { 3319 this.mutate({ datesDelta: startDelta }); 3320 } 3321 else { 3322 this.mutate({ startDelta: startDelta }); 3323 } 3324 } 3325 }; 3326 EventApi.prototype.setEnd = function (endInput, options) { 3327 if (options === void 0) { options = {}; } 3328 var dateEnv = this._context.dateEnv; 3329 var end; 3330 if (endInput != null) { 3331 end = dateEnv.createMarker(endInput); 3332 if (!end) { 3333 return; // TODO: warning if parsed bad 3334 } 3335 } 3336 if (this._instance) { 3337 if (end) { 3338 var endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity); 3339 this.mutate({ endDelta: endDelta }); 3340 } 3341 else { 3342 this.mutate({ standardProps: { hasEnd: false } }); 3343 } 3344 } 3345 }; 3346 EventApi.prototype.setDates = function (startInput, endInput, options) { 3347 if (options === void 0) { options = {}; } 3348 var dateEnv = this._context.dateEnv; 3349 var standardProps = { allDay: options.allDay }; 3350 var start = dateEnv.createMarker(startInput); 3351 var end; 3352 if (!start) { 3353 return; // TODO: warning if parsed bad 3354 } 3355 if (endInput != null) { 3356 end = dateEnv.createMarker(endInput); 3357 if (!end) { // TODO: warning if parsed bad 3358 return; 3359 } 3360 } 3361 if (this._instance) { 3362 var instanceRange = this._instance.range; 3363 // when computing the diff for an event being converted to all-day, 3364 // compute diff off of the all-day values the way event-mutation does. 3365 if (options.allDay === true) { 3366 instanceRange = computeAlignedDayRange(instanceRange); 3367 } 3368 var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); 3369 if (end) { 3370 var endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity); 3371 if (durationsEqual(startDelta, endDelta)) { 3372 this.mutate({ datesDelta: startDelta, standardProps: standardProps }); 3373 } 3374 else { 3375 this.mutate({ startDelta: startDelta, endDelta: endDelta, standardProps: standardProps }); 3376 } 3377 } 3378 else { // means "clear the end" 3379 standardProps.hasEnd = false;
3380 this.mutate({ datesDelta: startDelta, standardProps: standardProps }); 3381 } 3382 } 3383 }; 3384 EventApi.prototype.moveStart = function (deltaInput) { 3385 var delta = createDuration(deltaInput); 3386 if (delta) { // TODO: warning if parsed bad 3387 this.mutate({ startDelta: delta }); 3388 } 3389 }; 3390 EventApi.prototype.moveEnd = function (deltaInput) { 3391 var delta = createDuration(deltaInput); 3392 if (delta) { // TODO: warning if parsed bad 3393 this.mutate({ endDelta: delta }); 3394 } 3395 }; 3396 EventApi.prototype.moveDates = function (deltaInput) { 3397 var delta = createDuration(deltaInput); 3398 if (delta) { // TODO: warning if parsed bad 3399 this.mutate({ datesDelta: delta }); 3400 } 3401 }; 3402 EventApi.prototype.setAllDay = function (allDay, options) { 3403 if (options === void 0) { options = {}; } 3404 var standardProps = { allDay: allDay }; 3405 var maintainDuration = options.maintainDuration; 3406 if (maintainDuration == null) { 3407 maintainDuration = this._context.options.allDayMaintainDuration; 3408 } 3409 if (this._def.allDay !== allDay) { 3410 standardProps.hasEnd = maintainDuration; 3411 } 3412 this.mutate({ standardProps: standardProps }); 3413 }; 3414 EventApi.prototype.formatRange = function (formatInput) { 3415 var dateEnv = this._context.dateEnv; 3416 var instance = this._instance; 3417 var formatter = createFormatter(formatInput); 3418 if (this._def.hasEnd) { 3419 return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, { 3420 forcedStartTzo: instance.forcedStartTzo, 3421 forcedEndTzo: instance.forcedEndTzo 3422 }); 3423 } 3424 else { 3425 return dateEnv.format(instance.range.start, formatter, { 3426 forcedTzo: instance.forcedStartTzo 3427 }); 3428 } 3429 }; 3430 EventApi.prototype.mutate = function (mutation) { 3431 var instance = this._instance; 3432 if (instance) { 3433 var def = this._def; 3434 var context_1 = this._context; 3435 var eventStore = context_1.getCurrentData().eventStore; 3436 var relevantEvents_1 = getRelevantEvents(eventStore, instance.instanceId); 3437 var eventConfigBase = { 3438 '': { 3439 display: '', 3440 startEditable: true, 3441 durationEditable: true, 3442 constraints: [], 3443 overlap: null, 3444 allows: [], 3445 backgroundColor: '', 3446 borderColor: '', 3447 textColor: '', 3448 classNames: [] 3449 } 3450 }; 3451 relevantEvents_1 = applyMutationToEventStore(relevantEvents_1, eventConfigBase, mutation, context_1); 3452 var oldEvent = new EventApi(context_1, def, instance); // snapshot 3453 this._def = relevantEvents_1.defs[def.defId]; 3454 this._instance = relevantEvents_1.instances[instance.instanceId]; 3455 context_1.dispatch({ 3456 type: 'MERGE_EVENTS', 3457 eventStore: relevantEvents_1 3458 }); 3459 context_1.emitter.trigger('eventChange', { 3460 oldEvent: oldEvent, 3461 event: this, 3462 relatedEvents: buildEventApis(relevantEvents_1, context_1, instance), 3463 revert: function () { 3464 context_1.dispatch({ 3465 type: 'REMOVE_EVENTS', 3466 eventStore: relevantEvents_1 3467 }); 3468 } 3469 }); 3470 } 3471 }; 3472 EventApi.prototype.remove = function () { 3473 var context = this._context; 3474 var asStore = eventApiToStore(this); 3475 context.dispatch({
3476 type: 'REMOVE_EVENTS', 3477 eventStore: asStore 3478 }); 3479 context.emitter.trigger('eventRemove', { 3480 event: this, 3481 relatedEvents: [], 3482 revert: function () { 3483 context.dispatch({ 3484 type: 'MERGE_EVENTS', 3485 eventStore: asStore 3486 }); 3487 } 3488 }); 3489 }; 3490 Object.defineProperty(EventApi.prototype, "source", { 3491 get: function () { 3492 var sourceId = this._def.sourceId; 3493 if (sourceId) { 3494 return new EventSourceApi(this._context, this._context.getCurrentData().eventSources[sourceId]); 3495 } 3496 return null; 3497 }, 3498 enumerable: false, 3499 configurable: true 3500 }); 3501 Object.defineProperty(EventApi.prototype, "start", { 3502 get: function () { 3503 return this._instance ? 3504 this._context.dateEnv.toDate(this._instance.range.start) : 3505 null; 3506 }, 3507 enumerable: false, 3508 configurable: true 3509 }); 3510 Object.defineProperty(EventApi.prototype, "end", { 3511 get: function () { 3512 return (this._instance && this._def.hasEnd) ? 3513 this._context.dateEnv.toDate(this._instance.range.end) : 3514 null; 3515 }, 3516 enumerable: false, 3517 configurable: true 3518 }); 3519 Object.defineProperty(EventApi.prototype, "startStr", { 3520 get: function () { 3521 var instance = this._instance; 3522 if (instance) { 3523 return this._context.dateEnv.formatIso(instance.range.start, { 3524 omitTime: this._def.allDay, 3525 forcedTzo: instance.forcedStartTzo 3526 }); 3527 } 3528 return ''; 3529 }, 3530 enumerable: false, 3531 configurable: true 3532 }); 3533 Object.defineProperty(EventApi.prototype, "endStr", { 3534 get: function () { 3535 var instance = this._instance; 3536 if (instance && this._def.hasEnd) { 3537 return this._context.dateEnv.formatIso(instance.range.end, { 3538 omitTime: this._def.allDay, 3539 forcedTzo: instance.forcedEndTzo 3540 }); 3541 } 3542 return ''; 3543 }, 3544 enumerable: false, 3545 configurable: true 3546 }); 3547 Object.defineProperty(EventApi.prototype, "id", { 3548 // computable props that all access the def
3549 // TODO: find a TypeScript-compatible way to do this at scale 3550 get: function () { return this._def.publicId; }, 3551 enumerable: false, 3552 configurable: true 3553 }); 3554 Object.defineProperty(EventApi.prototype, "groupId", { 3555 get: function () { return this._def.groupId; }, 3556 enumerable: false, 3557 configurable: true 3558 }); 3559 Object.defineProperty(EventApi.prototype, "allDay", { 3560 get: function () { return this._def.allDay; }, 3561 enumerable: false, 3562 configurable: true 3563 }); 3564 Object.defineProperty(EventApi.prototype, "title", { 3565 get: function () { return this._def.title; }, 3566 enumerable: false, 3567 configurable: true 3568 }); 3569 Object.defineProperty(EventApi.prototype, "url", { 3570 get: function () { return this._def.url; }, 3571 enumerable: false, 3572 configurable: true 3573 }); 3574 Object.defineProperty(EventApi.prototype, "display", { 3575 get: function () { return this._def.ui.display || 'auto'; } // bad. just normalize the type earlier 3576 , 3577 enumerable: false, 3578 configurable: true 3579 }); 3580 Object.defineProperty(EventApi.prototype, "startEditable", { 3581 get: function () { return this._def.ui.startEditable; }, 3582 enumerable: false, 3583 configurable: true 3584 }); 3585 Object.defineProperty(EventApi.prototype, "durationEditable", { 3586 get: function () { return this._def.ui.durationEditable; }, 3587 enumerable: false, 3588 configurable: true 3589 }); 3590 Object.defineProperty(EventApi.prototype, "constraint", { 3591 get: function () { return this._def.ui.constraints[0] || null; }, 3592 enumerable: false, 3593 configurable: true 3594 }); 3595 Object.defineProperty(EventApi.prototype, "overlap", { 3596 get: function () { return this._def.ui.overlap; }, 3597 enumerable: false, 3598 configurable: true 3599 }); 3600 Object.defineProperty(EventApi.prototype, "allow", { 3601 get: function () { return this._def.ui.allows[0] || null; }, 3602 enumerable: false, 3603 configurable: true 3604 }); 3605 Object.defineProperty(EventApi.prototype, "backgroundColor", { 3606 get: function () { return this._def.ui.backgroundColor; }, 3607 enumerable: false, 3608 configurable: true 3609 }); 3610 Object.defineProperty(EventApi.prototype, "borderColor", { 3611 get: function () { return this._def.ui.borderColor; }, 3612 enumerable: false, 3613 configurable: true 3614 }); 3615 Object.defineProperty(EventApi.prototype, "textColor", { 3616 get: function () { return this._def.ui.textColor; }, 3617 enumerable: false, 3618 configurable: true 3619 }); 3620 Object.defineProperty(EventApi.prototype, "classNames", { 3621 // NOTE: user can't modify these because Object.freeze was called in event-def parsing 3622 get: function () { return this._def.ui.classNames; }, 3623 enumerable: false, 3624 configurable: true 3625 }); 3626 Object.defineProperty(EventApi.prototype, "extendedProps", { 3627 get: function () { return this._def.extendedProps; }, 3628 enumerable: false, 3629 configurable: true 3630 }); 3631 EventApi.prototype.toPlainObject = function (settings) { 3632 if (settings === void 0) { settings = {}; } 3633 var def = this._def; 3634 var ui = def.ui; 3635 var _a = this, startStr = _a.startStr, endStr = _a.endStr; 3636 var res = {}; 3637 if (def.title) { 3638 res.title = def.title; 3639 } 3640 if (startStr) { 3641 res.start = startStr; 3642 } 3643 if (endStr) { 3644 res.end = endStr; 3645 } 3646 if (def.publicId) { 3647 res.id = def.publicId; 3648 } 3649 if (def.groupId) { 3650 res.groupId = def.groupId; 3651 } 3652 if (def.url) { 3653 res.url = def.url; 3654 } 3655 if (ui.display && ui.display !== 'auto') { 3656 res.display = ui.display; 3657 } 3658 // TODO: what about recurring-event properties??? 3659 // TODO: include startEditable/durationEditable/constraint/overlap/allow 3660 if (settings.collapseColor && ui.backgroundColor && ui.backgroundColor === ui.borderColor) { 3661 res.color = ui.backgroundColor; 3662 } 3663 else { 3664 if (ui.backgroundColor) { 3665 res.backgroundColor = ui.backgroundColor; 3666 } 3667 if (ui.borderColor) { 3668 res.borderColor = ui.borderColor; 3669 } 3670 } 3671 if (ui.textColor) { 3672 res.textColor = ui.textColor; 3673 } 3674 if (ui.classNames.length) { 3675 res.classNames = ui.classNames; 3676 } 3677 if (Object.keys(def.extendedProps).length) { 3678 if (settings.collapseExtendedProps) { 3679 __assign(res, def.extendedProps); 3680 } 3681 else { 3682 res.extendedProps = def.extendedProps; 3683 } 3684 } 3685 return res; 3686 }; 3687 EventApi.prototype.toJSON = function () { 3688 return this.toPlainObject(); 3689 }; 3690 return EventApi; 3691 }()); 3692 function eventApiToStore(eventApi) { 3693 var _a, _b; 3694 var def = eventApi._def; 3695 var instance = eventApi._instance; 3696 return { 3697 defs: (_a = {}, _a[def.defId] = def, _a), 3698 instances: instance 3699 ? (_b = {}, _b[instance.instanceId] = instance, _b) : {} 3700 }; 3701 } 3702 function buildEventApis(eventStore, context, excludeInstance) { 3703 var defs = eventStore.defs, instances = eventStore.instances; 3704 var eventApis = []; 3705 var excludeInstanceId = excludeInstance ? excludeInstance.instanceId : ''; 3706 for (var id in instances) { 3707 var instance = instances[id]; 3708 var def = defs[instance.defId]; 3709 if (instance.instanceId !== excludeInstanceId) { 3710 eventApis.push(new EventApi(context, def, instance)); 3711 } 3712 } 3713 return eventApis; 3714 } 3715 3716 var calendarSystemClassMap = {}; 3717 function registerCalendarSystem(name, theClass) { 3718 calendarSystemClassMap[name] = theClass; 3719 } 3720 function createCalendarSystem(name) { 3721 return new calendarSystemClassMap[name](); 3722 } 3723 var GregorianCalendarSystem = /** @class */ (function () { 3724 function GregorianCalendarSystem() { 3725 } 3726 GregorianCalendarSystem.prototype.getMarkerYear = function (d) { 3727 return d.getUTCFullYear(); 3728 }; 3729 GregorianCalendarSystem.prototype.getMarkerMonth = function (d) { 3730 return d.getUTCMonth(); 3731 }; 3732 GregorianCalendarSystem.prototype.getMarkerDay = function (d) { 3733 return d.getUTCDate(); 3734 }; 3735 GregorianCalendarSystem.prototype.arrayToMarker = function (arr) { 3736 return arrayToUtcDate(arr); 3737 }; 3738 GregorianCalendarSystem.prototype.markerToArray = function (marker) { 3739 return dateToUtcArray(marker); 3740 }; 3741 return GregorianCalendarSystem; 3742 }()); 3743 registerCalendarSystem('gregory', GregorianCalendarSystem); 3744 3745 var ISO_RE = /^\s*(\d{4})(-?(\d{2})(-?(\d{2})([T ](\d{2}):?(\d{2})(:?(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/; 3746 function parse(str) { 3747 var m = ISO_RE.exec(str); 3748 if (m) { 3749 var marker = new Date(Date.UTC(Number(m[1]), m[3] ? Number(m[3]) - 1 : 0, Number(m[5] || 1), Number(m[7] || 0), Number(m[8] || 0), Number(m[10] || 0), m[12] ? Number('0.' + m[12]) * 1000 : 0)); 3750 if (isValidDate(marker)) { 3751 var timeZoneOffset = null; 3752 if (m[13]) { 3753 timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 + 3754 Number(m[18] || 0)); 3755 } 3756 return { 3757 marker: marker, 3758 isTimeUnspecified: !m[6], 3759 timeZoneOffset: timeZoneOffset 3760 }; 3761 } 3762 } 3763 return null; 3764 } 3765 3766 var DateEnv = /** @class */ (function () { 3767 function DateEnv(settings) { 3768 var timeZone = this.timeZone = settings.timeZone; 3769 var isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC'; 3770 if (settings.namedTimeZoneImpl && isNamedTimeZone) { 3771 this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone); 3772 } 3773 this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl); 3774 this.calendarSystem = createCalendarSystem(settings.calendarSystem); 3775 this.locale = settings.locale; 3776 this.weekDow = settings.locale.week.dow; 3777 this.weekDoy = settings.locale.week.doy; 3778 if (settings.weekNumberCalculation === 'ISO') { 3779 this.weekDow = 1; 3780 this.weekDoy = 4; 3781 } 3782 if (typeof settings.firstDay === 'number') { 3783 this.weekDow = settings.firstDay; 3784 } 3785 if (typeof settings.weekNumberCalculation === 'function') {
3786 this.weekNumberFunc = settings.weekNumberCalculation; 3787 } 3788 this.weekText = settings.weekText != null ? settings.weekText : settings.locale.options.weekText; 3789 this.cmdFormatter = settings.cmdFormatter; 3790 this.defaultSeparator = settings.defaultSeparator; 3791 } 3792 // Creating / Parsing 3793 DateEnv.prototype.createMarker = function (input) { 3794 var meta = this.createMarkerMeta(input); 3795 if (meta === null) { 3796 return null; 3797 } 3798 return meta.marker; 3799 }; 3800 DateEnv.prototype.createNowMarker = function () { 3801 if (this.canComputeOffset) { 3802 return this.timestampToMarker(new Date().valueOf()); 3803 } 3804 else { 3805 // if we can't compute the current date val for a timezone, 3806 // better to give the current local date vals than UTC 3807 return arrayToUtcDate(dateToLocalArray(new Date())); 3808 } 3809 }; 3810 DateEnv.prototype.createMarkerMeta = function (input) { 3811 if (typeof input === 'string') { 3812 return this.parse(input); 3813 } 3814 var marker = null; 3815 if (typeof input === 'number') { 3816 marker = this.timestampToMarker(input); 3817 } 3818 else if (input instanceof Date) { 3819 input = input.valueOf(); 3820 if (!isNaN(input)) { 3821 marker = this.timestampToMarker(input); 3822 } 3823 } 3824 else if (Array.isArray(input)) { 3825 marker = arrayToUtcDate(input); 3826 } 3827 if (marker === null || !isValidDate(marker)) { 3828 return null; 3829 } 3830 return { marker: marker, isTimeUnspecified: false, forcedTzo: null }; 3831 }; 3832 DateEnv.prototype.parse = function (s) { 3833 var parts = parse(s); 3834 if (parts === null) { 3835 return null; 3836 } 3837 var marker = parts.marker; 3838 var forcedTzo = null; 3839 if (parts.timeZoneOffset !== null) { 3840 if (this.canComputeOffset) { 3841 marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000); 3842 } 3843 else { 3844 forcedTzo = parts.timeZoneOffset; 3845 } 3846 } 3847 return { marker: marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo: forcedTzo }; 3848 }; 3849 // Accessors 3850 DateEnv.prototype.getYear = function (marker) { 3851 return this.calendarSystem.getMarkerYear(marker); 3852 }; 3853 DateEnv.prototype.getMonth = function (marker) { 3854 return this.calendarSystem.getMarkerMonth(marker); 3855 }; 3856 // Adding / Subtracting 3857 DateEnv.prototype.add = function (marker, dur) { 3858 var a = this.calendarSystem.markerToArray(marker); 3859 a[0] += dur.years; 3860 a[1] += dur.months; 3861 a[2] += dur.days; 3862 a[6] += dur.milliseconds; 3863 return this.calendarSystem.arrayToMarker(a); 3864 }; 3865 DateEnv.prototype.subtract = function (marker, dur) { 3866 var a = this.calendarSystem.markerToArray(marker); 3867 a[0] -= dur.years; 3868 a[1] -= dur.months; 3869 a[2] -= dur.days; 3870 a[6] -= dur.milliseconds; 3871 return this.calendarSystem.arrayToMarker(a); 3872 }; 3873 DateEnv.prototype.addYears = function (marker, n) { 3874 var a = this.calendarSystem.markerToArray(marker); 3875 a[0] += n; 3876 return this.calendarSystem.arrayToMarker(a); 3877 }; 3878 DateEnv.prototype.addMonths = function (marker, n) { 3879 var a = this.calendarSystem.markerToArray(marker); 3880 a[1] += n; 3881 return this.calendarSystem.arrayToMarker(a); 3882 }; 3883 // Diffing Whole Units 3884 DateEnv.prototype.diffWholeYears = function (m0, m1) { 3885 var calendarSystem = this.calendarSystem; 3886 if (timeAsMs(m0) === timeAsMs(m1) && 3887 calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) && 3888 calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) { 3889 return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0); 3890 } 3891 return null; 3892 }; 3893 DateEnv.prototype.diffWholeMonths = function (m0, m1) { 3894 var calendarSystem = this.calendarSystem; 3895 if (timeAsMs(m0) === timeAsMs(m1) && 3896 calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) { 3897 return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) + 3898 (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12; 3899 } 3900 return null; 3901 }; 3902 // Range / Duration 3903 DateEnv.prototype.greatestWholeUnit = function (m0, m1) { 3904 var n = this.diffWholeYears(m0, m1); 3905 if (n !== null) { 3906 return { unit: 'year', value: n }; 3907 } 3908 n = this.diffWholeMonths(m0, m1); 3909 if (n !== null) { 3910 return { unit: 'month', value: n }; 3911 } 3912 n = diffWholeWeeks(m0, m1); 3913 if (n !== null) { 3914 return { unit: 'week', value: n }; 3915 } 3916 n = diffWholeDays(m0, m1); 3917 if (n !== null) { 3918 return { unit: 'day', value: n }; 3919 } 3920 n = diffHours(m0, m1); 3921 if (isInt(n)) { 3922 return { unit: 'hour', value: n }; 3923 } 3924 n = diffMinutes(m0, m1); 3925 if (isInt(n)) { 3926 return { unit: 'minute', value: n }; 3927 } 3928 n = diffSeconds(m0, m1); 3929 if (isInt(n)) { 3930 return { unit: 'second', value: n }; 3931 } 3932 return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() }; 3933 }; 3934 DateEnv.prototype.countDurationsBetween = function (m0, m1, d) { 3935 // TODO: can use greatestWholeUnit 3936 var diff; 3937 if (d.years) { 3938 diff = this.diffWholeYears(m0, m1); 3939 if (diff !== null) { 3940 return diff / asRoughYears(d); 3941 } 3942 } 3943 if (d.months) { 3944 diff = this.diffWholeMonths(m0, m1); 3945 if (diff !== null) { 3946 return diff / asRoughMonths(d); 3947 } 3948 } 3949 if (d.days) { 3950 diff = diffWholeDays(m0, m1); 3951 if (diff !== null) { 3952 return diff / asRoughDays(d); 3953 } 3954 } 3955 return (m1.valueOf() - m0.valueOf()) / asRoughMs(d); 3956 }; 3957 // Start-Of 3958 // these DON'T return zoned-dates. only UTC start-of dates 3959 DateEnv.prototype.startOf = function (m, unit) { 3960 if (unit === 'year') { 3961 return this.startOfYear(m); 3962 } 3963 else if (unit === 'month') { 3964 return this.startOfMonth(m); 3965 } 3966 else if (unit === 'week') { 3967 return this.startOfWeek(m); 3968 } 3969 else if (unit === 'day') { 3970 return startOfDay(m); 3971 } 3972 else if (unit === 'hour') { 3973 return startOfHour(m); 3974 } 3975 else if (unit === 'minute') { 3976 return startOfMinute(m); 3977 } 3978 else if (unit === 'second') { 3979 return startOfSecond(m); 3980 } 3981 }; 3982 DateEnv.prototype.startOfYear = function (m) { 3983 return this.calendarSystem.arrayToMarker([ 3984 this.calendarSystem.getMarkerYear(m) 3985 ]); 3986 }; 3987 DateEnv.prototype.startOfMonth = function (m) { 3988 return this.calendarSystem.arrayToMarker([ 3989 this.calendarSystem.getMarkerYear(m), 3990 this.calendarSystem.getMarkerMonth(m) 3991 ]); 3992 }; 3993 DateEnv.prototype.startOfWeek = function (m) { 3994 return this.calendarSystem.arrayToMarker([ 3995 this.calendarSystem.getMarkerYear(m), 3996 this.calendarSystem.getMarkerMonth(m), 3997 m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7) 3998 ]); 3999 }; 4000 // Week Number 4001 DateEnv.prototype.computeWeekNumber = function (marker) { 4002 if (this.weekNumberFunc) { 4003 return this.weekNumberFunc(this.toDate(marker)); 4004 } 4005 else { 4006 return weekOfYear(marker, this.weekDow, this.weekDoy); 4007 } 4008 }; 4009 // TODO: choke on timeZoneName: long 4010 DateEnv.prototype.format = function (marker, formatter, dateOptions) { 4011 if (dateOptions === void 0) { dateOptions = {}; } 4012 return formatter.format({ 4013 marker: marker, 4014 timeZoneOffset: dateOptions.forcedTzo != null ? 4015 dateOptions.forcedTzo : 4016 this.offsetForMarker(marker) 4017 }, this); 4018 }; 4019 DateEnv.prototype.formatRange = function (start, end, formatter, dateOptions) { 4020 if (dateOptions === void 0) { dateOptions = {}; } 4021 if (dateOptions.isEndExclusive) { 4022 end = addMs(end, -1); 4023 } 4024 return formatter.formatRange({ 4025 marker: start, 4026 timeZoneOffset: dateOptions.forcedStartTzo != null ? 4027 dateOptions.forcedStartTzo : 4028 this.offsetForMarker(start) 4029 }, { 4030 marker: end, 4031 timeZoneOffset: dateOptions.forcedEndTzo != null ? 4032 dateOptions.forcedEndTzo : 4033 this.offsetForMarker(end) 4034 }, this, dateOptions.defaultSeparator); 4035 }; 4036 /* 4037 DUMB: the omitTime arg is dumb. if we omit the time, we want to omit the timezone offset. and if we do that, 4038 might as well use buildIsoString or some other util directly 4039 */ 4040 DateEnv.prototype.formatIso = function (marker, extraOptions) { 4041 if (extraOptions === void 0) { extraOptions = {}; } 4042 var timeZoneOffset = null; 4043 if (!extraOptions.omitTimeZoneOffset) { 4044 if (extraOptions.forcedTzo != null) { 4045 timeZoneOffset = extraOptions.forcedTzo; 4046 } 4047 else { 4048 timeZoneOffset = this.offsetForMarker(marker); 4049 } 4050 } 4051 return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime); 4052 }; 4053 // TimeZone 4054 DateEnv.prototype.timestampToMarker = function (ms) { 4055 if (this.timeZone === 'local') { 4056 return arrayToUtcDate(dateToLocalArray(new Date(ms))); 4057 } 4058 else if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) { 4059 return new Date(ms); 4060 } 4061 else { 4062 return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms)); 4063 } 4064 }; 4065 DateEnv.prototype.offsetForMarker = function (m) { 4066 if (this.timeZone === 'local') { 4067 return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset 4068 } 4069 else if (this.timeZone === 'UTC') { 4070 return 0; 4071 } 4072 else if (this.namedTimeZoneImpl) { 4073 return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)); 4074 } 4075 return null; 4076 }; 4077 // Conversion 4078 DateEnv.prototype.toDate = function (m, forcedTzo) { 4079 if (this.timeZone === 'local') { 4080 return arrayToLocalDate(dateToUtcArray(m)); 4081 } 4082 else if (this.timeZone === 'UTC') { 4083 return new Date(m.valueOf()); // make sure it's a copy 4084 } 4085 else if (!this.namedTimeZoneImpl) { 4086 return new Date(m.valueOf() - (forcedTzo || 0)); 4087 } 4088 else { 4089 return new Date(m.valueOf() - 4090 this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60 // convert minutes -> ms 4091 ); 4092 } 4093 }; 4094 return DateEnv; 4095 }()); 4096 4097 var globalLocales = []; 4098 4099 var RAW_EN_LOCALE = { 4100 code: 'en', 4101 week: { 4102 dow: 0, 4103 doy: 4 // 4 days need to be within the year to be considered the first week 4104 }, 4105 direction: 'ltr', 4106 buttonText: { 4107 prev: 'prev', 4108 next: 'next', 4109 prevYear: 'prev year', 4110 nextYear: 'next year', 4111 year: 'year', 4112 today: 'today', 4113 month: 'month', 4114 week: 'week', 4115 day: 'day', 4116 list: 'list' 4117 }, 4118 weekText: 'W', 4119 allDayText: 'all-day', 4120 moreLinkText: 'more', 4121 noEventsText: 'No events to display' 4122 }; 4123 function organizeRawLocales(explicitRawLocales) { 4124 var defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en'; 4125 var allRawLocales = globalLocales.concat(explicitRawLocales); 4126 var rawLocaleMap = { 4127 en: RAW_EN_LOCALE // necessary? 4128 }; 4129 for (var _i = 0, allRawLocales_1 = allRawLocales; _i < allRawLocales_1.length; _i++) { 4130 var rawLocale = allRawLocales_1[_i]; 4131 rawLocaleMap[rawLocale.code] = rawLocale; 4132 } 4133 return { 4134 map: rawLocaleMap, 4135 defaultCode: defaultCode 4136 }; 4137 } 4138 function buildLocale(inputSingular, available) { 4139 if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) { 4140 return parseLocale(inputSingular.code, [inputSingular.code], inputSingular); 4141 } 4142 else { 4143 return queryLocale(inputSingular, available); 4144 } 4145 } 4146 function queryLocale(codeArg, available) { 4147 var codes = [].concat(codeArg || []); // will convert to array 4148 var raw = queryRawLocale(codes, available) || RAW_EN_LOCALE; 4149 return parseLocale(codeArg, codes, raw); 4150 } 4151 function queryRawLocale(codes, available) { 4152 for (var i = 0; i < codes.length; i++) { 4153 var parts = codes[i].toLocaleLowerCase().split('-'); 4154 for (var j = parts.length; j > 0; j--) { 4155 var simpleId = parts.slice(0, j).join('-'); 4156 if (available[simpleId]) { 4157 return available[simpleId]; 4158 } 4159 } 4160 } 4161 return null; 4162 } 4163 function parseLocale(codeArg, codes, raw) { 4164 var merged = mergeProps([RAW_EN_LOCALE, raw], ['buttonText']); 4165 delete merged.code; // don't want this part of the options 4166 var week = merged.week; 4167 delete merged.week; 4168 return { 4169 codeArg: codeArg, 4170 codes: codes, 4171 week: week, 4172 simpleNumberFormat: new Intl.NumberFormat(codeArg), 4173 options: merged 4174 }; 4175 } 4176 4177 function formatDate(dateInput, options) { 4178 if (options === void 0) { options = {}; } 4179 var dateEnv = buildDateEnv(options); 4180 var formatter = createFormatter(options); 4181 var dateMeta = dateEnv.createMarkerMeta(dateInput); 4182 if (!dateMeta) { // TODO: warning? 4183 return ''; 4184 } 4185 return dateEnv.format(dateMeta.marker, formatter, { 4186 forcedTzo: dateMeta.forcedTzo 4187 }); 4188 } 4189 function formatRange(startInput, endInput, options // mixture of env and formatter settings 4190 ) { 4191 var dateEnv = buildDateEnv(typeof options === 'object' && options ? options : {}); // pass in if non-null object 4192 var formatter = createFormatter(options); 4193 var startMeta = dateEnv.createMarkerMeta(startInput); 4194 var endMeta = dateEnv.createMarkerMeta(endInput); 4195 if (!startMeta || !endMeta) { // TODO: warning? 4196 return ''; 4197 } 4198 return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, { 4199 forcedStartTzo: startMeta.forcedTzo, 4200 forcedEndTzo: endMeta.forcedTzo, 4201 isEndExclusive: options.isEndExclusive, 4202 defaultS
4202eparator: BASE_OPTION_DEFAULTS.defaultRangeSeparator 4203 }); 4204 } 4205 // TODO: more DRY and optimized 4206 function buildDateEnv(settings) { 4207 var locale = buildLocale(settings.locale || 'en', organizeRawLocales([]).map); // TODO: don't hardcode 'en' everywhere 4208 return new DateEnv(__assign(__assign({ timeZone: BASE_OPTION_DEFAULTS.timeZone, calendarSystem: 'gregory' }, settings), { locale: locale })); 4209 } 4210 4211 var DEF_DEFAULTS = { 4212 startTime: '09:00', 4213 endTime: '17:00', 4214 daysOfWeek: [1, 2, 3, 4, 5], 4215 display: 'inverse-background', 4216 classNames: 'fc-non-business', 4217 groupId: '_businessHours' // so multiple defs get grouped 4218 }; 4219 /* 4220 TODO: pass around as EventDefHash!!! 4221 */ 4222 function parseBusinessHours(input, context) { 4223 return parseEvents(refineInputs(input), null, context); 4224 } 4225 function refineInputs(input) { 4226 var rawDefs; 4227 if (input === true) { 4228 rawDefs = [{}]; // will get DEF_DEFAULTS verbatim 4229 } 4230 else if (Array.isArray(input)) { 4231 // if specifying an array, every sub-definition NEEDS a day-of-week 4232 rawDefs = input.filter(function (rawDef) { 4233 return rawDef.daysOfWeek; 4234 }); 4235 } 4236 else if (typeof input === 'object' && input) { // non-null object 4237 rawDefs = [input]; 4238 } 4239 else { // is probably false 4240 rawDefs = []; 4241 } 4242 rawDefs = rawDefs.map(function (rawDef) { 4243 return __assign(__assign({}, DEF_DEFAULTS), rawDef); 4244 }); 4245 return rawDefs; 4246 } 4247 4248 function pointInsideRect(point, rect) { 4249 return point.left >= rect.left && 4250 point.left < rect.right && 4251 point.top >= rect.top && 4252 point.top < rect.bottom; 4253 } 4254 // Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false 4255 function intersectRects(rect1, rect2) { 4256 var res = { 4257 left: Math.max(rect1.left, rect2.left), 4258 right: Math.min(rect1.right, rect2.right), 4259 top: Math.max(rect1.top, rect2.top), 4260 bottom: Math.min(rect1.bottom, rect2.bottom) 4261 }; 4262 if (res.left < res.right && res.top < res.bottom) { 4263 return res; 4264 } 4265 return false; 4266 } 4267 function translateRect(rect, deltaX, deltaY) { 4268 return { 4269 left: rect.left + deltaX, 4270 right: rect.right + deltaX, 4271 top: rect.top + deltaY, 4272 bottom: rect.bottom + deltaY 4273 }; 4274 } 4275 // Returns a new point that will have been moved to reside within the given rectangle 4276 function constrainPoint(point, rect) { 4277 return { 4278 left: Math.min(Math.max(point.left, rect.left), rect.right), 4279 top: Math.min(Math.max(point.top, rect.top), rect.bottom) 4280 }; 4281 } 4282 // Returns a point that is the center of the given rectangle 4283 function getRectCenter(rect) { 4284 return { 4285 left: (rect.left + rect.right) / 2, 4286 top: (rect.top + rect.bottom) / 2 4287 }; 4288 } 4289 // Subtracts point2's coordinates from point1's coordinates, returning a delta 4290 function diffPoints(point1, point2) { 4291 return { 4292 left: point1.left - point2.left, 4293 top: point1.top - point2.top 4294 }; 4295 } 4296 4297 var canVGrowWithinCell; 4298 function getCanVGrowWithinCell() { 4299 if (canVGrowWithinCell == null) { 4300 canVGrowWithinCell = computeCanVGrowWithinCell(); 4301 } 4302 return canVGrowWithinCell; 4303 } 4304 function computeCanVGrowWithinCell() { 4305 // for SSR, because this function is call immediately at top-level 4306 // TODO: just make this logic execute top-level, immediately, instead of doing lazily 4307 if (typeof document === 'undefined') { 4308 return true; 4309 } 4310 var el = document.createElement('div'); 4311 el.style.position = 'absolute'; 4312 el.style.top = '0px'; 4313 el.style.left = '0px'; 4314 el.innerHTML = '<table><tr><td><div></div></td></tr></table>'; 4315 el.querySelector('table').style.height = '100px'; 4316 el.querySelector('div').style.height = '100%'; 4317 document.body.appendChild(el); 4318 var div = el.querySelector('div'); 4319 var possible = div.offsetHeight > 0; 4320 document.body.removeChild(el); 4321 return possible; 4322 } 4323 4324 var EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere 4325 var Splitter = /** @class */ (function () { 4326 function Splitter() {
4327 this.getKeysForEventDefs = memoize(this._getKeysForEventDefs); 4328 this.splitDateSelection = memoize(this._splitDateSpan); 4329 this.splitEventStore = memoize(this._splitEventStore); 4330 this.splitIndividualUi = memoize(this._splitIndividualUi); 4331 this.splitEventDrag = memoize(this._splitInteraction); 4332 this.splitEventResize = memoize(this._splitInteraction); 4333 this.eventUiBuilders = {}; // TODO: typescript protection 4334 } 4335 Splitter.prototype.splitProps = function (props) { 4336 var _this = this; 4337 var keyInfos = this.getKeyInfo(props); 4338 var defKeys = this.getKeysForEventDefs(props.eventStore); 4339 var dateSelections = this.splitDateSelection(props.dateSelection); 4340 var individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases* 4341 var eventStores = this.splitEventStore(props.eventStore, defKeys); 4342 var eventDrags = this.splitEventDrag(props.eventDrag); 4343 var eventResizes = this.splitEventResize(props.eventResize); 4344 var splitProps = {}; 4345 this.eventUiBuilders = mapHash(keyInfos, function (info, key) { 4346 return _this.eventUiBuilders[key] || memoize(buildEventUiForKey); 4347 }); 4348 for (var key in keyInfos) { 4349 var keyInfo = keyInfos[key]; 4350 var eventStore = eventStores[key] || EMPTY_EVENT_STORE; 4351 var buildEventUi = this.eventUiBuilders[key]; 4352 splitProps[key] = { 4353 businessHours: keyInfo.businessHours || props.businessHours, 4354 dateSelection: dateSelections[key] || null, 4355 eventStore: eventStore, 4356 eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]), 4357 eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '', 4358 eventDrag: eventDrags[key] || null, 4359 eventResize: eventResizes[key] || null 4360 }; 4361 } 4362 return splitProps; 4363 }; 4364 Splitter.prototype._splitDateSpan = function (dateSpan) { 4365 var dateSpans = {}; 4366 if (dateSpan) { 4367 var keys = this.getKeysForDateSpan(dateSpan); 4368 for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { 4369 var key = keys_1[_i]; 4370 dateSpans[key] = dateSpan; 4371 } 4372 } 4373 return dateSpans; 4374 }; 4375 Splitter.prototype._getKeysForEventDefs = function (eventStore) { 4376 var _this = this; 4377 return mapHash(eventStore.defs, function (eventDef) { 4378 return _this.getKeysForEventDef(eventDef); 4379 }); 4380 }; 4381 Splitter.prototype._splitEventStore = function (eventStore, defKeys) { 4382 var defs = eventStore.defs, instances = eventStore.instances; 4383 var splitStores = {}; 4384 for (var defId in defs) { 4385 for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) { 4386 var key = _a[_i]; 4387 if (!splitStores[key]) { 4388 splitStores[key] = createEmptyEventStore(); 4389 } 4390 splitStores[key].defs[defId] = defs[defId]; 4391 } 4392 } 4393 for (var instanceId in instances) { 4394 var instance = instances[instanceId]; 4395 for (var _b = 0, _c = defKeys[instance.defId]; _b < _c.length; _b++) { 4396 var key = _c[_b]; 4397 if (splitStores[key]) { // must have already been created 4398 splitStores[key].instances[instanceId] = instance; 4399 } 4400 } 4401 } 4402 return splitStores; 4403 }; 4404 Splitter.prototype._splitIndividualUi = function (eventUiBases, defKeys) { 4405 var splitHashes = {}; 4406 for (var defId in eventUiBases) { 4407 if (defId) { // not the '' key 4408 for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) { 4409 var key = _a[_i]; 4410 if (!splitHashes[key]) { 4411 splitHashes[key] = {}; 4412 } 4413 splitHashes[key][defId] = eventUiBases[defId]; 4414 } 4415 } 4416 } 4417 return splitHashes; 4418 }; 4419 Splitter.prototype._splitInteraction = function (interaction) { 4420 var splitStates = {}; 4421 if (interaction) { 4422 var affectedStores_1 = this._splitEventStore(interaction.affectedEvents, this._getKeys
4422ForEventDefs(interaction.affectedEvents) // can't use cached. might be events from other calendar 4423 ); 4424 // can't rely on defKeys because event data is mutated 4425 var mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents); 4426 var mutatedStores_1 = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId); 4427 var populate = function (key) { 4428 if (!splitStates[key]) { 4429 splitStates[key] = { 4430 affectedEvents: affectedStores_1[key] || EMPTY_EVENT_STORE, 4431 mutatedEvents: mutatedStores_1[key] || EMPTY_EVENT_STORE, 4432 isEvent: interaction.isEvent 4433 }; 4434 } 4435 }; 4436 for (var key in affectedStores_1) { 4437 populate(key); 4438 } 4439 for (var key in mutatedStores_1) { 4440 populate(key); 4441 } 4442 } 4443 return splitStates; 4444 }; 4445 return Splitter; 4446 }()); 4447 function buildEventUiForKey(allUi, eventUiForKey, individualUi) { 4448 var baseParts = []; 4449 if (allUi) { 4450 baseParts.push(allUi); 4451 } 4452 if (eventUiForKey) { 4453 baseParts.push(eventUiForKey); 4454 } 4455 var stuff = { 4456 '': combineEventUis(baseParts) 4457 }; 4458 if (individualUi) { 4459 __assign(stuff, individualUi); 4460 } 4461 return stuff; 4462 } 4463 4464 function getDateMeta(date, todayRange, nowDate, dateProfile) { 4465 return { 4466 dow: date.getUTCDay(), 4467 isDisabled: Boolean(dateProfile && !rangeContainsMarker(dateProfile.activeRange, date)), 4468 isOther: Boolean(dateProfile && !rangeContainsMarker(dateProfile.currentRange, date)), 4469 isToday: Boolean(todayRange && rangeContainsMarker(todayRange, date)), 4470 isPast: Boolean(nowDate ? (date < nowDate) : todayRange ? (date < todayRange.start) : false), 4471 isFuture: Boolean(nowDate ? (date > nowDate) : todayRange ? (date >= todayRange.end) : false) 4472 }; 4473 } 4474 function getDayClassNames(meta, theme) { 4475 var classNames = [ 4476 'fc-day', 4477 'fc-day-' + DAY_IDS[meta.dow] 4478 ]; 4479 if (meta.isDisabled) { 4480 classNames.push('fc-day-disabled'); 4481 } 4482 else { 4483 if (meta.isToday) { 4484 classNames.push('fc-day-today'); 4485 classNames.push(theme.getClass('today')); 4486 } 4487 if (meta.isPast) { 4488 classNames.push('fc-day-past'); 4489 } 4490 if (meta.isFuture) { 4491 classNames.push('fc-day-future'); 4492 } 4493 if (meta.isOther) { 4494 classNames.push('fc-day-other'); 4495 } 4496 } 4497 return classNames; 4498 } 4499 function getSlotClassNames(meta, theme) { 4500 var classNames = [ 4501 'fc-slot', 4502 'fc-slot-' + DAY_IDS[meta.dow] 4503 ]; 4504 if (meta.isDisabled) { 4505 classNames.push('fc-slot-disabled'); 4506 } 4507 else { 4508 if (meta.isToday) { 4509 classNames.push('fc-slot-today'); 4510 classNames.push(theme.getClass('today')); 4511 } 4512 if (meta.isPast) { 4513 classNames.push('fc-slot-past'); 4514 } 4515 if (meta.isFuture) { 4516 classNames.push('fc-slot-future'); 4517 } 4518 } 4519 return classNames; 4520 } 4521 4522 function buildNavLinkData(date, type) { 4523 if (type === void 0) { type = 'day'; } 4524 return JSON.stringify({ 4525 date: formatDayString(date), 4526 type: type 4527 }); 4528 } 4529 4530 var _isRtlScrollbarOnLeft = null; 4531 function getIsRtlScrollbarOnLeft() { 4532 if (_isRtlScrollbarOnLeft === null) { 4533 _isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft(); 4534 } 4535 return _isRtlScrollbarOnLeft; 4536 } 4537 function computeIsRtlScrollbarOnLeft() { 4538 var outerEl = document.createElement('div'); 4539 applyStyle(outerEl, { 4540 position: 'absolute', 4541 top: -1000, 4542 left: 0, 4543 border: 0, 4544 padding: 0, 4545 overflow: 'scroll', 4546 direction: 'rtl' 4547 }); 4548 outerEl.innerHTML = '<div></div>'; 4549 document.body.appendChild(outerEl); 4550 var innerEl = outerEl.firstChild; 4551 var res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left; 4552 removeElement(outerEl); 4553 return res; 4554 } 4555 4556 var _scrollbarWidths; 4557 function getScrollbarWidths() { 4558 if (!_scrollbarWidths) {
4559 _scrollbarWidths = computeScrollbarWidths(); 4560 } 4561 return _scrollbarWidths; 4562 } 4563 function computeScrollbarWidths() { 4564 var el = document.createElement('div'); 4565 el.style.overflow = 'scroll'; 4566 document.body.appendChild(el); 4567 var res = computeScrollbarWidthsForEl(el); 4568 document.body.removeChild(el); 4569 return res; 4570 } 4571 // WARNING: will include border 4572 function computeScrollbarWidthsForEl(el) { 4573 return { 4574 x: el.offsetHeight - el.clientHeight, 4575 y: el.offsetWidth - el.clientWidth 4576 }; 4577 } 4578 4579 function computeEdges(el, getPadding) { 4580 if (getPadding === void 0) { getPadding = false; } 4581 var computedStyle = window.getComputedStyle(el); 4582 var borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0; 4583 var borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0; 4584 var borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0; 4585 var borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0; 4586 var badScrollbarWidths = computeScrollbarWidthsForEl(el); // includes border! 4587 var scrollbarLeftRight = badScrollbarWidths.y - borderLeft - borderRight; 4588 var scrollbarBottom = badScrollbarWidths.x - borderTop - borderBottom; 4589 var res = { 4590 borderLeft: borderLeft, 4591 borderRight: borderRight, 4592 borderTop: borderTop, 4593 borderBottom: borderBottom, 4594 scrollbarBottom: scrollbarBottom, 4595 scrollbarLeft: 0, 4596 scrollbarRight: 0 4597 }; 4598 if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side? 4599 res.scrollbarLeft = scrollbarLeftRight; 4600 } 4601 else { 4602 res.scrollbarRight = scrollbarLeftRight; 4603 } 4604 if (getPadding) { 4605 res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0; 4606 res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0; 4607 res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0; 4608 res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0; 4609 } 4610 return res; 4611 } 4612 function computeInnerRect(el, goWithinPadding, doFromWindowViewport) { 4613 if (goWithinPadding === void 0) { goWithinPadding = false; } 4614 var outerRect = doFromWindowViewport ? el.getBoundingClientRect() : computeRect(el); 4615 var edges = computeEdges(el, goWithinPadding); 4616 var res = { 4617 left: outerRect.left + edges.borderLeft + edges.scrollbarLeft, 4618 right: outerRect.right - edges.borderRight - edges.scrollbarRight, 4619 top: outerRect.top + edges.borderTop, 4620 bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom 4621 }; 4622 if (goWithinPadding) { 4623 res.left += edges.paddingLeft; 4624 res.right -= edges.paddingRight; 4625 res.top += edges.paddingTop; 4626 res.bottom -= edges.paddingBottom; 4627 } 4628 return res; 4629 } 4630 function computeRect(el) { 4631 var rect = el.getBoundingClientRect(); 4632 return { 4633 left: rect.left + window.pageXOffset, 4634 top: rect.top + window.pageYOffset, 4635 right: rect.right + window.pageXOffset, 4636 bottom: rect.bottom + window.pageYOffset 4637 }; 4638 } 4639 function computeHeightAndMargins(el) { 4640 return el.getBoundingClientRect().height + computeVMargins(el); 4641 } 4642 function computeVMargins(el) { 4643 var computed = window.getComputedStyle(el); 4644 return parseInt(computed.marginTop, 10) + 4645 parseInt(computed.marginBottom, 10); 4646 } 4647 // does not return window 4648 function getClippingParents(el) { 4649 var parents = []; 4650 while (el instanceof HTMLElement) { // will stop when gets to document or null 4651 var computedStyle = window.getComputedStyle(el); 4652 if (computedStyle.position === 'fixed') { 4653 break; 4654 } 4655 if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) { 4656 parents.push(el); 4657 } 4658 el = el.parentNode; 4659 } 4660 return parents; 4661 } 4662 4663 // given a function that resolves a result asynchronously. 4664 // the function can either call passed-in success and failure callbacks, 4665 // or it can return a promise. 4666 // if you need to pass additional params to func, bind them first. 4667 function unpromisify(func, success, failure) { 4668 // guard against success/failure callbacks being called more than once 4669 // and guard against a promise AND callback being used together. 4670 var isResolved = false;
4671 var wrappedSuccess = function () { 4672 if (!isResolved) { 4673 isResolved = true; 4674 success.apply(this, arguments); 4675 } 4676 }; 4677 var wrappedFailure = function () { 4678 if (!isResolved) { 4679 isResolved = true; 4680 if (failure) { 4681 failure.apply(this, arguments); 4682 } 4683 } 4684 }; 4685 var res = func(wrappedSuccess, wrappedFailure); 4686 if (res && typeof res.then === 'function') { 4687 res.then(wrappedSuccess, wrappedFailure); 4688 } 4689 } 4690 4691 var Emitter = /** @class */ (function () { 4692 function Emitter() { 4693 this.handlers = {}; 4694 this.thisContext = null; 4695 } 4696 Emitter.prototype.setThisContext = function (thisContext) { 4697 this.thisContext = thisContext; 4698 }; 4699 Emitter.prototype.setOptions = function (options) { 4700 this.options = options; 4701 }; 4702 Emitter.prototype.on = function (type, handler) { 4703 addToHash(this.handlers, type, handler); 4704 }; 4705 Emitter.prototype.off = function (type, handler) { 4706 removeFromHash(this.handlers, type, handler); 4707 }; 4708 Emitter.prototype.trigger = function (type) { 4709 var args = []; 4710 for (var _i = 1; _i < arguments.length; _i++) { 4711 args[_i - 1] = arguments[_i]; 4712 } 4713 var attachedHandlers = this.handlers[type] || []; 4714 var optionHandler = this.options && this.options[type]; 4715 var handlers = [].concat(optionHandler || [], attachedHandlers); 4716 for (var _a = 0, handlers_1 = handlers; _a < handlers_1.length; _a++) { 4717 var handler = handlers_1[_a]; 4718 handler.apply(this.thisContext, args); 4719 } 4720 }; 4721 Emitter.prototype.hasHandlers = function (type) { 4722 return (this.handlers[type] && this.handlers[type].length) || 4723 (this.options && this.options[type]); 4724 }; 4725 return Emitter; 4726 }()); 4727 function addToHash(hash, type, handler) { 4728 (hash[type] || (hash[type] = [])) 4729 .push(handler); 4730 } 4731 function removeFromHash(hash, type, handler) { 4732 if (handler) { 4733 if (hash[type]) { 4734 hash[type] = hash[type].filter(function (func) { 4735 return func !== handler; 4736 }); 4737 } 4738 } 4739 else { 4740 delete hash[type]; // remove all handler funcs for this type 4741 } 4742 } 4743 4744 /* 4745 Records offset information for a set of elements, relative to an origin element. 4746 Can record the left/right OR the top/bottom OR both. 4747 Provides methods for querying the cache by position. 4748 */ 4749 var PositionCache = /** @class */ (function () { 4750 function PositionCache(originEl, els, isHorizontal, isVertical) { 4751 this.els = els; 4752 var originClientRect = this.originClientRect = originEl.getBoundingClientRect(); // relative to viewport top-left 4753 if (isHorizontal) { 4754 this.buildElHorizontals(originClientRect.left); 4755 } 4756 if (isVertical) { 4757 this.buildElVerticals(originClientRect.top); 4758 } 4759 } 4760 // Populates the left/right internal coordinate arrays 4761 PositionCache.prototype.buildElHorizontals = function (originClientLeft) { 4762 var lefts = []; 4763 var rights = []; 4764 for (var _i = 0, _a = this.els; _i < _a.length; _i++) { 4765 var el = _a[_i]; 4766 var rect = el.getBoundingClientRect(); 4767 lefts.push(rect.left - originClientLeft); 4768 rights.push(rect.right - originClientLeft); 4769 } 4770 this.lefts = lefts; 4771 this.rights = rights; 4772 }; 4773 // Populates the top/bottom internal coordinate arrays 4774 PositionCache.prototype.buildElVerticals = function (originClientTop) { 4775 var tops = []; 4776 var bottoms = []; 4777 for (var _i = 0, _a = this.els; _i < _a.length; _i++) { 4778 var el = _a[_i]; 4779 var rect = el.getBoundingClientRect(); 4780 tops.push(rect.top - originClientTop); 4781 bottoms.push(rect.bottom - originClientTop); 4782 } 4783 this.tops = tops; 4784 this.bottoms = bottoms; 4785 }; 4786 // Given a left offset (from document left), returns the index of the el that it horizontally intersects. 4787 // If no intersection is made, returns undefined. 4788 PositionCache.prototype.leftToIndex = function (leftPosition) { 4789 var lefts = this.lefts; 4790 var rights = this.rights; 4791 var len = lefts.length; 4792 var i; 4793 for (i = 0; i < len; i++) { 4794 if (leftPosition >= lefts[i] && leftPosition < rights[i]) { 4795 return i; 4796 } 4797 } 4798 }; 4799 // Given a top offset (from document top), returns the index of the el that it vertically intersects. 4800 // If no intersection is made, returns undefined. 4801 PositionCache.prototype.topToIndex = function (topPosition) { 4802 var tops = this.tops; 4803 var bottoms = this.bottoms; 4804 var len = tops.length; 4805 var i; 4806 for (i = 0; i < len; i++) { 4807 if (topPosition >= tops[i] && topPosition < bottoms[i]) { 4808 return i; 4809 } 4810 } 4811 }; 4812 // Gets the width of the element at the given index 4813 PositionCache.prototype.getWidth = function (leftIndex) { 4814 return this.rights[leftIndex] - this.lefts[leftIndex]; 4815 }; 4816 // Gets the height of the element at the given index 4817 PositionCache.prototype.getHeight = function (topIndex) { 4818 return this.bottoms[topIndex] - this.tops[topIndex]; 4819 }; 4820 return PositionCache; 4821 }()); 4822 4823 /* 4824 An object for getting/setting scroll-related information for an element. 4825 Internally, this is done very differently for window versus DOM element, 4826 so this object serves as a common interface. 4827 */ 4828 var ScrollController = /** @class */ (function () {
4829 function ScrollController() { 4830 } 4831 ScrollController.prototype.getMaxScrollTop = function () { 4832 return this.getScrollHeight() - this.getClientHeight(); 4833 }; 4834 ScrollController.prototype.getMaxScrollLeft = function () { 4835 return this.getScrollWidth() - this.getClientWidth(); 4836 }; 4837 ScrollController.prototype.canScrollVertically = function () { 4838 return this.getMaxScrollTop() > 0; 4839 }; 4840 ScrollController.prototype.canScrollHorizontally = function () { 4841 return this.getMaxScrollLeft() > 0; 4842 }; 4843 ScrollController.prototype.canScrollUp = function () { 4844 return this.getScrollTop() > 0; 4845 }; 4846 ScrollController.prototype.canScrollDown = function () { 4847 return this.getScrollTop() < this.getMaxScrollTop(); 4848 }; 4849 ScrollController.prototype.canScrollLeft = function () { 4850 return this.getScrollLeft() > 0; 4851 }; 4852 ScrollController.prototype.canScrollRight = function () { 4853 return this.getScrollLeft() < this.getMaxScrollLeft(); 4854 }; 4855 return ScrollController; 4856 }()); 4857 var ElementScrollController = /** @class */ (function (_super) { 4858 __extends(ElementScrollController, _super); 4859 function ElementScrollController(el) { 4860 var _this = _super.call(this) || this; 4861 _this.el = el; 4862 return _this; 4863 } 4864 ElementScrollController.prototype.getScrollTop = function () { 4865 return this.el.scrollTop; 4866 }; 4867 ElementScrollController.prototype.getScrollLeft = function () { 4868 return this.el.scrollLeft; 4869 }; 4870 ElementScrollController.prototype.setScrollTop = function (top) { 4871 this.el.scrollTop = top; 4872 }; 4873 ElementScrollController.prototype.setScrollLeft = function (left) { 4874 this.el.scrollLeft = left; 4875 }; 4876 ElementScrollController.prototype.getScrollWidth = function () { 4877 return this.el.scrollWidth; 4878 }; 4879 ElementScrollController.prototype.getScrollHeight = function () { 4880 return this.el.scrollHeight; 4881 }; 4882 ElementScrollController.prototype.getClientHeight = function () { 4883 return this.el.clientHeight; 4884 }; 4885 ElementScrollController.prototype.getClientWidth = function () { 4886 return this.el.clientWidth; 4887 }; 4888 return ElementScrollController; 4889 }(ScrollController)); 4890 var WindowScrollController = /** @class */ (function (_super) { 4891 __extends(WindowScrollController, _super); 4892 function WindowScrollController() { 4893 return _super !== null && _super.apply(this, arguments) || this; 4894 } 4895 WindowScrollController.prototype.getScrollTop = function () { 4896 return window.pageYOffset; 4897 }; 4898 WindowScrollController.prototype.getScrollLeft = function () { 4899 return window.pageXOffset; 4900 }; 4901 WindowScrollController.prototype.setScrollTop = function (n) { 4902 window.scroll(window.pageXOffset, n); 4903 }; 4904 WindowScrollController.prototype.setScrollLeft = function (n) { 4905 window.scroll(n, window.pageYOffset); 4906 }; 4907 WindowScrollController.prototype.getScrollWidth = function () { 4908 return document.documentElement.scrollWidth; 4909 }; 4910 WindowScrollController.prototype.getScrollHeight = function () { 4911 return document.documentElement.scrollHeight; 4912 }; 4913 WindowScrollController.prototype.getClientHeight = function () { 4914 return document.documentElement.clientHeight; 4915 }; 4916 WindowScrollController.prototype.getClientWidth = function () { 4917 return document.documentElement.clientWidth; 4918 }; 4919 return WindowScrollController; 4920 }(ScrollController)); 4921 4922 var Theme = /** @class */ (function () { 4923 function Theme(calendarOptions) { 4924 if (this.iconOverrideOption) { 4925 this.setIconOverride(calendarOptions[this.iconOverrideOption]); 4926 } 4927 } 4928 Theme.prototype.setIconOverride = function (iconOverrideHash) { 4929 var iconClassesCopy; 4930 var buttonName; 4931 if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object 4932 iconClassesCopy = __assign({}, this.iconClasses); 4933 for (buttonName in iconOverrideHash) { 4934 iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]); 4935 } 4936 this.iconClasses = iconClassesCopy; 4937 } 4938 else if (iconOverrideHash === false) { 4939 this.iconClasses = {}; 4940 } 4941 }; 4942 Theme.prototype.applyIconOverridePrefix = function (className) { 4943 var prefix = this.iconOverridePrefix; 4944 if (prefix && className.indexOf(prefix) !== 0) { // if not already present 4945 className = prefix + className; 4946 } 4947 return className; 4948 }; 4949 Theme.prototype.getClass = function (key) { 4950 return this.classes[key] || ''; 4951 }; 4952 Theme.prototype.getIconClass = function (buttonName, isRtl) { 4953 var className; 4954 if (isRtl && this.rtlIconClasses) { 4955 className = this.rtlIconClasses[buttonName] || this.iconClasses[buttonName]; 4956 } 4957 else { 4958 className = this.iconClasses[buttonName]; 4959 } 4960 if (className) { 4961 return this.baseIconClass + ' ' + className; 4962 } 4963 return ''; 4964 }; 4965 Theme.prototype.getCustomButtonIconClass = function (customButtonProps) { 4966 var className; 4967 if (this.iconOverrideCustomButtonOption) { 4968 className = customButtonProps[this.iconOverrideCustomButtonOption]; 4969 if (className) { 4970 return this.baseIconClass + ' ' + this.applyIconOverridePrefix(className); 4971 } 4972 } 4973 return ''; 4974 }; 4975 return Theme; 4976 }()); 4977 Theme.prototype.classes = {}; 4978 Theme.prototype.iconClasses = {}; 4979 Theme.prototype.baseIconClass = ''; 4980 Theme.prototype.iconOverridePrefix = ''; 4981 4982 /// <reference types="@fullcalendar/core-vdom" /> 4983 if (typeof FullCalendarVDom === 'undefined') { 4984 throw new Error('Please import the top-level fullcalendar lib before attempting to import a plugin.'); 4985 } 4986 var Component = FullCalendarVDom.Component; 4987 var createElement = FullCalendarVDom.createElement; 4988 var render = FullCalendarVDom.render; 4989 var createRef = FullCalendarVDom.createRef; 4990 var Fragment = FullCalendarVDom.Fragment; 4991 var createContext$1 = FullCalendarVDom.createContext; 4992 var flushToDom$1 = FullCalendarVDom.flushToDom; 4993 4994 var ScrollResponder = /** @class */ (function () { 4995 function ScrollResponder(execFunc, emitter, scrollTime) { 4996 var _this = this; 4997 this.execFunc = execFunc; 4998 this.emitter = emitter; 4999 this.scrollTime = scrollTime; 5000 this.handleScrollRequest = function (request) { 5001 _this.queuedRequest = __assign({}, _this.queuedRequest || {}, request); 5002 _this.drain(); 5003 }; 5004 emitter.on('_scrollRequest', this.handleScrollRequest); 5005 this.fireInitialScroll(); 5006 } 5007 ScrollResponder.prototype.detach = function () { 5008 this.emitter.off('_scrollRequest', this.handleScrollRequest); 5009 }; 5010 ScrollResponder.prototype.update = function (isDatesNew) { 5011 if (isDatesNew) { 5012 this.fireInitialScroll(); // will drain 5013 } 5014 else { 5015 this.drain(); 5016 } 5017 }; 5018 ScrollResponder.prototype.fireInitialScroll = function () { 5019 this.handleScrollRequest({ 5020 time: this.scrollTime 5021 }); 5022 };
5023 ScrollResponder.prototype.drain = function () { 5024 if (this.queuedRequest && this.execFunc(this.queuedRequest)) { 5025 this.queuedRequest = null; 5026 } 5027 }; 5028 return ScrollResponder; 5029 }()); 5030 5031 var ViewContextType = createContext$1({}); // for Components 5032 function buildViewContext(viewSpec, viewApi, viewOptions, dateProfileGenerator, dateEnv, theme, pluginHooks, dispatch, getCurrentData, emitter, calendarApi, registerInteractiveComponent, unregisterInteractiveComponent) { 5033 return { 5034 dateEnv: dateEnv, 5035 options: viewOptions, 5036 pluginHooks: pluginHooks, 5037 emitter: emitter, 5038 dispatch: dispatch, 5039 getCurrentData: getCurrentData, 5040 calendarApi: calendarApi, 5041 viewSpec: viewSpec, 5042 viewApi: viewApi, 5043 dateProfileGenerator: dateProfileGenerator, 5044 theme: theme, 5045 isRtl: viewOptions.direction === 'rtl', 5046 addResizeHandler: function (handler) { 5047 emitter.on('_resize', handler); 5048 }, 5049 removeResizeHandler: function (handler) { 5050 emitter.off('_resize', handler); 5051 }, 5052 createScrollResponder: function (execFunc) { 5053 return new ScrollResponder(execFunc, emitter, createDuration(viewOptions.scrollTime)); 5054 }, 5055 registerInteractiveComponent: registerInteractiveComponent, 5056 unregisterInteractiveComponent: unregisterInteractiveComponent 5057 }; 5058 } 5059 5060 var PureComponent = /** @class */ (function (_super) { 5061 __extends(PureComponent, _super); 5062 function PureComponent() { 5063 return _super !== null && _super.apply(this, arguments) || this; 5064 } 5065 PureComponent.prototype.shouldComponentUpdate = function (nextProps, nextState) { 5066 if (this.debug) { 5067 console.log(getUnequalProps(nextProps, this.props), getUnequalProps(nextState, this.state)); 5068 } 5069 return !compareObjs(this.props, nextProps, this.propEquality) || 5070 !compareObjs(this.state, nextState, this.stateEquality); 5071 }; 5072 PureComponent.addPropsEquality = addPropsEquality; 5073 PureComponent.addStateEquality = addStateEquality; 5074 PureComponent.contextType = ViewContextType; 5075 return PureComponent; 5076 }(Component)); 5077 PureComponent.prototype.propEquality = {}; 5078 PureComponent.prototype.stateEquality = {}; 5079 var BaseComponent = /** @class */ (function (_super) { 5080 __extends(BaseComponent, _super); 5081 function BaseComponent() { 5082 return _super !== null && _super.apply(this, arguments) || this; 5083 } 5084 BaseComponent.contextType = ViewContextType; 5085 return BaseComponent; 5086 }(PureComponent)); 5087 function addPropsEquality(propEquality) { 5088 var hash = Object.create(this.prototype.propEquality); 5089 __assign(hash, propEquality); 5090 this.prototype.propEquality = hash; 5091 } 5092 function addStateEquality(stateEquality) { 5093 var hash = Object.create(this.prototype.stateEquality); 5094 __assign(hash, stateEquality); 5095 this.prototype.stateEquality = hash; 5096 } 5097 // use other one 5098 function setRef(ref, current) { 5099 if (typeof ref === 'function') { 5100 ref(current); 5101 } 5102 else if (ref) { 5103 // see https://github.com/facebook/react/issues/13029 5104 ref.current = current; 5105 } 5106 } 5107 5108 function reduceEventStore(eventStore, action, eventSources, dateProfile, context) { 5109 switch (action.type) { 5110 case 'RECEIVE_EVENTS': // raw 5111 return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, context); 5112 case 'ADD_EVENTS': // already parsed, but not expanded 5113 return addEvent(eventStore, action.eventStore, // new ones 5114 dateProfile ? dateProfile.activeRange : null, context); 5115 case 'MERGE_EVENTS': // already parsed and expanded 5116 return mergeEventStores(eventStore, action.eventStore); 5117 case 'PREV': // TODO: how do we track all actions that affect dateProfile :( 5118 case 'NEXT': 5119 case 'CHANGE_DATE': 5120 case 'CHANGE_VIEW_TYPE': 5121 if (dateProfile) { 5122 return expandRecurring(eventStore, dateProfile.activeRange, context); 5123 } 5124 else { 5125 return eventStore; 5126 }
5127 case 'REMOVE_EVENTS': 5128 return excludeSubEventStore(eventStore, action.eventStore); 5129 case 'REMOVE_EVENT_SOURCE': 5130 return excludeEventsBySourceId(eventStore, action.sourceId); 5131 case 'REMOVE_ALL_EVENT_SOURCES': 5132 return filterEventStoreDefs(eventStore, function (eventDef) { 5133 return !eventDef.sourceId; // only keep events with no source id 5134 }); 5135 case 'REMOVE_ALL_EVENTS': 5136 return createEmptyEventStore(); 5137 default: 5138 return eventStore; 5139 } 5140 } 5141 function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, context) { 5142 if (eventSource && // not already removed 5143 fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources 5144 ) { 5145 var subset = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context); 5146 if (fetchRange) { 5147 subset = expandRecurring(subset, fetchRange, context); 5148 } 5149 return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset); 5150 } 5151 return eventStore; 5152 } 5153 function transformRawEvents(rawEvents, eventSource, context) { 5154 var calEachTransform = context.options.eventDataTransform; 5155 var sourceEachTransform = eventSource ? eventSource.eventDataTransform : null; 5156 if (sourceEachTransform) { 5157 rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform); 5158 } 5159 if (calEachTransform) { 5160 rawEvents = transformEachRawEvent(rawEvents, calEachTransform); 5161 } 5162 return rawEvents; 5163 } 5164 function transformEachRawEvent(rawEvents, func) { 5165 var refinedEvents; 5166 if (!func) { 5167 refinedEvents = rawEvents; 5168 } 5169 else { 5170 refinedEvents = []; 5171 for (var _i = 0, rawEvents_1 = rawEvents; _i < rawEvents_1.length; _i++) { 5172 var rawEvent = rawEvents_1[_i]; 5173 var refinedEvent = func(rawEvent); 5174 if (refinedEvent) { 5175 refinedEvents.push(refinedEvent); 5176 } 5177 else if (refinedEvent == null) { 5178 refinedEvents.push(rawEvent); 5179 } // if a different falsy value, do nothing 5180 } 5181 } 5182 return refinedEvents; 5183 } 5184 function addEvent(eventStore, subset, expandRange, context) { 5185 if (expandRange) { 5186 subset = expandRecurring(subset, expandRange, context); 5187 } 5188 return mergeEventStores(eventStore, subset); 5189 } 5190 function rezoneEventStoreDates(eventStore, oldDateEnv, newDateEnv) { 5191 var defs = eventStore.defs; 5192 var instances = mapHash(eventStore.instances, function (instance) { 5193 var def = defs[instance.defId]; 5194 if (def.allDay || def.recurringDef) { 5195 return instance; // isn't dependent on timezone 5196 } 5197 else { 5198 return __assign(__assign({}, instance), { range: { 5199 start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)), 5200 end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo)) 5201 }, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo }); 5202 } 5203 }); 5204 return { defs: defs, instances: instances }; 5205 } 5206 function excludeEventsBySourceId(eventStore, sourceId) { 5207 return filterEventStoreDefs(eventStore, function (eventDef) { 5208 return eventDef.sourceId !== sourceId; 5209 }); 5210 } 5211 // QUESTION: why not just return instances? do a general object-property-exclusion util 5212 function excludeInstances(eventStore, removals) { 5213 return { 5214 defs: eventStore.defs, 5215 instances: filterHash(eventStore.instances, function (instance) { 5216 return !removals[instance.instanceId]; 5217 }) 5218 }; 5219 } 5220 5221 // high-level segmenting-aware tester functions 5222 // ------------------------------------------------------------------------------------------------------------------------ 5223 function isInteractionValid(interaction, context) { 5224 return isNewPropsValid({ eventDrag: interaction }, context); // HACK: the eventDrag props is used for ALL interactions 5225 } 5226 function isDateSelectionValid(dateSelection, context) { 5227 return isNewPropsValid({ dateSelection: dateSelection }, context); 5228 } 5229 function isNewPropsValid(newProps, context) { 5230 var calendarState = context.getCurrentData(); 5231 var props = __assign({ businessHours: calendarState.businessHours, dateSelection: '', eventStore: calendarState.eventStore, eventUiBases: calendarState.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps); 5232 return (context.pluginHooks.isPropsValid || isPropsValid)(props, context); 5233 } 5234 function isPropsValid(state, context, dateSpanMeta, filterConfig) {
5235 if (dateSpanMeta === void 0) { dateSpanMeta = {}; } 5236 if (state.eventDrag && !isInteractionPropsValid(state, context, dateSpanMeta, filterConfig)) { 5237 return false; 5238 } 5239 if (state.dateSelection && !isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig)) { 5240 return false; 5241 } 5242 return true; 5243 } 5244 // Moving Event Validation 5245 // ------------------------------------------------------------------------------------------------------------------------ 5246 function isInteractionPropsValid(state, context, dateSpanMeta, filterConfig) { 5247 var currentState = context.getCurrentData(); 5248 var interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions 5249 var subjectEventStore = interaction.mutatedEvents; 5250 var subjectDefs = subjectEventStore.defs; 5251 var subjectInstances = subjectEventStore.instances; 5252 var subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ? 5253 state.eventUiBases : 5254 { '': currentState.selectionConfig } // if not a real event, validate as a selection 5255 ); 5256 if (filterConfig) { 5257 subjectConfigs = mapHash(subjectConfigs, filterConfig); 5258 } 5259 var otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances); // exclude the subject events. TODO: exclude defs too? 5260 var otherDefs = otherEventStore.defs; 5261 var otherInstances = otherEventStore.instances; 5262 var otherConfigs = compileEventUis(otherDefs, state.eventUiBases); 5263 for (var subjectInstanceId in subjectInstances) { 5264 var subjectInstance = subjectInstances[subjectInstanceId]; 5265 var subjectRange = subjectInstance.range; 5266 var subjectConfig = subjectConfigs[subjectInstance.defId]; 5267 var subjectDef = subjectDefs[subjectInstance.defId]; 5268 // constraint 5269 if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, context)) { 5270 return false; 5271 } 5272 // overlap 5273 var eventOverlap = context.options.eventOverlap; 5274 var eventOverlapFunc = typeof eventOverlap === 'function' ? eventOverlap : null; 5275 for (var otherInstanceId in otherInstances) { 5276 var otherInstance = otherInstances[otherInstanceId]; 5277 // intersect! evaluate 5278 if (rangesIntersect(subjectRange, otherInstance.range)) { 5279 var otherOverlap = otherConfigs[otherInstance.defId].overlap; 5280 // consider the other event's overlap. only do this if the subject event is a "real" event 5281 if (otherOverlap === false && interaction.isEvent) { 5282 return false; 5283 } 5284 if (subjectConfig.overlap === false) { 5285 return false; 5286 } 5287 if (eventOverlapFunc && !eventOverlapFunc(new EventApi(context, otherDefs[otherInstance.defId], otherInstance), // still event 5288 new EventApi(context, subjectDef, subjectInstance) // moving event 5289 )) { 5290 return false; 5291 } 5292 } 5293 } 5294 // allow (a function) 5295 var calendarEventStore = currentState.eventStore; // need global-to-calendar, not local to component (splittable)state 5296 for (var _i = 0, _a = subjectConfig.allows; _i < _a.length; _i++) { 5297 var subjectAllow = _a[_i]; 5298 var subjectDateSpan = __assign(__assign({}, dateSpanMeta), { range: subjectInstance.range, allDay: subjectDef.allDay }); 5299 var origDef = calendarEventStore.defs[subjectDef.defId]; 5300 var origInstance = calendarEventStore.instances[subjectInstanceId]; 5301 var eventApi = void 0; 5302 if (origDef) { // was previously in the calendar 5303 eventApi = new EventApi(context, origDef, origInstance); 5304 } 5305 else { // was an external event 5306 eventApi = new EventApi(context, subjectDef); // no instance, because had no dates 5307 } 5308 if (!subjectAllow(buildDateSpanApiWithContext(subjectDateSpan, context), eventApi)) { 5309 return false;
5310 } 5311 } 5312 } 5313 return true; 5314 } 5315 // Date Selection Validation 5316 // ------------------------------------------------------------------------------------------------------------------------ 5317 function isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig) { 5318 var relevantEventStore = state.eventStore; 5319 var relevantDefs = relevantEventStore.defs; 5320 var relevantInstances = relevantEventStore.instances; 5321 var selection = state.dateSelection; 5322 var selectionRange = selection.range; 5323 var selectionConfig = context.getCurrentData().selectionConfig; 5324 if (filterConfig) { 5325 selectionConfig = filterConfig(selectionConfig); 5326 } 5327 // constraint 5328 if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, context)) { 5329 return false; 5330 } 5331 // overlap 5332 var selectOverlap = context.options.selectOverlap; 5333 var selectOverlapFunc = typeof selectOverlap === 'function' ? selectOverlap : null; 5334 for (var relevantInstanceId in relevantInstances) { 5335 var relevantInstance = relevantInstances[relevantInstanceId]; 5336 // intersect! evaluate 5337 if (rangesIntersect(selectionRange, relevantInstance.range)) { 5338 if (selectionConfig.overlap === false) { 5339 return false; 5340 } 5341 if (selectOverlapFunc && !selectOverlapFunc(new EventApi(context, relevantDefs[relevantInstance.defId], relevantInstance), null)) { 5342 return false; 5343 } 5344 } 5345 } 5346 // allow (a function) 5347 for (var _i = 0, _a = selectionConfig.allows; _i < _a.length; _i++) { 5348 var selectionAllow = _a[_i]; 5349 var fullDateSpan = __assign(__assign({}, dateSpanMeta), selection); 5350 if (!selectionAllow(buildDateSpanApiWithContext(fullDateSpan, context), null)) { 5351 return false; 5352 } 5353 } 5354 return true; 5355 } 5356 // Constraint Utils 5357 // ------------------------------------------------------------------------------------------------------------------------ 5358 function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, context) { 5359 for (var _i = 0, constraints_1 = constraints; _i < constraints_1.length; _i++) { 5360 var constraint = constraints_1[_i]; 5361 if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, context), subjectRange)) { 5362 return false; 5363 } 5364 } 5365 return true; 5366 } 5367 function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours 5368 otherEventStore, // for if constraint is an even group ID 5369 businessHoursUnexpanded, // for if constraint is 'businessHours' 5370 context // for expanding businesshours 5371 ) { 5372 if (constraint === 'businessHours') { 5373 return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, context)); 5374 } 5375 else if (typeof constraint === 'string') { // an group ID 5376 return eventStoreToRanges(filterEventStoreDefs(otherEventStore, function (eventDef) { 5377 return eventDef.groupId === constraint; 5378 })); 5379 } 5380 else if (typeof constraint === 'object' && constraint) { // non-null object 5381 return eventStoreToRanges(expandRecurring(constraint, subjectRange, context)); 5382 } 5383 return []; // if it's false 5384 } 5385 // TODO: move to event-store file? 5386 function eventStoreToRanges(eventStore) { 5387 var instances = eventStore.instances; 5388 var ranges = []; 5389 for (var instanceId in instances) { 5390 ranges.push(instances[instanceId].range); 5391 } 5392 return ranges; 5393 } 5394 // TODO: move to geom file? 5395 function anyRangesContainRange(outerRanges, innerRange) { 5396 for (var _i = 0, outerRanges_1 = outerRanges; _i < outerRanges_1.length; _i++) { 5397 var outerRange = outerRanges_1[_i]; 5398 if (rangeContainsRange(outerRange, innerRange)) { 5399 return true; 5400 } 5401 } 5402 return false;
5403 } 5404 5405 /* 5406 an INTERACTABLE date component 5407 5408 PURPOSES: 5409 - hook up to fg, fill, and mirror renderers 5410 - interface for dragging and hits 5411 */ 5412 var DateComponent = /** @class */ (function (_super) { 5413 __extends(DateComponent, _super); 5414 function DateComponent() { 5415 var _this = _super !== null && _super.apply(this, arguments) || this; 5416 _this.uid = guid(); 5417 return _this; 5418 } 5419 // Hit System 5420 // ----------------------------------------------------------------------------------------------------------------- 5421 DateComponent.prototype.prepareHits = function () { 5422 }; 5423 DateComponent.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) { 5424 return null; // this should be abstract 5425 }; 5426 // Validation 5427 // ----------------------------------------------------------------------------------------------------------------- 5428 DateComponent.prototype.isInteractionValid = function (interaction) { 5429 var dateProfile = this.props.dateProfile; // HACK 5430 var instances = interaction.mutatedEvents.instances; 5431 if (dateProfile) { // HACK for MorePopover 5432 for (var instanceId in instances) { 5433 if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) { 5434 return false; 5435 } 5436 } 5437 } 5438 return isInteractionValid(interaction, this.context); 5439 }; 5440 DateComponent.prototype.isDateSelectionValid = function (selection) { 5441 var dateProfile = this.props.dateProfile; // HACK 5442 if (dateProfile && // HACK for MorePopover 5443 !rangeContainsRange(dateProfile.validRange, selection.range)) { 5444 return false; 5445 } 5446 return isDateSelectionValid(selection, this.context); 5447 }; 5448 // Pointer Interaction Utils 5449 // ----------------------------------------------------------------------------------------------------------------- 5450 DateComponent.prototype.isValidSegDownEl = function (el) { 5451 return !this.props.eventDrag && // HACK 5452 !this.props.eventResize && // HACK 5453 !elementClosest(el, '.fc-event-mirror') && 5454 (this.isPopover() || !this.isInPopover(el)); 5455 // ^above line ensures we don't detect a seg interaction within a nested component. 5456 // it's a HACK because it only supports a popover as the nested component. 5457 }; 5458 DateComponent.prototype.isValidDateDownEl = function (el) { 5459 return !elementClosest(el, '.fc-event:not(.fc-bg-event)') && 5460 !elementClosest(el, '.fc-daygrid-more-link') && // a "more.." link 5461 !elementClosest(el, 'a[data-navlink]') && // a clickable nav link 5462 !this.isInPopover(el); 5463 }; 5464 DateComponent.prototype.isPopover = function () { 5465 return false; 5466 }; 5467 DateComponent.prototype.isInPopover = function (el) { 5468 return Boolean(elementClosest(el, '.fc-popover')); 5469 }; 5470 return DateComponent; 5471 }(BaseComponent)); 5472 5473 // TODO: easier way to add new hooks? need to update a million things 5474 function createPlugin(input) { 5475 return { 5476 id: guid(), 5477 deps: input.deps || [], 5478 reducers: input.reducers || [], 5479 contextInit: [].concat(input.contextInit || []), 5480 eventRefiners: input.eventRefiners || {}, 5481 eventDefMemberAdders: input.eventDefMemberAdders || [], 5482 eventSourceRefiners: input.eventSourceRefiners || {}, 5483 isDraggableTransformers: input.isDraggableTransformers || [], 5484 eventDragMutationMassagers: input.eventDragMutationMassagers || [], 5485 eventDefMutationAppliers: input.eventDefMutationAppliers || [], 5486 dateSelectionTransformers: input.dateSelectionTransformers || [], 5487 datePointTransforms: input.datePointTransforms || [], 5488 dateSpanTransforms: input.dateSpanTransforms || [], 5489 views: input.views || {}, 5490 viewPropsTransformers: input.viewPropsTransformers || [], 5491 isPropsValid: input.isPropsValid || null, 5492 externalDefTransforms: input.externalDefTransforms || [], 5493 eventResizeJoinTransforms: input.eventResizeJoinTransforms || [], 5494 viewContainerAppends: input.viewContainerAppends || [], 5495 eventDropTransformers: input.eventDropTransformers || [], 5496 componentInteractions: input.componentInteractions || [], 5497 calendarInteractions: input.calendarInteractions || [],
5498 themeClasses: input.themeClasses || {}, 5499 eventSourceDefs: input.eventSourceDefs || [], 5500 cmdFormatter: input.cmdFormatter, 5501 recurringTypes: input.recurringTypes || [], 5502 namedTimeZonedImpl: input.namedTimeZonedImpl, 5503 initialView: input.initialView || '', 5504 elementDraggingImpl: input.elementDraggingImpl, 5505 optionChangeHandlers: input.optionChangeHandlers || {}, 5506 scrollGridImpl: input.scrollGridImpl || null, 5507 contentTypeHandlers: input.contentTypeHandlers || {}, 5508 listenerRefiners: input.listenerRefiners || {}, 5509 optionRefiners: input.optionRefiners || {}, 5510 propSetHandlers: input.propSetHandlers || {} 5511 }; 5512 } 5513 function buildPluginHooks(pluginDefs, globalDefs) { 5514 var isAdded = {}; 5515 var hooks = { 5516 reducers: [], 5517 contextInit: [], 5518 eventRefiners: {}, 5519 eventDefMemberAdders: [], 5520 eventSourceRefiners: {}, 5521 isDraggableTransformers: [], 5522 eventDragMutationMassagers: [], 5523 eventDefMutationAppliers: [], 5524 dateSelectionTransformers: [], 5525 datePointTransforms: [], 5526 dateSpanTransforms: [], 5527 views: {}, 5528 viewPropsTransformers: [], 5529 isPropsValid: null, 5530 externalDefTransforms: [], 5531 eventResizeJoinTransforms: [], 5532 viewContainerAppends: [], 5533 eventDropTransformers: [], 5534 componentInteractions: [], 5535 calendarInteractions: [], 5536 themeClasses: {}, 5537 eventSourceDefs: [], 5538 cmdFormatter: null, 5539 recurringTypes: [], 5540 namedTimeZonedImpl: null, 5541 initialView: '', 5542 elementDraggingImpl: null, 5543 optionChangeHandlers: {}, 5544 scrollGridImpl: null, 5545 contentTypeHandlers: {}, 5546 listenerRefiners: {}, 5547 optionRefiners: {}, 5548 propSetHandlers: {} 5549 }; 5550 function addDefs(defs) { 5551 for (var _i = 0, defs_1 = defs; _i < defs_1.length; _i++) { 5552 var def = defs_1[_i]; 5553 if (!isAdded[def.id]) { 5554 isAdded[def.id] = true; 5555 addDefs(def.deps); 5556 hooks = combineHooks(hooks, def); 5557 } 5558 } 5559 } 5560 if (pluginDefs) { 5561 addDefs(pluginDefs); 5562 } 5563 addDefs(globalDefs); 5564 return hooks; 5565 } 5566 function buildBuildPluginHooks() { 5567 var currentOverrideDefs = []; 5568 var currentGlobalDefs = []; 5569 var currentHooks; 5570 return function (overrideDefs, globalDefs) { 5571 if (!currentHooks || !isArraysEqual(overrideDefs, currentOverrideDefs) || !isArraysEqual(globalDefs, currentGlobalDefs)) { 5572 currentHooks = buildPluginHooks(overrideDefs, globalDefs); 5573 } 5574 currentOverrideDefs = overrideDefs; 5575 currentGlobalDefs = globalDefs; 5576 return currentHooks; 5577 }; 5578 } 5579 function combineHooks(hooks0, hooks1) { 5580 return { 5581 reducers: hooks0.reducers.concat(hooks1.reducers), 5582 contextInit: hooks0.contextInit.concat(hooks1.contextInit), 5583 eventRefiners: __assign(__assign({}, hooks0.eventRefiners), hooks1.eventRefiners), 5584 eventDefMemberAdders: hooks0.eventDefMemberAdders.concat(hooks1.eventDefMemberAdders), 5585 eventSourceRefiners: __assign(__assign({}, hooks0.eventSourceRefiners), hooks1.eventSourceRefiners), 5586 isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers), 5587 eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers), 5588 eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers), 5589 dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers), 5590 datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms), 5591 dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms), 5592 views: __assign(__assign({}, hooks0.views), hooks1.views), 5593 viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers), 5594 isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid, 5595 externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms), 5596 eventResizeJoinTransforms: hooks0.eventResizeJoinTransforms.concat(hooks1.eventResizeJoinTransforms), 5597 viewContainerAppends: hooks0.viewContainerAppends.concat(hooks1.viewContainerAppends), 5598 eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers), 5599 calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions), 5600 componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions),
5601 themeClasses: __assign(__assign({}, hooks0.themeClasses), hooks1.themeClasses), 5602 eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs), 5603 cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter, 5604 recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes), 5605 namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl, 5606 initialView: hooks0.initialView || hooks1.initialView, 5607 elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl, 5608 optionChangeHandlers: __assign(__assign({}, hooks0.optionChangeHandlers), hooks1.optionChangeHandlers), 5609 scrollGridImpl: hooks1.scrollGridImpl || hooks0.scrollGridImpl, 5610 contentTypeHandlers: __assign(__assign({}, hooks0.contentTypeHandlers), hooks1.contentTypeHandlers), 5611 listenerRefiners: __assign(__assign({}, hooks0.listenerRefiners), hooks1.listenerRefiners), 5612 optionRefiners: __assign(__assign({}, hooks0.optionRefiners), hooks1.optionRefiners), 5613 propSetHandlers: __assign(__assign({}, hooks0.propSetHandlers), hooks1.propSetHandlers) 5614 }; 5615 } 5616 5617 var StandardTheme = /** @class */ (function (_super) { 5618 __extends(StandardTheme, _super); 5619 function StandardTheme() { 5620 return _super !== null && _super.apply(this, arguments) || this; 5621 } 5622 return StandardTheme; 5623 }(Theme)); 5624 StandardTheme.prototype.classes = { 5625 root: 'fc-theme-standard', 5626 tableCellShaded: 'fc-cell-shaded', 5627 buttonGroup: 'fc-button-group', 5628 button: 'fc-button fc-button-primary', 5629 buttonActive: 'fc-button-active' 5630 }; 5631 StandardTheme.prototype.baseIconClass = 'fc-icon'; 5632 StandardTheme.prototype.iconClasses = { 5633 close: 'fc-icon-x', 5634 prev: 'fc-icon-chevron-left', 5635 next: 'fc-icon-chevron-right', 5636 prevYear: 'fc-icon-chevrons-left', 5637 nextYear: 'fc-icon-chevrons-right' 5638 }; 5639 StandardTheme.prototype.rtlIconClasses = { 5640 prev: 'fc-icon-chevron-right', 5641 next: 'fc-icon-chevron-left', 5642 prevYear: 'fc-icon-chevrons-right', 5643 nextYear: 'fc-icon-chevrons-left' 5644 }; 5645 StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; // TODO: make TS-friendly 5646 StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon'; 5647 StandardTheme.prototype.iconOverridePrefix = 'fc-icon-'; 5648 5649 function compileViewDefs(defaultConfigs, overrideConfigs) { 5650 var hash = {}; 5651 var viewType; 5652 for (viewType in defaultConfigs) { 5653 ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs); 5654 } 5655 for (viewType in overrideConfigs) { 5656 ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs); 5657 } 5658 return hash; 5659 } 5660 function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) { 5661 if (hash[viewType]) { 5662 return hash[viewType]; 5663 } 5664 var viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs); 5665 if (viewDef) { 5666 hash[viewType] = viewDef; 5667 } 5668 return viewDef; 5669 } 5670 function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) { 5671 var defaultConfig = defaultConfigs[viewType]; 5672 var overrideConfig = overrideConfigs[viewType]; 5673 var queryProp = function (name) { 5674 return (defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] : 5675 ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null); 5676 }; 5677 var theComponent = queryProp('component'); 5678 var superType = queryProp('superType'); 5679 var superDef = null; 5680 if (superType) { 5681 if (superType === viewType) { 5682 throw new Error('Can\'t have a custom view type that references itself'); 5683 } 5684 superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs); 5685 } 5686 if (!theComponent && superDef) { 5687 theComponent = superDef.component; 5688 } 5689 if (!theComponent) { 5690 return null; // don't throw a warning, might be settings for a single-unit view 5691 } 5692 return { 5693 type: viewType, 5694 component: theComponent, 5695 defaults: __assign(__assign({}, (superDef ? superDef.defaults : {})), (defaultConfig ? defaultConfig.rawOptions : {})), 5696 overrides: __assign(__assign({}, (superDef ? superDef.overrides : {})), (overrideConfig ? overrideConfig.rawOptions : {})) 5697 }; 5698 } 5699 5700 // NOTE: in JSX, you should always use this class with <HookProps> arg. otherwise, will default to any??? 5701 var RenderHook = /** @class */ (function (_super) { 5702 __extends(RenderHook, _super);
5703 function RenderHook() { 5704 var _this = _super !== null && _super.apply(this, arguments) || this; 5705 _this.rootElRef = createRef(); 5706 _this.handleRootEl = function (el) { 5707 setRef(_this.rootElRef, el); 5708 if (_this.props.elRef) { 5709 setRef(_this.props.elRef, el); 5710 } 5711 }; 5712 return _this; 5713 } 5714 RenderHook.prototype.render = function () { 5715 var _this = this; 5716 var props = this.props; 5717 var hookProps = props.hookProps; 5718 return (createElement(MountHook, { hookProps: hookProps, didMount: props.didMount, willUnmount: props.willUnmount, elRef: this.handleRootEl }, function (rootElRef) { return (createElement(ContentHook, { hookProps: hookProps, content: props.content, defaultContent: props.defaultContent, backupElRef: _this.rootElRef }, function (innerElRef, innerContent) { return props.children(rootElRef, normalizeClassNames(props.classNames, hookProps), innerElRef, innerContent); })); })); 5719 }; 5720 return RenderHook; 5721 }(BaseComponent)); 5722 // for forcing rerender of components that use the ContentHook 5723 var CustomContentRenderContext = createContext$1(0); 5724 function ContentHook(props) { 5725 return (createElement(CustomContentRenderContext.Consumer, null, function (renderId) { return (createElement(ContentHookInner, __assign({ renderId: renderId }, props))); })); 5726 } 5727 var ContentHookInner = /** @class */ (function (_super) { 5728 __extends(ContentHookInner, _super); 5729 function ContentHookInner() { 5730 var _this = _super !== null && _super.apply(this, arguments) || this; 5731 _this.innerElRef = createRef(); 5732 return _this; 5733 } 5734 ContentHookInner.prototype.render = function () { 5735 return this.props.children(this.innerElRef, this.renderInnerContent()); 5736 }; 5737 ContentHookInner.prototype.componentDidMount = function () { 5738 this.updateCustomContent(); 5739 }; 5740 ContentHookInner.prototype.componentDidUpdate = function () { 5741 this.updateCustomContent(); 5742 }; 5743 ContentHookInner.prototype.renderInnerContent = function () { 5744 var contentTypeHandlers = this.context.pluginHooks.contentTypeHandlers; 5745 var _a = this, props = _a.props, customContentInfo = _a.customContentInfo; 5746 var rawVal = props.content; 5747 var innerContent = normalizeContent(rawVal, props.hookProps); 5748 var innerContentVDom = null; 5749 if (innerContent === undefined) { // use the default 5750 innerContent = normalizeContent(props.defaultContent, props.hookProps); 5751 } 5752 if (innerContent !== undefined) { // we allow custom content handlers to return nothing 5753 if (customContentInfo) { 5754 customContentInfo.contentVal = innerContent[customContentInfo.contentKey]; 5755 } 5756 else if (typeof innerContent === 'object') { 5757 // look for a prop that would indicate a custom content handler is needed 5758 for (var contentKey in contentTypeHandlers) { 5759 if (innerContent[contentKey] !== undefined) { 5760 customContentInfo = this.customContentInfo = { 5761 contentKey: contentKey, 5762 contentVal: innerContent[contentKey], 5763 handler: contentTypeHandlers[contentKey]() 5764 }; 5765 break; 5766 } 5767 } 5768 } 5769 if (customContentInfo) { 5770 innerContentVDom = []; // signal that something was specified 5771 } 5772 else { 5773 innerContentVDom = innerContent; // assume a [p]react vdom node. use it 5774 } 5775 } 5776 return innerContentVDom; 5777 }; 5778 ContentHookInner.prototype.updateCustomContent = function () { 5779 if (this.customContentInfo) { 5780 this.customContentInfo.handler(this.innerElRef.current || this.props.backupElRef.current, // the element to render into 5781 this.customContentInfo.contentVal); 5782 } 5783 }; 5784 return ContentHookInner; 5785 }(BaseComponent)); 5786 var MountHook = /** @class */ (function (_super) { 5787 __extends(MountHook, _super); 5788 function MountHook() { 5789 var _this = _super !== null && _super.apply(this, arguments) || this; 5790 _this.handleRootEl = function (rootEl) { 5791 _this.rootEl = rootEl; 5792 if (_this.props.elRef) { 5793 setRef(_this.props.elRef, rootEl); 5794 } 5795 }; 5796 return _this; 5797 } 5798 MountHook.prototype.render = function () { 5799 return this.props.children(this.handleRootEl); 5800 }; 5801 MountHook.prototype.componentDidMount = function () { 5802 var callback = this.props.didMount; 5803 callback && callback(__assign(__assign({}, this.props.hookProps), { el: this.rootEl })); 5804 }; 5805 MountHook.prototype.componentWillUnmount = function () { 5806 var callback = this.props.willUnmount; 5807 callback && callback(__assign(__assign({}, this.props.hookProps), { el: this.rootEl })); 5808 }; 5809 return MountHook; 5810 }(BaseComponent)); 5811 function buildClassNameNormalizer() { 5812 var currentGenerator; 5813 var currentHookProps; 5814 var currentClassNames = []; 5815 return function (generator, hookProps) { 5816 if (!currentHookProps || !isPropsEqual(currentHookProps, hookProps) || generator !== currentGenerator) { 5817 currentGenerator = generator; 5818 currentHookProps = hookProps; 5819 currentClassNames = normalizeClassNames(generator, hookProps); 5820 } 5821 return currentClassNames; 5822 }; 5823 } 5824 function normalizeClassNames(classNames, hookProps) { 5825 if (typeof classNames === 'function') { 5826 classNames = classNames(hookProps); 5827 } 5828 return parseClassNames(classNames); 5829 } 5830 function normalizeContent(input, hookProps) { 5831 if (typeof input === 'function') { 5832 return input(hookProps, createElement); // give the function the vdom-creation func 5833 } 5834 else { 5835 return input; 5836 } 5837 } 5838 5839 var ViewRoot = /** @class */ (function (_super) { 5840 __extends(ViewRoot, _super); 5841 function ViewRoot() { 5842 var _this = _super !== null && _super.apply(this, arguments) || this; 5843 _this.normalizeClassNames = buildClassNameNormalizer(); 5844 return _this; 5845 } 5846 ViewRoot.prototype.render = function () { 5847 var _a = this, props = _a.props, context = _a.context; 5848 var options = context.options; 5849 var hookProps = { view: context.viewApi }; 5850 var customClassNames = this.normalizeClassNames(options.viewClassNames, hookProps); 5851 return (createElement(MountHook, { hookProps: hookProps, didMount: options.viewDidMount, willUnmount: options.viewWillUnmount, elRef: props.elRef }, function (rootElRef) { return props.children(rootElRef, ["fc-" + props.viewSpec.type + "-view", 'fc-view'].concat(customClassNames)); })); 5852 }; 5853 return ViewRoot; 5854 }(BaseComponent)); 5855 5856 function parseViewConfigs(inputs) { 5857 return mapHash(inputs, parseViewConfig); 5858 } 5859 function parseViewConfig(input) { 5860 var rawOptions = typeof input === 'function' ? 5861 { component: input } : 5862 input; 5863 var component = rawOptions.component; 5864 if (rawOptions.content) { 5865 component = createViewHookComponent(rawOptions); 5866 // TODO: remove content/classNames/didMount/etc from options? 5867 } 5868 return { 5869 superType: rawOptions.type, 5870 component: component, 5871 rawOptions: rawOptions // includes type and component too :( 5872 }; 5873 } 5874 function createViewHookComponent(options) { 5875 return function (viewProps) { 5876 return (createElement(ViewContextType.Consumer, null, function (context) { return (createElement(ViewRoot, { viewSpec: context.viewSpec }, function (rootElRef, viewClassNames) { 5877 var hookProps = __assign(__assign({}, viewProps), { nextDayThreshold: context.options.nextDayThreshold }); 5878 return (createElement(RenderHook, { hookProps: hookProps, classNames: options.classNames, content: options.content, didMount: options.didMount, willUnmount: options.willUnmount, elRef: rootElRef }, function (rootElRef, customClassNames, innerElRef, innerContent) { return (createElement("div", { className: viewClassNames.c
5878oncat(customClassNames).join(' '), ref: rootElRef }, innerContent)); })); 5879 })); })); 5880 }; 5881 } 5882 5883 function buildViewSpecs(defaultInputs, optionOverrides, dynamicOptionOverrides, localeDefaults) { 5884 var defaultConfigs = parseViewConfigs(defaultInputs); 5885 var overrideConfigs = parseViewConfigs(optionOverrides.views); 5886 var viewDefs = compileViewDefs(defaultConfigs, overrideConfigs); 5887 return mapHash(viewDefs, function (viewDef) { 5888 return buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults); 5889 }); 5890 } 5891 function buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults) { 5892 var durationInput = viewDef.overrides.duration || 5893 viewDef.defaults.duration || 5894 dynamicOptionOverrides.duration || 5895 optionOverrides.duration; 5896 var duration = null; 5897 var durationUnit = ''; 5898 var singleUnit = ''; 5899 var singleUnitOverrides = {}; 5900 if (durationInput) { 5901 duration = createDurationCached(durationInput); 5902 if (duration) { // valid? 5903 var denom = greatestDurationDenominator(duration); 5904 durationUnit = denom.unit; 5905 if (denom.value === 1) { 5906 singleUnit = durationUnit; 5907 singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].rawOptions : {}; 5908 } 5909 } 5910 } 5911 var queryButtonText = function (optionsSubset) { 5912 var buttonTextMap = optionsSubset.buttonText || {}; 5913 var buttonTextKey = viewDef.defaults.buttonTextKey; 5914 if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) { 5915 return buttonTextMap[buttonTextKey]; 5916 } 5917 if (buttonTextMap[viewDef.type] != null) { 5918 return buttonTextMap[viewDef.type]; 5919 } 5920 if (buttonTextMap[singleUnit] != null) { 5921 return buttonTextMap[singleUnit]; 5922 } 5923 }; 5924 return { 5925 type: viewDef.type, 5926 component: viewDef.component, 5927 duration: duration, 5928 durationUnit: durationUnit, 5929 singleUnit: singleUnit, 5930 optionDefaults: viewDef.defaults, 5931 optionOverrides: __assign(__assign({}, singleUnitOverrides), viewDef.overrides), 5932 buttonTextOverride: queryButtonText(dynamicOptionOverrides) || 5933 queryButtonText(optionOverrides) || // constructor-specified buttonText lookup hash takes precedence 5934 viewDef.overrides.buttonText, 5935 buttonTextDefault: queryButtonText(localeDefaults) || 5936 viewDef.defaults.buttonText || 5937 queryButtonText(BASE_OPTION_DEFAULTS) || 5938 viewDef.type // fall back to given view name 5939 }; 5940 } 5941 // hack to get memoization working 5942 var durationInputMap = {}; 5943 function createDurationCached(durationInput) { 5944 var json = JSON.stringify(durationInput); 5945 var res = durationInputMap[json]; 5946 if (res === undefined) { 5947 res = createDuration(durationInput); 5948 durationInputMap[json] = res; 5949 } 5950 return res; 5951 } 5952 5953 var DateProfileGenerator = /** @class */ (function () { 5954 function DateProfileGenerator(props) { 5955 this.props = props; 5956 this.nowDate = getNow(props.nowInput, props.dateEnv); 5957 this.initHiddenDays(); 5958 } 5959 /* Date Range Computation 5960 ------------------------------------------------------------------------------------------------------------------*/ 5961 // Builds a structure with info about what the dates/ranges will be for the "prev" view. 5962 DateProfileGenerator.prototype.buildPrev = function (currentDateProfile, currentDate, forceToValid) { 5963 var dateEnv = this.props.dateEnv; 5964 var prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month 5965 currentDateProfile.dateIncrement); 5966 return this.build(prevDate, -1, forceToValid); 5967 }; 5968 // Builds a structure with info about what the dates/ranges will be for the "next" view. 5969 DateProfileGenerator.prototype.buildNext = function (currentDateProfile, currentDate, forceToValid) { 5970 var dateEnv = this.props.dateEnv; 5971 var nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month 5972 currentDateProfile.dateIncrement); 5973 return this.build(nextDate, 1, forceToValid); 5974 }; 5975 // Builds a structure holding dates/ranges for rendering around the given date. 5976 // Optional direction param indicates whether the date is being incremented/decremented 5977 // from its previous value. decremented = -1, incremented = 1 (default). 5978 DateProfileGenerator.prototype.build = function (currentDate, direction, forceToValid) { 5979 if (forceToValid === void 0) { forceToValid = true; } 5980 var props = this.props;
5981 var validRange; 5982 var currentInfo; 5983 var isRangeAllDay; 5984 var renderRange; 5985 var activeRange; 5986 var isValid; 5987 validRange = this.buildValidRange(); 5988 validRange = this.trimHiddenDays(validRange); 5989 if (forceToValid) { 5990 currentDate = constrainMarkerToRange(currentDate, validRange); 5991 } 5992 currentInfo = this.buildCurrentRangeInfo(currentDate, direction); 5993 isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit); 5994 renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay); 5995 renderRange = this.trimHiddenDays(renderRange); 5996 activeRange = renderRange; 5997 if (!props.showNonCurrentDates) { 5998 activeRange = intersectRanges(activeRange, currentInfo.range); 5999 } 6000 activeRange = this.adjustActiveRange(activeRange); 6001 activeRange = intersectRanges(activeRange, validRange); // might return null 6002 // it's invalid if the originally requested date is not contained, 6003 // or if the range is completely outside of the valid range. 6004 isValid = rangesIntersect(currentInfo.range, validRange); 6005 return { 6006 // constraint for where prev/next operations can go and where events can be dragged/resized to. 6007 // an object with optional start and end properties. 6008 validRange: validRange, 6009 // range the view is formally responsible for. 6010 // for example, a month view might have 1st-31st, excluding padded dates 6011 currentRange: currentInfo.range, 6012 // name of largest unit being displayed, like "month" or "week" 6013 currentRangeUnit: currentInfo.unit, 6014 isRangeAllDay: isRangeAllDay, 6015 // dates that display events and accept drag-n-drop 6016 // will be `null` if no dates accept events 6017 activeRange: activeRange, 6018 // date range with a rendered skeleton 6019 // includes not-active days that need some sort of DOM 6020 renderRange: renderRange, 6021 // Duration object that denotes the first visible time of any given day 6022 slotMinTime: props.slotMinTime, 6023 // Duration object that denotes the exclusive visible end time of any given day 6024 slotMaxTime: props.slotMaxTime, 6025 isValid: isValid, 6026 // how far the current date will move for a prev/next operation 6027 dateIncrement: this.buildDateIncrement(currentInfo.duration) 6028 // pass a fallback (might be null) ^ 6029 }; 6030 }; 6031 // Builds an object with optional start/end properties. 6032 // Indicates the minimum/maximum dates to display. 6033 // not responsible for trimming hidden days. 6034 DateProfileGenerator.prototype.buildValidRange = function () { 6035 var input = this.props.validRangeInput; 6036 var simpleInput = typeof input === 'function' 6037 ? input.call(this.props.calendarApi, this.nowDate) 6038 : input; 6039 return this.refineRange(simpleInput) || 6040 { start: null, end: null }; // completely open-ended 6041 }; 6042 // Builds a structure with info about the "current" range, the range that is 6043 // highlighted as being the current month for example. 6044 // See build() for a description of `direction`. 6045 // Guaranteed to have `range` and `unit` properties. `duration` is optional. 6046 DateProfileGenerator.prototype.buildCurrentRangeInfo = function (date, direction) { 6047 var props = this.props; 6048 var duration = null; 6049 var unit = null; 6050 var range = null; 6051 var dayCount; 6052 if (props.duration) { 6053 duration = props.duration; 6054 unit = props.durationUnit; 6055 range = this.buildRangeFromDuration(date, direction, duration, unit); 6056 } 6057 else if ((dayCount = this.props.dayCount)) { 6058 unit = 'day'; 6059 range = this.buildRangeFromDayCount(date, direction, dayCount); 6060 } 6061 else if ((range = this.buildCustomVisibleRange(date))) { 6062 unit = props.dateEnv.greatestWholeUnit(range.start, range.end).unit; 6063 } 6064 else { 6065 duration = this.getFallbackDuration(); 6066 unit = greatestDurationDenominator(duration).unit; 6067 range = this.buildRangeFromDuration(date, direction, duration, unit); 6068 } 6069 return { duration: duration, unit: unit, range: range }; 6070 }; 6071 DateProfileGenerator.prototype.getFallbackDuration = function () { 6072 return createDuration({ day: 1 }); 6073 }; 6074 // Returns a new activeRange to have time values (un-ambiguate) 6075 // slotMinTime or slotMaxTime causes the range to expand. 6076 DateProfileGenerator.prototype.adjustActiveRange = function (range) { 6077 var _a = this.props, dateEnv = _a.dateEnv, usesMinMaxTime = _a.usesMinMaxTime, slotMinTime = _a.slotMinTime, slotMaxTime = _a.slotMaxTime; 6078 var start = range.start; 6079 var end = range.end; 6080 if (usesMinMaxTime) { 6081 // expand active range if slotMinTime is negative (why not when positive?) 6082 if (asRoughDays(slotMinTime) < 0) { 6083 start = startOfDay(start); // necessary? 6084 start = dateEnv.add(start, slotMinTime); 6085 } 6086 // expand active range if slotMaxTime is beyond one day (why not when negative?) 6087 if (asRoughDays(slotMaxTime) > 1) { 6088 end = startOfDay(end); // necessary? 6089 end = addDays(end, -1); 6090 end = dateEnv.add(end, slotMaxTime); 6091 } 6092 } 6093 return { start: start, end: end }; 6094 }; 6095 // Builds the "current" range when it is specified as an explicit duration. 6096 // `unit` is the already-computed greatestDurationDenominator unit of duration. 6097 DateProfileGenerator.prototype.buildRangeFromDuration = function (date, direction, duration, unit) { 6098 var _a = this.props, dateEnv = _a.dateEnv, dateAlignment = _a.dateAlignment; 6099 var start; 6100 var end; 6101 var res; 6102 // compute what the alignment should be 6103 if (!dateAlignment) { 6104 var dateIncrement = this.props.dateIncrement; 6105 if (dateIncrement) { 6106 // use the smaller of the two units 6107 if (asRoughMs(dateIncrement) < asRoughMs(duration)) { 6108 dateAlignment = greatestDurationDenominator(dateIncrement).unit; 6109 } 6110 else { 6111 dateAlignment = unit; 6112 } 6113 } 6114 else { 6115 dateAlignment = unit; 6116 } 6117 }
6118 // if the view displays a single day or smaller 6119 if (asRoughDays(duration) <= 1) { 6120 if (this.isHiddenDay(start)) { 6121 start = this.skipHiddenDays(start, direction); 6122 start = startOfDay(start); 6123 } 6124 } 6125 function computeRes() { 6126 start = dateEnv.startOf(date, dateAlignment); 6127 end = dateEnv.add(start, duration); 6128 res = { start: start, end: end }; 6129 } 6130 computeRes(); 6131 // if range is completely enveloped by hidden days, go past the hidden days 6132 if (!this.trimHiddenDays(res)) { 6133 date = this.skipHiddenDays(date, direction); 6134 computeRes(); 6135 } 6136 return res; 6137 }; 6138 // Builds the "current" range when a dayCount is specified. 6139 DateProfileGenerator.prototype.buildRangeFromDayCount = function (date, direction, dayCount) { 6140 var _a = this.props, dateEnv = _a.dateEnv, dateAlignment = _a.dateAlignment; 6141 var runningCount = 0; 6142 var start = date; 6143 var end; 6144 if (dateAlignment) { 6145 start = dateEnv.startOf(start, dateAlignment); 6146 } 6147 start = startOfDay(start); 6148 start = this.skipHiddenDays(start, direction); 6149 end = start; 6150 do { 6151 end = addDays(end, 1); 6152 if (!this.isHiddenDay(end)) { 6153 runningCount++; 6154 } 6155 } while (runningCount < dayCount); 6156 return { start: start, end: end }; 6157 }; 6158 // Builds a normalized range object for the "visible" range, 6159 // which is a way to define the currentRange and activeRange at the same time. 6160 DateProfileGenerator.prototype.buildCustomVisibleRange = function (date) { 6161 var props = this.props; 6162 var input = props.visibleRangeInput; 6163 var simpleInput = typeof input === 'function' 6164 ? input.call(props.calendarApi, props.dateEnv.toDate(date)) 6165 : input; 6166 var range = this.refineRange(simpleInput); 6167 if (range && (range.start == null || range.end == null)) { 6168 return null; 6169 } 6170 return range; 6171 }; 6172 // Computes the range that will represent the element/cells for *rendering*, 6173 // but which may have voided days/times. 6174 // not responsible for trimming hidden days. 6175 DateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) { 6176 return currentRange; 6177 }; 6178 // Compute the duration value that should be added/substracted to the current date 6179 // when a prev/next operation happens. 6180 DateProfileGenerator.prototype.buildDateIncrement = function (fallback) { 6181 var dateIncrement = this.props.dateIncrement; 6182 var customAlignment; 6183 if (dateIncrement) { 6184 return dateIncrement; 6185 } 6186 else if ((customAlignment = this.props.dateAlignment)) { 6187 return createDuration(1, customAlignment); 6188 } 6189 else if (fallback) { 6190 return fallback; 6191 } 6192 else { 6193 return createDuration({ days: 1 }); 6194 } 6195 }; 6196 DateProfileGenerator.prototype.refineRange = function (rangeInput) { 6197 if (rangeInput) { 6198 var range = parseRange(rangeInput, this.props.dateEnv); 6199 if (range) { 6200 range = computeVisibleDayRange(range); 6201 } 6202 return range; 6203 } 6204 return null; 6205 }; 6206 /* Hidden Days 6207 ------------------------------------------------------------------------------------------------------------------*/ 6208 // Initializes internal variables related to calculating hidden days-of-week 6209 DateProfileGenerator.prototype.initHiddenDays = function () { 6210 var hiddenDays = this.props.hiddenDays || []; // array of day-of-week indices that are hidden
6211 var isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool) 6212 var dayCnt = 0; 6213 var i; 6214 if (this.props.weekends === false) { 6215 hiddenDays.push(0, 6); // 0=sunday, 6=saturday 6216 } 6217 for (i = 0; i < 7; i++) { 6218 if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) { 6219 dayCnt++; 6220 } 6221 } 6222 if (!dayCnt) { 6223 throw new Error('invalid hiddenDays'); // all days were hidden? bad. 6224 } 6225 this.isHiddenDayHash = isHiddenDayHash; 6226 }; 6227 // Remove days from the beginning and end of the range that are computed as hidden. 6228 // If the whole range is trimmed off, returns null 6229 DateProfileGenerator.prototype.trimHiddenDays = function (range) { 6230 var start = range.start; 6231 var end = range.end; 6232 if (start) { 6233 start = this.skipHiddenDays(start); 6234 } 6235 if (end) { 6236 end = this.skipHiddenDays(end, -1, true); 6237 } 6238 if (start == null || end == null || start < end) { 6239 return { start: start, end: end }; 6240 } 6241 return null; 6242 }; 6243 // Is the current day hidden? 6244 // `day` is a day-of-week index (0-6), or a Date (used for UTC) 6245 DateProfileGenerator.prototype.isHiddenDay = function (day) { 6246 if (day instanceof Date) { 6247 day = day.getUTCDay(); 6248 } 6249 return this.isHiddenDayHash[day]; 6250 }; 6251 // Incrementing the current day until it is no longer a hidden day, returning a copy. 6252 // DOES NOT CONSIDER validRange! 6253 // If the initial value of `date` is not a hidden day, don't do anything. 6254 // Pass `isExclusive` as `true` if you are dealing with an end date. 6255 // `inc` defaults to `1` (increment one day forward each time) 6256 DateProfileGenerator.prototype.skipHiddenDays = function (date, inc, isExclusive) { 6257 if (inc === void 0) { inc = 1; } 6258 if (isExclusive === void 0) { isExclusive = false; } 6259 while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) { 6260 date = addDays(date, inc); 6261 } 6262 return date; 6263 }; 6264 return DateProfileGenerator; 6265 }()); 6266 6267 function reduceViewType(viewType, action) { 6268 switch (action.type) { 6269 case 'CHANGE_VIEW_TYPE': 6270 return viewType = action.viewType; 6271 } 6272 return viewType; 6273 } 6274 6275 function reduceDynamicOptionOverrides(dynamicOptionOverrides, action) { 6276 var _a; 6277 switch (action.type) { 6278 case 'SET_OPTION': 6279 return __assign(__assign({}, dynamicOptionOverrides), (_a = {}, _a[action.optionName] = action.rawOptionValue, _a)); 6280 default: 6281 return dynamicOptionOverrides; 6282 } 6283 } 6284 6285 function reduceDateProfile(currentDateProfile, action, currentDate, dateProfileGenerator) { 6286 var dp; 6287 switch (action.type) { 6288 case 'CHANGE_VIEW_TYPE': 6289 return dateProfileGenerator.build(action.dateMarker || currentDate); 6290 case 'CHANGE_DATE': 6291 if (!currentDateProfile.activeRange || 6292 !rangeContainsMarker(currentDateProfile.currentRange, action.dateMarker) // don't move if date already in view 6293 ) { 6294 return dateProfileGenerator.build(action.dateMarker); 6295 } 6296 break; 6297 case 'PREV': 6298 dp = dateProfileGenerator.buildPrev(currentDateProfile, currentDate); 6299 if (dp.isValid) { 6300 return dp; 6301 } 6302 break; 6303 case 'NEXT': 6304 dp = dateProfileGenerator.buildNext(currentDateProfile, currentDate); 6305 if (dp.isValid) { 6306 return dp; 6307 } 6308 break; 6309 } 6310 return currentDateProfile; 6311 } 6312 6313 function initEventSources(calendarOptions, dateProfile, context) { 6314 var activeRange = dateProfile ? dateProfile.activeRange : null; 6315 return addSources({}, parseInitialSources(calendarOptions, context), activeRange, context); 6316 } 6317 function reduceEventSources(eventSources, action, dateProfile, context) { 6318 var activeRange = dateProfile ? dateProfile.activeRange : null; // need this check? 6319 switch (action.type) { 6320 case 'ADD_EVENT_SOURCES': // already parsed 6321 return addSources(eventSources, action.sources, activeRange, context);
6322 case 'REMOVE_EVENT_SOURCE': 6323 return removeSource(eventSources, action.sourceId); 6324 case 'PREV': // TODO: how do we track all actions that affect dateProfile :( 6325 case 'NEXT': 6326 case 'CHANGE_DATE': 6327 case 'CHANGE_VIEW_TYPE': 6328 if (dateProfile) { 6329 return fetchDirtySources(eventSources, activeRange, context); 6330 } 6331 else { 6332 return eventSources; 6333 } 6334 case 'FETCH_EVENT_SOURCES': 6335 return fetchSourcesByIds(eventSources, action.sourceIds ? // why no type? 6336 arrayToHash(action.sourceIds) : 6337 excludeStaticSources(eventSources, context), activeRange, context); 6338 case 'RECEIVE_EVENTS': 6339 case 'RECEIVE_EVENT_ERROR': 6340 return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange); 6341 case 'REMOVE_ALL_EVENT_SOURCES': 6342 return {}; 6343 default: 6344 return eventSources; 6345 } 6346 } 6347 function reduceEventSourcesNewTimeZone(eventSources, dateProfile, context) { 6348 var activeRange = dateProfile ? dateProfile.activeRange : null; // need this check? 6349 return fetchSourcesByIds(eventSources, excludeStaticSources(eventSources, context), activeRange, context); 6350 } 6351 function computeEventSourceLoadingLevel(eventSources) { 6352 var cnt = 0; 6353 for (var sourceId in eventSources) { 6354 if (eventSources[sourceId].isFetching) { 6355 cnt++; 6356 } 6357 } 6358 return cnt; 6359 } 6360 function addSources(eventSourceHash, sources, fetchRange, context) { 6361 var hash = {}; 6362 for (var _i = 0, sources_1 = sources; _i < sources_1.length; _i++) { 6363 var source = sources_1[_i]; 6364 hash[source.sourceId] = source; 6365 } 6366 if (fetchRange) { 6367 hash = fetchDirtySources(hash, fetchRange, context); 6368 } 6369 return __assign(__assign({}, eventSourceHash), hash); 6370 } 6371 function removeSource(eventSourceHash, sourceId) { 6372 return filterHash(eventSourceHash, function (eventSource) { 6373 return eventSource.sourceId !== sourceId; 6374 }); 6375 } 6376 function fetchDirtySources(sourceHash, fetchRange, context) { 6377 return fetchSourcesByIds(sourceHash, filterHash(sourceHash, function (eventSource) { 6378 return isSourceDirty(eventSource, fetchRange, context); 6379 }), fetchRange, context); 6380 } 6381 function isSourceDirty(eventSource, fetchRange, context) { 6382 if (!doesSourceNeedRange(eventSource, context)) { 6383 return !eventSource.latestFetchId; 6384 } 6385 else { 6386 return !context.options.lazyFetching || 6387 !eventSource.fetchRange || 6388 eventSource.isFetching || // always cancel outdated in-progress fetches 6389 fetchRange.start < eventSource.fetchRange.start || 6390 fetchRange.end > eventSource.fetchRange.end; 6391 } 6392 } 6393 function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, context) { 6394 var nextSources = {}; 6395 for (var sourceId in prevSources) { 6396 var source = prevSources[sourceId]; 6397 if (sourceIdHash[sourceId]) { 6398 nextSources[sourceId] = fetchSource(source, fetchRange, context); 6399 } 6400 else { 6401 nextSources[sourceId] = source; 6402 } 6403 } 6404 return nextSources; 6405 } 6406 function fetchSource(eventSource, fetchRange, context) { 6407 var options = context.options, calendarApi = context.calendarApi; 6408 var sourceDef = context.pluginHooks.eventSourceDefs[eventSource.sourceDefId]; 6409 var fetchId = guid(); 6410 sourceDef.fetch({ 6411 eventSource: eventSource, 6412 range: fetchRange, 6413 context: context 6414 }, function (res) { 6415 var rawEvents = res.rawEvents; 6416 if (options.eventSourceSuccess) { 6417 rawEvents = options.eventSourceSuccess.call(calendarApi, rawEvents, res.xhr) || rawEvents; 6418 } 6419 if (eventSource.success) { 6420 rawEvents = eventSource.success.call(calendarApi, rawEvents, res.xhr) || rawEvents; 6421 } 6422 context.dispatch({ 6423 type: 'RECEIVE_EVENTS', 6424 sourceId: eventSource.sourceId, 6425 fetchId: fetchId, 6426 fetchRange: fetchRange, 6427 rawEvents: rawEvents 6428 }); 6429 }, function (error) { 6430 console.warn(error.message, error); 6431 if (options.eventSourceFailure) { 6432 options.eventSourceFailure.call(calendarApi, error); 6433 } 6434 if (eventSource.failure) { 6435 eventSource.failure(error); 6436 } 6437 context.dispatch({ 6438 type: 'RECEIVE_EVENT_ERROR', 6439 sourceId: eventSource.sourceId, 6440 fetchId: fetchId, 6441 fetchRange: fetchRange, 6442 error: error 6443 }); 6444 }); 6445 return __assign(__assign({}, eventSource), { isFetching: true, latestFetchId: fetchId }); 6446 } 6447 function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) { 6448 var _a; 6449 var eventSource = sourceHash[sourceId]; 6450 if (eventSource && // not already removed 6451 fetchId === eventSource.latestFetchId) { 6452 return __assign(__assign({}, sourceHash), (_a = {}, _a[sourceId] = __assign(__assign({}, eventSource), { isFetching: false, fetchRange: fetchRange // also serves as a marker that at least one fetch has completed 6453 }), _a)); 6454 } 6455 return sourceHash; 6456 } 6457 function excludeStaticSources(eventSources, context) { 6458 return filterHash(eventSources, function (eventSource) { 6459 return doesSourceNeedRange(eventSource, context); 6460 }); 6461 } 6462 function parseInitialSources(rawOptions, context) { 6463 var refiners = buildEventSourceRefiners(context); 6464 var rawSources = [].concat(rawOptions.eventSources || []); 6465 var sources = []; // parsed 6466 if (rawOptions.initialEvents) { 6467 rawSources.unshift(rawOptions.initialEvents); 6468 } 6469 if (rawOptions.events) { 6470 rawSources.unshift(rawOptions.events); 6471 } 6472 for (var _i = 0, rawSources_1 = rawSources; _i < rawSources_1.length; _i++) { 6473 var rawSource = rawSources_1[_i]; 6474 var source = parseEventSource(rawSource, context, refiners); 6475 if (source) { 6476 sources.push(source); 6477 } 6478 } 6479 return sources; 6480 } 6481 function doesSourceNeedRange(eventSource, context) { 6482 var defs = context.pluginHooks.eventSourceDefs; 6483 return !defs[eventSource.sourceDefId].ignoreRange; 6484 } 6485 6486 function reduceDateSelection(currentSelection, action) { 6487 switch (action.type) { 6488 case 'UNSELECT_DATES': 6489 return null; 6490 case 'SELECT_DATES': 6491 return action.selection; 6492 default: 6493 return currentSelection; 6494 } 6495 } 6496 6497 function reduceSelectedEvent(currentInstanceId, action) { 6498 switch (action.type) { 6499 case 'UNSELECT_EVENT': 6500 return ''; 6501 case 'SELECT_EVENT': 6502 return action.eventInstanceId; 6503 default: 6504 return currentInstanceId; 6505 } 6506 } 6507 6508 function reduceEventDrag(currentDrag, action) { 6509 var newDrag; 6510 switch (action.type) { 6511 case 'UNSET_EVENT_DRAG': 6512 return null; 6513 case 'SET_EVENT_DRAG': 6514 newDrag = action.state; 6515 return { 6516 affectedEvents: newDrag.affectedEvents, 6517 mutatedEvents: newDrag.mutatedEvents, 6518 isEvent: newDrag.isEvent 6519 }; 6520 default: 6521 return currentDrag; 6522 } 6523 } 6524 6525 function reduceEventResize(currentResize, action) { 6526 var newResize; 6527 switch (action.type) { 6528 case 'UNSET_EVENT_RESIZE': 6529 return null; 6530 case 'SET_EVENT_RESIZE': 6531 newResize = action.state; 6532 return { 6533 affectedEvents: newResize.affectedEvents, 6534 mutatedEvents: newResize.mutatedEvents, 6535 isEvent: newResize.isEvent 6536 }; 6537 default: 6538 return currentResize; 6539 } 6540 } 6541 6542 function parseToolbars(calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) { 6543 var viewsWithButtons = []; 6544 var headerToolbar = calendarOptions.headerToolbar ? parseToolbar(calendarOptions.headerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons) : null; 6545 var footerToolbar = calendarOptions.footerToolbar ? parseToolbar(calendarOptions.footerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons) : null; 6546 return { headerToolbar: headerToolbar, footerToolbar: footerToolbar, viewsWithButtons: viewsWithButtons }; 6547 } 6548 function parseToolbar(sectionStrHash, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons // dump side effects 6549 ) { 6550 return mapHash(sectionStrHash, function (sectionStr) { return parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons); }); 6551 } 6552 /* 6553 BAD: querying icons and text here. should be done at render time 6554 */ 6555 function parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons // dump side effects 6556 ) { 6557 var isRtl = calendarOptions.direction === 'rtl'; 6558 var calendarCustomButtons = calendarOptions.customButtons || {}; 6559 var calendarButtonTextOverrides = calendarOptionOverrides.buttonText || {}; 6560 var calendarButtonText = calendarOptions.buttonText || {}; 6561 var sectionSubstrs = sectionStr ? sectionStr.split(' ') : []; 6562 return sectionSubstrs.map(function (buttonGroupStr) { 6563 return buttonGroupStr.split(',').map(function (buttonName) { 6564 if (buttonName === 'title') { 6565 return { buttonName: buttonName }; 6566 } 6567 else { 6568 var customButtonProps_1; 6569 var viewSpec = void 0; 6570 var buttonClick = void 0; 6571 var buttonIcon = void 0; // only one of these will be set 6572 var buttonText = void 0; // " 6573 if ((customButtonProps_1 = calendarCustomButtons[buttonName])) { 6574 buttonClick = function (ev) { 6575 if (customButtonProps_1.click) { 6576 customButtonProps_1.click.call(ev.target, ev, ev.target); 6577 } 6578 }; 6579 (buttonIcon = theme.getCustomButtonIconClass(customButtonProps_1)) || 6580 (buttonIcon = theme.getIconClass(buttonName, isRtl)) || 6581 (buttonText = customButtonProps_1.text); 6582 } 6583 else if ((viewSpec = viewSpecs[buttonName])) { 6584 viewsWithButtons.push(buttonName); 6585 buttonClick = function () { 6586 calendarApi.changeView(buttonName); 6587 }; 6588 (buttonText = viewSpec.buttonTextOverride) || 6589 (buttonIcon = theme.getIconClass(buttonName, isRtl)) || 6590 (buttonText = viewSpec.buttonTextDefault); 6591 } 6592 else if (calendarApi[buttonName]) { // a calendarApi method 6593 buttonClick = function () { 6594 calendarApi[buttonName](); 6595 }; 6596 (buttonText = calendarButtonTextOverrides[buttonName]) || 6597 (buttonIcon = theme.getIconClass(buttonName, isRtl)) || 6598 (buttonText = calendarButtonText[buttonName]); 6599 // ^ everything else is considered default 6600 } 6601 return { buttonName: buttonName, buttonClick: buttonClick, buttonIcon: buttonIcon, buttonText: buttonText }; 6602 } 6603 }); 6604 }); 6605 } 6606 6607 var eventSourceDef = { 6608 ignoreRange: true, 6609 parseMeta: function (refined) { 6610 if (Array.isArray(refined.events)) { 6611 return refined.events; 6612 } 6613 return null; 6614 }, 6615 fetch: function (arg, success) { 6616 success({ 6617 rawEvents: arg.eventSource.meta 6618 }); 6619 } 6620 }; 6621 var arrayEventSourcePlugin = createPlugin({ 6622 eventSourceDefs: [eventSourceDef] 6623 }); 6624 6625 var eventSourceDef$1 = { 6626 parseMeta: function (refined) { 6627 if (typeof refined.events === 'function') { 6628 return refined.events; 6629 } 6630 return null; 6631 }, 6632 fetch: function (arg, success, failure) { 6633 var dateEnv = arg.context.dateEnv; 6634 var func = arg.eventSource.meta; 6635 unpromisify(func.bind(null, buildRangeApiWithTimeZone(arg.range, dateEnv)), function (rawEvents) { 6636 success({ rawEvents: rawEvents }); // needs an object response 6637 }, failure // send errorObj directly to failure callback 6638 ); 6639 } 6640 }; 6641 var funcEventSourcePlugin = createPlugin({ 6642 eventSourceDefs: [eventSourceDef$1] 6643 }); 6644 6645 function requestJson(method, url, params, successCallback, failureCallback) { 6646 method = method.toUpperCase(); 6647 var body = null; 6648 if (method === 'GET') { 6649 url = injectQueryStringParams(url, params); 6650 } 6651 else { 6652 body = encodeParams(params); 6653 } 6654 var xhr = new XMLHttpRequest(); 6655 xhr.open(method, url, true); 6656 if (method !== 'GET') { 6657 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 6658 } 6659 xhr.onload = function () { 6660 if (xhr.status >= 200 && xhr.status < 400) { 6661 var parsed = false;
6662 var res = void 0; 6663 try { 6664 res = JSON.parse(xhr.responseText); 6665 parsed = true; 6666 } 6667 catch (err) { 6668 // will handle parsed=false 6669 } 6670 if (parsed) { 6671 successCallback(res, xhr); 6672 } 6673 else { 6674 failureCallback('Failure parsing JSON', xhr); 6675 } 6676 } 6677 else { 6678 failureCallback('Request failed', xhr); 6679 } 6680 }; 6681 xhr.onerror = function () { 6682 failureCallback('Request failed', xhr); 6683 }; 6684 xhr.send(body); 6685 } 6686 function injectQueryStringParams(url, params) { 6687 return url + 6688 (url.indexOf('?') === -1 ? '?' : '&') + 6689 encodeParams(params); 6690 } 6691 function encodeParams(params) { 6692 var parts = []; 6693 for (var key in params) { 6694 parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key])); 6695 } 6696 return parts.join('&'); 6697 } 6698 6699 var JSON_FEED_EVENT_SOURCE_REFINERS = { 6700 method: String, 6701 extraParams: identity, 6702 startParam: String, 6703 endParam: String, 6704 timeZoneParam: String 6705 }; 6706 6707 var eventSourceDef$2 = { 6708 parseMeta: function (refined) { 6709 if (refined.url) { 6710 return { 6711 url: refined.url, 6712 method: (refined.method || 'GET').toUpperCase(), 6713 extraParams: refined.extraParams, 6714 startParam: refined.startParam, 6715 endParam: refined.endParam, 6716 timeZoneParam: refined.timeZoneParam 6717 }; 6718 } 6719 return null; 6720 }, 6721 fetch: function (arg, success, failure) { 6722 var meta = arg.eventSource.meta; 6723 var requestParams = buildRequestParams(meta, arg.range, arg.context); 6724 requestJson(meta.method, meta.url, requestParams, function (rawEvents, xhr) { 6725 success({ rawEvents: rawEvents, xhr: xhr }); 6726 }, function (errorMessage, xhr) { 6727 failure({ message: errorMessage, xhr: xhr }); 6728 }); 6729 } 6730 }; 6731 var jsonFeedEventSourcePlugin = createPlugin({ 6732 eventSourceRefiners: JSON_FEED_EVENT_SOURCE_REFINERS, 6733 eventSourceDefs: [eventSourceDef$2] 6734 }); 6735 function buildRequestParams(meta, range, context) { 6736 var dateEnv = context.dateEnv, options = context.options; 6737 var startParam; 6738 var endParam; 6739 var timeZoneParam;
6740 var customRequestParams; 6741 var params = {}; 6742 startParam = meta.startParam; 6743 if (startParam == null) { 6744 startParam = options.startParam; 6745 } 6746 endParam = meta.endParam; 6747 if (endParam == null) { 6748 endParam = options.endParam; 6749 } 6750 timeZoneParam = meta.timeZoneParam; 6751 if (timeZoneParam == null) { 6752 timeZoneParam = options.timeZoneParam; 6753 } 6754 // retrieve any outbound GET/POST data from the options 6755 if (typeof meta.extraParams === 'function') { 6756 // supplied as a function that returns a key/value object 6757 customRequestParams = meta.extraParams(); 6758 } 6759 else { 6760 // probably supplied as a straight key/value object 6761 customRequestParams = meta.extraParams || {}; 6762 } 6763 __assign(params, customRequestParams); 6764 params[startParam] = dateEnv.formatIso(range.start); 6765 params[endParam] = dateEnv.formatIso(range.end); 6766 if (dateEnv.timeZone !== 'local') { 6767 params[timeZoneParam] = dateEnv.timeZone; 6768 } 6769 return params; 6770 } 6771 6772 var SIMPLE_RECURRING_REFINERS = { 6773 daysOfWeek: identity, 6774 startTime: createDuration, 6775 endTime: createDuration, 6776 duration: createDuration, 6777 startRecur: identity, 6778 endRecur: identity 6779 }; 6780 6781 var recurring = { 6782 parse: function (refined, dateEnv) { 6783 if (refined.daysOfWeek || refined.startTime || refined.endTime || refined.startRecur || refined.endRecur) { 6784 var recurringData = { 6785 daysOfWeek: refined.daysOfWeek || null, 6786 startTime: refined.startTime || null, 6787 endTime: refined.endTime || null, 6788 startRecur: refined.startRecur ? dateEnv.createMarker(refined.startRecur) : null, 6789 endRecur: refined.endRecur ? dateEnv.createMarker(refined.endRecur) : null 6790 }; 6791 var duration = void 0; 6792 if (refined.duration) { 6793 duration = refined.duration; 6794 } 6795 if (!duration && refined.startTime && refined.endTime) { 6796 duration = subtractDurations(refined.endTime, refined.startTime); 6797 } 6798 return { 6799 allDayGuess: Boolean(!refined.startTime && !refined.endTime), 6800 duration: duration, 6801 typeData: recurringData // doesn't need endTime anymore but oh well 6802 }; 6803 } 6804 return null; 6805 }, 6806 expand: function (typeData, framingRange, dateEnv) { 6807 var clippedFramingRange = intersectRanges(framingRange, { start: typeData.startRecur, end: typeData.endRecur }); 6808 if (clippedFramingRange) { 6809 return expandRanges(typeData.daysOfWeek, typeData.startTime, clippedFramingRange, dateEnv); 6810 } 6811 else { 6812 return []; 6813 } 6814 } 6815 }; 6816 var simpleRecurringEventsPlugin = createPlugin({ 6817 recurringTypes: [recurring], 6818 eventRefiners: SIMPLE_RECURRING_REFINERS 6819 }); 6820 function expandRanges(daysOfWeek, startTime, framingRange, dateEnv) { 6821 var dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null; 6822 var dayMarker = startOfDay(framingRange.start); 6823 var endMarker = framingRange.end; 6824 var instanceStarts = []; 6825 while (dayMarker < endMarker) { 6826 var instanceStart 6827 // if everyday, or this particular day-of-week 6828 = void 0; 6829 // if everyday, or this particular day-of-week 6830 if (!dowHash || dowHash[dayMarker.getUTCDay()]) { 6831 if (startTime) { 6832 instanceStart = dateEnv.add(dayMarker, startTime); 6833 } 6834 else { 6835 instanceStart = dayMarker; 6836 } 6837 instanceStarts.push(instanceStart); 6838 } 6839 dayMarker = addDays(dayMarker, 1); 6840 } 6841 return instanceStarts; 6842 } 6843 6844 var changeHandlerPlugin = createPlugin({ 6845 optionChangeHandlers: { 6846 events: function (events, context) { 6847 handleEventSources([events], context); 6848 }, 6849 eventSources: handleEventSources 6850 } 6851 }); 6852 /* 6853 BUG: if `event` was supplied, all previously-given `eventSources` will be wiped out 6854 */ 6855 function handleEventSources(inputs, context) { 6856 var unfoundSources = hashValuesToArray(context.getCurrentData().eventSources);
6857 var newInputs = []; 6858 for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) { 6859 var input = inputs_1[_i]; 6860 var inputFound = false; 6861 for (var i = 0; i < unfoundSources.length; i++) { 6862 if (unfoundSources[i]._raw === input) { 6863 unfoundSources.splice(i, 1); // delete 6864 inputFound = true; 6865 break; 6866 } 6867 } 6868 if (!inputFound) { 6869 newInputs.push(input); 6870 } 6871 } 6872 for (var _a = 0, unfoundSources_1 = unfoundSources; _a < unfoundSources_1.length; _a++) { 6873 var unfoundSource = unfoundSources_1[_a]; 6874 context.dispatch({ 6875 type: 'REMOVE_EVENT_SOURCE', 6876 sourceId: unfoundSource.sourceId 6877 }); 6878 } 6879 for (var _b = 0, newInputs_1 = newInputs; _b < newInputs_1.length; _b++) { 6880 var newInput = newInputs_1[_b]; 6881 context.calendarApi.addEventSource(newInput); 6882 } 6883 } 6884 6885 function handleDateProfile(dateProfile, context) { 6886 context.emitter.trigger('datesSet', __assign(__assign({}, buildRangeApiWithTimeZone(dateProfile.activeRange, context.dateEnv)), { view: context.viewApi })); 6887 } 6888 6889 function handleEventStore(eventStore, context) { 6890 var emitter = context.emitter; 6891 if (emitter.hasHandlers('eventsSet')) { 6892 emitter.trigger('eventsSet', buildEventApis(eventStore, context)); 6893 } 6894 } 6895 6896 /* 6897 this array is exposed on the root namespace so that UMD plugins can add to it. 6898 see the rollup-bundles script. 6899 */ 6900 var globalPlugins = [ 6901 arrayEventSourcePlugin, 6902 funcEventSourcePlugin, 6903 jsonFeedEventSourcePlugin, 6904 simpleRecurringEventsPlugin, 6905 changeHandlerPlugin, 6906 createPlugin({ 6907 contentTypeHandlers: { 6908 html: function () { return injectHtml; }, 6909 domNodes: function () { return injectDomNodes; } 6910 }, 6911 propSetHandlers: { 6912 dateProfile: handleDateProfile, 6913 eventStore: handleEventStore 6914 } 6915 }) 6916 ]; 6917 function injectHtml(el, html) { 6918 el.innerHTML = html; 6919 } 6920 function injectDomNodes(el, domNodes) { 6921 var oldNodes = Array.prototype.slice.call(el.childNodes); // TODO: use array util 6922 var newNodes = Array.prototype.slice.call(domNodes); // TODO: use array util 6923 if (!isArraysEqual(oldNodes, newNodes)) { 6924 for (var _i = 0, newNodes_1 = newNodes; _i < newNodes_1.length; _i++) { 6925 var newNode = newNodes_1[_i]; 6926 el.appendChild(newNode); 6927 } 6928 oldNodes.forEach(removeElement); 6929 } 6930 } 6931 6932 var DelayedRunner = /** @class */ (function () { 6933 function DelayedRunner(drainedOption) { 6934 this.drainedOption = drainedOption; 6935 this.isRunning = false; 6936 this.isDirty = false; 6937 this.pauseDepths = {}; 6938 this.timeoutId = 0; 6939 } 6940 DelayedRunner.prototype.request = function (delay) { 6941 this.isDirty = true; 6942 if (!this.isPaused()) { 6943 this.clearTimeout(); 6944 if (delay == null) { 6945 this.tryDrain(); 6946 } 6947 else { 6948 this.timeoutId = setTimeout(// NOT OPTIMAL! TODO: look at debounce 6949 this.tryDrain.bind(this), delay); 6950 } 6951 } 6952 }; 6953 DelayedRunner.prototype.pause = function (scope) { 6954 if (scope === void 0) { scope = ''; } 6955 var pauseDepths = this.pauseDepths; 6956 pauseDepths[scope] = (pauseDepths[scope] || 0) + 1; 6957 this.clearTimeout(); 6958 }; 6959 DelayedRunner.prototype.resume = function (scope, force) { 6960 if (scope === void 0) { scope = ''; } 6961 var pauseDepths = this.pauseDepths; 6962 if (scope in pauseDepths) { 6963 if (force) { 6964 delete pauseDepths[scope]; 6965 } 6966 else { 6967 var depth = --pauseDepths[scope]; 6968 if (depth <= 0) { 6969 delete pauseDepths[scope]; 6970 } 6971 } 6972 this.tryDrain(); 6973 } 6974 }; 6975 DelayedRunner.prototype.isPaused = function () { 6976 return Object.keys(this.pauseDepths).length; 6977 }; 6978 DelayedRunner.prototype.tryDrain = function () { 6979 if (!this.isRunning && !this.isPaused()) { 6980 this.isRunning = true; 6981 while (this.isDirty) { 6982 this.isDirty = false;
6983 this.drained(); // might set isDirty to true again 6984 } 6985 this.isRunning = false; 6986 } 6987 }; 6988 DelayedRunner.prototype.clear = function () { 6989 this.clearTimeout(); 6990 this.isDirty = false; 6991 this.pauseDepths = {}; 6992 }; 6993 DelayedRunner.prototype.clearTimeout = function () { 6994 if (this.timeoutId) { 6995 clearTimeout(this.timeoutId); 6996 this.timeoutId = 0; 6997 } 6998 }; 6999 DelayedRunner.prototype.drained = function () { 7000 if (this.drainedOption) { 7001 this.drainedOption(); 7002 } 7003 }; 7004 return DelayedRunner; 7005 }()); 7006 var TaskRunner = /** @class */ (function () { 7007 function TaskRunner(runTaskOption, drainedOption) { 7008 this.runTaskOption = runTaskOption; 7009 this.drainedOption = drainedOption; 7010 this.queue = []; 7011 this.delayedRunner = new DelayedRunner(this.drain.bind(this)); 7012 } 7013 TaskRunner.prototype.request = function (task, delay) { 7014 this.queue.push(task); 7015 this.delayedRunner.request(delay); 7016 }; 7017 TaskRunner.prototype.pause = function (scope) { 7018 this.delayedRunner.pause(scope); 7019 }; 7020 TaskRunner.prototype.resume = function (scope, force) { 7021 this.delayedRunner.resume(scope, force); 7022 }; 7023 TaskRunner.prototype.drain = function () { 7024 var queue = this.queue; 7025 while (queue.length) { 7026 var completedTasks = []; 7027 var task = void 0; 7028 while ((task = queue.shift())) { 7029 this.runTask(task); 7030 completedTasks.push(task); 7031 } 7032 this.drained(completedTasks); 7033 } // keep going, in case new tasks were added in the drained handler 7034 }; 7035 TaskRunner.prototype.runTask = function (task) { 7036 if (this.runTaskOption) { 7037 this.runTaskOption(task); 7038 } 7039 }; 7040 TaskRunner.prototype.drained = function (completedTasks) { 7041 if (this.drainedOption) { 7042 this.drainedOption(completedTasks); 7043 } 7044 }; 7045 return TaskRunner; 7046 }()); 7047 7048 // Computes what the title at the top of the calendarApi should be for this view 7049 function buildTitle(dateProfile, viewOptions, dateEnv) { 7050 var range; 7051 // for views that span a large unit of time, show the proper interval, ignoring stray days before and after 7052 if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) { 7053 range = dateProfile.currentRange; 7054 } 7055 else { // for day units or smaller, use the actual day range 7056 range = dateProfile.activeRange; 7057 } 7058 return dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || buildTitleFormat(dateProfile)), { 7059 isEndExclusive: dateProfile.isRangeAllDay, 7060 defaultSeparator: viewOptions.titleRangeSeparator 7061 }); 7062 } 7063 // Generates the format string that should be used to generate the title for the current date range. 7064 // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`. 7065 function buildTitleFormat(dateProfile) { 7066 var currentRangeUnit = dateProfile.currentRangeUnit; 7067 if (currentRangeUnit === 'year') { 7068 return { year: 'numeric' }; 7069 } 7070 else if (currentRangeUnit === 'month') { 7071 return { year: 'numeric', month: 'long' }; // like "September 2014" 7072 } 7073 else { 7074 var days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end); 7075 if (days !== null && days > 1) { 7076 // multi-day range. shorter, like "Sep 9 - 10 2014" 7077 return { year: 'numeric', month: 'short', day: 'numeric' }; 7078 } 7079 else { 7080 // one day. longer, like "September 9 2014" 7081 return { year: 'numeric', month: 'long', day: 'numeric' }; 7082 } 7083 } 7084 } 7085 7086 // in future refactor, do the redux-style function(state=initial) for initial-state 7087 // also, whatever is happening in constructor, have it happen in action queue too 7088 var CalendarDataManager = /** @class */ (function () { 7089 function CalendarDataManager(props) { 7090 var _this = this; 7091 this.computeOptionsData = memoize(this._computeOptionsData); 7092 this.computeCurrentViewData = memoize(this._computeCurrentViewData);
7093 this.organizeRawLocales = memoize(organizeRawLocales); 7094 this.buildLocale = memoize(buildLocale); 7095 this.buildPluginHooks = buildBuildPluginHooks(); 7096 this.buildDateEnv = memoize(buildDateEnv$1); 7097 this.buildTheme = memoize(buildTheme); 7098 this.parseToolbars = memoize(parseToolbars); 7099 this.buildViewSpecs = memoize(buildViewSpecs); 7100 this.buildDateProfileGenerator = memoizeObjArg(buildDateProfileGenerator); 7101 this.buildViewApi = memoize(buildViewApi); 7102 this.buildViewUiProps = memoizeObjArg(buildViewUiProps); 7103 this.buildEventUiBySource = memoize(buildEventUiBySource, isPropsEqual); 7104 this.buildEventUiBases = memoize(buildEventUiBases); 7105 this.parseContextBusinessHours = memoizeObjArg(parseContextBusinessHours); 7106 this.buildTitle = memoize(buildTitle); 7107 this.emitter = new Emitter(); 7108 this.actionRunner = new TaskRunner(this._handleAction.bind(this), this.updateData.bind(this)); 7109 this.currentCalendarOptionsInput = {}; 7110 this.currentCalendarOptionsRefined = {}; 7111 this.currentViewOptionsInput = {}; 7112 this.currentViewOptionsRefined = {}; 7113 this.currentCalendarOptionsRefiners = {}; 7114 this.getCurrentData = function () { 7115 return _this.data; 7116 }; 7117 this.dispatch = function (action) { 7118 _this.actionRunner.request(action); // protects against recursive calls to _handleAction 7119 }; 7120 this.props = props; 7121 this.actionRunner.pause(); 7122 var dynamicOptionOverrides = {}; 7123 var optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi); 7124 var currentViewType = optionsData.calendarOptions.initialView || optionsData.pluginHooks.initialView; 7125 var currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides); 7126 // wire things up 7127 // TODO: not DRY 7128 props.calendarApi.currentDataManager = this; 7129 this.emitter.setThisContext(props.calendarApi); 7130 this.emitter.setOptions(currentViewData.options); 7131 var currentDate = getInitialDate(optionsData.calendarOptions, optionsData.dateEnv); 7132 var dateProfile = currentViewData.dateProfileGenerator.build(currentDate); 7133 if (!rangeContainsMarker(dateProfile.activeRange, currentDate)) { 7134 currentDate = dateProfile.currentRange.start; 7135 } 7136 var calendarContext = { 7137 dateEnv: optionsData.dateEnv, 7138 options: optionsData.calendarOptions, 7139 pluginHooks: optionsData.pluginHooks, 7140 calendarApi: props.calendarApi, 7141 dispatch: this.dispatch, 7142 emitter: this.emitter, 7143 getCurrentData: this.getCurrentData 7144 }; 7145 // needs to be after setThisContext 7146 for (var _i = 0, _a = optionsData.pluginHooks.contextInit; _i < _a.length; _i++) { 7147 var callback = _a[_i]; 7148 callback(calendarContext); 7149 } 7150 // NOT DRY 7151 var eventSources = initEventSources(optionsData.calendarOptions, dateProfile, calendarContext); 7152 var initialState = { 7153 dynamicOptionOverrides: dynamicOptionOverrides, 7154 currentViewType: currentViewType, 7155 currentDate: currentDate, 7156 dateProfile: dateProfile, 7157 businessHours: this.parseContextBusinessHours(calendarContext), 7158 eventSources: eventSources, 7159 eventUiBases: {}, 7160 loadingLevel: computeEventSourceLoadingLevel(eventSources), 7161 eventStore: createEmptyEventStore(), 7162 renderableEventStore: createEmptyEventStore(), 7163 dateSelection: null, 7164 eventSelection: '', 7165 eventDrag: null, 7166 eventResize: null, 7167 selectionConfig: this.buildViewUiProps(calendarContext).selectionConfig 7168 }; 7169 var contextAndState = __assign(__assign({}, calendarContext), initialState); 7170 for (var _b = 0, _c = optionsData.pluginHooks.reducers; _b < _c.length; _b++) { 7171 var reducer = _c[_b]; 7172 __assign(initialState, reducer(null, null, contextAndState)); 7173 } 7174 if (initialState.loadingLevel) { 7175 this.emitter.trigger('loading', true); // NOT DRY 7176 } 7177 this.state = initialState; 7178 this.updateData(); 7179 this.actionRunner.resume(); 7180 } 7181 CalendarDataManager.prototype.resetOptions = function (optionOverrides, append) { 7182 var props = this.props; 7183 props.optionOverrides = append 7184 ? __assign(__assign({}, props.optionOverrides), optionOverrides) : optionOverrides; 7185 this.actionRunner.request({ 7186 type: 'NOTHING' 7187 }); 7188 }; 7189 CalendarDataManager.prototype._handleAction = function (action) { 7190 var _a = this, props = _a.props, state = _a.state, emitter = _a.emitter; 7191 var dynamicOptionOverrides = reduceDynamicOptionOverrides(state.dynamicOptionOverrides, action); 7192 var optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi); 7193 var currentViewType = reduceViewType(state.currentViewType, action); 7194 var currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides); 7195 // wire things up 7196 // TODO: not DRY 7197 props.calendarApi.currentDataManager = this; 7198 emitter.setThisContext(props.calendarApi); 7199 emitter.setOptions(currentViewData.options); 7200 var calendarContext = { 7201 dateEnv: optionsData.dateEnv, 7202 options: optionsData.calendarOptions, 7203 pluginHooks: optionsData.pluginHooks, 7204 calendarApi: props.calendarApi, 7205 dispatch: this.dispatch, 7206 emitter: emitter, 7207 getCurrentData: this.getCurrentData 7208 }; 7209 var currentDate = state.currentDate; 7210 var dateProfile = state.dateProfile; 7211 if (this.data && this.data.dateProfileGenerator !== currentViewData.dateProfileGenerator) { // hack 7212 dateProfile = currentViewData.dateProfileGenerator.build(currentDate); 7213 } 7214 currentDate = reduceCurrentDate(currentDate, action); 7215 dateProfile = reduceDateProfile(dateProfile, action, currentDate, currentViewData.dateProfileGenerator); 7216 if (!rangeContainsMarker(dateProfile.currentRange, currentDate)) { 7217 currentDate = dateProfile.currentRange.start; 7218 } 7219 var eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendarContext); 7220 var eventSourceLoadingLevel = computeEventSourceLoadingLevel(eventSources); 7221 var eventStore = reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendarContext); 7222 var renderableEventStore = (eventSourceLoadingLevel && !currentViewData.options.progressiveEventRendering) ? 7223 (state.renderableEventStore || eventStore) : // try from previous state 7224 eventStore; 7225 var _b = this.buildViewUiProps(calendarContext), eventUiSingleBase = _b.eventUiSingleBase, selectionConfig = _b.selectionConfig; // will memoize obj 7226 var eventUiBySource = this.buildEventUiBySource(eventSources); 7227 var eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource); 7228 var prevLoadingLevel = state.loadingLevel || 0; 7229 var loadingLevel = eventSourceLoadingLevel; 7230 var newState = { 7231 dynamicOptionOverrides: dynamicOptionOverrides, 7232 currentViewType: currentViewType, 7233 currentDate: currentDate, 7234 dateProfile: dateProfile, 7235 eventSources: eventSources, 7236 eventStore: eventStore, 7237 renderableEventStore: renderableEventStore, 7238 selectionConfig: selectionConfig, 7239 eventUiBases: eventUiBases, 7240 loadingLevel: loadingLevel, 7241 businessHours: this.parseContextBusinessHours(calendarContext), 7242 dateSelection: reduceDateSelection(state.dateSelection, action), 7243 eventSelection: reduceSelectedEvent(state.eventSelection, action), 7244 eventDrag: reduceEventDrag(state.eventDrag, action), 7245 eventResize: reduceEventResize(state.eventResize, action) 7246 }; 7247 var contextAndState = __assign(__assign({}, calendarContext), newState); 7248 for (var _i = 0, _c = optionsData.pluginHooks.reducers; _i < _c.length; _i++) { 7249 var reducer = _c[_i]; 7250 __assign(newState, reducer(state, action, contextAndState)); // give the OLD state, for old value 7251 } 7252 // TODO: use propSetHandlers in plugin system 7253 if (!prevLoadingLevel && loadingLevel) { 7254 emitter.trigger('loading', true); 7255 } 7256 else if (prevLoadingLevel && !loadingLevel) { 7257 emitter.trigger('loading', false); 7258 } 7259 this.state = newState; 7260 if (props.onAction) { 7261 props.onAction(action); 7262 } 7263 }; 7264 CalendarDataManager.prototype.updateData = function () { 7265 var _a = this, props = _a.props, state = _a.state; 7266 var oldData = this.data; 7267 var optionsData = this.computeOptionsData(props.optionOverrides, state.dynamicOptionOverrides, props.calendarApi); 7268 var currentViewData = this.computeCurrentViewData(state.currentViewType, optionsData, props.optionOverrides, state.dynamicOptionOverrides); 7269 var data = this.data = __assign(__assign(__assign({ viewTitle: this.buildTitle(state.dateProfile, currentViewData.options, optionsData.dateEnv), calendarApi: props.calendarApi, dispatch: this.dispatch, emitter: this.emitter, getCurrentData: this.getCurrentData }, optionsData), currentViewData), state); 7270 var changeHandlers = optionsData.pluginHooks.optionChangeHandlers; 7271 var oldCalendarOptions = oldData && oldData.calendarOptions; 7272 var newCalendarOptions = optionsData.calendarOptions; 7273 if (oldCalendarOptions && oldCalendarOptions !== newCalendarOptions) { 7274 if (oldCalendarOptions.timeZone !== newCalendarOptions.timeZone) { 7275 // hack 7276 state.eventSources = data.eventSources = reduceEventSourcesNe
7276wTimeZone(data.eventSources, state.dateProfile, data); 7277 state.eventStore = data.eventStore = rezoneEventStoreDates(data.eventStore, oldData.dateEnv, data.dateEnv); 7278 } 7279 for (var optionName in changeHandlers) { 7280 if (oldCalendarOptions[optionName] !== newCalendarOptions[optionName]) { 7281 changeHandlers[optionName](newCalendarOptions[optionName], data); 7282 } 7283 } 7284 } 7285 if (props.onData) { 7286 props.onData(data); 7287 } 7288 }; 7289 CalendarDataManager.prototype._computeOptionsData = function (optionOverrides, dynamicOptionOverrides, calendarApi) { 7290 // TODO: blacklist options that are handled by optionChangeHandlers 7291 var _a = this.processRawCalendarOptions(optionOverrides, dynamicOptionOverrides), refinedOptions = _a.refinedOptions, pluginHooks = _a.pluginHooks, localeDefaults = _a.localeDefaults, availableLocaleData = _a.availableLocaleData, extra = _a.extra; 7292 warnUnknownOptions(extra); 7293 var dateEnv = this.buildDateEnv(refinedOptions.timeZone, refinedOptions.locale, refinedOptions.weekNumberCalculation, refinedOptions.firstDay, refinedOptions.weekText, pluginHooks, availableLocaleData, refinedOptions.defaultRangeSeparator); 7294 var viewSpecs = this.buildViewSpecs(pluginHooks.views, optionOverrides, dynamicOptionOverrides, localeDefaults); 7295 var theme = this.buildTheme(refinedOptions, pluginHooks); 7296 var toolbarConfig = this.parseToolbars(refinedOptions, optionOverrides, theme, viewSpecs, calendarApi); 7297 return { 7298 calendarOptions: refinedOptions, 7299 pluginHooks: pluginHooks, 7300 dateEnv: dateEnv, 7301 viewSpecs: viewSpecs, 7302 theme: theme, 7303 toolbarConfig: toolbarConfig, 7304 localeDefaults: localeDefaults, 7305 availableRawLocales: availableLocaleData.map 7306 }; 7307 }; 7308 // always called from behind a memoizer 7309 CalendarDataManager.prototype.processRawCalendarOptions = function (optionOverrides, dynamicOptionOverrides) { 7310 var _a = mergeRawOptions([ 7311 BASE_OPTION_DEFAULTS, 7312 optionOverrides, 7313 dynamicOptionOverrides 7314 ]), locales = _a.locales, locale = _a.locale; 7315 var availableLocaleData = this.organizeRawLocales(locales); 7316 var availableRawLocales = availableLocaleData.map; 7317 var localeDefaults = this.buildLocale(locale || availableLocaleData.defaultCode, availableRawLocales).options; 7318 var pluginHooks = this.buildPluginHooks(optionOverrides.plugins || [], globalPlugins); 7319 var refiners = this.currentCalendarOptionsRefiners = __assign(__assign(__assign(__assign(__assign({}, BASE_OPTION_REFINERS), CALENDAR_LISTENER_REFINERS), CALENDAR_OPTION_REFINERS), pluginHooks.listenerRefiners), pluginHooks.optionRefiners); 7320 var extra = {}; 7321 var raw = mergeRawOptions([ 7322 BASE_OPTION_DEFAULTS, 7323 localeDefaults, 7324 optionOverrides, 7325 dynamicOptionOverrides 7326 ]); 7327 var refined = {}; 7328 var currentRaw = this.currentCalendarOptionsInput; 7329 var currentRefined = this.currentCalendarOptionsRefined; 7330 var anyChanges = false; 7331 for (var optionName in raw) { 7332 if (optionName !== 'plugins') { // because plugins is special-cased 7333 if (raw[optionName] === currentRaw[optionName] || 7334 (COMPLEX_OPTION_COMPARATORS[optionName] && (optionName in currentRaw) && COMPLEX_OPTION_COMPARATORS[optionName](currentRaw[optionName], raw[optionName]))) { 7335 refined[optionName] = currentRefined[optionName]; 7336 } 7337 else if (refiners[optionName]) { 7338 refined[optionName] = refiners[optionName](raw[optionName]); 7339 anyChanges = true; 7340 } 7341 else { 7342 extra[optionName] = currentRaw[optionName]; 7343 } 7344 } 7345 }
7346 if (anyChanges) { 7347 this.currentCalendarOptionsInput = raw; 7348 this.currentCalendarOptionsRefined = refined; 7349 } 7350 return { 7351 rawOptions: this.currentCalendarOptionsInput, 7352 refinedOptions: this.currentCalendarOptionsRefined, 7353 pluginHooks: pluginHooks, 7354 availableLocaleData: availableLocaleData, 7355 localeDefaults: localeDefaults, 7356 extra: extra 7357 }; 7358 }; 7359 CalendarDataManager.prototype._computeCurrentViewData = function (viewType, optionsData, optionOverrides, dynamicOptionOverrides) { 7360 var viewSpec = optionsData.viewSpecs[viewType]; 7361 if (!viewSpec) { 7362 throw new Error("viewType \"" + viewType + "\" is not available. Please make sure you've loaded all neccessary plugins"); 7363 } 7364 var _a = this.processRawViewOptions(viewSpec, optionsData.pluginHooks, optionsData.localeDefaults, optionOverrides, dynamicOptionOverrides), refinedOptions = _a.refinedOptions, extra = _a.extra; 7365 warnUnknownOptions(extra); 7366 var dateProfileGenerator = this.buildDateProfileGenerator({ 7367 dateProfileGeneratorClass: viewSpec.optionDefaults.dateProfileGeneratorClass, 7368 duration: viewSpec.duration, 7369 durationUnit: viewSpec.durationUnit, 7370 usesMinMaxTime: viewSpec.optionDefaults.usesMinMaxTime, 7371 dateEnv: optionsData.dateEnv, 7372 calendarApi: this.props.calendarApi, 7373 slotMinTime: refinedOptions.slotMinTime, 7374 slotMaxTime: refinedOptions.slotMaxTime, 7375 showNonCurrentDates: refinedOptions.showNonCurrentDates, 7376 dayCount: refinedOptions.dayCount, 7377 dateAlignment: refinedOptions.dateAlignment, 7378 dateIncrement: refinedOptions.dateIncrement, 7379 hiddenDays: refinedOptions.hiddenDays, 7380 weekends: refinedOptions.weekends, 7381 nowInput: refinedOptions.now, 7382 validRangeInput: refinedOptions.validRange, 7383 visibleRangeInput: refinedOptions.visibleRange, 7384 monthMode: refinedOptions.monthMode, 7385 fixedWeekCount: refinedOptions.fixedWeekCount 7386 }); 7387 var viewApi = this.buildViewApi(viewType, this.getCurrentData, optionsData.dateEnv); 7388 return { viewSpec: viewSpec, options: refinedOptions, dateProfileGenerator: dateProfileGenerator, viewApi: viewApi }; 7389 }; 7390 CalendarDataManager.prototype.processRawViewOptions = function (viewSpec, pluginHooks, localeDefaults, optionOverrides, dynamicOptionOverrides) { 7391 var raw = mergeRawOptions([ 7392 BASE_OPTION_DEFAULTS, 7393 viewSpec.optionDefaults, 7394 localeDefaults, 7395 optionOverrides, 7396 viewSpec.optionOverrides, 7397 dynamicOptionOverrides 7398 ]); 7399 var refiners = __assign(__assign(__assign(__assign(__assign(__assign({}, BASE_OPTION_REFINERS), CALENDAR_LISTENER_REFINERS), CALENDAR_OPTION_REFINERS), VIEW_OPTION_REFINERS), pluginHooks.listenerRefiners), pluginHooks.optionRefiners); 7400 var refined = {}; 7401 var currentRaw = this.currentViewOptionsInput; 7402 var currentRefined = this.currentViewOptionsRefined; 7403 var anyChanges = false; 7404 var extra = {}; 7405 for (var optionName in raw) { 7406 if (raw[optionName] === currentRaw[optionName]) { 7407 refined[optionName] = currentRefined[optionName]; 7408 } 7409 else { 7410 if (raw[optionName] === this.currentCalendarOptionsInput[optionName]) { 7411 if (optionName in this.currentCalendarOptionsRefined) { // might be an "extra" prop 7412 refined[optionName] = this.currentCalendarOptionsRefined[optionName]; 7413 } 7414 } 7415 else if (refiners[optionName]) { 7416 refined[optionName] = refiners[optionName](raw[optionName]); 7417 } 7418 else { 7419 extra[optionName] = raw[optionName]; 7420 } 7421 anyChanges = true; 7422 } 7423 }
7424 if (anyChanges) { 7425 this.currentViewOptionsInput = raw; 7426 this.currentViewOptionsRefined = refined; 7427 } 7428 return { 7429 rawOptions: this.currentViewOptionsInput, 7430 refinedOptions: this.currentViewOptionsRefined, 7431 extra: extra 7432 }; 7433 }; 7434 return CalendarDataManager; 7435 }()); 7436 function buildDateEnv$1(timeZone, explicitLocale, weekNumberCalculation, firstDay, weekText, pluginHooks, availableLocaleData, defaultSeparator) { 7437 var locale = buildLocale(explicitLocale || availableLocaleData.defaultCode, availableLocaleData.map); 7438 return new DateEnv({ 7439 calendarSystem: 'gregory', 7440 timeZone: timeZone, 7441 namedTimeZoneImpl: pluginHooks.namedTimeZonedImpl, 7442 locale: locale, 7443 weekNumberCalculation: weekNumberCalculation, 7444 firstDay: firstDay, 7445 weekText: weekText, 7446 cmdFormatter: pluginHooks.cmdFormatter, 7447 defaultSeparator: defaultSeparator 7448 }); 7449 } 7450 function buildTheme(options, pluginHooks) { 7451 var ThemeClass = pluginHooks.themeClasses[options.themeSystem] || StandardTheme; 7452 return new ThemeClass(options); 7453 } 7454 function buildDateProfileGenerator(props) { 7455 var DateProfileGeneratorClass = props.dateProfileGeneratorClass || DateProfileGenerator; 7456 return new DateProfileGeneratorClass(props); 7457 } 7458 function buildViewApi(type, getCurrentData, dateEnv) { 7459 return new ViewApi(type, getCurrentData, dateEnv); 7460 } 7461 function buildEventUiBySource(eventSources) { 7462 return mapHash(eventSources, function (eventSource) { 7463 return eventSource.ui; 7464 }); 7465 } 7466 function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) { 7467 var eventUiBases = { '': eventUiSingleBase }; 7468 for (var defId in eventDefs) { 7469 var def = eventDefs[defId]; 7470 if (def.sourceId && eventUiBySource[def.sourceId]) { 7471 eventUiBases[defId] = eventUiBySource[def.sourceId]; 7472 } 7473 } 7474 return eventUiBases; 7475 } 7476 function buildViewUiProps(calendarContext) { 7477 var options = calendarContext.options; 7478 return { 7479 eventUiSingleBase: createEventUi({ 7480 display: options.eventDisplay, 7481 editable: options.editable, 7482 startEditable: options.eventStartEditable, 7483 durationEditable: options.eventDurationEditable, 7484 constraint: options.eventConstraint, 7485 overlap: typeof options.eventOverlap === 'boolean' ? options.eventOverlap : undefined, 7486 allow: options.eventAllow, 7487 backgroundColor: options.eventBackgroundColor, 7488 borderColor: options.eventBorderColor, 7489 textColor: options.eventTextColor, 7490 color: options.eventColor 7491 // classNames: options.eventClassNames // render hook will handle this 7492 }, calendarContext), 7493 selectionConfig: createEventUi({ 7494 constraint: options.selectConstraint, 7495 overlap: typeof options.selectOverlap === 'boolean' ? options.selectOverlap : undefined, 7496 allow: options.selectAllow 7497 }, calendarContext) 7498 }; 7499 } 7500 function parseContextBusinessHours(calendarContext) { 7501 return parseBusinessHours(calendarContext.options.businessHours, calendarContext); 7502 } 7503 function warnUnknownOptions(options, viewName) { 7504 for (var optionName in options) { 7505 console.warn("Unknown option '" + optionName + "'" + 7506 (viewName ? " for view '" + viewName + "'" : '')); 7507 } 7508 } 7509 7510 // TODO: move this to react plugin? 7511 var CalendarDataProvider = /** @class */ (function (_super) { 7512 __extends(CalendarDataProvider, _super); 7513 function CalendarDataProvider(props) { 7514 var _this = _super.call(this, props) || this; 7515 _this.handleData = function (data) { 7516 if (!_this.dataManager) { // still within initial run, before assignment in constructor 7517 // eslint-disable-next-line react/no-direct-mutation-state 7518 _this.state = data; // can't use setState yet 7519 } 7520 else { 7521 _this.setState(data); 7522 } 7523 }; 7524 _this.dataManager = new CalendarDataManager({ 7525 optionOverrides: props.optionOverrides, 7526 calendarApi: props.calendarApi, 7527 onData: _this.handleData 7528 }); 7529 return _this; 7530 } 7531 CalendarDataProvider.prototype.render = function () { 7532 return this.props.children(this.state); 7533 }; 7534 CalendarDataProvider.prototype.componentDidUpdate = function (prevProps) { 7535 var newOptionOverrides = this.props.optionOverrides; 7536 if (newOptionOverrides !== prevProps.optionOverrides) { // prevent recursive handleData 7537 this.dataManager.resetOptions(newOptionOverrides); 7538 } 7539 }; 7540 return CalendarDataProvider; 7541 }(Component)); 7542 7543 // HELPERS 7544 /* 7545 if nextDayThreshold is specified, slicing is done in an all-day fashion. 7546 you can get nextDayThreshold from context.nextDayThreshold 7547 */ 7548 function sliceEvents(props, allDay) { 7549 return sliceEventStore(props.eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? props.nextDayThreshold : null).fg; 7550 } 7551 7552 var NamedTimeZoneImpl = /** @class */ (function () { 7553 function NamedTimeZoneImpl(timeZoneName) { 7554 this.timeZoneName = timeZoneName; 7555 } 7556 return NamedTimeZoneImpl; 7557 }()); 7558 7559 var Interaction = /** @class */ (function () { 7560 function Interaction(settings) { 7561 this.component = settings.component; 7562 } 7563 Interaction.prototype.destroy = function () { 7564 }; 7565 return Interaction; 7566 }()); 7567 function parseInteractionSettings(component, input) { 7568 return { 7569 component: component, 7570 el: input.el, 7571 useEventCenter: input.useEventCenter != null ? input.useEventCenter : true 7572 }; 7573 } 7574 function interactionSettingsToStore(settings) { 7575 var _a; 7576 return _a = {}, 7577 _a[settings.component.uid] = settings, 7578 _a; 7579 } 7580 // global state 7581 var interactionSettingsStore = {}; 7582 7583 /* 7584 An abstraction for a dragging interaction originating on an event. 7585 Does higher-level things than PointerDragger, such as possibly: 7586 - a "mirror" that moves with the pointer 7587 - a minimum number of pixels or other criteria for a true drag to begin 7588 7589 subclasses must emit: 7590 - pointerdown 7591 - dragstart 7592 - dragmove 7593 - pointerup 7594 - dragend 7595 */ 7596 var ElementDragging = /** @class */ (function () { 7597 function ElementDragging(el, selector) { 7598 this.emitter = new Emitter(); 7599 } 7600 ElementDragging.prototype.destroy = function () { 7601 }; 7602 ElementDragging.prototype.setMirrorIsVisible = function (bool) {
7603 // optional if subclass doesn't want to support a mirror 7604 }; 7605 ElementDragging.prototype.setMirrorNeedsRevert = function (bool) { 7606 // optional if subclass doesn't want to support a mirror 7607 }; 7608 ElementDragging.prototype.setAutoScrollEnabled = function (bool) { 7609 // optional 7610 }; 7611 return ElementDragging; 7612 }()); 7613 7614 // TODO: get rid of this in favor of options system, 7615 // tho it's really easy to access this globally rather than pass thru options. 7616 var config = {}; 7617 7618 /* 7619 Information about what will happen when an external element is dragged-and-dropped 7620 onto a calendar. Contains information for creating an event. 7621 */ 7622 var DRAG_META_REFINERS = { 7623 startTime: createDuration, 7624 duration: createDuration, 7625 create: Boolean, 7626 sourceId: String 7627 }; 7628 function parseDragMeta(raw) { 7629 var _a = refineProps(raw, DRAG_META_REFINERS), refined = _a.refined, extra = _a.extra; 7630 return { 7631 startTime: refined.startTime || null, 7632 duration: refined.duration || null, 7633 create: refined.create != null ? refined.create : true, 7634 sourceId: refined.sourceId, 7635 leftoverProps: extra 7636 }; 7637 } 7638 7639 var Toolbar = /** @class */ (function (_super) { 7640 __extends(Toolbar, _super); 7641 function Toolbar() { 7642 return _super !== null && _super.apply(this, arguments) || this; 7643 } 7644 Toolbar.prototype.render = function () { 7645 var _a = this.props, model = _a.model, extraClassName = _a.extraClassName; 7646 var forceLtr = false; 7647 var startContent, endContent; 7648 var centerContent = model.center; 7649 if (model.left) { 7650 forceLtr = true; 7651 startContent = model.left; 7652 } 7653 else { 7654 startContent = model.start; 7655 } 7656 if (model.right) { 7657 forceLtr = true; 7658 endContent = model.right; 7659 } 7660 else { 7661 endContent = model.end; 7662 } 7663 var classNames = [ 7664 extraClassName || '', 7665 'fc-toolbar', 7666 forceLtr ? 'fc-toolbar-ltr' : '' 7667 ]; 7668 return (createElement("div", { className: classNames.join(' ') }, 7669 this.renderSection('start', startContent || []), 7670 this.renderSection('center', centerContent || []), 7671 this.renderSection('end', endContent || []))); 7672 }; 7673 Toolbar.prototype.renderSection = function (key, widgetGroups) { 7674 var props = this.props; 7675 return (createElement(ToolbarSection, { key: key, widgetGroups: widgetGroups, title: props.title, activeButton: props.activeButton, isTodayEnabled: props.isTodayEnabled, isPrevEnabled: props.isPrevEnabled, isNextEnabled: props.isNextEnabled })); 7676 }; 7677 return Toolbar; 7678 }(BaseComponent)); 7679 var ToolbarSection = /** @class */ (function (_super) { 7680 __extends(ToolbarSection, _super); 7681 function ToolbarSection() { 7682 return _super !== null && _super.apply(this, arguments) || this; 7683 } 7684 ToolbarSection.prototype.render = function () { 7685 var _this = this; 7686 var children = this.props.widgetGroups.map(function (widgetGroup) { return _this.renderWidgetGroup(widgetGroup); }); 7687 return createElement.apply(void 0, __spreadArrays(['div', { className: 'fc-toolbar-chunk' }], children)); 7688 }; 7689 ToolbarSection.prototype.renderWidgetGroup = function (widgetGroup) { 7690 var props = this.props; 7691 var theme = this.context.theme; 7692 var children = []; 7693 var isOnlyButtons = true; 7694 for (var _i = 0, widgetGroup_1 = widgetGroup; _i < widgetGroup_1.length; _i++) { 7695 var widget = widgetGroup_1[_i]; 7696 var buttonName = widget.buttonName, buttonClick = widget.buttonClick, buttonText = widget.buttonText, buttonIcon = widget.buttonIcon; 7697 if (buttonName === 'title') { 7698 isOnlyButtons = false;
7699 children.push(createElement("h2", { className: 'fc-toolbar-title' }, props.title)); 7700 } 7701 else { 7702 var ariaAttrs = buttonIcon ? { 'aria-label': buttonName } : {}; 7703 var buttonClasses = ['fc-' + buttonName + '-button', theme.getClass('button')]; 7704 if (buttonName === props.activeButton) { 7705 buttonClasses.push(theme.getClass('buttonActive')); 7706 } 7707 var isDisabled = (!props.isTodayEnabled && buttonName === 'today') || 7708 (!props.isPrevEnabled && buttonName === 'prev') || 7709 (!props.isNextEnabled && buttonName === 'next'); 7710 children.push(createElement("button", __assign({ disabled: isDisabled, className: buttonClasses.join(' '), onClick: buttonClick, type: 'button' }, ariaAttrs), buttonText || (buttonIcon ? createElement("span", { className: buttonIcon }) : ''))); 7711 } 7712 } 7713 if (children.length > 1) { 7714 var groupClassName = (isOnlyButtons && theme.getClass('buttonGroup')) || ''; 7715 return createElement.apply(void 0, __spreadArrays(['div', { className: groupClassName }], children)); 7716 } 7717 else { 7718 return children[0]; 7719 } 7720 }; 7721 return ToolbarSection; 7722 }(BaseComponent)); 7723 7724 // TODO: do function component? 7725 var ViewContainer = /** @class */ (function (_super) { 7726 __extends(ViewContainer, _super); 7727 function ViewContainer() { 7728 var _this = _super !== null && _super.apply(this, arguments) || this; 7729 _this.state = { 7730 availableWidth: null 7731 }; 7732 _this.handleEl = function (el) { 7733 _this.el = el; 7734 setRef(_this.props.elRef, el); 7735 _this.updateAvailableWidth(); 7736 }; 7737 _this.handleResize = function () { 7738 _this.updateAvailableWidth(); 7739 }; 7740 return _this; 7741 } 7742 ViewContainer.prototype.render = function () { 7743 var _a = this, props = _a.props, state = _a.state; 7744 var aspectRatio = props.aspectRatio; 7745 var classNames = [ 7746 'fc-view-harness', 7747 (aspectRatio || props.liquid || props.height) 7748 ? 'fc-view-harness-active' // harness controls the height 7749 : 'fc-view-harness-passive' // let the view do the height 7750 ]; 7751 var height = ''; 7752 var paddingBottom = ''; 7753 if (aspectRatio) { 7754 if (state.availableWidth !== null) { 7755 height = state.availableWidth / aspectRatio; 7756 } 7757 else { 7758 // while waiting to know availableWidth, we can't set height to *zero* 7759 // because will cause lots of unnecessary scrollbars within scrollgrid. 7760 // BETTER: don't start rendering ANYTHING yet until we know container width 7761 // NOTE: why not always use paddingBottom? Causes height oscillation (issue 5606) 7762 paddingBottom = (1 / aspectRatio) * 100 + '%'; 7763 } 7764 } 7765 else { 7766 height = props.height || ''; 7767 } 7768 return (createElement("div", { ref: this.handleEl, onClick: props.onClick, className: classNames.join(' '), style: { height: height, paddingBottom: paddingBottom } }, props.children)); 7769 }; 7770 ViewContainer.prototype.componentDidMount = function () { 7771 this.context.addResizeHandler(this.handleResize); 7772 }; 7773 ViewContainer.prototype.componentWillUnmount = function () { 7774 this.context.removeResizeHandler(this.handleResize); 7775 }; 7776 ViewContainer.prototype.updateAvailableWidth = function () { 7777 if (this.el && // needed. but why? 7778 this.props.aspectRatio // aspectRatio is the only height setting that needs availableWidth 7779 ) { 7780 this.setState({ availableWidth: this.el.offsetWidth }); 7781 } 7782 }; 7783 return ViewContainer; 7784 }(BaseComponent)); 7785 7786 /* 7787 Detects when the user clicks on an event within a DateComponent 7788 */ 7789 var EventClicking = /** @class */ (function (_super) { 7790 __extends(EventClicking, _super);
7791 function EventClicking(settings) { 7792 var _this = _super.call(this, settings) || this; 7793 _this.handleSegClick = function (ev, segEl) { 7794 var component = _this.component; 7795 var context = component.context; 7796 var seg = getElSeg(segEl); 7797 if (seg && // might be the <div> surrounding the more link 7798 component.isValidSegDownEl(ev.target)) { 7799 // our way to simulate a link click for elements that can't be <a> tags 7800 // grab before trigger fired in case trigger trashes DOM thru rerendering 7801 var hasUrlContainer = elementClosest(ev.target, '.fc-event-forced-url'); 7802 var url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : ''; 7803 context.emitter.trigger('eventClick', { 7804 el: segEl, 7805 event: new EventApi(component.context, seg.eventRange.def, seg.eventRange.instance), 7806 jsEvent: ev, 7807 view: context.viewApi 7808 }); 7809 if (url && !ev.defaultPrevented) { 7810 window.location.href = url; 7811 } 7812 } 7813 }; 7814 _this.destroy = listenBySelector(settings.el, 'click', '.fc-event', // on both fg and bg events 7815 _this.handleSegClick); 7816 return _this; 7817 } 7818 return EventClicking; 7819 }(Interaction)); 7820 7821 /* 7822 Triggers events and adds/removes core classNames when the user's pointer 7823 enters/leaves event-elements of a component. 7824 */ 7825 var EventHovering = /** @class */ (function (_super) { 7826 __extends(EventHovering, _super); 7827 function EventHovering(settings) { 7828 var _this = _super.call(this, settings) || this; 7829 // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it 7830 _this.handleEventElRemove = function (el) { 7831 if (el === _this.currentSegEl) { 7832 _this.handleSegLeave(null, _this.currentSegEl); 7833 } 7834 }; 7835 _this.handleSegEnter = function (ev, segEl) { 7836 if (getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper 7837 _this.currentSegEl = segEl; 7838 _this.triggerEvent('eventMouseEnter', ev, segEl); 7839 } 7840 }; 7841 _this.handleSegLeave = function (ev, segEl) { 7842 if (_this.currentSegEl) { 7843 _this.currentSegEl = null; 7844 _this.triggerEvent('eventMouseLeave', ev, segEl); 7845 } 7846 }; 7847 _this.removeHoverListeners = listenToHoverBySelector(settings.el, '.fc-event', // on both fg and bg events 7848 _this.handleSegEnter, _this.handleSegLeave); 7849 return _this; 7850 } 7851 EventHovering.prototype.destroy = function () { 7852 this.removeHoverListeners(); 7853 }; 7854 EventHovering.prototype.triggerEvent = function (publicEvName, ev, segEl) { 7855 var component = this.component; 7856 var context = component.context; 7857 var seg = getElSeg(segEl); 7858 if (!ev || component.isValidSegDownEl(ev.target)) { 7859 context.emitter.trigger(publicEvName, { 7860 el: segEl, 7861 event: new EventApi(context, seg.eventRange.def, seg.eventRange.instance), 7862 jsEvent: ev, 7863 view: context.viewApi 7864 }); 7865 } 7866 }; 7867 return EventHovering; 7868 }(Interaction)); 7869 7870 var CalendarContent = /** @class */ (function (_super) { 7871 __extends(CalendarContent, _super); 7872 function CalendarContent() { 7873 var _this = _super !== null && _super.apply(this, arguments) || this; 7874 _this.buildViewContext = memoize(buildViewContext); 7875 _this.buildViewPropTransformers = memoize(buildViewPropTransformers); 7876 _this.buildToolbarProps = memoize(buildToolbarProps); 7877 _this.handleNavLinkClick = buildDelegationHandler('a[data-navlink]', _this._handleNavLinkClick.bind(_this)); 7878 _this.headerRef = createRef(); 7879 _this.footerRef = createRef(); 7880 _this.interactionsStore = {}; 7881 // Component Registration 7882 // ----------------------------------------------------------------------------------------------------------------- 7883 _this.registerInteractiveComponent = function (component, settingsInput) { 7884 var settings = parseInteractionSettings(component, settingsInput); 7885 var DEFAULT_INTERACTIONS = [ 7886 EventClicking, 7887 EventHovering 7888 ]; 7889 var interactionClasses = DEFAULT_INTERACTIONS.concat(_this.props.pluginHooks.componentInteractions); 7890 var interactions = interactionClasses.map(function (interactionClass) { 7891 return new interactionClass(settings); 7892 }); 7893 _this.interactionsStore[component.uid] = interactions; 7894 interactionSettingsStore[component.uid] = settings; 7895 }; 7896 _this.unregisterInteractiveComponent = function (component) { 7897 for (var _i = 0, _a = _this.interactionsStore[component.uid]; _i < _a.length; _i++) { 7898 var listener = _a[_i]; 7899 listener.destroy(); 7900 } 7901 delete _this.interactionsStore[component.uid]; 7902 delete interactionSettingsStore[component.uid]; 7903 }; 7904 // Resizing 7905 // ----------------------------------------------------------------------------------------------------------------- 7906 _this.resizeRunner = new DelayedRunner(function () { 7907 _this.props.emitter.trigger('_resize', true); // should window resizes be considered "forced" ? 7908 _this.props.emitter.trigger('windowResize', { view: _this.props.viewApi }); 7909 }); 7910 _this.handleWindowResize = function (ev) { 7911 var options = _this.props.options; 7912 if (options.handleWindowResize && 7913 ev.target === window // avoid jqui events 7914 ) { 7915 _this.resizeRunner.request(options.windowResizeDelay); 7916 } 7917 }; 7918 return _this; 7919 } 7920 /* 7921 renders INSIDE of an outer div 7922 */ 7923 CalendarContent.prototype.render = function () { 7924 var props = this.props; 7925 var toolbarConfig = props.toolbarConfig, options = props.options; 7926 var toolbarProps = this.buildToolbarProps(props.viewSpec, props.dateProfile, props.dateProfileGenerator, props.currentDate, getNow(props.options.now, props.dateEnv), // TODO: use NowTimer???? 7927 props.viewTitle); 7928 var viewVGrow = false;
7929 var viewHeight = ''; 7930 var viewAspectRatio; 7931 if (props.isHeightAuto || props.forPrint) { 7932 viewHeight = ''; 7933 } 7934 else if (options.height != null) { 7935 viewVGrow = true; 7936 } 7937 else if (options.contentHeight != null) { 7938 viewHeight = options.contentHeight; 7939 } 7940 else { 7941 viewAspectRatio = Math.max(options.aspectRatio, 0.5); // prevent from getting too tall 7942 } 7943 var viewContext = this.buildViewContext(props.viewSpec, props.viewApi, props.options, props.dateProfileGenerator, props.dateEnv, props.theme, props.pluginHooks, props.dispatch, props.getCurrentData, props.emitter, props.calendarApi, this.registerInteractiveComponent, this.unregisterInteractiveComponent); 7944 return (createElement(ViewContextType.Provider, { value: viewContext }, 7945 toolbarConfig.headerToolbar && 7946 createElement(Toolbar, __assign({ ref: this.headerRef, extraClassName: 'fc-header-toolbar', model: toolbarConfig.headerToolbar }, toolbarProps)), 7947 createElement(ViewContainer, { liquid: viewVGrow, height: viewHeight, aspectRatio: viewAspectRatio, onClick: this.handleNavLinkClick }, 7948 this.renderView(props), 7949 this.buildAppendContent()), 7950 toolbarConfig.footerToolbar && 7951 createElement(Toolbar, __assign({ ref: this.footerRef, extraClassName: 'fc-footer-toolbar', model: toolbarConfig.footerToolbar }, toolbarProps)))); 7952 }; 7953 CalendarContent.prototype.componentDidMount = function () { 7954 var props = this.props; 7955 this.calendarInteractions = props.pluginHooks.calendarInteractions 7956 .map(function (calendarInteractionClass) { 7957 return new calendarInteractionClass(props); 7958 }); 7959 window.addEventListener('resize', this.handleWindowResize); 7960 var propSetHandlers = props.pluginHooks.propSetHandlers; 7961 for (var propName in propSetHandlers) { 7962 propSetHandlers[propName](props[propName], props); 7963 } 7964 }; 7965 CalendarContent.prototype.componentDidUpdate = function (prevProps) { 7966 var props = this.props; 7967 var propSetHandlers = props.pluginHooks.propSetHandlers; 7968 for (var propName in propSetHandlers) { 7969 if (props[propName] !== prevProps[propName]) { 7970 propSetHandlers[propName](props[propName], props); 7971 } 7972 } 7973 }; 7974 CalendarContent.prototype.componentWillUnmount = function () { 7975 window.removeEventListener('resize', this.handleWindowResize); 7976 this.resizeRunner.clear(); 7977 for (var _i = 0, _a = this.calendarInteractions; _i < _a.length; _i++) { 7978 var interaction = _a[_i]; 7979 interaction.destroy(); 7980 } 7981 this.props.emitter.trigger('_unmount'); 7982 }; 7983 CalendarContent.prototype._handleNavLinkClick = function (ev, anchorEl) { 7984 var _a = this.props, dateEnv = _a.dateEnv, options = _a.options, calendarApi = _a.calendarApi; 7985 var navLinkOptions = anchorEl.getAttribute('data-navlink'); 7986 navLinkOptions = navLinkOptions ? JSON.parse(navLinkOptions) : {}; 7987 var dateMarker = dateEnv.createMarker(navLinkOptions.date); 7988 var viewType = navLinkOptions.type; 7989 var customAction = viewType === 'day' ? options.navLinkDayClick : 7990 viewType === 'week' ? options.navLinkWeekClick : null; 7991 if (typeof customAction === 'function') { 7992 customAction.call(calendarApi, dateEnv.toDate(dateMarker), ev); 7993 } 7994 else { 7995 if (typeof customAction === 'string') { 7996 viewType = customAction; 7997 } 7998 calendarApi.zoomTo(dateMarker, viewType); 7999 } 8000 }; 8001 CalendarContent.prototype.buildAppendContent = function () { 8002 var props = this.props; 8003 var children = props.pluginHooks.viewContainerAppends.map(function (buildAppendContent) { return buildAppendContent(props); }); 8004 return createElement.apply(void 0, __spreadArrays([Fragment, {}], children)); 8005 }; 8006 CalendarContent.prototype.renderView = function (props) { 8007 var pluginHooks = props.pluginHooks; 8008 var viewSpec = props.viewSpec; 8009 var viewProps = { 8010 dateProfile: props.dateProfile, 8011 businessHours: props.businessHours, 8012 eventStore: props.renderableEventStore, 8013 eventUiBases: props.eventUiBases, 8014 dateSelection: props.dateSelection, 8015 eventSelection: props.eventSelection, 8016 eventDrag: props.eventDrag, 8017 eventResize: props.eventResize, 8018 isHeightAuto: props.isHeightAuto, 8019 forPrint: props.forPrint 8020 }; 8021 var transformers = this.buildViewPropTransformers(pluginHooks.viewPropsTransformers); 8022 for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) { 8023 var transformer = transformers_1[_i]; 8024 __assign(viewProps, transformer.transform(viewProps, props)); 8025 } 8026 var ViewComponent = viewSpec.component; 8027 return (createElement(ViewComponent, __assign({}, viewProps))); 8028 }; 8029 return CalendarContent; 8030 }(PureComponent)); 8031 function buildToolbarProps(viewSpec, dateProfile, dateProfileGenerator, currentDate, now, title) { 8032 // don't force any date-profiles to valid date profiles (the `false`) so that we can tell if it's invalid 8033 var todayInfo = dateProfileGenerator.build(now, undefined, false); // TODO: need `undefined` or else INFINITE LOOP for some reason 8034 var prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate, false); 8035 var nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate, false); 8036 return { 8037 title: title, 8038 activeButton: viewSpec.type, 8039 isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now), 8040 isPrevEnabled: prevInfo.isValid, 8041 isNextEnabled: nextInfo.isValid 8042 }; 8043 } 8044 // Plugin 8045 // ----------------------------------------------------------------------------------------------------------------- 8046 function buildViewPropTransformers(theClasses) { 8047 return theClasses.map(function (theClass) { 8048 return new theClass(); 8049 }); 8050 } 8051 8052 var CalendarRoot = /** @class */ (function (_super) { 8053 __extends(CalendarRoot, _super); 8054 function CalendarRoot() { 8055 var _this = _super !== null && _super.apply(this, arguments) || this; 8056 _this.state = { 8057 forPrint: false 8058 }; 8059 _this.handleBeforePrint = function () { 8060 _this.setState({ forPrint: true }); 8061 }; 8062 _this.handleAfterPrint = function () { 8063 _this.setState({ forPrint: false }); 8064 }; 8065 return _this; 8066 } 8067 CalendarRoot.prototype.render = function () { 8068 var props = this.props; 8069 var options = props.options; 8070 var forPrint = this.state.forPrint; 8071 var isHeightAuto = forPrint || options.height === 'auto' || options.contentHeight === 'auto'; 8072 var height = (!isHeightAuto && options.height != null) ? options.height : ''; 8073 var classNames = [ 8074 'fc', 8075 forPrint ? 'fc-media-print' : 'fc-media-screen', 8076 'fc-direction-' + options.direction, 8077 props.theme.getClass('root') 8078 ]; 8079 if (!getCanVGrowWithinCell()) { 8080 classNames.push('fc-liquid-hack'); 8081 } 8082 return props.children(classNames, height, isHeightAuto, forPrint); 8083 }; 8084 CalendarRoot.prototype.componentDidMount = function () { 8085 var emitter = this.props.emitter; 8086 emitter.on('_beforeprint', this.handleBeforePrint); 8087 emitter.on('_afterprint', this.handleAfterPrint); 8088 }; 8089 CalendarRoot.prototype.componentWillUnmount = function () { 8090 var emitter = this.props.emitter; 8091 emitter.off('_beforeprint', this.handleBeforePrint); 8092 emitter.off('_afterprint', this.handleAfterPrint); 8093 }; 8094 return CalendarRoot; 8095 }(BaseComponent)); 8096 8097 // Computes a default column header formatting string if `colFormat` is not explicitly defined 8098 function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) { 8099 // if more than one week row, or if there are a lot of columns with not much space, 8100 // put just the day numbers will be in each cell 8101 if (!datesRepDistinctDays || dayCnt > 10) { 8102 return createFormatter({ weekday: 'short' }); // "Sat" 8103 } 8104 else if (dayCnt > 1) { 8105 return createFormatter({ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }); // "Sat 11/12" 8106 } 8107 else { 8108 return createFormatter({ weekday: 'long' }); // "Saturday" 8109 } 8110 } 8111 8112 var CLASS_NAME = 'fc-col-header-cell'; // do the cushion too? no 8113 var TableDateCell = /** @class */ (function (_super) { 8114 __extends(TableDateCell, _super); 8115 function TableDateCell() { 8116 return _super !== null && _super.apply(this, arguments) || this; 8117 } 8118 TableDateCell.prototype.render = function () { 8119 var _a = this.context, dateEnv = _a.dateEnv, options = _a.options, theme = _a.theme, viewApi = _a.viewApi; 8120 var props = this.props; 8121 var date = props.date, dateProfile = props.dateProfile;
8122 var dayMeta = getDateMeta(date, props.todayRange, null, dateProfile); 8123 var classNames = [CLASS_NAME].concat(getDayClassNames(dayMeta, theme)); 8124 var text = dateEnv.format(date, props.dayHeaderFormat); 8125 // if colCnt is 1, we are already in a day-view and don't need a navlink 8126 var navLinkAttrs = (options.navLinks && !dayMeta.isDisabled && props.colCnt > 1) 8127 ? { 'data-navlink': buildNavLinkData(date), tabIndex: 0 } 8128 : {}; 8129 var hookProps = __assign(__assign(__assign({ date: dateEnv.toDate(date), view: viewApi }, props.extraHookProps), { text: text }), dayMeta); 8130 return (createElement(RenderHook, { hookProps: hookProps, classNames: options.dayHeaderClassNames, content: options.dayHeaderContent, defaultContent: renderInner, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, function (rootElRef, customClassNames, innerElRef, innerContent) { return (createElement("th", __assign({ ref: rootElRef, className: classNames.concat(customClassNames).join(' '), "data-date": !dayMeta.isDisabled ? formatDayString(date) : undefined, colSpan: props.colSpan }, props.extraDataAttrs), 8131 createElement("div", { className: 'fc-scrollgrid-sync-inner' }, !dayMeta.isDisabled && 8132 createElement("a", __assign({ ref: innerElRef, className: [ 8133 'fc-col-header-cell-cushion', 8134 props.isSticky ? 'fc-sticky' : '' 8135 ].join(' ') }, navLinkAttrs), innerContent)))); })); 8136 }; 8137 return TableDateCell; 8138 }(BaseComponent)); 8139 var TableDowCell = /** @class */ (function (_super) { 8140 __extends(TableDowCell, _super); 8141 function TableDowCell() { 8142 return _super !== null && _super.apply(this, arguments) || this; 8143 } 8144 TableDowCell.prototype.render = function () { 8145 var props = this.props; 8146 var _a = this.context, dateEnv = _a.dateEnv, theme = _a.theme, viewApi = _a.viewApi, options = _a.options; 8147 var date = addDays(new Date(259200000), props.dow); // start with Sun, 04 Jan 1970 00:00:00 GMT 8148 var dateMeta = { 8149 dow: props.dow, 8150 isDisabled: false, 8151 isFuture: false, 8152 isPast: false, 8153 isToday: false, 8154 isOther: false 8155 }; 8156 var classNames = [CLASS_NAME].concat(getDayClassNames(dateMeta, theme), props.extraClassNames || []); 8157 var text = dateEnv.format(date, props.dayHeaderFormat); 8158 var hookProps = __assign(__assign(__assign(__assign({ // TODO: make this public? 8159 date: date }, dateMeta), { view: viewApi }), props.extraHookProps), { text: text }); 8160 return (createElement(RenderHook, { hookProps: hookProps, classNames: options.dayHeaderClassNames, content: options.dayHeaderContent, defaultContent: renderInner, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, function (rootElRef, customClassNames, innerElRef, innerContent) { return (createElement("th", __assign({ ref: rootElRef, className: classNames.concat(customClassNames).join(' '), colSpan: props.colSpan }, props.extraDataAttrs), 8161 createElement("div", { className: 'fc-scrollgrid-sync-inner' }, 8162 createElement("a", { className: [ 8163 'fc-col-header-cell-cushion', 8164 props.isSticky ? 'fc-sticky' : '' 8165 ].join(' '), ref: innerElRef }, innerContent)))); })); 8166 }; 8167 return TableDowCell; 8168 }(BaseComponent)); 8169 function renderInner(hookProps) { 8170 return hookProps.text; 8171 } 8172 8173 var NowTimer = /** @class */ (function (_super) { 8174 __extends(NowTimer, _super); 8175 function NowTimer(props, context) { 8176 var _this = _super.call(this, props, context) || this; 8177 _this.initialNowDate = getNow(context.options.now, context.dateEnv); 8178 _this.initialNowQueriedMs = new Date().valueOf(); 8179 _this.state = _this.computeTiming().currentState; 8180 return _this; 8181 } 8182 NowTimer.prototype.render = function () { 8183 var _a = this, props = _a.props, state = _a.state; 8184 return props.children(state.nowDate, state.todayRange); 8185 }; 8186 NowTimer.prototype.componentDidMount = function () { 8187 this.setTimeout(); 8188 }; 8189 NowTimer.prototype.componentDidUpdate = function (prevProps) { 8190 if (prevProps.unit !== this.props.unit) { 8191 this.clearTimeout(); 8192 this.setTimeout(); 8193 } 8194 }; 8195 NowTimer.prototype.componentWillUnmount = function () { 8196 this.clearTimeout(); 8197 }; 8198 NowTimer.prototype.computeTiming = function () { 8199 var _a = this, props = _a.props, context = _a.context; 8200 var unroundedNow = addMs(this.initialNowDate, new Date().valueOf() - this.initialNowQueriedMs); 8201 var currentUnitStart = context.dateEnv.startOf(unroundedNow, props.unit); 8202 var nextUnitStart = context.dateEnv.add(currentUnitStart, createDuration(1, props.unit)); 8203 var waitMs = nextUnitStart.valueOf() - unroundedNow.valueOf(); 8204 return { 8205 currentState: { nowDate: currentUnitStart, todayRange: buildDayRange(currentUnitStart) }, 8206 nextState: { nowDate: nextUnitStart, todayRange: buildDayRange(nextUnitStart) }, 8207 waitMs: waitMs 8208 }; 8209 }; 8210 NowTimer.prototype.setTimeout = function () { 8211 var _this = this; 8212 var _a = this.computeTiming(), nextState = _a.nextState, waitMs = _a.waitMs; 8213 this.timeoutId = setTimeout(function () { 8214 _this.setState(nextState, function () { 8215 _this.setTimeout(); 8216 }); 8217 }, waitMs); 8218 }; 8219 NowTimer.prototype.clearTimeout = function () { 8220 if (this.timeoutId) { 8221 clearTimeout(this.timeoutId); 8222 } 8223 }; 8224 NowTimer.contextType = ViewContextType; 8225 return NowTimer; 8226 }(Component)); 8227 function buildDayRange(date) { 8228 var start = startOfDay(date); 8229 var end = addDays(start, 1); 8230 return { start: start, end: end }; 8231 } 8232 8233 var DayHeader = /** @class */ (function (_super) { 8234 __extends(DayHeader, _super); 8235 function DayHeader() { 8236 var _this = _super !== null && _super.apply(this, arguments) || this; 8237 _this.createDayHeaderFormatter = memoize(createDayHeaderFormatter); 8238 return _this; 8239 } 8240 DayHeader.prototype.render = function () { 8241 var context = this.context; 8242 var _a = this.props, dates = _a.dates, dateProfile = _a.dateProfile, datesRepDistinctDays = _a.datesRepDistinctDays, renderIntro = _a.renderIntro; 8243 var dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dates.length); 8244 return (createElement(NowTimer, { unit: 'day' }, function (nowDate, todayRange) { return (createElement("tr", null, 8245 renderIntro && renderIntro(), 8246 dates.map(function (date) { return (datesRepDistinctDays ? 8247 createElement(TableDateCell, { key: date.toISOString(), date: date, dateProfile: dateProfile, todayRange: todayRange, colCnt: dates.length, dayHeaderFormat: dayHeaderFormat }) : 8248 createElement(TableDowCell, { key: date.getUTCDay(), dow: date.getUTCDay(), dayHeaderFormat: dayHeaderFormat })); }))); })); 8249 }; 8250 return DayHeader; 8251 }(BaseComponent)); 8252 function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) { 8253 return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt); 8254 } 8255
8256 var DaySeriesModel = /** @class */ (function () { 8257 function DaySeriesModel(range, dateProfileGenerator) { 8258 var date = range.start; 8259 var end = range.end; 8260 var indices = []; 8261 var dates = []; 8262 var dayIndex = -1; 8263 while (date < end) { // loop each day from start to end 8264 if (dateProfileGenerator.isHiddenDay(date)) { 8265 indices.push(dayIndex + 0.5); // mark that it's between indices 8266 } 8267 else { 8268 dayIndex++; 8269 indices.push(dayIndex); 8270 dates.push(date); 8271 } 8272 date = addDays(date, 1); 8273 } 8274 this.dates = dates; 8275 this.indices = indices; 8276 this.cnt = dates.length; 8277 } 8278 DaySeriesModel.prototype.sliceRange = function (range) { 8279 var firstIndex = this.getDateDayIndex(range.start); // inclusive first index 8280 var lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index 8281 var clippedFirstIndex = Math.max(0, firstIndex); 8282 var clippedLastIndex = Math.min(this.cnt - 1, lastIndex); 8283 // deal with in-between indices 8284 clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell 8285 clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell 8286 if (clippedFirstIndex <= clippedLastIndex) { 8287 return { 8288 firstIndex: clippedFirstIndex, 8289 lastIndex: clippedLastIndex, 8290 isStart: firstIndex === clippedFirstIndex, 8291 isEnd: lastIndex === clippedLastIndex 8292 }; 8293 } 8294 else { 8295 return null; 8296 } 8297 }; 8298 // Given a date, returns its chronolocial cell-index from the first cell of the grid. 8299 // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets. 8300 // If before the first offset, returns a negative number. 8301 // If after the last offset, returns an offset past the last cell offset. 8302 // Only works for *start* dates of cells. Will not work for exclusive end dates for cells. 8303 DaySeriesModel.prototype.getDateDayIndex = function (date) { 8304 var indices = this.indices; 8305 var dayOffset = Math.floor(diffDays(this.dates[0], date)); 8306 if (dayOffset < 0) { 8307 return indices[0] - 1; 8308 } 8309 else if (dayOffset >= indices.length) { 8310 return indices[indices.length - 1] + 1; 8311 } 8312 else { 8313 return indices[dayOffset]; 8314 } 8315 };
8316 return DaySeriesModel; 8317 }()); 8318 8319 var DayTableModel = /** @class */ (function () { 8320 function DayTableModel(daySeries, breakOnWeeks) { 8321 var dates = daySeries.dates; 8322 var daysPerRow; 8323 var firstDay; 8324 var rowCnt; 8325 if (breakOnWeeks) { 8326 // count columns until the day-of-week repeats 8327 firstDay = dates[0].getUTCDay(); 8328 for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow++) { 8329 if (dates[daysPerRow].getUTCDay() === firstDay) { 8330 break; 8331 } 8332 } 8333 rowCnt = Math.ceil(dates.length / daysPerRow); 8334 } 8335 else { 8336 rowCnt = 1; 8337 daysPerRow = dates.length; 8338 } 8339 this.rowCnt = rowCnt; 8340 this.colCnt = daysPerRow; 8341 this.daySeries = daySeries; 8342 this.cells = this.buildCells(); 8343 this.headerDates = this.buildHeaderDates(); 8344 } 8345 DayTableModel.prototype.buildCells = function () { 8346 var rows = []; 8347 for (var row = 0; row < this.rowCnt; row++) { 8348 var cells = []; 8349 for (var col = 0; col < this.colCnt; col++) { 8350 cells.push(this.buildCell(row, col)); 8351 } 8352 rows.push(cells); 8353 } 8354 return rows; 8355 }; 8356 DayTableModel.prototype.buildCell = function (row, col) { 8357 var date = this.daySeries.dates[row * this.colCnt + col]; 8358 return { 8359 key: date.toISOString(), 8360 date: date 8361 }; 8362 }; 8363 DayTableModel.prototype.buildHeaderDates = function () { 8364 var dates = []; 8365 for (var col = 0; col < this.colCnt; col++) { 8366 dates.push(this.cells[0][col].date); 8367 } 8368 return dates; 8369 }; 8370 DayTableModel.prototype.sliceRange = function (range) { 8371 var colCnt = this.colCnt; 8372 var seriesSeg = this.daySeries.sliceRange(range); 8373 var segs = []; 8374 if (seriesSeg) { 8375 var firstIndex = seriesSeg.firstIndex, lastIndex = seriesSeg.lastIndex; 8376 var index = firstIndex; 8377 while (index <= lastIndex) { 8378 var row = Math.floor(index / colCnt); 8379 var nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1); 8380 segs.push({ 8381 row: row, 8382 firstCol: index % colCnt, 8383 lastCol: (nextIndex - 1) % colCnt, 8384 isStart: seriesSeg.isStart && index === firstIndex, 8385 isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex 8386 }); 8387 index = nextIndex; 8388 } 8389 } 8390 return segs; 8391 }; 8392 return DayTableModel; 8393 }()); 8394 8395 var Slicer = /** @class */ (function () { 8396 function Slicer() { 8397 this.sliceBusinessHours = memoize(this._sliceBusinessHours); 8398 this.sliceDateSelection = memoize(this._sliceDateSpan); 8399 this.sliceEventStore = memoize(this._sliceEventStore); 8400 this.sliceEventDrag = memoize(this._sliceInteraction); 8401 this.sliceEventResize = memoize(this._sliceInteraction); 8402 this.forceDayIfListItem = false; // hack 8403 } 8404 Slicer.prototype.sliceProps = function (props, dateProfile, nextDayThreshold, context) { 8405 var extraArgs = []; 8406 for (var _i = 4; _i < arguments.length; _i++) { 8407 extraArgs[_i - 4] = arguments[_i]; 8408 } 8409 var eventUiBases = props.eventUiBases; 8410 var eventSegs = this.sliceEventStore.apply(this, __spreadArrays([props.eventStore, eventUiBases, dateProfile, nextDayThreshold], extraArgs)); 8411 return { 8412 dateSelectionSegs: this.sliceDateSelection.apply(this, __spreadArrays([props.dateSelection, eventUiBases, context], extraArgs)), 8413 businessHourSegs: this.sliceBusinessHours.apply(this, __spreadArrays([props.businessHours, dateProfile, nextDayThreshold, context], extraArgs)), 8414 fgEventSegs: eventSegs.fg, 8415 bgEventSegs: eventSegs.bg, 8416 eventDrag: this.sliceEventDrag.apply(this, __spreadArrays([props.eventDrag, eventUiBases, dateProfile, nextDayThreshold], extraArgs)), 8417 eventResize: this.sliceEventResize.apply(this, __spreadArrays([props.eventResize, eventUiBases, dateProfile, nextDayThreshold], extraArgs)), 8418 eventSelection: props.eventSelection 8419 }; // TODO: give interactionSegs? 8420 }; 8421 Slicer.prototype.sliceNowDate = function (// does not memoize 8422 date, context) { 8423 var extraArgs = []; 8424 for (var _i = 2; _i < arguments.length; _i++) { 8425 extraArgs[_i - 2] = arguments[_i]; 8426 } 8427 return this._sliceDateSpan.apply(this, __spreadArrays([{ range: { start: date, end: addMs(date, 1) }, allDay: false }, 8428 {}, 8429 context], extraArgs)); 8430 }; 8431 Slicer.prototype._sliceBusinessHours = function (businessHours, dateProfile, nextDayThreshold, context) { 8432 var extraArgs = []; 8433 for (var _i = 4; _i < arguments.length; _i++) { 8434 extraArgs[_i - 4] = arguments[_i]; 8435 } 8436 if (!businessHours) { 8437 return []; 8438 } 8439 return this._sliceEventStore.apply(this, __spreadArrays([expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), context), 8440 {}, 8441 dateProfile, 8442 nextDayThreshold], extraArgs)).bg; 8443 }; 8444 Slicer.prototype._sliceEventStore = function (eventStore, eventUiBases, dateProfile, nextDayThreshold) { 8445 var extraArgs = []; 8446 for (var _i = 4; _i < arguments.length; _i++) { 8447 extraArgs[_i - 4] = arguments[_i]; 8448 } 8449 if (eventStore) { 8450 var rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold); 8451 return { 8452 bg: this.sliceEventRanges(rangeRes.bg, extraArgs), 8453 fg: this.sliceEventRanges(rangeRes.fg, extraArgs) 8454 }; 8455 } 8456 else { 8457 return { bg: [], fg: [] }; 8458 } 8459 }; 8460 Slicer.prototype._sliceInteraction = function (interaction, eventUiBases, dateProfile, nextDayThreshold) { 8461 var extraArgs = []; 8462 for (var _i = 4; _i < arguments.length; _i++) { 8463 extraArgs[_i - 4] = arguments[_i]; 8464 } 8465 if (!interaction) { 8466 return null; 8467 } 8468 var rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold); 8469 return { 8470 segs: this.sliceEventRanges(rangeRes.fg, extraArgs), 8471 affectedInstances: interaction.affectedEvents.instances, 8472 isEvent: interaction.isEvent 8473 }; 8474 }; 8475 Slicer.prototype._sliceDateSpan = function (dateSpan, eventUiBases, context) { 8476 var extraArgs = []; 8477 for (var _i = 3; _i < arguments.length; _i++) { 8478 extraArgs[_i - 3] = arguments[_i]; 8479 } 8480 if (!dateSpan) { 8481 return []; 8482 } 8483 var eventRange = fabricateEventRange(dateSpan, eventUiBases, context); 8484 var segs = this.sliceRange.apply(this, __spreadArrays([dateSpan.range], extraArgs)); 8485 for (var _a = 0, segs_1 = segs; _a < segs_1.length; _a++) { 8486 var seg = segs_1[_a]; 8487 seg.eventRange = eventRange; 8488 } 8489 return segs; 8490 }; 8491 /* 8492 "complete" seg means it has component and eventRange 8493 */ 8494 Slicer.prototype.sliceEventRanges = function (eventRanges, extraArgs) { 8495 var segs = []; 8496 for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) { 8497 var eventRange = eventRanges_1[_i]; 8498 segs.push.apply(segs, this.sliceEventRange(eventRange, extraArgs)); 8499 } 8500 return segs; 8501 }; 8502 /* 8503 "complete" seg means it has component and eventRange 8504 */ 8505 Slicer.prototype.sliceEventRange = function (eventRange, extraArgs) { 8506 var dateRange = eventRange.range; 8507 // hack to make multi-day events that are being force-displayed as list-items to take up only one day 8508 if (this.forceDayIfListItem && eventRange.ui.display === 'list-item') { 8509 dateRange = { 8510 start: dateRange.start, 8511 end: addDays(dateRange.start, 1) 8512 }; 8513 } 8514 var segs = this.sliceRange.apply(this, __spreadArrays([dateRange], extraArgs)); 8515 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 8516 var seg = segs_2[_i]; 8517 seg.eventRange = eventRange; 8518 seg.isStart = eventRange.isStart && seg.isStart; 8519 seg.isEnd = eventRange.isEnd && seg.isEnd; 8520 } 8521 return segs; 8522 }; 8523 return Slicer; 8524 }()); 8525 /* 8526 for incorporating slotMinTime/slotMaxTime if appropriate 8527 TODO: should be part of DateProfile! 8528 TimelineDateProfile already does this btw 8529 */ 8530 function computeActiveRange(dateProfile, isComponentAllDay) { 8531 var range = dateProfile.activeRange; 8532 if (isComponentAllDay) { 8533 return range; 8534 } 8535 return { 8536 start: addMs(range.start, dateProfile.slotMinTime.milliseconds), 8537 end: addMs(range.end, dateProfile.slotMaxTime.milliseconds - 864e5) // 864e5 = ms in a day 8538 }; 8539 } 8540 8541 var VISIBLE_HIDDEN_RE = /^(visible|hidden)$/; 8542 var Scroller = /** @class */ (function (_super) { 8543 __extends(Scroller, _super); 8544 function Scroller() { 8545 var _this = _super !== null && _super.apply(this, arguments) || this; 8546 _this.handleEl = function (el) { 8547 _this.el = el; 8548 setRef(_this.props.elRef, el); 8549 }; 8550 return _this; 8551 } 8552 Scroller.prototype.render = function () { 8553 var props = this.props; 8554 var liquid = props.liquid, liquidIsAbsolute = props.liquidIsAbsolute; 8555 var isAbsolute = liquid && liquidIsAbsolute; 8556 var className = ['fc-scroller']; 8557 if (liquid) { 8558 if (liquidIsAbsolute) { 8559 className.push('fc-scroller-liquid-absolute'); 8560 } 8561 else { 8562 className.push('fc-scroller-liquid'); 8563 } 8564 } 8565 return (createElement("div", { ref: this.handleEl, className: className.join(' '), style: { 8566 overflowX: props.overflowX, 8567 overflowY: props.overflowY, 8568 left: (isAbsolute && -(props.overcomeLeft || 0)) || '', 8569 right: (isAbsolute && -(props.overcomeRight || 0
8569)) || '', 8570 bottom: (isAbsolute && -(props.overcomeBottom || 0)) || '', 8571 marginLeft: (!isAbsolute && -(props.overcomeLeft || 0)) || '', 8572 marginRight: (!isAbsolute && -(props.overcomeRight || 0)) || '', 8573 marginBottom: (!isAbsolute && -(props.overcomeBottom || 0)) || '', 8574 maxHeight: props.maxHeight || '' 8575 } }, props.children)); 8576 }; 8577 Scroller.prototype.needsXScrolling = function () { 8578 if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) { 8579 return false; 8580 } 8581 // testing scrollWidth>clientWidth is unreliable cross-browser when pixel heights aren't integers. 8582 // much more reliable to see if children are taller than the scroller, even tho doesn't account for 8583 // inner-child margins and absolute positioning 8584 var el = this.el; 8585 var realClientWidth = this.el.getBoundingClientRect().width - this.getYScrollbarWidth(); 8586 var children = el.children; 8587 for (var i = 0; i < children.length; i++) { 8588 var childEl = children[i]; 8589 if (childEl.getBoundingClientRect().width > realClientWidth) { 8590 return true; 8591 } 8592 } 8593 return false; 8594 }; 8595 Scroller.prototype.needsYScrolling = function () { 8596 if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) { 8597 return false; 8598 } 8599 // testing scrollHeight>clientHeight is unreliable cross-browser when pixel heights aren't integers. 8600 // much more reliable to see if children are taller than the scroller, even tho doesn't account for 8601 // inner-child margins and absolute positioning 8602 var el = this.el; 8603 var realClientHeight = this.el.getBoundingClientRect().height - this.getXScrollbarWidth(); 8604 var children = el.children; 8605 for (var i = 0; i < children.length; i++) { 8606 var childEl = children[i]; 8607 if (childEl.getBoundingClientRect().height > realClientHeight) { 8608 return true; 8609 } 8610 } 8611 return false; 8612 }; 8613 Scroller.prototype.getXScrollbarWidth = function () { 8614 if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) { 8615 return 0; 8616 } 8617 else { 8618 return this.el.offsetHeight - this.el.clientHeight; // only works because we guarantee no borders. TODO: add to CSS with important? 8619 } 8620 }; 8621 Scroller.prototype.getYScrollbarWidth = function () { 8622 if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) { 8623 return 0; 8624 } 8625 else { 8626 return this.el.offsetWidth - this.el.clientWidth; // only works because we guarantee no borders. TODO: add to CSS with important? 8627 } 8628 }; 8629 return Scroller; 8630 }(BaseComponent)); 8631 8632 /* 8633 TODO: somehow infer OtherArgs from masterCallback? 8634 TODO: infer RefType from masterCallback if provided 8635 */ 8636 var RefMap = /** @class */ (function () { 8637 function RefMap(masterCallback) { 8638 var _this = this; 8639 this.masterCallback = masterCallback; 8640 this.currentMap = {}; 8641 this.depths = {}; 8642 this.callbackMap = {}; 8643 this.handleValue = function (val, key) { 8644 var _a = _this, depths = _a.depths, currentMap = _a.currentMap; 8645 var removed = false; 8646 var added = false; 8647 if (val !== null) { 8648 removed = (key in currentMap); // for bug... ACTUALLY: can probably do away with this now that callers don't share numeric indices anymore 8649 currentMap[key] = val; 8650 depths[key] = (depths[key] || 0) + 1; 8651 added = true; 8652 } 8653 else if (--depths[key] === 0) { 8654 delete currentMap[key]; 8655 delete _this.callbackMap[key]; 8656 removed = true; 8657 } 8658 if (_this.masterCallback) { 8659 if (removed) { 8660 _this.masterCallback(null, String(key)); 8661 } 8662 if (added) { 8663 _this.masterCallback(val, String(key)); 8664 } 8665 } 8666 }; 8667 } 8668 RefMap.prototype.createRef = function (key) { 8669 var _this = this; 8670 var refCallback = this.callbackMap[key]; 8671 if (!refCallback) { 8672 refCallback = this.callbackMap[key] = function (val) { 8673 _this.handleValue(val, String(key)); 8674 }; 8675 } 8676 return refCallback; 8677 }; 8678 // TODO: check callers that don't care about order. should use getAll instead 8679 // NOTE: this method has become less valuable now that we are encouraged to map order by some other index 8680 // TODO: provide ONE array-export function, buildArray, which fails on non-numeric indexes. caller can manipulate and "collect" 8681 RefMap.prototype.collect = function (startIndex, endIndex, step) { 8682 return collectFromHash(this.currentMap, startIndex, endIndex, step); 8683 }; 8684 RefMap.prototype.getAll = function () { 8685 return hashValuesToArray(this.currentMap); 8686 }; 8687 return RefMap; 8688 }()); 8689 8690 function computeShrinkWidth(chunkEls) { 8691 var shrinkCells = findElements(chunkEls, '.fc-scrollgrid-shrink'); 8692 var largestWidth = 0; 8693 for (var _i = 0, shrinkCells_1 = shrinkCells; _i < shrinkCells_1.length; _i++) { 8694 var shrinkCell = shrinkCells_1[_i]; 8695 largestWidth = Math.max(largestWidth, computeSmallestCellWidth(shrinkCell)); 8696 } 8697 return Math.ceil(largestWidth); // <table> elements work best with integers. round up to ensure contents fits 8698 } 8699 function getSectionHasLiquidHeight(props, sectionConfig) { 8700 return props.liquid && sectionConfig.liquid; // does the section do liquid-height? (need to have whole scrollgrid liquid-height as well) 8701 } 8702 function getAllowYScrolling(props, sectionConfig) { 8703 return sectionConfig.maxHeight != null || // if its possible for the height to max out, we might need scrollbars 8704 getSectionHasLiquidHeight(props, sectionConfig); // if the section is liquid height, it might condense enough to require scrollbars 8705 } 8706 // TODO: ONLY use `arg`. force out internal function to use same API 8707 function renderChunkContent(sectionConfig, chunkConfig, arg) { 8708 var expandRows = arg.expandRows; 8709 var content = typeof chunkConfig.content === 'function' ? 8710 chunkConfig.content(arg) : 8711 createElement('table', { 8712 className: [ 8713 chunkConfig.tableClassName, 8714 sectionConfig.syncRowHeights ? 'fc-scrollgrid-sync-table' : '' 8715 ].join(' '), 8716 style: { 8717 minWidth: arg.tableMinWidth, 8718 width: arg.clientWidth, 8719 height: expandRows ? arg.clientHeight : '' // css `height` on a <table> serves as a min-height 8720 } 8721 }, arg.tableColGroupNode, createElement('tbody', {}, typeof chunkConfig.rowContent === 'function' ? chunkConfig.rowContent(arg) : chunkConfig.rowContent)); 8722 return content; 8723 } 8724 function isColPropsEqual(cols0, cols1) { 8725 return isArraysEqual(cols0, cols1, isPropsEqual); 8726 } 8727 function renderMicroColGroup(cols, shrinkWidth) { 8728 var colNodes = []; 8729 /* 8730 for ColProps with spans, it would have been great to make a single <col span=""> 8731 HOWEVER, Chrome was getting messing up distributing the width to <td>/<th> elements with colspans. 8732 SOLUTION: making individual <col> elements makes Chrome behave. 8733 */ 8734 for (var _i = 0, cols_1 = cols; _i < cols_1.length; _i++) { 8735 var colProps = cols_1[_i]; 8736 var span = colProps.span || 1; 8737 for (var i = 0; i < span; i++) {
8738 colNodes.push(createElement("col", { style: { 8739 width: colProps.width === 'shrink' ? sanitizeShrinkWidth(shrinkWidth) : (colProps.width || ''), 8740 minWidth: colProps.minWidth || '' 8741 } })); 8742 } 8743 } 8744 return createElement.apply(void 0, __spreadArrays(['colgroup', {}], colNodes)); 8745 } 8746 function sanitizeShrinkWidth(shrinkWidth) { 8747 /* why 4? if we do 0, it will kill any border, which are needed for computeSmallestCellWidth 8748 4 accounts for 2 2-pixel borders. TODO: better solution? */ 8749 return shrinkWidth == null ? 4 : shrinkWidth; 8750 } 8751 function hasShrinkWidth(cols) { 8752 for (var _i = 0, cols_2 = cols; _i < cols_2.length; _i++) { 8753 var col = cols_2[_i]; 8754 if (col.width === 'shrink') { 8755 return true; 8756 } 8757 } 8758 return false; 8759 } 8760 function getScrollGridClassNames(liquid, context) { 8761 var classNames = [ 8762 'fc-scrollgrid', 8763 context.theme.getClass('table') 8764 ]; 8765 if (liquid) { 8766 classNames.push('fc-scrollgrid-liquid'); 8767 } 8768 return classNames; 8769 } 8770 function getSectionClassNames(sectionConfig, wholeTableVGrow) { 8771 var classNames = [ 8772 'fc-scrollgrid-section', 8773 'fc-scrollgrid-section-' + sectionConfig.type, 8774 sectionConfig.className // used? 8775 ]; 8776 if (wholeTableVGrow && sectionConfig.liquid && sectionConfig.maxHeight == null) { 8777 classNames.push('fc-scrollgrid-section-liquid'); 8778 } 8779 if (sectionConfig.isSticky) { 8780 classNames.push('fc-scrollgrid-section-sticky'); 8781 } 8782 return classNames; 8783 }
8784 function renderScrollShim(arg) { 8785 return (createElement("div", { className: 'fc-scrollgrid-sticky-shim', style: { 8786 width: arg.clientWidth, 8787 minWidth: arg.tableMinWidth 8788 } })); 8789 } 8790 function getStickyHeaderDates(options) { 8791 var stickyHeaderDates = options.stickyHeaderDates; 8792 if (stickyHeaderDates == null || stickyHeaderDates === 'auto') { 8793 stickyHeaderDates = options.height === 'auto' || options.viewHeight === 'auto'; 8794 } 8795 return stickyHeaderDates; 8796 } 8797 function getStickyFooterScrollbar(options) { 8798 var stickyFooterScrollbar = options.stickyFooterScrollbar; 8799 if (stickyFooterScrollbar == null || stickyFooterScrollbar === 'auto') { 8800 stickyFooterScrollbar = options.height === 'auto' || options.viewHeight === 'auto'; 8801 } 8802 return stickyFooterScrollbar; 8803 } 8804 8805 var SimpleScrollGrid = /** @class */ (function (_super) { 8806 __extends(SimpleScrollGrid, _super); 8807 function SimpleScrollGrid() { 8808 var _this = _super !== null && _super.apply(this, arguments) || this; 8809 _this.processCols = memoize(function (a) { return a; }, isColPropsEqual); // so we get same `cols` props every time 8810 _this.renderMicroColGroup = memoize(renderMicroColGroup); // yucky to memoize VNodes, but much more efficient for consumers 8811 _this.scrollerRefs = new RefMap(); 8812 _this.scrollerElRefs = new RefMap(_this._handleScrollerEl.bind(_this)); 8813 _this.state = { 8814 shrinkWidth: null, 8815 forceYScrollbars: false, 8816 scrollerClientWidths: {}, 8817 scrollerClientHeights: {} 8818 }; 8819 // TODO: can do a really simple print-view. dont need to join rows 8820 _this.handleSizing = function () { 8821 _this.setState(__assign({ shrinkWidth: _this.computeShrinkWidth() }, _this.computeScrollerDims())); 8822 }; 8823 return _this; 8824 } 8825 SimpleScrollGrid.prototype.render = function () { 8826 var _a = this, props = _a.props, state = _a.state, context = _a.context; 8827 var sectionConfigs = props.sections || []; 8828 var cols = this.processCols(props.cols); 8829 var microColGroupNode = this.renderMicroColGroup(cols, state.shrinkWidth); 8830 var classNames = getScrollGridClassNames(props.liquid, context); 8831 // TODO: make DRY 8832 var configCnt = sectionConfigs.length; 8833 var configI = 0; 8834 var currentConfig; 8835 var headSectionNodes = []; 8836 var bodySectionNodes = []; 8837 var footSectionNodes = []; 8838 while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'header') { 8839 headSectionNodes.push(this.renderSection(currentConfig, configI, microColGroupNode)); 8840 configI++; 8841 } 8842 while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'body') { 8843 bodySectionNodes.push(this.renderSection(currentConfig, configI, microColGroupNode)); 8844 configI++; 8845 } 8846 while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'footer') { 8847 footSectionNodes.push(this.renderSection(currentConfig, configI, microColGroupNode)); 8848 configI++; 8849 } 8850 // firefox bug: when setting height on table and there is a thead or tfoot, 8851 // the necessary height:100% on the liquid-height body section forces the *whole* table to be taller. (bug #5524) 8852 // use getCanVGrowWithinCell as a way to detect table-stupid firefox. 8853 // if so, use a simpler dom structure, jam everything into a lone tbody. 8854 var isBuggy = !getCanVGrowWithinCell(); 8855 return createElement('table', { 8856 className: classNames.join(' '), 8857 style: { height: props.height } 8858 }, Boolean(!isBuggy && headSectionNodes.length) && createElement.apply(void 0, __spreadArrays(['thead', {}
8858], headSectionNodes)), Boolean(!isBuggy && bodySectionNodes.length) && createElement.apply(void 0, __spreadArrays(['tbody', {}], bodySectionNodes)), Boolean(!isBuggy && footSectionNodes.length) && createElement.apply(void 0, __spreadArrays(['tfoot', {}], footSectionNodes)), isBuggy && createElement.apply(void 0, __spreadArrays(['tbody', {}], headSectionNodes, bodySectionNodes, footSectionNodes))); 8859 }; 8860 SimpleScrollGrid.prototype.renderSection = function (sectionConfig, sectionI, microColGroupNode) { 8861 if ('outerContent' in sectionConfig) { 8862 return (createElement(Fragment, { key: sectionConfig.key }, sectionConfig.outerContent)); 8863 } 8864 return (createElement("tr", { key: sectionConfig.key, className: getSectionClassNames(sectionConfig, this.props.liquid).join(' ') }, this.renderChunkTd(sectionConfig, sectionI, microColGroupNode, sectionConfig.chunk))); 8865 }; 8866 SimpleScrollGrid.prototype.renderChunkTd = function (sectionConfig, sectionI, microColGroupNode, chunkConfig) { 8867 if ('outerContent' in chunkConfig) { 8868 return chunkConfig.outerContent; 8869 } 8870 var props = this.props; 8871 var _a = this.state, forceYScrollbars = _a.forceYScrollbars, scrollerClientWidths = _a.scrollerClientWidths, scrollerClientHeights = _a.scrollerClientHeights; 8872 var needsYScrolling = getAllowYScrolling(props, sectionConfig); // TODO: do lazily. do in section config? 8873 var isLiquid = getSectionHasLiquidHeight(props, sectionConfig); 8874 // for `!props.liquid` - is WHOLE scrollgrid natural height? 8875 // TODO: do same thing in advanced scrollgrid? prolly not b/c always has horizontal scrollbars 8876 var overflowY = !props.liquid ? 'visible' : 8877 forceYScrollbars ? 'scroll' : 8878 !needsYScrolling ? 'hidden' : 8879 'auto'; 8880 var content = renderChunkContent(sectionConfig, chunkConfig, { 8881 tableColGroupNode: microColGroupNode, 8882 tableMinWidth: '', 8883 clientWidth: scrollerClientWidths[sectionI] !== undefined ? scrollerClientWidths[sectionI] : null, 8884 clientHeight: scrollerClientHeights[sectionI] !== undefined ? scrollerClientHeights[sectionI] : null, 8885 expandRows: sectionConfig.expandRows, 8886 syncRowHeights: false, 8887 rowSyncHeights: [], 8888 reportRowHeightChange: function () { } 8889 }); 8890 return (createElement("td", { ref: chunkConfig.elRef }, 8891 createElement("div", { className: 'fc-scroller-harness' + (isLiquid ? ' fc-scroller-harness-liquid' : '') }, 8892 createElement(Scroller, { ref: this.scrollerRefs.createRef(sectionI), elRef: this.scrollerElRefs.createRef(sectionI), overflowY: overflowY, overflowX: !props.liquid ? 'visible' : 'hidden' /* natural height? */, maxHeight: sectionConfig.maxHeight, liquid: isLiquid, liquidIsAbsolute: true /* because its within a harness */ }, content)))); 8893 }; 8894 SimpleScrollGrid.prototype._handleScrollerEl = function (scrollerEl, key) { 8895 var sectionI = parseInt(key, 10); 8896 var chunkConfig = this.props.sections[sectionI].chunk; 8897 setRef(chunkConfig.scrollerElRef, scrollerEl); 8898 }; 8899 SimpleScrollGrid.prototype.componentDidMount = function () { 8900 this.handleSizing(); 8901 this.context.addResizeHandler(this.handleSizing); 8902 }; 8903 SimpleScrollGrid.prototype.componentDidUpdate = function () { 8904 // TODO: need better solution when state contains non-sizing things 8905 this.handleSizing(); 8906 }; 8907 SimpleScrollGrid.prototype.componentWillUnmount = function () { 8908 this.context.removeResizeHandler(this.handleSizing); 8909 }; 8910 SimpleScrollGrid.prototype.computeShrinkWidth = function () { 8911 return hasShrinkWidth(this.props.cols) 8912 ? computeShrinkWidth(this.scrollerElRefs.getAll()) 8913 : 0; 8914 }; 8915 SimpleScrollGrid.prototype.computeScrollerDims = function () { 8916 var scrollbarWidth = getScrollbarWidths(); 8917 var sectionCnt = this.props.sections.length; 8918 var _a = this, scrollerRefs = _a.scrollerRefs, scrollerElRefs = _a.scrollerElRefs; 8919 var forceYScrollbars = false;
8920 var scrollerClientWidths = {}; 8921 var scrollerClientHeights = {}; 8922 for (var sectionI = 0; sectionI < sectionCnt; sectionI++) { // along edge 8923 var scroller = scrollerRefs.currentMap[sectionI]; 8924 if (scroller && scroller.needsYScrolling()) { 8925 forceYScrollbars = true; 8926 break; 8927 } 8928 } 8929 for (var sectionI = 0; sectionI < sectionCnt; sectionI++) { // along edge 8930 var scrollerEl = scrollerElRefs.currentMap[sectionI]; 8931 if (scrollerEl) { 8932 var harnessEl = scrollerEl.parentNode; // TODO: weird way to get this. need harness b/c doesn't include table borders 8933 scrollerClientWidths[sectionI] = Math.floor(harnessEl.getBoundingClientRect().width - (forceYScrollbars 8934 ? scrollbarWidth.y // use global because scroller might not have scrollbars yet but will need them in future 8935 : 0)); 8936 scrollerClientHeights[sectionI] = Math.floor(harnessEl.getBoundingClientRect().height // never has horizontal scrollbars 8937 ); 8938 } 8939 } 8940 return { forceYScrollbars: forceYScrollbars, scrollerClientWidths: scrollerClientWidths, scrollerClientHeights: scrollerClientHeights }; 8941 }; 8942 return SimpleScrollGrid; 8943 }(BaseComponent)); 8944 SimpleScrollGrid.addStateEquality({ 8945 scrollerClientWidths: isPropsEqual, 8946 scrollerClientHeights: isPropsEqual 8947 }); 8948 8949 var EventRoot = /** @class */ (function (_super) { 8950 __extends(EventRoot, _super); 8951 function EventRoot() { 8952 var _this = _super !== null && _super.apply(this, arguments) || this; 8953 _this.elRef = createRef(); 8954 return _this; 8955 } 8956 EventRoot.prototype.render = function () { 8957 var _a = this, props = _a.props, context = _a.context; 8958 var options = context.options; 8959 var seg = props.seg; 8960 var eventRange = seg.eventRange; 8961 var ui = eventRange.ui; 8962 var hookProps = { 8963 event: new EventApi(context, eventRange.def, eventRange.instance), 8964 view: context.viewApi, 8965 timeText: props.timeText, 8966 textColor: ui.textColor, 8967 backgroundColor: ui.backgroundColor, 8968 borderColor: ui.borderColor, 8969 isDraggable: !props.disableDragging && computeSegDraggable(seg, context), 8970 isStartResizable: !props.disableResizing && computeSegStartResizable(seg, context), 8971 isEndResizable: !props.disableResizing && computeSegEndResizable(seg), 8972 isMirror: Boolean(props.isDragging || props.isResizing || props.isDateSelecting), 8973 isStart: Boolean(seg.isStart), 8974 isEnd: Boolean(seg.isEnd), 8975 isPast: Boolean(props.isPast), 8976 isFuture: Boolean(props.isFuture), 8977 isToday: Boolean(props.isToday), 8978 isSelected: Boolean(props.isSelected), 8979 isDragging: Boolean(props.isDragging), 8980 isResizing: Boolean(props.isResizing) 8981 }; 8982 var standardClassNames = getEventClassNames(hookProps).concat(ui.classNames); 8983 return (createElement(RenderHook, { hookProps: hookProps, classNames: options.eventClassNames, content: options.eventContent, defaultContent: props.defaultContent, didMount: options.eventDidMount, willUnmount: options.eventWillUnmount, elRef: this.elRef }, function (rootElRef, customClassNames, innerElRef, innerContent) { return props.children(rootElRef, standardClassNames.concat(customClassNames), innerElRef, innerContent, hookProps); })); 8984 }; 8985 EventRoot.prototype.componentDidMount = function () { 8986 setElSeg(this.elRef.current, this.props.seg); 8987 }; 8988 /* 8989 need to re-assign seg to the element if seg changes, even if the element is the same 8990 */ 8991 EventRoot.prototype.componentDidUpdate = function (prevProps) { 8992 var seg = this.props.seg; 8993 if (seg !== prevProps.seg) { 8994 setElSeg(this.elRef.current, seg); 8995 } 8996 }; 8997 return EventRoot; 8998 }(BaseComponent)); 8999 9000 // should not be a purecomponent 9001 var StandardEvent = /** @class */ (function (_super) { 9002 __extends(StandardEvent, _super); 9003 function StandardEvent() { 9004 return _super !== null && _super.apply(this, arguments) || this; 9005 } 9006 StandardEvent.prototype.render = function () { 9007 var _a = this, props = _a.props, context = _a.context; 9008 var seg = props.seg; 9009 var timeFormat = context.options.eventTimeFormat || props.defaultTimeFormat; 9010 var timeText = buildSegTimeText(seg, timeFormat, context, props.defaultDisplayEventTime, props.defaultDisplayEventEnd); 9011 return (createElement(EventRoot, { seg: seg, timeText: timeText, disableDragging: props.disableDragging, disableResizing: props.disableResizing, defaultContent: props.defaultContent || renderInnerContent, isDragging: props.isDragging, isResizing: props.isResizing, isDateSelecting: props.isDateSelecting, isSelected: props.isSelected, isPast: props.isPast, isFuture: props.isFuture, isToday: props.isToday }, function (rootElRef, classNames, innerElRef, innerContent, hookProps) { return (createElement("a", __assign({ className: props.extraClassNames.c
9011oncat(classNames).join(' '), style: { 9012 borderColor: hookProps.borderColor, 9013 backgroundColor: hookProps.backgroundColor 9014 }, ref: rootElRef }, getSegAnchorAttrs(seg)), 9015 createElement("div", { className: 'fc-event-main', ref: innerElRef, style: { color: hookProps.textColor } }, innerContent), 9016 hookProps.isStartResizable && 9017 createElement("div", { className: 'fc-event-resizer fc-event-resizer-start' }), 9018 hookProps.isEndResizable && 9019 createElement("div", { className: 'fc-event-resizer fc-event-resizer-end' }))); })); 9020 }; 9021 return StandardEvent; 9022 }(BaseComponent)); 9023 function renderInnerContent(innerProps) { 9024 return (createElement("div", { className: 'fc-event-main-frame' }, 9025 innerProps.timeText && 9026 createElement("div", { className: 'fc-event-time' }, innerProps.timeText), 9027 createElement("div", { className: 'fc-event-title-container' }, 9028 createElement("div", { className: 'fc-event-title fc-sticky' }, innerProps.event.title || createElement(Fragment, null, "\u00A0"))))); 9029 } 9030 function getSegAnchorAttrs(seg) { 9031 var url = seg.eventRange.def.url; 9032 return url ? { href: url } : {}; 9033 } 9034 9035 var NowIndicatorRoot = function (props) { return (createElement(ViewContextType.Consumer, null, function (context) { 9036 var options = context.options; 9037 var hookProps = { 9038 isAxis: props.isAxis, 9039 date: context.dateEnv.toDate(props.date), 9040 view: context.viewApi 9041 }; 9042 return (createElement(RenderHook, { hookProps: hookProps, classNames: options.nowIndicatorClassNames, content: options.nowIndicatorContent, didMount: options.nowIndicatorDidMount, willUnmount: options.nowIndicatorWillUnmount }, props.children)); 9043 })); }; 9044 9045 var DAY_NUM_FORMAT = createFormatter({ day: 'numeric' }); 9046 var DayCellRoot = /** @class */ (function (_super) { 9047 __extends(DayCellRoot, _super); 9048 function DayCellRoot() { 9049 var _this = _super !== null && _super.apply(this, arguments) || this; 9050 _this.refineHookProps = memoizeObjArg(refineHookProps); 9051 _this.normalizeClassNames = buildClassNameNormalizer(); 9052 return _this; 9053 } 9054 DayCellRoot.prototype.render = function () { 9055 var _a = this, props = _a.props, context = _a.context; 9056 var options = context.options; 9057 var hookProps = this.refineHookProps({ 9058 date: props.date, 9059 dateProfile: props.dateProfile, 9060 todayRange: props.todayRange, 9061 showDayNumber: props.showDayNumber, 9062 extraProps: props.extraHookProps, 9063 viewApi: context.viewApi, 9064 dateEnv: context.dateEnv 9065 }); 9066 var classNames = getDayClassNames(hookProps, context.theme).concat(hookProps.isDisabled 9067 ? [] // don't use custom classNames if disabled 9068 : this.normalizeClassNames(options.dayCellClassNames, hookProps)); 9069 var dataAttrs = hookProps.isDisabled ? {} : { 9070 'data-date': formatDayString(props.date) 9071 }; 9072 return (createElement(MountHook, { hookProps: hookProps, didMount: options.dayCellDidMount, willUnmount: options.dayCellWillUnmount, elRef: props.elRef }, function (rootElRef) { return props.children(rootElRef, classNames, dataAttrs, hookProps.isDisabled); })); 9073 }; 9074 return DayCellRoot; 9075 }(BaseComponent)); 9076 var DayCellContent = /** @class */ (function (_super) { 9077 __extends(DayCellContent, _super); 9078 function DayCellContent() { 9079 return _super !== null && _super.apply(this, arguments) || this; 9080 } 9081 DayCellContent.prototype.render = function () { 9082 var _a = this, props = _a.props, context = _a.context; 9083 var options = context.options; 9084 var hookProps = refineHookProps({ 9085 date: props.date, 9086 dateProfile: props.dateProfile, 9087 todayRange: props.todayRange, 9088 showDayNumber: props.showDayNumber, 9089 extraProps: props.extraHookProps, 9090 viewApi: context.viewApi, 9091 dateEnv: context.dateEnv 9092 }); 9093 return (createElement(ContentHook, { hookProps: hookProps, content: options.dayCellContent, defaultContent: props.defaultContent }, props.children)); 9094 }; 9095 return DayCellContent; 9096 }(BaseComponent)); 9097 function refineHookProps(raw) { 9098 var date = raw.date, dateEnv = raw.dateEnv;
9099 var dayMeta = getDateMeta(date, raw.todayRange, null, raw.dateProfile); 9100 return __assign(__assign(__assign({ date: dateEnv.toDate(date), view: raw.viewApi }, dayMeta), { dayNumberText: raw.showDayNumber ? dateEnv.format(date, DAY_NUM_FORMAT) : '' }), raw.extraProps); 9101 } 9102 9103 function renderFill(fillType) { 9104 return (createElement("div", { className: "fc-" + fillType })); 9105 } 9106 var BgEvent = function (props) { return (createElement(EventRoot, { defaultContent: renderInnerContent$1, seg: props.seg /* uselesss i think */, timeText: '' /* weird */, disableDragging: true, disableResizing: true, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false, isPast: props.isPast, isFuture: props.isFuture, isToday: props.isToday }, function (rootElRef, classNames, innerElRef, innerContent, hookProps) { return (createElement("div", { ref: rootElRef, className: ['fc-bg-event'].concat(classNames).join(' '), style: { 9107 backgroundColor: hookProps.backgroundColor 9108 } }, innerContent)); })); }; 9109 function renderInnerContent$1(props) { 9110 var title = props.event.title; 9111 return title && (createElement("div", { className: 'fc-event-title' }, props.event.title)); 9112 } 9113 9114 var WeekNumberRoot = function (props) { return (createElement(ViewContextType.Consumer, null, function (context) { 9115 var dateEnv = context.dateEnv, options = context.options; 9116 var date = props.date; 9117 var format = options.weekNumberFormat || props.defaultFormat; 9118 var num = dateEnv.computeWeekNumber(date); // TODO: somehow use for formatting as well? 9119 var text = dateEnv.format(date, format); 9120 var hookProps = { num: num, text: text, date: date }; 9121 return (createElement(RenderHook, { hookProps: hookProps, classNames: options.weekNumberClassNames, content: options.weekNumberContent, defaultContent: renderInner$1, didMount: options.weekNumberDidMount, willUnmount: options.weekNumberWillUnmount }, props.children)); 9122 })); }; 9123 function renderInner$1(innerProps) { 9124 return innerProps.text; 9125 } 9126 9127 // exports 9128 // -------------------------------------------------------------------------------------------------- 9129 var version = '<%= version %>'; // important to type it, so .d.ts has generic string 9130 9131 var Calendar = /** @class */ (function (_super) { 9132 __extends(Calendar, _super); 9133 function Calendar(el, optionOverrides) { 9134 if (optionOverrides === void 0) { optionOverrides = {}; } 9135 var _this = _super.call(this) || this; 9136 _this.isRendering = false; 9137 _this.isRendered = false; 9138 _this.currentClassNames = []; 9139 _this.customContentRenderId = 0; // will affect custom generated classNames? 9140 _this.handleAction = function (action) { 9141 // actions we know we want to render immediately 9142 switch (action.type) { 9143 case 'SET_EVENT_DRAG': 9144 case 'SET_EVENT_RESIZE': 9145 _this.renderRunner.tryDrain(); 9146 } 9147 }; 9148 _this.handleData = function (data) { 9149 _this.currentData = data; 9150 _this.renderRunner.request(data.calendarOptions.rerenderDelay); 9151 }; 9152 _this.handleRenderRequest = function () { 9153 if (_this.isRendering) { 9154 _this.isRendered = true; 9155 var currentData_1 = _this.currentData; 9156 render(createElement(CalendarRoot, { options: currentData_1.calendarOptions, theme: currentData_1.theme, emitter: currentData_1.emitter }, function (classNames, height, isHeightAuto, forPrint) { 9157 _this.setClassNames(classNames); 9158 _this.setHeight(height); 9159 return (createElement(CustomContentRenderContext.Provider, { value: _this.customContentRenderId }, 9160 createElement(CalendarContent, __assign({ isHeightAuto: isHeightAuto, forPrint: forPrint }, currentData_1)))); 9161 }), _this.el); 9162 } 9163 else if (_this.isRendered) { 9164 _this.isRendered = false;
9165 render(null, _this.el); 9166 _this.setClassNames([]); 9167 _this.setHeight(''); 9168 } 9169 flushToDom$1(); 9170 }; 9171 _this.el = el; 9172 _this.renderRunner = new DelayedRunner(_this.handleRenderRequest); 9173 new CalendarDataManager({ 9174 optionOverrides: optionOverrides, 9175 calendarApi: _this, 9176 onAction: _this.handleAction, 9177 onData: _this.handleData 9178 }); 9179 return _this; 9180 } 9181 Object.defineProperty(Calendar.prototype, "view", { 9182 get: function () { return this.currentData.viewApi; } // for public API 9183 , 9184 enumerable: false, 9185 configurable: true 9186 }); 9187 Calendar.prototype.render = function () { 9188 var wasRendering = this.isRendering; 9189 if (!wasRendering) { 9190 this.isRendering = true; 9191 } 9192 else { 9193 this.customContentRenderId++; 9194 } 9195 this.renderRunner.request(); 9196 if (wasRendering) { 9197 this.updateSize(); 9198 } 9199 }; 9200 Calendar.prototype.destroy = function () { 9201 if (this.isRendering) { 9202 this.isRendering = false; 9203 this.renderRunner.request(); 9204 } 9205 }; 9206 Calendar.prototype.updateSize = function () { 9207 _super.prototype.updateSize.call(this); 9208 flushToDom$1(); 9209 }; 9210 Calendar.prototype.batchRendering = function (func) { 9211 this.renderRunner.pause('batchRendering'); 9212 func(); 9213 this.renderRunner.resume('batchRendering'); 9214 }; 9215 Calendar.prototype.pauseRendering = function () { 9216 this.renderRunner.pause('pauseRendering'); 9217 }; 9218 Calendar.prototype.resumeRendering = function () { 9219 this.renderRunner.resume('pauseRendering', true); 9220 }; 9221 Calendar.prototype.resetOptions = function (optionOverrides, append) { 9222 this.currentDataManager.resetOptions(optionOverrides, append); 9223 }; 9224 Calendar.prototype.setClassNames = function (classNames) { 9225 if (!isArraysEqual(classNames, this.currentClassNames)) { 9226 var classList = this.el.classList; 9227 for (var _i = 0, _a = this.currentClassNames; _i < _a.length; _i++) { 9228 var className = _a[_i]; 9229 classList.remove(className); 9230 } 9231 for (var _b = 0, classNames_1 = classNames; _b < classNames_1.length; _b++) { 9232 var className = classNames_1[_b]; 9233 classList.add(className); 9234 } 9235 this.currentClassNames = classNames; 9236 } 9237 }; 9238 Calendar.prototype.setHeight = function (height) { 9239 applyStyleProp(this.el, 'height', height); 9240 }; 9241 return Calendar; 9242 }(CalendarApi)); 9243 9244 config.touchMouseIgnoreWait = 500; 9245 var ignoreMouseDepth = 0; 9246 var listenerCnt = 0; 9247 var isWindowTouchMoveCancelled = false; 9248 /* 9249 Uses a "pointer" abstraction, which monitors UI events for both mouse and touch. 9250 Tracks when the pointer "drags" on a certain element, meaning down+move+up. 9251 9252 Also, tracks if there was touch-scrolling. 9253 Also, can prevent touch-scrolling from happening. 9254 Also, can fire pointermove events when scrolling happens underneath, even when no real pointer movement. 9255 9256 emits: 9257 - pointerdown 9258 - pointermove 9259 - pointerup 9260 */ 9261 var PointerDragging = /** @class */ (function () { 9262 function PointerDragging(containerEl) { 9263 var _this = this; 9264 this.subjectEl = null; 9265 // options that can be directly assigned by caller 9266 this.selector = ''; // will cause subjectEl in all emitted events to be this element 9267 this.handleSelector = ''; 9268 this.shouldIgnoreMove = false; 9269 this.shouldWatchScroll = true; // for simulating pointermove on scroll 9270 // internal states 9271 this.isDragging = false;
9272 this.isTouchDragging = false; 9273 this.wasTouchScroll = false; 9274 // Mouse 9275 // ---------------------------------------------------------------------------------------------------- 9276 this.handleMouseDown = function (ev) { 9277 if (!_this.shouldIgnoreMouse() && 9278 isPrimaryMouseButton(ev) && 9279 _this.tryStart(ev)) { 9280 var pev = _this.createEventFromMouse(ev, true); 9281 _this.emitter.trigger('pointerdown', pev); 9282 _this.initScrollWatch(pev); 9283 if (!_this.shouldIgnoreMove) { 9284 document.addEventListener('mousemove', _this.handleMouseMove); 9285 } 9286 document.addEventListener('mouseup', _this.handleMouseUp); 9287 } 9288 }; 9289 this.handleMouseMove = function (ev) { 9290 var pev = _this.createEventFromMouse(ev); 9291 _this.recordCoords(pev); 9292 _this.emitter.trigger('pointermove', pev); 9293 }; 9294 this.handleMouseUp = function (ev) { 9295 document.removeEventListener('mousemove', _this.handleMouseMove); 9296 document.removeEventListener('mouseup', _this.handleMouseUp); 9297 _this.emitter.trigger('pointerup', _this.createEventFromMouse(ev)); 9298 _this.cleanup(); // call last so that pointerup has access to props 9299 }; 9300 // Touch 9301 // ---------------------------------------------------------------------------------------------------- 9302 this.handleTouchStart = function (ev) { 9303 if (_this.tryStart(ev)) { 9304 _this.isTouchDragging = true; 9305 var pev = _this.createEventFromTouch(ev, true); 9306 _this.emitter.trigger('pointerdown', pev); 9307 _this.initScrollWatch(pev); 9308 // unlike mouse, need to attach to target, not document 9309 // https://stackoverflow.com/a/45760014 9310 var targetEl = ev.target; 9311 if (!_this.shouldIgnoreMove) { 9312 targetEl.addEventListener('touchmove', _this.handleTouchMove); 9313 } 9314 targetEl.addEventListener('touchend', _this.handleTouchEnd); 9315 targetEl.addEventListener('touchcancel', _this.handleTouchEnd); // treat it as a touch end 9316 // attach a handler to get called when ANY scroll action happens on the page. 9317 // this was impossible to do with normal on/off because 'scroll' doesn't bubble. 9318 // http://stackoverflow.com/a/32954565/96342 9319 window.addEventListener('scroll', _this.handleTouchScroll, true // useCapture 9320 ); 9321 } 9322 }; 9323 this.handleTouchMove = function (ev) { 9324 var pev = _this.createEventFromTouch(ev); 9325 _this.recordCoords(pev); 9326 _this.emitter.trigger('pointermove', pev); 9327 }; 9328 this.handleTouchEnd = function (ev) { 9329 if (_this.isDragging) { // done to guard against touchend followed by touchcancel 9330 var targetEl = ev.target; 9331 targetEl.removeEventListener('touchmove', _this.handleTouchMove); 9332 targetEl.removeEventListener('touchend', _this.handleTouchEnd); 9333 targetEl.removeEventListener('touchcancel', _this.handleTouchEnd); 9334 window.removeEventListener('scroll', _this.handleTouchScroll, true); // useCaptured=true 9335 _this.emitter.trigger('pointerup', _this.createEventFromTouch(ev)); 9336 _this.cleanup(); // call last so that pointerup has access to props 9337 _this.isTouchDragging = false; 9338 startIgnoringMouse(); 9339 } 9340 }; 9341 this.handleTouchScroll = function () { 9342 _this.wasTouchScroll = true; 9343 }; 9344 this.handleScroll = function (ev) { 9345 if (!_this.shouldIgnoreMove) { 9346 var pageX = (window.pageXOffset - _this.prevScrollX) + _this.prevPageX; 9347 var pageY = (window.pageYOffset - _this.prevScrollY) + _this.prevPageY; 9348 _this.emitter.trigger('pointermove', { 9349 origEvent: ev, 9350 isTouch: _this.isTouchDragging, 9351 subjectEl: _this.subjectEl, 9352 pageX: pageX, 9353 pageY: pageY, 9354 deltaX: pageX - _this.origPageX, 9355 deltaY: pageY - _this.origPageY 9356 }); 9357 } 9358 }; 9359 this.containerEl = containerEl; 9360 this.emitter = new Emitter(); 9361 containerEl.addEventListener('mousedown', this.handleMouseDown); 9362 containerEl.addEventListener('touchstart', this.handleTouchStart, { passive: true }); 9363 listenerCreated(); 9364 } 9365 PointerDragging.prototype.destroy = function () { 9366 this.containerEl.removeEventListener('mousedown', this.handleMouseDown); 9367 this.containerEl.removeEventListener('touchstart', this.handleTouchStart, { passive: true }); 9368 listenerDestroyed(); 9369 }; 9370 PointerDragging.prototype.tryStart = function (ev) {
9371 var subjectEl = this.querySubjectEl(ev); 9372 var downEl = ev.target; 9373 if (subjectEl && 9374 (!this.handleSelector || elementClosest(downEl, this.handleSelector))) { 9375 this.subjectEl = subjectEl; 9376 this.isDragging = true; // do this first so cancelTouchScroll will work 9377 this.wasTouchScroll = false; 9378 return true; 9379 } 9380 return false; 9381 }; 9382 PointerDragging.prototype.cleanup = function () { 9383 isWindowTouchMoveCancelled = false; 9384 this.isDragging = false; 9385 this.subjectEl = null; 9386 // keep wasTouchScroll around for later access 9387 this.destroyScrollWatch(); 9388 }; 9389 PointerDragging.prototype.querySubjectEl = function (ev) { 9390 if (this.selector) { 9391 return elementClosest(ev.target, this.selector); 9392 } 9393 else { 9394 return this.containerEl; 9395 } 9396 }; 9397 PointerDragging.prototype.shouldIgnoreMouse = function () { 9398 return ignoreMouseDepth || this.isTouchDragging; 9399 }; 9400 // can be called by user of this class, to cancel touch-based scrolling for the current drag 9401 PointerDragging.prototype.cancelTouchScroll = function () { 9402 if (this.isDragging) { 9403 isWindowTouchMoveCancelled = true; 9404 } 9405 }; 9406 // Scrolling that simulates pointermoves 9407 // ---------------------------------------------------------------------------------------------------- 9408 PointerDragging.prototype.initScrollWatch = function (ev) { 9409 if (this.shouldWatchScroll) { 9410 this.recordCoords(ev); 9411 window.addEventListener('scroll', this.handleScroll, true); // useCapture=true 9412 } 9413 }; 9414 PointerDragging.prototype.recordCoords = function (ev) { 9415 if (this.shouldWatchScroll) { 9416 this.prevPageX = ev.pageX; 9417 this.prevPageY = ev.pageY; 9418 this.prevScrollX = window.pageXOffset; 9419 this.prevScrollY = window.pageYOffset; 9420 } 9421 }; 9422 PointerDragging.prototype.destroyScrollWatch = function () { 9423 if (this.shouldWatchScroll) { 9424 window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true 9425 } 9426 }; 9427 // Event Normalization 9428 // ---------------------------------------------------------------------------------------------------- 9429 PointerDragging.prototype.createEventFromMouse = function (ev, isFirst) { 9430 var deltaX = 0; 9431 var deltaY = 0; 9432 // TODO: repeat code 9433 if (isFirst) { 9434 this.origPageX = ev.pageX; 9435 this.origPageY = ev.pageY; 9436 } 9437 else { 9438 deltaX = ev.pageX - this.origPageX; 9439 deltaY = ev.pageY - this.origPageY; 9440 } 9441 return { 9442 origEvent: ev, 9443 isTouch: false, 9444 subjectEl: this.subjectEl, 9445 pageX: ev.pageX, 9446 pageY: ev.pageY, 9447 deltaX: deltaX, 9448 deltaY: deltaY 9449 }; 9450 }; 9451 PointerDragging.prototype.createEventFromTouch = function (ev, isFirst) { 9452 var touches = ev.touches; 9453 var pageX; 9454 var pageY; 9455 var deltaX = 0; 9456 var deltaY = 0; 9457 // if touch coords available, prefer, 9458 // because FF would give bad ev.pageX ev.pageY 9459 if (touches && touches.length) { 9460 pageX = touches[0].pageX; 9461 pageY = touches[0].pageY; 9462 } 9463 else { 9464 pageX = ev.pageX; 9465 pageY = ev.pageY; 9466 } 9467 // TODO: repeat code 9468 if (isFirst) { 9469 this.origPageX = pageX; 9470 this.origPageY = pageY; 9471 } 9472 else { 9473 deltaX = pageX - this.origPageX; 9474 deltaY = pageY - this.origPageY; 9475 } 9476 return { 9477 origEvent: ev, 9478 isTouch: true, 9479 subjectEl: this.subjectEl, 9480 pageX: pageX, 9481 pageY: pageY, 9482 deltaX: deltaX, 9483 deltaY: deltaY 9484 }; 9485 }; 9486 return PointerDragging; 9487 }());
9488 // Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac) 9489 function isPrimaryMouseButton(ev) { 9490 return ev.button === 0 && !ev.ctrlKey; 9491 } 9492 // Ignoring fake mouse events generated by touch 9493 // ---------------------------------------------------------------------------------------------------- 9494 function startIgnoringMouse() { 9495 ignoreMouseDepth++; 9496 setTimeout(function () { 9497 ignoreMouseDepth--; 9498 }, config.touchMouseIgnoreWait); 9499 } 9500 // We want to attach touchmove as early as possible for Safari 9501 // ---------------------------------------------------------------------------------------------------- 9502 function listenerCreated() { 9503 if (!(listenerCnt++)) { 9504 window.addEventListener('touchmove', onWindowTouchMove, { passive: false }); 9505 } 9506 } 9507 function listenerDestroyed() { 9508 if (!(--listenerCnt)) { 9509 window.removeEventListener('touchmove', onWindowTouchMove, { passive: false }); 9510 } 9511 } 9512 function onWindowTouchMove(ev) { 9513 if (isWindowTouchMoveCancelled) { 9514 ev.preventDefault(); 9515 } 9516 } 9517 9518 /* 9519 An effect in which an element follows the movement of a pointer across the screen. 9520 The moving element is a clone of some other element. 9521 Must call start + handleMove + stop. 9522 */ 9523 var ElementMirror = /** @class */ (function () { 9524 function ElementMirror() { 9525 this.isVisible = false; // must be explicitly enabled 9526 this.sourceEl = null; 9527 this.mirrorEl = null; 9528 this.sourceElRect = null; // screen coords relative to viewport 9529 // options that can be set directly by caller 9530 this.parentNode = document.body; 9531 this.zIndex = 9999; 9532 this.revertDuration = 0; 9533 } 9534 ElementMirror.prototype.start = function (sourceEl, pageX, pageY) { 9535 this.sourceEl = sourceEl; 9536 this.sourceElRect = this.sourceEl.getBoundingClientRect(); 9537 this.origScreenX = pageX - window.pageXOffset; 9538 this.origScreenY = pageY - window.pageYOffset; 9539 this.deltaX = 0; 9540 this.deltaY = 0; 9541 this.updateElPosition(); 9542 }; 9543 ElementMirror.prototype.handleMove = function (pageX, pageY) { 9544 this.deltaX = (pageX - window.pageXOffset) - this.origScreenX; 9545 this.deltaY = (pageY - window.pageYOffset) - this.origScreenY; 9546 this.updateElPosition(); 9547 }; 9548 // can be called before start 9549 ElementMirror.prototype.setIsVisible = function (bool) { 9550 if (bool) { 9551 if (!this.isVisible) { 9552 if (this.mirrorEl) { 9553 this.mirrorEl.style.display = ''; 9554 } 9555 this.isVisible = bool; // needs to happen before updateElPosition 9556 this.updateElPosition(); // because was not updating the position while invisible 9557 } 9558 } 9559 else { 9560 if (this.isVisible) { 9561 if (this.mirrorEl) { 9562 this.mirrorEl.style.display = 'none'; 9563 } 9564 this.isVisible = bool; 9565 } 9566 } 9567 }; 9568 // always async 9569 ElementMirror.prototype.stop = function (needsRevertAnimation, callback) { 9570 var _this = this; 9571 var done = function () { 9572 _this.cleanup(); 9573 callback(); 9574 }; 9575 if (needsRevertAnimation && 9576 this.mirrorEl && 9577 this.isVisible && 9578 this.revertDuration && // if 0, transition won't work 9579 (this.deltaX || this.deltaY) // if same coords, transition won't work 9580 ) { 9581 this.doRevertAnimation(done, this.revertDuration); 9582 } 9583 else { 9584 setTimeout(done, 0); 9585 } 9586 }; 9587 ElementMirror.prototype.doRevertAnimation = function (callback, revertDuration) { 9588 var mirrorEl = this.mirrorEl; 9589 var finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened 9590 mirrorEl.style.transition = 9591 'top ' + revertDuration + 'ms,' + 9592 'left ' + revertDuration + 'ms'; 9593 applyStyle(mirrorEl, { 9594 left: finalSourceElRect.left, 9595 top: finalSourceElRect.top 9596 }); 9597 whenTransitionDone(mirrorEl, function () { 9598 mirrorEl.style.transition = ''; 9599 callback(); 9600 }); 9601 }; 9602 ElementMirror.prototype.cleanup = function () { 9603 if (this.mirrorEl) { 9604 removeElement(this.mirrorEl); 9605 this.mirrorEl = null; 9606 } 9607 this.sourceEl = null; 9608 }; 9609 ElementMirror.prototype.updateElPosition = function () { 9610 if (this.sourceEl && this.isVisible) { 9611 applyStyle(this.getMirrorEl(), { 9612 left: this.sourceElRect.left + this.deltaX,
9613 top: this.sourceElRect.top + this.deltaY 9614 }); 9615 } 9616 }; 9617 ElementMirror.prototype.getMirrorEl = function () { 9618 var sourceElRect = this.sourceElRect; 9619 var mirrorEl = this.mirrorEl; 9620 if (!mirrorEl) { 9621 mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true 9622 // we don't want long taps or any mouse interaction causing selection/menus. 9623 // would use preventSelection(), but that prevents selectstart, causing problems. 9624 mirrorEl.classList.add('fc-unselectable'); 9625 mirrorEl.classList.add('fc-event-dragging'); 9626 applyStyle(mirrorEl, { 9627 position: 'fixed', 9628 zIndex: this.zIndex, 9629 visibility: '', 9630 boxSizing: 'border-box', 9631 width: sourceElRect.right - sourceElRect.left, 9632 height: sourceElRect.bottom - sourceElRect.top, 9633 right: 'auto', 9634 bottom: 'auto', 9635 margin: 0 9636 }); 9637 this.parentNode.appendChild(mirrorEl); 9638 } 9639 return mirrorEl; 9640 }; 9641 return ElementMirror; 9642 }()); 9643 9644 /* 9645 Is a cache for a given element's scroll information (all the info that ScrollController stores) 9646 in addition the "client rectangle" of the element.. the area within the scrollbars. 9647 9648 The cache can be in one of two modes: 9649 - doesListening:false - ignores when the container is scrolled by someone else 9650 - doesListening:true - watch for scrolling and update the cache 9651 */ 9652 var ScrollGeomCache = /** @class */ (function (_super) { 9653 __extends(ScrollGeomCache, _super); 9654 function ScrollGeomCache(scrollController, doesListening) { 9655 var _this = _super.call(this) || this; 9656 _this.handleScroll = function () { 9657 _this.scrollTop = _this.scrollController.getScrollTop(); 9658 _this.scrollLeft = _this.scrollController.getScrollLeft(); 9659 _this.handleScrollChange(); 9660 }; 9661 _this.scrollController = scrollController; 9662 _this.doesListening = doesListening; 9663 _this.scrollTop = _this.origScrollTop = scrollController.getScrollTop(); 9664 _this.scrollLeft = _this.origScrollLeft = scrollController.getScrollLeft();
9665 _this.scrollWidth = scrollController.getScrollWidth(); 9666 _this.scrollHeight = scrollController.getScrollHeight(); 9667 _this.clientWidth = scrollController.getClientWidth(); 9668 _this.clientHeight = scrollController.getClientHeight(); 9669 _this.clientRect = _this.computeClientRect(); // do last in case it needs cached values 9670 if (_this.doesListening) { 9671 _this.getEventTarget().addEventListener('scroll', _this.handleScroll); 9672 } 9673 return _this; 9674 } 9675 ScrollGeomCache.prototype.destroy = function () { 9676 if (this.doesListening) { 9677 this.getEventTarget().removeEventListener('scroll', this.handleScroll); 9678 } 9679 }; 9680 ScrollGeomCache.prototype.getScrollTop = function () { 9681 return this.scrollTop; 9682 }; 9683 ScrollGeomCache.prototype.getScrollLeft = function () { 9684 return this.scrollLeft; 9685 }; 9686 ScrollGeomCache.prototype.setScrollTop = function (top) { 9687 this.scrollController.setScrollTop(top); 9688 if (!this.doesListening) { 9689 // we are not relying on the element to normalize out-of-bounds scroll values 9690 // so we need to sanitize ourselves 9691 this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0); 9692 this.handleScrollChange(); 9693 } 9694 }; 9695 ScrollGeomCache.prototype.setScrollLeft = function (top) { 9696 this.scrollController.setScrollLeft(top); 9697 if (!this.doesListening) { 9698 // we are not relying on the element to normalize out-of-bounds scroll values 9699 // so we need to sanitize ourselves 9700 this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0); 9701 this.handleScrollChange(); 9702 } 9703 }; 9704 ScrollGeomCache.prototype.getClientWidth = function () { 9705 return this.clientWidth; 9706 }; 9707 ScrollGeomCache.prototype.getClientHeight = function () { 9708 return this.clientHeight; 9709 }; 9710 ScrollGeomCache.prototype.getScrollWidth = function () { 9711 return this.scrollWidth; 9712 }; 9713 ScrollGeomCache.prototype.getScrollHeight = function () { 9714 return this.scrollHeight; 9715 }; 9716 ScrollGeomCache.prototype.handleScrollChange = function () { 9717 }; 9718 return ScrollGeomCache; 9719 }(ScrollController)); 9720 var ElementScrollGeomCache = /** @class */ (function (_super) { 9721 __extends(ElementScrollGeomCache, _super); 9722 function ElementScrollGeomCache(el, doesListening) { 9723 return _super.call(this, new ElementScrollController(el), doesListening) || this; 9724 } 9725 ElementScrollGeomCache.prototype.getEventTarget = function () { 9726 return this.scrollController.el; 9727 }; 9728 ElementScrollGeomCache.prototype.computeClientRect = function () { 9729 return computeInnerRect(this.scrollController.el); 9730 }; 9731 return ElementScrollGeomCache; 9732 }(ScrollGeomCache)); 9733 var WindowScrollGeomCache = /** @class */ (function (_super) { 9734 __extends(WindowScrollGeomCache, _super); 9735 function WindowScrollGeomCache(doesListening) { 9736 return _super.call(this, new WindowScrollController(), doesListening) || this; 9737 } 9738 WindowScrollGeomCache.prototype.getEventTarget = function () { 9739 return window; 9740 }; 9741 WindowScrollGeomCache.prototype.computeClientRect = function () { 9742 return { 9743 left: this.scrollLeft, 9744 right: this.scrollLeft + this.clientWidth, 9745 top: this.scrollTop, 9746 bottom: this.scrollTop + this.clientHeight 9747 }; 9748 }; 9749 // the window is the only scroll object that changes it's rectangle relative 9750 // to the document's topleft as it scrolls 9751 WindowScrollGeomCache.prototype.handleScrollChange = function () { 9752 this.clientRect = this.computeClientRect(); 9753 }; 9754 return WindowScrollGeomCache; 9755 }(ScrollGeomCache)); 9756 9757 // If available we are using native "performance" API instead of "Date" 9758 // Read more about it on MDN: 9759 // https://developer.mozilla.org/en-US/docs/Web/API/Performance 9760 var getTime = typeof performance === 'function' ? performance.now : Date.now; 9761 /* 9762 For a pointer interaction, automatically scrolls certain scroll containers when the pointer 9763 approaches the edge. 9764 9765 The caller must call start + handleMove + stop. 9766 */ 9767 var AutoScroller = /** @class */ (function () { 9768 function AutoScroller() { 9769 var _this = this; 9770 // options that can be set by caller 9771 this.isEnabled = true; 9772 this.scrollQuery = [window, '.fc-scroller']; 9773 this.edgeThreshold = 50; // pixels 9774 this.maxVelocity = 300; // pixels per second 9775 // internal state 9776 this.pointerScreenX = null; 9777 this.pointerScreenY = null; 9778 this.isAnimating = false;
9779 this.scrollCaches = null; 9780 // protect against the initial pointerdown being too close to an edge and starting the scroll 9781 this.everMovedUp = false; 9782 this.everMovedDown = false; 9783 this.everMovedLeft = false; 9784 this.everMovedRight = false; 9785 this.animate = function () { 9786 if (_this.isAnimating) { // wasn't cancelled between animation calls 9787 var edge = _this.computeBestEdge(_this.pointerScreenX + window.pageXOffset, _this.pointerScreenY + window.pageYOffset); 9788 if (edge) { 9789 var now = getTime(); 9790 _this.handleSide(edge, (now - _this.msSinceRequest) / 1000); 9791 _this.requestAnimation(now); 9792 } 9793 else { 9794 _this.isAnimating = false; // will stop animation 9795 } 9796 } 9797 }; 9798 } 9799 AutoScroller.prototype.start = function (pageX, pageY) { 9800 if (this.isEnabled) { 9801 this.scrollCaches = this.buildCaches(); 9802 this.pointerScreenX = null; 9803 this.pointerScreenY = null; 9804 this.everMovedUp = false; 9805 this.everMovedDown = false; 9806 this.everMovedLeft = false; 9807 this.everMovedRight = false; 9808 this.handleMove(pageX, pageY); 9809 } 9810 }; 9811 AutoScroller.prototype.handleMove = function (pageX, pageY) { 9812 if (this.isEnabled) { 9813 var pointerScreenX = pageX - window.pageXOffset; 9814 var pointerScreenY = pageY - window.pageYOffset; 9815 var yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY; 9816 var xDelta = this.pointerScreenX === null ? 0 : pointerScreenX - this.pointerScreenX; 9817 if (yDelta < 0) { 9818 this.everMovedUp = true; 9819 } 9820 else if (yDelta > 0) { 9821 this.everMovedDown = true; 9822 } 9823 if (xDelta < 0) { 9824 this.everMovedLeft = true; 9825 } 9826 else if (xDelta > 0) { 9827 this.everMovedRight = true; 9828 } 9829 this.pointerScreenX = pointerScreenX; 9830 this.pointerScreenY = pointerScreenY; 9831 if (!this.isAnimating) { 9832 this.isAnimating = true; 9833 this.requestAnimation(getTime()); 9834 } 9835 } 9836 }; 9837 AutoScroller.prototype.stop = function () { 9838 if (this.isEnabled) { 9839 this.isAnimating = false; // will stop animation 9840 for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { 9841 var scrollCache = _a[_i]; 9842 scrollCache.destroy(); 9843 } 9844 this.scrollCaches = null; 9845 } 9846 }; 9847 AutoScroller.prototype.requestAnimation = function (now) { 9848 this.msSinceRequest = now; 9849 requestAnimationFrame(this.animate); 9850 }; 9851 AutoScroller.prototype.handleSide = function (edge, seconds) { 9852 var scrollCache = edge.scrollCache; 9853 var edgeThreshold = this.edgeThreshold; 9854 var invDistance = edgeThreshold - edge.distance; 9855 var velocity = // the closer to the edge, the faster we scroll 9856 (invDistance * invDistance) / (edgeThreshold * edgeThreshold) * // quadratic 9857 this.maxVelocity * seconds; 9858 var sign = 1; 9859 switch (edge.name) { 9860 case 'left': 9861 sign = -1; 9862 // falls through 9863 case 'right': 9864 scrollCache.setScrollLeft(scrollCache.getScrollLeft() + velocity * sign); 9865 break; 9866 case 'top': 9867 sign = -1; 9868 // falls through 9869 case 'bottom': 9870 scrollCache.setScrollTop(scrollCache.getScrollTop() + velocity * sign); 9871 break; 9872 } 9873 }; 9874 // left/top are relative to document topleft 9875 AutoScroller.prototype.computeBestEdge = function (left, top) { 9876 var edgeThreshold = this.edgeThreshold; 9877 var bestSide = null; 9878 for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { 9879 var scrollCache = _a[_i]; 9880 var rect = scrollCache.clientRect; 9881 var leftDist = left - rect.left; 9882 var rightDist = rect.right - left; 9883 var topDist = top - rect.top; 9884 var bottomDist = rect.bottom - top; 9885 // completely within the rect? 9886 if (leftDist >= 0 && rightDist >= 0 && topDist >= 0 && bottomDist >= 0) { 9887 if (topDist <= edgeThreshold && this.everMovedUp && scrollCache.canScrollUp() && 9888 (!bestSide || bestSide.distance > topDist)) { 9889 bestSide = { scrollCache: scrollCache, name: 'top', distance: topDist }; 9890 } 9891 if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() && 9892 (!bestSide || bestSide.distance > bottomDist)) { 9893 bestSide = { scrollCache: scrollCache, name: 'bottom', distance: bottomDist }; 9894 } 9895 if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() && 9896 (!bestSide || bestSide.distance > leftDist)) { 9897 bestSide = { scrollCache: scrollCache, name: 'left', distance: leftDist }; 9898 } 9899 if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() && 9900 (!bestSide || bestSide.distance > rightDist)) { 9901 bestSide = { scrollCache: scrollCache, name: 'right', distance: rightDist }; 9902 } 9903 } 9904 } 9905 return bestSide; 9906 }; 9907 AutoScroller.prototype.buildCaches = function () { 9908 return this.queryScrollEls().map(function (el) { 9909 if (el === window) { 9910 return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls 9911 } 9912 else { 9913 return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls 9914 } 9915 }); 9916 }; 9917 AutoScroller.prototype.queryScrollEls = function () { 9918 var els = []; 9919 for (var _i = 0, _a = this.scrollQuery; _i < _a.length; _i++) { 9920 var query = _a[_i]; 9921 if (typeof query === 'object') { 9922 els.push(query); 9923 } 9924 else { 9925 els.push.apply(els, Array.prototype.slice.call(document.querySelectorAll(query))); 9926 } 9927 } 9928 return els; 9929 }; 9930 return AutoScroller; 9931 }()); 9932 9933 /* 9934 Monitors dragging on an element. Has a number of high-level features: 9935 - minimum distance required before dragging 9936 - minimum wait time ("delay") before dragging 9937 - a mirror element that follows the pointer 9938 */ 9939 var FeaturefulElementDragging = /** @class */ (function (_super) { 9940 __extends(FeaturefulElementDragging, _super); 9941 function FeaturefulElementDragging(containerEl, selector) { 9942 var _this = _super.call(this, containerEl) || this; 9943 // options that can be directly set by caller 9944 // the caller can also set the PointerDragging's options as well 9945 _this.delay = null; 9946 _this.minDistance = 0; 9947 _this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag 9948 _this.mirrorNeedsRevert = false;
9949 _this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup 9950 _this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation 9951 _this.isDelayEnded = false; 9952 _this.isDistanceSurpassed = false; 9953 _this.delayTimeoutId = null; 9954 _this.onPointerDown = function (ev) { 9955 if (!_this.isDragging) { // so new drag doesn't happen while revert animation is going 9956 _this.isInteracting = true; 9957 _this.isDelayEnded = false; 9958 _this.isDistanceSurpassed = false; 9959 preventSelection(document.body); 9960 preventContextMenu(document.body); 9961 // prevent links from being visited if there's an eventual drag. 9962 // also prevents selection in older browsers (maybe?). 9963 // not necessary for touch, besides, browser would complain about passiveness. 9964 if (!ev.isTouch) { 9965 ev.origEvent.preventDefault(); 9966 } 9967 _this.emitter.trigger('pointerdown', ev); 9968 if (_this.isInteracting && // not destroyed via pointerdown handler 9969 !_this.pointer.shouldIgnoreMove) { 9970 // actions related to initiating dragstart+dragmove+dragend... 9971 _this.mirror.setIsVisible(false); // reset. caller must set-visible 9972 _this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down 9973 _this.startDelay(ev); 9974 if (!_this.minDistance) { 9975 _this.handleDistanceSurpassed(ev); 9976 } 9977 } 9978 } 9979 }; 9980 _this.onPointerMove = function (ev) { 9981 if (_this.isInteracting) { 9982 _this.emitter.trigger('pointermove', ev); 9983 if (!_this.isDistanceSurpassed) { 9984 var minDistance = _this.minDistance; 9985 var distanceSq = void 0; // current distance from the origin, squared 9986 var deltaX = ev.deltaX, deltaY = ev.deltaY; 9987 distanceSq = deltaX * deltaX + deltaY * deltaY; 9988 if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem 9989 _this.handleDistanceSurpassed(ev); 9990 } 9991 } 9992 if (_this.isDragging) { 9993 // a real pointer move? (not one simulated by scrolling) 9994 if (ev.origEvent.type !== 'scroll') { 9995 _this.mirror.handleMove(ev.pageX, ev.pageY); 9996 _this.autoScroller.handleMove(ev.pageX, ev.pageY); 9997 } 9998 _this.emitter.trigger('dragmove', ev); 9999 } 10000 } 10001 }; 10002 _this.onPointerUp = function (ev) { 10003 if (_this.isInteracting) { 10004 _this.isInteracting = false; 10005 allowSelection(document.body); 10006 allowContextMenu(document.body); 10007 _this.emitter.trigger('pointerup', ev); // can potentially set mirrorNeedsRevert 10008 if (_this.isDragging) { 10009 _this.autoScroller.stop(); 10010 _this.tryStopDrag(ev); // which will stop the mirror 10011 } 10012 if (_this.delayTimeoutId) { 10013 clearTimeout(_this.delayTimeoutId); 10014 _this.delayTimeoutId = null; 10015 } 10016 } 10017 }; 10018 var pointer = _this.pointer = new PointerDragging(containerEl); 10019 pointer.emitter.on('pointerdown', _this.onPointerDown); 10020 pointer.emitter.on('pointermove', _this.onPointerMove); 10021 pointer.emitter.on('pointerup', _this.onPointerUp); 10022 if (selector) { 10023 pointer.selector = selector; 10024 } 10025 _this.mirror = new ElementMirror(); 10026 _this.autoScroller = new AutoScroller(); 10027 return _this; 10028 } 10029 FeaturefulElementDragging.prototype.destroy = function () { 10030 this.pointer.destroy(); 10031 // HACK: simulate a pointer-up to end the current drag
10032 // TODO: fire 'dragend' directly and stop interaction. discourage use of pointerup event (b/c might not fire) 10033 this.onPointerUp({}); 10034 }; 10035 FeaturefulElementDragging.prototype.startDelay = function (ev) { 10036 var _this = this; 10037 if (typeof this.delay === 'number') { 10038 this.delayTimeoutId = setTimeout(function () { 10039 _this.delayTimeoutId = null; 10040 _this.handleDelayEnd(ev); 10041 }, this.delay); // not assignable to number! 10042 } 10043 else { 10044 this.handleDelayEnd(ev); 10045 } 10046 }; 10047 FeaturefulElementDragging.prototype.handleDelayEnd = function (ev) { 10048 this.isDelayEnded = true; 10049 this.tryStartDrag(ev); 10050 }; 10051 FeaturefulElementDragging.prototype.handleDistanceSurpassed = function (ev) { 10052 this.isDistanceSurpassed = true; 10053 this.tryStartDrag(ev); 10054 }; 10055 FeaturefulElementDragging.prototype.tryStartDrag = function (ev) { 10056 if (this.isDelayEnded && this.isDistanceSurpassed) { 10057 if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) { 10058 this.isDragging = true; 10059 this.mirrorNeedsRevert = false; 10060 this.autoScroller.start(ev.pageX, ev.pageY); 10061 this.emitter.trigger('dragstart', ev); 10062 if (this.touchScrollAllowed === false) { 10063 this.pointer.cancelTouchScroll(); 10064 } 10065 } 10066 } 10067 }; 10068 FeaturefulElementDragging.prototype.tryStopDrag = function (ev) { 10069 // .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events 10070 // that come from the document to fire beforehand. much more convenient this way. 10071 this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev) // bound with args 10072 ); 10073 }; 10074 FeaturefulElementDragging.prototype.stopDrag = function (ev) { 10075 this.isDragging = false; 10076 this.emitter.trigger('dragend', ev); 10077 }; 10078 // fill in the implementations... 10079 FeaturefulElementDragging.prototype.setIgnoreMove = function (bool) { 10080 this.pointer.shouldIgnoreMove = bool; 10081 }; 10082 FeaturefulElementDragging.prototype.setMirrorIsVisible = function (bool) { 10083 this.mirror.setIsVisible(bool); 10084 }; 10085 FeaturefulElementDragging.prototype.setMirrorNeedsRevert = function (bool) { 10086 this.mirrorNeedsRevert = bool; 10087 }; 10088 FeaturefulElementDragging.prototype.setAutoScrollEnabled = function (bool) { 10089 this.autoScroller.isEnabled = bool; 10090 }; 10091 return FeaturefulElementDragging; 10092 }(ElementDragging)); 10093 10094 /* 10095 When this class is instantiated, it records the offset of an element (relative to the document topleft), 10096 and continues to monitor scrolling, updating the cached coordinates if it needs to. 10097 Does not access the DOM after instantiation, so highly performant. 10098 10099 Also keeps track of all scrolling/overflow:hidden containers that are parents of the given element 10100 and an determine if a given point is inside the combined clipping rectangle. 10101 */ 10102 var OffsetTracker = /** @class */ (function () { 10103 function OffsetTracker(el) { 10104 this.origRect = computeRect(el); 10105 // will work fine for divs that have overflow:hidden 10106 this.scrollCaches = getClippingParents(el).map(function (el) { 10107 return new ElementScrollGeomCache(el, true); // listen=true 10108 }); 10109 } 10110 OffsetTracker.prototype.destroy = function () { 10111 for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { 10112 var scrollCache = _a[_i]; 10113 scrollCache.destroy(); 10114 } 10115 }; 10116 OffsetTracker.prototype.computeLeft = function () { 10117 var left = this.origRect.left; 10118 for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { 10119 var scrollCache = _a[_i]; 10120 left += scrollCache.origScrollLeft - scrollCache.getScrollLeft(); 10121 } 10122 return left; 10123 }; 10124 OffsetTracker.prototype.computeTop = function () { 10125 var top = this.origRect.top; 10126 for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { 10127 var scrollCache = _a[_i]; 10128 top += scrollCache.origScrollTop - scrollCache.getScrollTop(); 10129 } 10130 return top; 10131 }; 10132 OffsetTracker.prototype.isWithinClipping = function (pageX, pageY) { 10133 var point = { left: pageX, top: pageY }; 10134 for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { 10135 var scrollCache = _a[_i];
10136 if (!isIgnoredClipping(scrollCache.getEventTarget()) && 10137 !pointInsideRect(point, scrollCache.clientRect)) { 10138 return false; 10139 } 10140 } 10141 return true; 10142 }; 10143 return OffsetTracker; 10144 }()); 10145 // certain clipping containers should never constrain interactions, like <html> and <body> 10146 // https://github.com/fullcalendar/fullcalendar/issues/3615 10147 function isIgnoredClipping(node) { 10148 var tagName = node.tagName; 10149 return tagName === 'HTML' || tagName === 'BODY'; 10150 } 10151 10152 /* 10153 Tracks movement over multiple droppable areas (aka "hits") 10154 that exist in one or more DateComponents. 10155 Relies on an existing draggable. 10156 10157 emits: 10158 - pointerdown 10159 - dragstart 10160 - hitchange - fires initially, even if not over a hit 10161 - pointerup 10162 - (hitchange - again, to null, if ended over a hit) 10163 - dragend 10164 */ 10165 var HitDragging = /** @class */ (function () { 10166 function HitDragging(dragging, droppableStore) { 10167 var _this = this; 10168 // options that can be set by caller 10169 this.useSubjectCenter = false; 10170 this.requireInitial = true; // if doesn't start out on a hit, won't emit any events 10171 this.initialHit = null; 10172 this.movingHit = null; 10173 this.finalHit = null; // won't ever be populated if shouldIgnoreMove 10174 this.handlePointerDown = function (ev) { 10175 var dragging = _this.dragging; 10176 _this.initialHit = null; 10177 _this.movingHit = null; 10178 _this.finalHit = null; 10179 _this.prepareHits(); 10180 _this.processFirstCoord(ev); 10181 if (_this.initialHit || !_this.requireInitial) { 10182 dragging.setIgnoreMove(false); 10183 _this.emitter.trigger('pointerdown', ev); // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :( 10184 } 10185 else { 10186 dragging.setIgnoreMove(true); 10187 } 10188 }; 10189 this.handleDragStart = function (ev) { 10190 _this.emitter.trigger('dragstart', ev); 10191 _this.handleMove(ev, true); // force = fire even if initially null 10192 }; 10193 this.handleDragMove = function (ev) { 10194 _this.emitter.trigger('dragmove', ev); 10195 _this.handleMove(ev); 10196 }; 10197 this.handlePointerUp = function (ev) { 10198 _this.releaseHits(); 10199 _this.emitter.trigger('pointerup', ev); 10200 }; 10201 this.handleDragEnd = function (ev) { 10202 if (_this.movingHit) { 10203 _this.emitter.trigger('hitupdate', null, true, ev); 10204 } 10205 _this.finalHit = _this.movingHit; 10206 _this.movingHit = null; 10207 _this.emitter.trigger('dragend', ev); 10208 }; 10209 this.droppableStore = droppableStore; 10210 dragging.emitter.on('pointerdown', this.handlePointerDown); 10211 dragging.emitter.on('dragstart', this.handleDragStart); 10212 dragging.emitter.on('dragmove', this.handleDragMove); 10213 dragging.emitter.on('pointerup', this.handlePointerUp); 10214 dragging.emitter.on('dragend', this.handleDragEnd); 10215 this.dragging = dragging; 10216 this.emitter = new Emitter(); 10217 } 10218 // sets initialHit 10219 // sets coordAdjust 10220 HitDragging.prototype.processFirstCoord = function (ev) { 10221 var origPoint = { left: ev.pageX, top: ev.pageY }; 10222 var adjustedPoint = origPoint; 10223 var subjectEl = ev.subjectEl; 10224 var subjectRect; 10225 if (subjectEl !== document) { 10226 subjectRect = computeRect(subjectEl); 10227 adjustedPoint = constrainPoint(adjustedPoint, subjectRect); 10228 } 10229 var initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top); 10230 if (initialHit) { 10231 if (this.useSubjectCenter && subjectRect) { 10232 var slicedSubjectRect = intersectRects(subjectRect, initialHit.rect); 10233 if (slicedSubjectRect) { 10234 adjustedPoint = getRectCenter(slicedSubjectRect); 10235 } 10236 } 10237 this.coordAdjust = diffPoints(adjustedPoint, origPoint); 10238 } 10239 else { 10240 this.coordAdjust = { left: 0, top: 0 }; 10241 } 10242 }; 10243 HitDragging.prototype.handleMove = function (ev, forceHandle) { 10244 var hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top); 10245 if (forceHandle || !isHitsEqual(this.movingHit, hit)) { 10246 this.movingHit = hit; 10247 this.emitter.trigger('hitupdate', hit, false, ev); 10248 } 10249 }; 10250 HitDragging.prototype.prepareHits = function () { 10251 this.offsetTrackers = mapHash(this.droppableStore, function (interactionSettings) { 10252 interactionSettings.component.prepareHits(); 10253 return new OffsetTracker(interactionSettings.el); 10254 }); 10255 }; 10256 HitDragging.prototype.releaseHits = function () { 10257 var offsetTrackers = this.offsetTrackers; 10258 for (var id in offsetTrackers) { 10259 offsetTrackers[id].destroy(); 10260 } 10261 this.offsetTrackers = {}; 10262 }; 10263 HitDragging.prototype.queryHitForOffset = function (offsetLeft, offsetTop) { 10264 var _a = this, droppableStore = _a.droppableStore, offsetTrackers = _a.offsetTrackers; 10265 var bestHit = null; 10266 for (var id in droppableStore) { 10267 var component = droppableStore[id].component; 10268 var offsetTracker = offsetTrackers[id]; 10269 if (offsetTracker && // wasn't destroyed mid-drag 10270 offsetTracker.isWithinClipping(offsetLeft, offsetTop)) { 10271 var originLeft = offsetTracker.computeLeft(); 10272 var originTop = offsetTracker.computeTop(); 10273 var positionLeft = offsetLeft - originLeft; 10274 var positionTop = offsetTop - originTop; 10275 var origRect = offsetTracker.origRect; 10276 var width = origRect.right - origRect.left; 10277 var height = origRect.bottom - origRect.top; 10278 if ( 10279 // must be within the element's bounds 10280 positionLeft >= 0 && positionLeft < width && 10281 positionTop >= 0 && positionTop < height) { 10282 var hit = component.queryHit(positionLeft, positionTop, width, height); 10283 var dateProfile = component.context.getCurrentData().dateProfile; 10284 if (hit && 10285 ( 10286 // make sure the hit is within activeRange, meaning it's not a deal cell 10287 rangeContainsRange(dateProfile.activeRange, hit.dateSpan.range)) && 10288 (!bestHit || hit.layer > bestHit.layer)) { 10289 // TODO: better way to re-orient rectangle 10290 hit.rect.left += originLeft; 10291 hit.rect.right += originLeft; 10292 hit.rect.top += originTop; 10293 hit.rect.bottom += originTop; 10294 bestHit = hit; 10295 } 10296 } 10297 } 10298 } 10299 return bestHit; 10300 }; 10301 return HitDragging; 10302 }()); 10303 function isHitsEqual(hit0, hit1) { 10304 if (!hit0 && !hit1) { 10305 return true; 10306 } 10307 if (Boolean(hit0) !== Boolean(hit1)) { 10308 return false;
10309 } 10310 return isDateSpansEqual(hit0.dateSpan, hit1.dateSpan); 10311 } 10312 10313 function buildDatePointApiWithContext(dateSpan, context) { 10314 var props = {}; 10315 for (var _i = 0, _a = context.pluginHooks.datePointTransforms; _i < _a.length; _i++) { 10316 var transform = _a[_i]; 10317 __assign(props, transform(dateSpan, context)); 10318 } 10319 __assign(props, buildDatePointApi(dateSpan, context.dateEnv)); 10320 return props; 10321 } 10322 function buildDatePointApi(span, dateEnv) { 10323 return { 10324 date: dateEnv.toDate(span.range.start), 10325 dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }), 10326 allDay: span.allDay 10327 }; 10328 } 10329 10330 /* 10331 Monitors when the user clicks on a specific date/time of a component. 10332 A pointerdown+pointerup on the same "hit" constitutes a click. 10333 */ 10334 var DateClicking = /** @class */ (function (_super) { 10335 __extends(DateClicking, _super); 10336 function DateClicking(settings) { 10337 var _this = _super.call(this, settings) || this; 10338 _this.handlePointerDown = function (pev) { 10339 var dragging = _this.dragging; 10340 var downEl = pev.origEvent.target; 10341 // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired 10342 dragging.setIgnoreMove(!_this.component.isValidDateDownEl(downEl)); 10343 }; 10344 // won't even fire if moving was ignored 10345 _this.handleDragEnd = function (ev) { 10346 var component = _this.component; 10347 var pointer = _this.dragging.pointer; 10348 if (!pointer.wasTouchScroll) { 10349 var _a = _this.hitDragging, initialHit = _a.initialHit, finalHit = _a.finalHit; 10350 if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) { 10351 var context = component.context; 10352 var arg = __assign(__assign({}, buildDatePointApiWithContext(initialHit.dateSpan, context)), { dayEl: initialHit.dayEl, jsEvent: ev.origEvent, view: context.viewApi || context.calendarApi.view }); 10353 context.emitter.trigger('dateClick', arg); 10354 } 10355 } 10356 }; 10357 // we DO want to watch pointer moves because otherwise finalHit won't get populated 10358 _this.dragging = new FeaturefulElementDragging(settings.el); 10359 _this.dragging.autoScroller.isEnabled = false; 10360 var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, interactionSettingsToStore(settings)); 10361 hitDragging.emitter.on('pointerdown', _this.handlePointerDown); 10362 hitDragging.emitter.on('dragend', _this.handleDragEnd); 10363 return _this; 10364 } 10365 DateClicking.prototype.destroy = function () { 10366 this.dragging.destroy(); 10367 }; 10368 return DateClicking; 10369 }(Interaction)); 10370 10371 /* 10372 Tracks when the user selects a portion of time of a component, 10373 constituted by a drag over date cells, with a possible delay at the beginning of the drag. 10374 */ 10375 var DateSelecting = /** @class */ (function (_super) { 10376 __extends(DateSelecting, _super); 10377 function DateSelecting(settings) { 10378 var _this = _super.call(this, settings) || this; 10379 _this.dragSelection = null; 10380 _this.handlePointerDown = function (ev) { 10381 var _a = _this, component = _a.component, dragging = _a.dragging; 10382 var options = component.context.options; 10383 var canSelect = options.selectable && 10384 component.isValidDateDownEl(ev.origEvent.target); 10385 // don't bother to watch expensive moves if component won't do selection 10386 dragging.setIgnoreMove(!canSelect); 10387 // if touch, require user to hold down 10388 dragging.delay = ev.isTouch ? getComponentTouchDelay(component) : null; 10389 }; 10390 _this.handleDragStart = function (ev) { 10391 _this.component.context.calendarApi.unselect(ev); // unselect previous selections 10392 }; 10393 _this.handleHitUpdate = function (hit, isFinal) { 10394 var context = _this.component.context; 10395 var dragSelection = null; 10396 var isInvalid = false;
10397 if (hit) { 10398 dragSelection = joinHitsIntoSelection(_this.hitDragging.initialHit, hit, context.pluginHooks.dateSelectionTransformers); 10399 if (!dragSelection || !_this.component.isDateSelectionValid(dragSelection)) { 10400 isInvalid = true; 10401 dragSelection = null; 10402 } 10403 } 10404 if (dragSelection) { 10405 context.dispatch({ type: 'SELECT_DATES', selection: dragSelection }); 10406 } 10407 else if (!isFinal) { // only unselect if moved away while dragging 10408 context.dispatch({ type: 'UNSELECT_DATES' }); 10409 } 10410 if (!isInvalid) { 10411 enableCursor(); 10412 } 10413 else { 10414 disableCursor(); 10415 } 10416 if (!isFinal) { 10417 _this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging 10418 } 10419 }; 10420 _this.handlePointerUp = function (pev) { 10421 if (_this.dragSelection) { 10422 // selection is already rendered, so just need to report selection 10423 triggerDateSelect(_this.dragSelection, pev, _this.component.context); 10424 _this.dragSelection = null; 10425 } 10426 }; 10427 var component = settings.component; 10428 var options = component.context.options; 10429 var dragging = _this.dragging = new FeaturefulElementDragging(settings.el); 10430 dragging.touchScrollAllowed = false; 10431 dragging.minDistance = options.selectMinDistance || 0; 10432 dragging.autoScroller.isEnabled = options.dragScroll; 10433 var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, interactionSettingsToStore(settings)); 10434 hitDragging.emitter.on('pointerdown', _this.handlePointerDown); 10435 hitDragging.emitter.on('dragstart', _this.handleDragStart); 10436 hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); 10437 hitDragging.emitter.on('pointerup', _this.handlePointerUp); 10438 return _this; 10439 } 10440 DateSelecting.prototype.destroy = function () { 10441 this.dragging.destroy(); 10442 }; 10443 return DateSelecting; 10444 }(Interaction)); 10445 function getComponentTouchDelay(component) { 10446 var options = component.context.options; 10447 var delay = options.selectLongPressDelay; 10448 if (delay == null) { 10449 delay = options.longPressDelay; 10450 } 10451 return delay; 10452 } 10453 function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) { 10454 var dateSpan0 = hit0.dateSpan; 10455 var dateSpan1 = hit1.dateSpan; 10456 var ms = [ 10457 dateSpan0.range.start, 10458 dateSpan0.range.end, 10459 dateSpan1.range.start, 10460 dateSpan1.range.end 10461 ]; 10462 ms.sort(compareNumbers); 10463 var props = {}; 10464 for (var _i = 0, dateSelectionTransformers_1 = dateSelectionTransformers; _i < dateSelectionTransformers_1.length; _i++) { 10465 var transformer = dateSelectionTransformers_1[_i]; 10466 var res = transformer(hit0, hit1); 10467 if (res === false) { 10468 return null; 10469 } 10470 else if (res) { 10471 __assign(props, res); 10472 } 10473 } 10474 props.range = { start: ms[0], end: ms[3] }; 10475 props.allDay = dateSpan0.allDay; 10476 return props; 10477 } 10478 10479 var EventDragging = /** @class */ (function (_super) { 10480 __extends(EventDragging, _super); 10481 function EventDragging(settings) { 10482 var _this = _super.call(this, settings) || this; 10483 // internal state 10484 _this.subjectEl = null; 10485 _this.subjectSeg = null; // the seg being selected/dragged 10486 _this.isDragging = false; 10487 _this.eventRange = null; 10488 _this.relevantEvents = null; // the events being dragged 10489 _this.receivingContext = null; 10490 _this.validMutation = null; 10491 _this.mutatedRelevantEvents = null; 10492 _this.handlePointerDown = function (ev) { 10493 var origTarget = ev.origEvent.target; 10494 var _a = _this, component = _a.component, dragging = _a.dragging; 10495 var mirror = dragging.mirror; 10496 var options = component.context.options; 10497 var initialContext = component.context; 10498 _this.subjectEl = ev.subjectEl; 10499 var subjectSeg = _this.subjectSeg = getElSeg(ev.subjectEl); 10500 var eventRange = _this.eventRange = subjectSeg.eventRange; 10501 var eventInstanceId = eventRange.instance.instanceId; 10502 _this.relevantEvents = getRelevantEvents(initialContext.getCurrentData().eventStore, eventInstanceId); 10503 dragging.minDistance = ev.isTouch ? 0 : options.eventDragMinDistance; 10504 dragging.delay = 10505 // only do a touch delay if touch and this event hasn't been selected yet 10506 (ev.isTouch && eventInstanceId !== component.props.eventSelection) ? 10507 getComponentTouchDelay$1(component) : 10508 null; 10509 mirror.parentNode = elementClosest(origTarget, '.fc'); 10510 mirror.revertDuration = options.dragRevertDuration; 10511 var isValid = component.isValidSegDownEl(origTarget) && 10512 !elementClosest(origTarget, '.fc-event-resizer'); // NOT on a resizer 10513 dragging.setIgnoreMove(!isValid); 10514 // disable dragging for elements that are resizable (ie, selectable) 10515 // but are not draggable 10516 _this.isDragging = isValid && 10517 ev.subjectEl.classList.contains('fc-event-draggable'); 10518 }; 10519 _this.handleDragStart = function (ev) { 10520 var initialContext = _this.component.context; 10521 var eventRange = _this.eventRange; 10522 var eventInstanceId = eventRange.instance.instanceId; 10523 if (ev.isTouch) { 10524 // need to select a different event? 10525 if (eventInstanceId !== _this.component.props.eventSelection) { 10526 initialContext.dispatch({ type: 'SELECT_EVENT', eventInstanceId: eventInstanceId }); 10527 } 10528 } 10529 else { 10530 // if now using mouse, but was previous touch interaction, clear selected event 10531 initialContext.dispatch({ type: 'UNSELECT_EVENT' }); 10532 } 10533 if (_this.isDragging) { 10534 initialContext.calendarApi.unselect(ev); // unselect *date* selection 10535 initialContext.emitter.trigger('eventDragStart', { 10536 el: _this.subjectEl, 10537 event: new EventApi(initialContext, eventRange.def, eventRange.instance), 10538 jsEvent: ev.origEvent, 10539 view: initialContext.viewApi 10540 }); 10541 } 10542 }; 10543 _this.handleHitUpdate = function (hit, isFinal) { 10544 if (!_this.isDragging) { 10545 return; 10546 } 10547 var relevantEvents = _this.relevantEvents; 10548 var initialHit = _this.hitDragging.initialHit; 10549 var initialContext = _this.component.context; 10550 // states based on new hit 10551 var receivingContext = null; 10552 var mutation = null; 10553 var mutatedRelevantEvents = null; 10554 var isInvalid = false;
10555 var interaction = { 10556 affectedEvents: relevantEvents, 10557 mutatedEvents: createEmptyEventStore(), 10558 isEvent: true 10559 }; 10560 if (hit) { 10561 var receivingComponent = hit.component; 10562 receivingContext = receivingComponent.context; 10563 var receivingOptions = receivingContext.options; 10564 if (initialContext === receivingContext || 10565 receivingOptions.editable && receivingOptions.droppable) { 10566 mutation = computeEventMutation(initialHit, hit, receivingContext.getCurrentData().pluginHooks.eventDragMutationMassagers); 10567 if (mutation) { 10568 mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, receivingContext.getCurrentData().eventUiBases, mutation, receivingContext); 10569 interaction.mutatedEvents = mutatedRelevantEvents; 10570 if (!receivingComponent.isInteractionValid(interaction)) { 10571 isInvalid = true; 10572 mutation = null; 10573 mutatedRelevantEvents = null; 10574 interaction.mutatedEvents = createEmptyEventStore(); 10575 } 10576 } 10577 } 10578 else { 10579 receivingContext = null; 10580 } 10581 } 10582 _this.displayDrag(receivingContext, interaction); 10583 if (!isInvalid) { 10584 enableCursor(); 10585 } 10586 else { 10587 disableCursor(); 10588 } 10589 if (!isFinal) { 10590 if (initialContext === receivingContext && // TODO: write test for this 10591 isHitsEqual(initialHit, hit)) { 10592 mutation = null; 10593 } 10594 _this.dragging.setMirrorNeedsRevert(!mutation); 10595 // render the mirror if no already-rendered mirror 10596 // TODO: wish we could somehow wait for dispatch to guarantee render 10597 _this.dragging.setMirrorIsVisible(!hit || !document.querySelector('.fc-event-mirror')); 10598 // assign states based on new hit 10599 _this.receivingContext = receivingContext; 10600 _this.validMutation = mutation; 10601 _this.mutatedRelevantEvents = mutatedRelevantEvents; 10602 } 10603 }; 10604 _this.handlePointerUp = function () { 10605 if (!_this.isDragging) { 10606 _this.cleanup(); // because handleDragEnd won't fire 10607 } 10608 }; 10609 _this.handleDragEnd = function (ev) { 10610 if (_this.isDragging) { 10611 var initialContext_1 = _this.component.context; 10612 var initialView = initialContext_1.viewApi; 10613 var _a = _this, receivingContext_1 = _a.receivingContext, validMutation = _a.validMutation; 10614 var eventDef = _this.eventRange.def; 10615 var eventInstance = _this.eventRange.instance; 10616 var eventApi = new EventApi(initialContext_1, eventDef, eventInstance); 10617 var relevantEvents_1 = _this.relevantEvents; 10618 var mutatedRelevantEvents_1 = _this.mutatedRelevantEvents; 10619 var finalHit = _this.hitDragging.finalHit; 10620 _this.clearDrag(); // must happen after revert animation 10621 initialContext_1.emitter.trigger('eventDragStop', { 10622 el: _this.subjectEl, 10623 event: eventApi, 10624 jsEvent: ev.origEvent, 10625 view: initialView 10626 }); 10627 if (validMutation) { 10628 // dropped within same calendar 10629 if (receivingContext_1 === initialContext_1) { 10630 var updatedEventApi = new EventApi(initialContext_1, mutatedRelevantEvents_1.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents_1.instances[eventInstance.instanceId] : null); 10631 initialContext_1.dispatch({ 10632 type: 'MERGE_EVENTS', 10633 eventStore: mutatedRelevantEvents_1 10634 }); 10635 var eventChangeArg = { 10636 oldEvent: eventApi, 10637 event: updatedEventApi, 10638 relatedEvents: buildEventApis(mutatedRelevantEvents_1, initialContext_1, eventInstance), 10639 revert: function () { 10640 initialContext_1.dispatch({ 10641 type: 'MERGE_EVENTS', 10642 eventStore: relevantEvents_1 // the pre-change data 10643 }); 10644 } 10645 }; 10646 var transformed = {}; 10647 for (var _i = 0, _b = initialContext_1.getCurrentData().pluginHooks.eventDropTransformers; _i < _b.length; _i++) { 10648 var transformer = _b[_i]; 10649 __assign(transformed, transformer(validMutation, initialContext_1)); 10650 } 10651 initialContext_1.emitter.trigger('eventDrop', __assign(__assign(__assign({}, eventChangeArg), transformed), { el: ev.subjectEl, delta: validMutation.datesDelta, jsEvent: ev.origEvent, view: initialView })); 10652 initialContext_1.emitter.trigger('eventChange', eventChangeArg); 10653 // dropped in different calendar 10654 } 10655 else if (receivingContext_1) { 10656 var eventRemoveArg = { 10657 event: eventApi, 10658 relatedEvents: buildEventApis(relevantEvents_1, initialContext_1, eventInstance), 10659 revert: function () { 10660 initialContext_1.dispatch({ 10661 type: 'MERGE_EVENTS', 10662 eventStore: relevantEvents_1 10663 }); 10664 } 10665 }; 10666 initialContext_1.emitter.trigger('eventLeave', __assign(__assign({}, eventRemoveArg), { draggedEl: ev.subjectEl, view: initialView })); 10667 initialContext_1.dispatch({
10668 type: 'REMOVE_EVENTS', 10669 eventStore: relevantEvents_1 10670 }); 10671 initialContext_1.emitter.trigger('eventRemove', eventRemoveArg); 10672 var addedEventDef = mutatedRelevantEvents_1.defs[eventDef.defId]; 10673 var addedEventInstance = mutatedRelevantEvents_1.instances[eventInstance.instanceId]; 10674 var addedEventApi = new EventApi(receivingContext_1, addedEventDef, addedEventInstance); 10675 receivingContext_1.dispatch({ 10676 type: 'MERGE_EVENTS', 10677 eventStore: mutatedRelevantEvents_1 10678 }); 10679 var eventAddArg = { 10680 event: addedEventApi, 10681 relatedEvents: buildEventApis(mutatedRelevantEvents_1, receivingContext_1, addedEventInstance), 10682 revert: function () { 10683 receivingContext_1.dispatch({ 10684 type: 'REMOVE_EVENTS', 10685 eventStore: mutatedRelevantEvents_1 10686 }); 10687 } 10688 }; 10689 receivingContext_1.emitter.trigger('eventAdd', eventAddArg); 10690 if (ev.isTouch) { 10691 receivingContext_1.dispatch({ 10692 type: 'SELECT_EVENT', 10693 eventInstanceId: eventInstance.instanceId 10694 }); 10695 } 10696 receivingContext_1.emitter.trigger('drop', __assign(__assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext_1)), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.component.context.viewApi })); 10697 receivingContext_1.emitter.trigger('eventReceive', __assign(__assign({}, eventAddArg), { draggedEl: ev.subjectEl, view: finalHit.component.context.viewApi })); 10698 } 10699 } 10700 else { 10701 initialContext_1.emitter.trigger('_noEventDrop'); 10702 } 10703 } 10704 _this.cleanup(); 10705 }; 10706 var component = _this.component; 10707 var options = component.context.options; 10708 var dragging = _this.dragging = new FeaturefulElementDragging(settings.el); 10709 dragging.pointer.selector = EventDragging.SELECTOR; 10710 dragging.touchScrollAllowed = false; 10711 dragging.autoScroller.isEnabled = options.dragScroll; 10712 var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, interactionSettingsStore); 10713 hitDragging.useSubjectCenter = settings.useEventCenter; 10714 hitDragging.emitter.on('pointerdown', _this.handlePointerDown); 10715 hitDragging.emitter.on('dragstart', _this.handleDragStart); 10716 hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); 10717 hitDragging.emitter.on('pointerup', _this.handlePointerUp); 10718 hitDragging.emitter.on('dragend', _this.handleDragEnd); 10719 return _this; 10720 } 10721 EventDragging.prototype.destroy = function () { 10722 this.dragging.destroy(); 10723 }; 10724 // render a drag state on the next receivingCalendar 10725 EventDragging.prototype.displayDrag = function (nextContext, state) { 10726 var initialContext = this.component.context; 10727 var prevContext = this.receivingContext; 10728 // does the previous calendar need to be cleared? 10729 if (prevContext && prevContext !== nextContext) { 10730 // does the initial calendar need to be cleared? 10731 // if so, don't clear all the way. we still need to to hide the affectedEvents 10732 if (prevContext === initialContext) { 10733 prevContext.dispatch({ 10734 type: 'SET_EVENT_DRAG', 10735 state: { 10736 affectedEvents: state.affectedEvents, 10737 mutatedEvents: createEmptyEventStore(), 10738 isEvent: true 10739 } 10740 }); 10741 // completely clear the old calendar if it wasn't the initial 10742 } 10743 else { 10744 prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' }); 10745 } 10746 } 10747 if (nextContext) { 10748 nextContext.dispatch({ type: 'SET_EVENT_DRAG', state: state }); 10749 } 10750 }; 10751 EventDragging.prototype.clearDrag = function () { 10752 var initialCalendar = this.component.context; 10753 var receivingContext = this.receivingContext; 10754 if (receivingContext) { 10755 receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' }); 10756 } 10757 // the initial calendar might have an dummy drag state from displayDrag 10758 if (initialCalendar !== receivingContext) { 10759 initialCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); 10760 } 10761 }; 10762 EventDragging.prototype.cleanup = function () { 10763 this.subjectSeg = null; 10764 this.isDragging = false;
10765 this.eventRange = null; 10766 this.relevantEvents = null; 10767 this.receivingContext = null; 10768 this.validMutation = null; 10769 this.mutatedRelevantEvents = null; 10770 }; 10771 // TODO: test this in IE11 10772 // QUESTION: why do we need it on the resizable??? 10773 EventDragging.SELECTOR = '.fc-event-draggable, .fc-event-resizable'; 10774 return EventDragging; 10775 }(Interaction)); 10776 function computeEventMutation(hit0, hit1, massagers) { 10777 var dateSpan0 = hit0.dateSpan; 10778 var dateSpan1 = hit1.dateSpan; 10779 var date0 = dateSpan0.range.start; 10780 var date1 = dateSpan1.range.start; 10781 var standardProps = {}; 10782 if (dateSpan0.allDay !== dateSpan1.allDay) { 10783 standardProps.allDay = dateSpan1.allDay; 10784 standardProps.hasEnd = hit1.component.context.options.allDayMaintainDuration; 10785 if (dateSpan1.allDay) { 10786 // means date1 is already start-of-day, 10787 // but date0 needs to be converted 10788 date0 = startOfDay(date0); 10789 } 10790 } 10791 var delta = diffDates(date0, date1, hit0.component.context.dateEnv, hit0.component === hit1.component ? 10792 hit0.component.largeUnit : 10793 null); 10794 if (delta.milliseconds) { // has hours/minutes/seconds 10795 standardProps.allDay = false; 10796 } 10797 var mutation = { 10798 datesDelta: delta, 10799 standardProps: standardProps 10800 }; 10801 for (var _i = 0, massagers_1 = massagers; _i < massagers_1.length; _i++) { 10802 var massager = massagers_1[_i]; 10803 massager(mutation, hit0, hit1); 10804 } 10805 return mutation; 10806 } 10807 function getComponentTouchDelay$1(component) { 10808 var options = component.context.options; 10809 var delay = options.eventLongPressDelay; 10810 if (delay == null) { 10811 delay = options.longPressDelay; 10812 } 10813 return delay; 10814 } 10815 10816 var EventResizing = /** @class */ (function (_super) { 10817 __extends(EventResizing, _super); 10818 function EventResizing(settings) { 10819 var _this = _super.call(this, settings) || this; 10820 // internal state 10821 _this.draggingSegEl = null; 10822 _this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg? 10823 _this.eventRange = null; 10824 _this.relevantEvents = null; 10825 _this.validMutation = null; 10826 _this.mutatedRelevantEvents = null; 10827 _this.handlePointerDown = function (ev) { 10828 var component = _this.component; 10829 var segEl = _this.querySegEl(ev); 10830 var seg = getElSeg(segEl); 10831 var eventRange = _this.eventRange = seg.eventRange; 10832 _this.dragging.minDistance = component.context.options.eventDragMinDistance; 10833 // if touch, need to be working with a selected event 10834 _this.dragging.setIgnoreMove(!_this.component.isValidSegDownEl(ev.origEvent.target) || 10835 (ev.isTouch && _this.component.props.eventSelection !== eventRange.instance.instanceId)); 10836 }; 10837 _this.handleDragStart = function (ev) { 10838 var context = _this.component.context; 10839 var eventRange = _this.eventRange; 10840 _this.relevantEvents = getRelevantEvents(context.getCurrentData().eventStore, _this.eventRange.instance.instanceId); 10841 var segEl = _this.querySegEl(ev); 10842 _this.draggingSegEl = segEl; 10843 _this.draggingSeg = getElSeg(segEl); 10844 context.calendarApi.unselect(); 10845 context.emitter.trigger('eventResizeStart', { 10846 el: segEl, 10847 event: new EventApi(context, eventRange.def, eventRange.instance), 10848 jsEvent: ev.origEvent, 10849 view: context.viewApi 10850 }); 10851 }; 10852 _this.handleHitUpdate = function (hit, isFinal, ev) { 10853 var context = _this.component.context; 10854 var relevantEvents = _this.relevantEvents; 10855 var initialHit = _this.hitDragging.initialHit; 10856 var eventInstance = _this.eventRange.instance; 10857 var mutation = null; 10858 var mutatedRelevantEvents = null; 10859 var isInvalid = false;
10860 var interaction = { 10861 affectedEvents: relevantEvents, 10862 mutatedEvents: createEmptyEventStore(), 10863 isEvent: true 10864 }; 10865 if (hit) { 10866 mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-event-resizer-start'), eventInstance.range, context.pluginHooks.eventResizeJoinTransforms); 10867 } 10868 if (mutation) { 10869 mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, context.getCurrentData().eventUiBases, mutation, context); 10870 interaction.mutatedEvents = mutatedRelevantEvents; 10871 if (!_this.component.isInteractionValid(interaction)) { 10872 isInvalid = true; 10873 mutation = null; 10874 mutatedRelevantEvents = null; 10875 interaction.mutatedEvents = null; 10876 } 10877 } 10878 if (mutatedRelevantEvents) { 10879 context.dispatch({ 10880 type: 'SET_EVENT_RESIZE', 10881 state: interaction 10882 }); 10883 } 10884 else { 10885 context.dispatch({ type: 'UNSET_EVENT_RESIZE' }); 10886 } 10887 if (!isInvalid) { 10888 enableCursor(); 10889 } 10890 else { 10891 disableCursor(); 10892 } 10893 if (!isFinal) { 10894 if (mutation && isHitsEqual(initialHit, hit)) { 10895 mutation = null; 10896 } 10897 _this.validMutation = mutation; 10898 _this.mutatedRelevantEvents = mutatedRelevantEvents; 10899 } 10900 }; 10901 _this.handleDragEnd = function (ev) { 10902 var context = _this.component.context; 10903 var eventDef = _this.eventRange.def; 10904 var eventInstance = _this.eventRange.instance; 10905 var eventApi = new EventApi(context, eventDef, eventInstance); 10906 var relevantEvents = _this.relevantEvents; 10907 var mutatedRelevantEvents = _this.mutatedRelevantEvents; 10908 context.emitter.trigger('eventResizeStop', { 10909 el: _this.draggingSegEl, 10910 event: eventApi, 10911 jsEvent: ev.origEvent, 10912 view: context.viewApi 10913 }); 10914 if (_this.validMutation) { 10915 var updatedEventApi = new EventApi(context, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null); 10916 context.dispatch({ 10917 type: 'MERGE_EVENTS', 10918 eventStore: mutatedRelevantEvents 10919 }); 10920 var eventChangeArg = { 10921 oldEvent: eventApi, 10922 event: updatedEventApi, 10923 relatedEvents: buildEventApis(mutatedRelevantEvents, context, eventInstance), 10924 revert: function () { 10925 context.dispatch({ 10926 type: 'MERGE_EVENTS', 10927 eventStore: relevantEvents // the pre-change events 10928 }); 10929 } 10930 }; 10931 context.emitter.trigger('eventResize', __assign(__assign({}, eventChangeArg), { el: _this.draggingSegEl, startDelta: _this.validMutation.startDelta || createDuration(0), endDelta: _this.validMutation.endDelta || createDuration(0), jsEvent: ev.origEvent, view: context.viewApi })); 10932 context.emitter.trigger('eventChange', eventChangeArg); 10933 } 10934 else { 10935 context.emitter.trigger('_noEventResize'); 10936 } 10937 // reset all internal state 10938 _this.draggingSeg = null; 10939 _this.relevantEvents = null; 10940 _this.validMutation = null; 10941 // okay to keep eventInstance around. useful to set it in handlePointerDown 10942 }; 10943 var component = settings.component; 10944 var dragging = _this.dragging = new FeaturefulElementDragging(settings.el); 10945 dragging.pointer.selector = '.fc-event-resizer'; 10946 dragging.touchScrollAllowed = false;
10947 dragging.autoScroller.isEnabled = component.context.options.dragScroll; 10948 var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, interactionSettingsToStore(settings)); 10949 hitDragging.emitter.on('pointerdown', _this.handlePointerDown); 10950 hitDragging.emitter.on('dragstart', _this.handleDragStart); 10951 hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); 10952 hitDragging.emitter.on('dragend', _this.handleDragEnd); 10953 return _this; 10954 } 10955 EventResizing.prototype.destroy = function () { 10956 this.dragging.destroy(); 10957 }; 10958 EventResizing.prototype.querySegEl = function (ev) { 10959 return elementClosest(ev.subjectEl, '.fc-event'); 10960 }; 10961 return EventResizing; 10962 }(Interaction)); 10963 function computeMutation(hit0, hit1, isFromStart, instanceRange, transforms) { 10964 var dateEnv = hit0.component.context.dateEnv; 10965 var date0 = hit0.dateSpan.range.start; 10966 var date1 = hit1.dateSpan.range.start; 10967 var delta = diffDates(date0, date1, dateEnv, hit0.component.largeUnit); 10968 var props = {}; 10969 for (var _i = 0, transforms_1 = transforms; _i < transforms_1.length; _i++) { 10970 var transform = transforms_1[_i]; 10971 var res = transform(hit0, hit1); 10972 if (res === false) { 10973 return null; 10974 } 10975 else if (res) { 10976 __assign(props, res); 10977 } 10978 } 10979 if (isFromStart) { 10980 if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) { 10981 props.startDelta = delta; 10982 return props; 10983 } 10984 } 10985 else { 10986 if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) { 10987 props.endDelta = delta; 10988 return props; 10989 } 10990 } 10991 return null; 10992 } 10993 10994 var UnselectAuto = /** @class */ (function () { 10995 function UnselectAuto(context) { 10996 var _this = this; 10997 this.context = context; 10998 this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system 10999 this.matchesCancel = false; 11000 this.matchesEvent = false; 11001 this.onSelect = function (selectInfo) { 11002 if (selectInfo.jsEvent) { 11003 _this.isRecentPointerDateSelect = true; 11004 } 11005 }; 11006 this.onDocumentPointerDown = function (pev) { 11007 var unselectCancel = _this.context.options.unselectCancel; 11008 var downEl = pev.origEvent.target; 11009 _this.matchesCancel = !!elementClosest(downEl, unselectCancel); 11010 _this.matchesEvent = !!elementClosest(downEl, EventDragging.SELECTOR); // interaction started on an event? 11011 }; 11012 this.onDocumentPointerUp = function (pev) { 11013 var context = _this.context; 11014 var documentPointer = _this.documentPointer; 11015 var calendarState = context.getCurrentData(); 11016 // touch-scrolling should never unfocus any type of selection 11017 if (!documentPointer.wasTouchScroll) { 11018 if (calendarState.dateSelection && // an existing date selection? 11019 !_this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp? 11020 ) { 11021 var unselectAuto = context.options.unselectAuto; 11022 if (unselectAuto && (!unselectAuto || !_this.matchesCancel)) { 11023 context.calendarApi.unselect(pev); 11024 } 11025 } 11026 if (calendarState.eventSelection && // an existing event selected? 11027 !_this.matchesEvent // interaction DIDN'T start on an event 11028 ) { 11029 context.dispatch({ type: 'UNSELECT_EVENT' }); 11030 } 11031 } 11032 _this.isRecentPointerDateSelect = false;
11033 }; 11034 var documentPointer = this.documentPointer = new PointerDragging(document); 11035 documentPointer.shouldIgnoreMove = true; 11036 documentPointer.shouldWatchScroll = false; 11037 documentPointer.emitter.on('pointerdown', this.onDocumentPointerDown); 11038 documentPointer.emitter.on('pointerup', this.onDocumentPointerUp); 11039 /* 11040 TODO: better way to know about whether there was a selection with the pointer 11041 */ 11042 context.emitter.on('select', this.onSelect); 11043 } 11044 UnselectAuto.prototype.destroy = function () { 11045 this.context.emitter.off('select', this.onSelect); 11046 this.documentPointer.destroy(); 11047 }; 11048 return UnselectAuto; 11049 }()); 11050 11051 var LISTENER_REFINERS = { 11052 dateClick: identity, 11053 eventDragStart: identity, 11054 eventDragStop: identity, 11055 eventDrop: identity, 11056 eventResizeStart: identity, 11057 eventResizeStop: identity, 11058 eventResize: identity, 11059 drop: identity, 11060 eventReceive: identity, 11061 eventLeave: identity 11062 }; 11063 11064 /* 11065 Given an already instantiated draggable object for one-or-more elements, 11066 Interprets any dragging as an attempt to drag an events that lives outside 11067 of a calendar onto a calendar. 11068 */ 11069 var ExternalElementDragging = /** @class */ (function () { 11070 function ExternalElementDragging(dragging, suppliedDragMeta) { 11071 var _this = this; 11072 this.receivingContext = null; 11073 this.droppableEvent = null; // will exist for all drags, even if create:false 11074 this.suppliedDragMeta = null; 11075 this.dragMeta = null; 11076 this.handleDragStart = function (ev) { 11077 _this.dragMeta = _this.buildDragMeta(ev.subjectEl); 11078 }; 11079 this.handleHitUpdate = function (hit, isFinal, ev) { 11080 var dragging = _this.hitDragging.dragging; 11081 var receivingContext = null; 11082 var droppableEvent = null; 11083 var isInvalid = false; 11084 var interaction = { 11085 affectedEvents: createEmptyEventStore(), 11086 mutatedEvents: createEmptyEventStore(), 11087 isEvent: _this.dragMeta.create 11088 }; 11089 if (hit) { 11090 receivingContext = hit.component.context; 11091 if (_this.canDropElOnCalendar(ev.subjectEl, receivingContext)) { 11092 droppableEvent = computeEventForDateSpan(hit.dateSpan, _this.dragMeta, receivingContext); 11093 interaction.mutatedEvents = eventTupleToStore(droppableEvent); 11094 isInvalid = !isInteractionValid(interaction, receivingContext); 11095 if (isInvalid) { 11096 interaction.mutatedEvents = createEmptyEventStore(); 11097 droppableEvent = null; 11098 } 11099 } 11100 } 11101 _this.displayDrag(receivingContext, interaction); 11102 // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?) 11103 // TODO: wish we could somehow wait for dispatch to guarantee render 11104 dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-event-mirror')); 11105 if (!isInvalid) { 11106 enableCursor(); 11107 } 11108 else { 11109 disableCursor(); 11110 } 11111 if (!isFinal) { 11112 dragging.setMirrorNeedsRevert(!droppableEvent); 11113 _this.receivingContext = receivingContext; 11114 _this.droppableEvent = droppableEvent; 11115 } 11116 }; 11117 this.handleDragEnd = function (pev) { 11118 var _a = _this, receivingContext = _a.receivingContext, droppableEvent = _a.droppableEvent; 11119 _this.clearDrag(); 11120 if (receivingContext && droppableEvent) { 11121 var finalHit = _this.hitDragging.finalHit; 11122 var finalView = finalHit.component.context.viewApi; 11123 var dragMeta = _this.dragMeta; 11124 receivingContext.emitter.trigger('drop', __assign(__assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView })); 11125 if (dragMeta.create) { 11126 var addingEvents_1 = eventTupleToStore(droppableEvent); 11127 receivingContext.dispatch({ 11128 type: 'MERGE_EVENTS', 11129 eventStore: addingEvents_1 11130 }); 11131 if (pev.isTouch) { 11132 receivingContext.dispatch({ 11133 type: 'SELECT_EVENT', 11134 eventInstanceId: droppableEvent.instance.instanceId 11135 }); 11136 } 11137 // signal that an external event landed 11138 receivingContext.emitter.trigger('eventReceive', { 11139 event: new EventApi(receivingContext, droppableEvent.def, droppableEvent.instance), 11140 relatedEvents: [], 11141 revert: function () { 11142 receivingContext.dispatch({
11143 type: 'REMOVE_EVENTS', 11144 eventStore: addingEvents_1 11145 }); 11146 }, 11147 draggedEl: pev.subjectEl, 11148 view: finalView 11149 }); 11150 } 11151 } 11152 _this.receivingContext = null; 11153 _this.droppableEvent = null; 11154 }; 11155 var hitDragging = this.hitDragging = new HitDragging(dragging, interactionSettingsStore); 11156 hitDragging.requireInitial = false; // will start outside of a component 11157 hitDragging.emitter.on('dragstart', this.handleDragStart); 11158 hitDragging.emitter.on('hitupdate', this.handleHitUpdate); 11159 hitDragging.emitter.on('dragend', this.handleDragEnd); 11160 this.suppliedDragMeta = suppliedDragMeta; 11161 } 11162 ExternalElementDragging.prototype.buildDragMeta = function (subjectEl) { 11163 if (typeof this.suppliedDragMeta === 'object') { 11164 return parseDragMeta(this.suppliedDragMeta); 11165 } 11166 else if (typeof this.suppliedDragMeta === 'function') { 11167 return parseDragMeta(this.suppliedDragMeta(subjectEl)); 11168 } 11169 else { 11170 return getDragMetaFromEl(subjectEl); 11171 } 11172 }; 11173 ExternalElementDragging.prototype.displayDrag = function (nextContext, state) { 11174 var prevContext = this.receivingContext; 11175 if (prevContext && prevContext !== nextContext) { 11176 prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' }); 11177 } 11178 if (nextContext) { 11179 nextContext.dispatch({ type: 'SET_EVENT_DRAG', state: state }); 11180 } 11181 }; 11182 ExternalElementDragging.prototype.clearDrag = function () { 11183 if (this.receivingContext) { 11184 this.receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' }); 11185 } 11186 }; 11187 ExternalElementDragging.prototype.canDropElOnCalendar = function (el, receivingContext) { 11188 var dropAccept = receivingContext.options.dropAccept; 11189 if (typeof dropAccept === 'function') { 11190 return dropAccept.call(receivingContext.calendarApi, el); 11191 } 11192 else if (typeof dropAccept === 'string' && dropAccept) { 11193 return Boolean(elementMatches(el, dropAccept)); 11194 } 11195 return true; 11196 }; 11197 return ExternalElementDragging; 11198 }()); 11199 // Utils for computing event store from the DragMeta 11200 // ---------------------------------------------------------------------------------------------------- 11201 function computeEventForDateSpan(dateSpan, dragMeta, context) { 11202 var defProps = __assign({}, dragMeta.leftoverProps); 11203 for (var _i = 0, _a = context.pluginHooks.externalDefTransforms; _i < _a.length; _i++) { 11204 var transform = _a[_i]; 11205 __assign(defProps, transform(dateSpan, dragMeta)); 11206 } 11207 var _b = refineEventDef(defProps, context), refined = _b.refined, extra = _b.extra; 11208 var def = parseEventDef(refined, extra, dragMeta.sourceId, dateSpan.allDay, context.options.forceEventDuration || Boolean(dragMeta.duration), // hasEnd 11209 context); 11210 var start = dateSpan.range.start; 11211 // only rely on time info if drop zone is all-day, 11212 // otherwise, we already know the time 11213 if (dateSpan.allDay && dragMeta.startTime) { 11214 start = context.dateEnv.add(start, dragMeta.startTime); 11215 } 11216 var end = dragMeta.duration ? 11217 context.dateEnv.add(start, dragMeta.duration) : 11218 getDefaultEventEnd(dateSpan.allDay, start, context); 11219 var instance = createEventInstance(def.defId, { start: start, end: end }); 11220 return { def: def, instance: instance }; 11221 } 11222 // Utils for extracting data from element 11223 // ---------------------------------------------------------------------------------------------------- 11224 function getDragMetaFromEl(el) { 11225 var str = getEmbeddedElData(el, 'event'); 11226 var obj = str ? 11227 JSON.parse(str) : 11228 { create: false }; // if no embedded data, assume no event creation 11229 return parseDragMeta(obj); 11230 } 11231 config.dataAttrPrefix = ''; 11232 function getEmbeddedElData(el, name) { 11233 var prefix = config.dataAttrPrefix; 11234 var prefixedName = (prefix ? prefix + '-' : '') + name; 11235 return el.getAttribute('data-' + prefixedName) || ''; 11236 } 11237 11238 /* 11239 Makes an element (that is *external* to any calendar) draggable. 11240 Can pass in data that determines how an event will be created when dropped onto a calendar. 11241 Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system. 11242 */
11243 var ExternalDraggable = /** @class */ (function () { 11244 function ExternalDraggable(el, settings) { 11245 var _this = this; 11246 if (settings === void 0) { settings = {}; } 11247 this.handlePointerDown = function (ev) { 11248 var dragging = _this.dragging; 11249 var _a = _this.settings, minDistance = _a.minDistance, longPressDelay = _a.longPressDelay; 11250 dragging.minDistance = 11251 minDistance != null ? 11252 minDistance : 11253 (ev.isTouch ? 0 : BASE_OPTION_DEFAULTS.eventDragMinDistance); 11254 dragging.delay = 11255 ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv 11256 (longPressDelay != null ? longPressDelay : BASE_OPTION_DEFAULTS.longPressDelay) : 11257 0; 11258 }; 11259 this.handleDragStart = function (ev) { 11260 if (ev.isTouch && 11261 _this.dragging.delay && 11262 ev.subjectEl.classList.contains('fc-event')) { 11263 _this.dragging.mirror.getMirrorEl().classList.add('fc-event-selected'); 11264 } 11265 }; 11266 this.settings = settings; 11267 var dragging = this.dragging = new FeaturefulElementDragging(el); 11268 dragging.touchScrollAllowed = false; 11269 if (settings.itemSelector != null) { 11270 dragging.pointer.selector = settings.itemSelector; 11271 } 11272 if (settings.appendTo != null) { 11273 dragging.mirror.parentNode = settings.appendTo; // TODO: write tests 11274 } 11275 dragging.emitter.on('pointerdown', this.handlePointerDown); 11276 dragging.emitter.on('dragstart', this.handleDragStart); 11277 new ExternalElementDragging(dragging, settings.eventData); 11278 } 11279 ExternalDraggable.prototype.destroy = function () { 11280 this.dragging.destroy(); 11281 }; 11282 return ExternalDraggable; 11283 }()); 11284 11285 /* 11286 Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements. 11287 The third-party system is responsible for drawing the visuals effects of the drag. 11288 This class simply monitors for pointer movements and fires events. 11289 It also has the ability to hide the moving element (the "mirror") during the drag. 11290 */ 11291 var InferredElementDragging = /** @class */ (function (_super) { 11292 __extends(InferredElementDragging, _super); 11293 function InferredElementDragging(containerEl) { 11294 var _this = _super.call(this, containerEl) || this; 11295 _this.shouldIgnoreMove = false; 11296 _this.mirrorSelector = ''; 11297 _this.currentMirrorEl = null; 11298 _this.handlePointerDown = function (ev) { 11299 _this.emitter.trigger('pointerdown', ev); 11300 if (!_this.shouldIgnoreMove) { 11301 // fire dragstart right away. does not support delay or min-distance 11302 _this.emitter.trigger('dragstart', ev); 11303 } 11304 }; 11305 _this.handlePointerMove = function (ev) { 11306 if (!_this.shouldIgnoreMove) { 11307 _this.emitter.trigger('dragmove', ev); 11308 } 11309 }; 11310 _this.handlePointerUp = function (ev) { 11311 _this.emitter.trigger('pointerup', ev); 11312 if (!_this.shouldIgnoreMove) { 11313 // fire dragend right away. does not support a revert animation 11314 _this.emitter.trigger('dragend', ev); 11315 } 11316 }; 11317 var pointer = _this.pointer = new PointerDragging(containerEl); 11318 pointer.emitter.on('pointerdown', _this.handlePointerDown); 11319 pointer.emitter.on('pointermove', _this.handlePointerMove); 11320 pointer.emitter.on('pointerup', _this.handlePointerUp); 11321 return _this; 11322 } 11323 InferredElementDragging.prototype.destroy = function () { 11324 this.pointer.destroy(); 11325 }; 11326 InferredElementDragging.prototype.setIgnoreMove = function (bool) { 11327 this.shouldIgnoreMove = bool; 11328 }; 11329 InferredElementDragging.prototype.setMirrorIsVisible = function (bool) { 11330 if (bool) { 11331 // restore a previously hidden element. 11332 // use the reference in case the selector class has already been removed. 11333 if (this.currentMirrorEl) { 11334 this.currentMirrorEl.style.visibility = ''; 11335 this.currentMirrorEl = null; 11336 } 11337 } 11338 else { 11339 var mirrorEl = this.mirrorSelector ? 11340 document.querySelector(this.mirrorSelector) : 11341 null; 11342 if (mirrorEl) { 11343 this.currentMirrorEl = mirrorEl; 11344 mirrorEl.style.visibility = 'hidden'; 11345 } 11346 } 11347 }; 11348 return InferredElementDragging; 11349 }(ElementDragging)); 11350 11351 /* 11352 Bridges third-party drag-n-drop systems with FullCalendar. 11353 Must be instantiated and destroyed by caller. 11354 */ 11355 var ThirdPartyDraggable = /** @class */ (function () { 11356 function ThirdPartyDraggable(containerOrSettings, settings) { 11357 var containerEl = document; 11358 if ( 11359 // wish we could just test instanceof EventTarget, but doesn't work in IE11 11360 containerOrSettings === document || 11361 containerOrSettings instanceof Element) { 11362 containerEl = containerOrSettings; 11363 settings = settings || {}; 11364 } 11365 else { 11366 settings = (containerOrSettings || {}); 11367 } 11368 var dragging = this.dragging = new InferredElementDragging(containerEl); 11369 if (typeof settings.itemSelector === 'string') { 11370 dragging.pointer.selector = settings.itemSelector; 11371 } 11372 else if (containerEl === document) { 11373 dragging.pointer.selector = '[data-event]'; 11374 } 11375 if (typeof settings.mirrorSelector === 'string') { 11376 dragging.mirrorSelector = settings.mirrorSelector; 11377 } 11378 new ExternalElementDragging(dragging, settings.eventData); 11379 } 11380 ThirdPartyDraggable.prototype.destroy = function () { 11381 this.dragging.destroy(); 11382 }; 11383 return ThirdPartyDraggable; 11384 }()); 11385 11386 var interactionPlugin = createPlugin({ 11387 componentInteractions: [DateClicking, DateSelecting, EventDragging, EventResizing], 11388 calendarInteractions: [UnselectAuto], 11389 elementDraggingImpl: FeaturefulElementDragging, 11390 listenerRefiners: LISTENER_REFINERS 11391 }); 11392 11393 /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells. 11394 ----------------------------------------------------------------------------------------------------------------------*/ 11395 // It is a manager for a Table subcomponent, which does most of the heavy lifting. 11396 // It is responsible for managing width/height. 11397 var TableView = /** @class */ (function (_super) { 11398 __extends(TableView, _super); 11399 function TableView() { 11400 var _this = _super !== null && _super.apply(this, arguments) || this; 11401 _this.headerElRef = createRef(); 11402 return _this; 11403 } 11404 TableView.prototype.renderSimpleLayout = function (headerRowContent, bodyContent) { 11405 var _a = this, props = _a.props, context = _a.context; 11406 var sections = []; 11407 var stickyHeaderDates = getStickyHeaderDates(context.options); 11408 if (headerRowContent) { 11409 sections.push({ 11410 type: 'header', 11411 key: 'header', 11412 isSticky: stickyHeaderDates, 11413 chunk: { 11414 elRef: this.headerElRef, 11415 tableClassName: 'fc-col-header', 11416 rowContent: headerRowContent 11417 } 11418 }); 11419 } 11420 sections.push({ 11421 type: 'body', 11422 key: 'body', 11423 liquid: true, 11424 chunk: { content: bodyContent } 11425 }); 11426 return (createElement(ViewRoot, { viewSpec: context.viewSpec }, function (rootElRef, classNames) { return (createElement("div", { ref: rootElRef, className: ['fc-daygri
11426d'].concat(classNames).join(' ') }, 11427 createElement(SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, cols: [] /* TODO: make optional? */, sections: sections }))); })); 11428 }; 11429 TableView.prototype.renderHScrollLayout = function (headerRowContent, bodyContent, colCnt, dayMinWidth) { 11430 var ScrollGrid = this.context.pluginHooks.scrollGridImpl; 11431 if (!ScrollGrid) { 11432 throw new Error('No ScrollGrid implementation'); 11433 } 11434 var _a = this, props = _a.props, context = _a.context; 11435 var stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options); 11436 var stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options); 11437 var sections = []; 11438 if (headerRowContent) { 11439 sections.push({ 11440 type: 'header', 11441 key: 'header', 11442 isSticky: stickyHeaderDates, 11443 chunks: [{ 11444 key: 'main', 11445 elRef: this.headerElRef, 11446 tableClassName: 'fc-col-header', 11447 rowContent: headerRowContent 11448 }] 11449 }); 11450 } 11451 sections.push({ 11452 type: 'body', 11453 key: 'body', 11454 liquid: true, 11455 chunks: [{ 11456 key: 'main', 11457 content: bodyContent 11458 }] 11459 }); 11460 if (stickyFooterScrollbar) { 11461 sections.push({ 11462 type: 'footer', 11463 key: 'footer', 11464 isSticky: true, 11465 chunks: [{ 11466 key: 'main', 11467 content: renderScrollShim 11468 }] 11469 }); 11470 } 11471 return (createElement(ViewRoot, { viewSpec: context.viewSpec }, function (rootElRef, classNames) { return (createElement("div", { ref: rootElRef, className: ['fc-daygrid'].concat(classNames).join(' ') }, 11472 createElement(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }], sections: sections }))); })); 11473 }; 11474 return TableView; 11475 }(DateComponent)); 11476 11477 function splitSegsByRow(segs, rowCnt) { 11478 var byRow = []; 11479 for (var i = 0; i < rowCnt; i++) { 11480 byRow[i] = []; 11481 } 11482 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 11483 var seg = segs_1[_i]; 11484 byRow[seg.row].push(seg); 11485 } 11486 return byRow; 11487 } 11488 function splitSegsByFirstCol(segs, colCnt) { 11489 var byCol = []; 11490 for (var i = 0; i < colCnt; i++) { 11491 byCol[i] = []; 11492 } 11493 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 11494 var seg = segs_2[_i]; 11495 byCol[seg.firstCol].push(seg); 11496 } 11497 return byCol; 11498 } 11499 function splitInteractionByRow(ui, rowCnt) { 11500 var byRow = []; 11501 if (!ui) { 11502 for (var i = 0; i < rowCnt; i++) { 11503 byRow[i] = null; 11504 } 11505 } 11506 else { 11507 for (var i = 0; i < rowCnt; i++) { 11508 byRow[i] = { 11509 affectedInstances: ui.affectedInstances, 11510 isEvent: ui.isEvent, 11511 segs: [] 11512 }; 11513 } 11514 for (var _i = 0, _a = ui.segs; _i < _a.length; _i++) { 11515 var seg = _a[_i]; 11516 byRow[seg.row].segs.push(seg); 11517 } 11518 } 11519 return byRow; 11520 } 11521 11522 var DEFAULT_WEEK_NUM_FORMAT = createFormatter({ week: 'narrow' }); 11523 var TableCell = /** @class */ (function (_super) { 11524 __extends(TableCell, _super); 11525 function TableCell() { 11526 var _this = _super !== null && _super.apply(this, arguments) || this; 11527 _this.handleRootEl = function (el) { 11528 _this.rootEl = el; 11529 setRef(_this.props.elRef, el); 11530 }; 11531 _this.handleMoreLinkClick = function (ev) { 11532 var props = _this.props; 11533 if (props.onMoreClick) { 11534 var allSegs = props.segsByEachCol; 11535 var hiddenSegs = allSegs.filter(function (seg) { return props.segIsHidden[seg.eventRange.instance.instanceId]; }); 11536 props.onMoreClick({ 11537 date: props.date, 11538 allSegs: allSegs, 11539 hiddenSegs: hiddenSegs, 11540 moreCnt: props.moreCnt, 11541 dayEl: _this.rootEl, 11542 ev: ev 11543 }); 11544 } 11545 }; 11546 return _this; 11547 } 11548 TableCell.prototype.render = function () { 11549 var _this = this; 11550 var _a = this.context, options = _a.options, viewApi = _a.viewApi; 11551 var props = this.props; 11552 var date = props.date, dateProfile = props.dateProfile; 11553 var hookProps = { 11554 num: props.moreCnt, 11555 text: props.buildMoreLinkText(props.moreCnt), 11556 view: viewApi 11557 }; 11558 var navLinkAttrs = options.navLinks 11559 ? { 'data-navlink': buildNavLinkData(date, 'week'), tabIndex: 0 } 11560 : {}; 11561 return (createElement(DayCellRoot, { date: date, dateProfile: dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, extraHookProps: props.extraHookProps, elRef: this.handleRootEl }, function (rootElRef, classNames, rootDataAttrs, isDisabled) { return (createElement("td", __assign({ ref: rootElRef, className: ['fc-daygri
11561d-day'].concat(classNames, props.extraClassNames || []).join(' ') }, rootDataAttrs, props.extraDataAttrs), 11562 createElement("div", { className: 'fc-daygrid-day-frame fc-scrollgrid-sync-inner', ref: props.innerElRef /* different from hook system! RENAME */ }, 11563 props.showWeekNumber && 11564 createElement(WeekNumberRoot, { date: date, defaultFormat: DEFAULT_WEEK_NUM_FORMAT }, function (rootElRef, classNames, innerElRef, innerContent) { return (createElement("a", __assign({ ref: rootElRef, className: ['fc-daygrid-week-number'].concat(classNames).join(' ') }, navLinkAttrs), innerContent)); }), 11565 !isDisabled && 11566 createElement(TableCellTop, { date: date, dateProfile: dateProfile, showDayNumber: props.showDayNumber, forceDayTop: props.forceDayTop, todayRange: props.todayRange, extraHookProps: props.extraHookProps }), 11567 createElement("div", { className: 'fc-daygrid-day-events', ref: props.fgContentElRef, style: { paddingBottom: props.fgPaddingBottom } }, 11568 props.fgContent, 11569 Boolean(props.moreCnt) && 11570 createElement("div", { className: 'fc-daygrid-day-bottom', style: { marginTop: props.moreMarginTop } }, 11571 createElement(RenderHook, { hookProps: hookProps, classNames: options.moreLinkClassNames, content: options.moreLinkContent, defaultContent: renderMoreLinkInner, didMount: options.moreLinkDidMount, willUnmount: options.moreLinkWillUnmount }, function (rootElRef, classNames, innerElRef, innerContent) { return (createElement("a", { onClick: _this.handleMoreLinkClick, ref: rootElRef, className: ['fc-daygrid-more-link'].concat(classNames).join(' ') }, innerContent)); }))), 11572 createElement("div", { className: 'fc-daygrid-day-bg' }, props.bgContent)))); })); 11573 }; 11574 return TableCell; 11575 }(DateComponent)); 11576 function renderTopInner(props) { 11577 return props.dayNumberText; 11578 } 11579 function renderMoreLinkInner(props) { 11580 return props.text; 11581 } 11582 var TableCellTop = /** @class */ (function (_super) { 11583 __extends(TableCellTop, _super); 11584 function TableCellTop() { 11585 return _super !== null && _super.apply(this, arguments) || this; 11586 } 11587 TableCellTop.prototype.render = function () { 11588 var props = this.props; 11589 var navLinkAttrs = this.context.options.navLinks 11590 ? { 'data-navlink': buildNavLinkData(props.date), tabIndex: 0 } 11591 : {}; 11592 return (createElement(DayCellContent, { date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, extraHookProps: props.extraHookProps, defaultContent: renderTopInner }, function (innerElRef, innerContent) { return ((innerContent || props.forceDayTop) && 11593 createElement("div", { className: 'fc-daygrid-day-top', ref: innerElRef }, 11594 createElement("a", __assign({ className: 'fc-daygrid-day-number' }, navLinkAttrs), innerContent || createElement(Fragment, null, "\u00A0")))); })); 11595 }; 11596 return TableCellTop; 11597 }(BaseComponent)); 11598 11599 var DEFAULT_TABLE_EVENT_TIME_FORMAT = createFormatter({ 11600 hour: 'numeric', 11601 minute: '2-digit', 11602 omitZeroMinute: true, 11603 meridiem: 'narrow' 11604 }); 11605 function hasListItemDisplay(seg) { 11606 var display = seg.eventRange.ui.display; 11607 return display === 'list-item' || (display === 'auto' && 11608 !seg.eventRange.def.allDay && 11609 seg.firstCol === seg.lastCol && // can't be multi-day 11610 seg.isStart && // " 11611 seg.isEnd // " 11612 ); 11613 } 11614 11615 var TableListItemEvent = /** @class */ (function (_super) { 11616 __extends(TableListItemEvent, _super); 11617 function TableListItemEvent() { 11618 return _super !== null && _super.apply(this, arguments) || this; 11619 } 11620 TableListItemEvent.prototype.render = function () { 11621 var _a = this, props = _a.props, context = _a.context; 11622 var timeFormat = context.options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT; 11623 var timeText = buildSegTimeText(props.seg, timeFormat, context, true, props.defaultDisplayEventEnd); 11624 return (createElement(EventRoot, { seg: props.seg, timeText: timeText, defaultContent: renderInnerContent$2, isDragging: props.isDragging, isResizing: false, isDateSelecting: false, isSelected: props.isSelected, isPast: props.isPast, isFuture: props.isFuture, isToday: props.isToday }, function (rootElRef, classNames, innerElRef, innerContent) { return ( // we don't use styles! 11625 createElement("a", __assign({ className: ['fc-daygri
11625d-event', 'fc-daygrid-dot-event'].concat(classNames).join(' '), ref: rootElRef }, getSegAnchorAttrs$1(props.seg)), innerContent)); })); 11626 }; 11627 return TableListItemEvent; 11628 }(BaseComponent)); 11629 function renderInnerContent$2(innerProps) { 11630 return (createElement(Fragment, null, 11631 createElement("div", { className: 'fc-daygrid-event-dot', style: { borderColor: innerProps.borderColor || innerProps.backgroundColor } }), 11632 innerProps.timeText && 11633 createElement("div", { className: 'fc-event-time' }, innerProps.timeText), 11634 createElement("div", { className: 'fc-event-title' }, innerProps.event.title || createElement(Fragment, null, "\u00A0")))); 11635 } 11636 function getSegAnchorAttrs$1(seg) { 11637 var url = seg.eventRange.def.url; 11638 return url ? { href: url } : {}; 11639 } 11640 11641 var TableBlockEvent = /** @class */ (function (_super) { 11642 __extends(TableBlockEvent, _super); 11643 function TableBlockEvent() { 11644 return _super !== null && _super.apply(this, arguments) || this; 11645 } 11646 TableBlockEvent.prototype.render = function () { 11647 var props = this.props; 11648 return (createElement(StandardEvent, __assign({}
11648, props, { extraClassNames: ['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 }))); 11649 }; 11650 return TableBlockEvent; 11651 }(BaseComponent)); 11652 11653 function computeFgSegPlacement(// for one row. TODO: print mode? 11654 cellModels, segs, dayMaxEvents, dayMaxEventRows, eventHeights, maxContentHeight, colCnt, eventOrderSpecs) { 11655 var colPlacements = []; // if event spans multiple cols, its present in each col 11656 var moreCnts = []; // by-col 11657 var segIsHidden = {}; 11658 var segTops = {}; // always populated for each seg 11659 var segMarginTops = {}; // simetimes populated for each seg 11660 var moreTops = {}; 11661 var paddingBottoms = {}; // for each cell's inner-wrapper div 11662 for (var i = 0; i < colCnt; i++) { 11663 colPlacements.push([]); 11664 moreCnts.push(0); 11665 } 11666 segs = sortEventSegs(segs, eventOrderSpecs); 11667 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 11668 var seg = segs_1[_i]; 11669 var instanceId = seg.eventRange.instance.instanceId; 11670 var eventHeight = eventHeights[instanceId + ':' + seg.firstCol]; 11671 placeSeg(seg, eventHeight || 0); // will keep colPlacements sorted by top 11672 } 11673 if (dayMaxEvents === true || dayMaxEventRows === true) { 11674 limitByMaxHeight(moreCnts, segIsHidden, colPlacements, maxContentHeight); // populates moreCnts/segIsHidden 11675 } 11676 else if (typeof dayMaxEvents === 'number') { 11677 limitByMaxEvents(moreCnts, segIsHidden, colPlacements, dayMaxEvents); // populates moreCnts/segIsHidden 11678 } 11679 else if (typeof dayMaxEventRows === 'number') { 11680 limitByMaxRows(moreCnts, segIsHidden, colPlacements, dayMaxEventRows); // populates moreCnts/segIsHidden 11681 } 11682 // computes segTops/segMarginTops/moreTops/paddingBottoms 11683 for (var col = 0; col < colCnt; col++) { 11684 var placements = colPlacements[col]; 11685 var currentNonAbsBottom = 0; 11686 var runningAbsHeight = 0; 11687 for (var _a = 0, placements_1 = placements; _a < placements_1.length; _a++) { 11688 var placement = placements_1[_a]; 11689 var seg = placement.seg; 11690 if (!segIsHidden[seg.eventRange.instance.instanceId]) { 11691 segTops[seg.eventRange.instance.instanceId] = placement.top; // from top of container 11692 if (seg.firstCol === seg.lastCol && seg.isStart && seg.isEnd) { // TODO: simpler way? NOT DRY 11693 segMarginTops[seg.eventRange.instance.instanceId] = 11694 placement.top - currentNonAbsBottom; // from previous seg bottom 11695 runningAbsHeight = 0; 11696 currentNonAbsBottom = placement.bottom; 11697 } 11698 else { // multi-col event, abs positioned 11699 runningAbsHeight += placement.bottom - placement.top; 11700 } 11701 } 11702 } 11703 if (runningAbsHeight) { 11704 if (moreCnts[col]) { 11705 moreTops[col] = runningAbsHeight; 11706 } 11707 else { 11708 paddingBottoms[col] = runningAbsHeight; 11709 } 11710 } 11711 } 11712 function placeSeg(seg, segHeight) { 11713 if (!tryPlaceSegAt(seg, segHeight, 0)) { 11714 for (var col = seg.firstCol; col <= seg.lastCol; col++) { 11715 for (var _i = 0, _a = colPlacements[col]; _i < _a.length; _i++) { // will repeat multi-day segs!!!!!!! bad!!!!!! 11716 var placement = _a[_i]; 11717 if (tryPlaceSegAt(seg, segHeight, placement.bottom)) { 11718 return; 11719 } 11720 } 11721 } 11722 } 11723 } 11724 function tryPlaceSegAt(seg, segHeight, top) { 11725 if (canPlaceSegAt(seg, segHeight, top)) {
11726 for (var col = seg.firstCol; col <= seg.lastCol; col++) { 11727 var placements = colPlacements[col]; 11728 var insertionIndex = 0; 11729 while (insertionIndex < placements.length && 11730 top >= placements[insertionIndex].top) { 11731 insertionIndex++; 11732 } 11733 placements.splice(insertionIndex, 0, { 11734 seg: seg, 11735 top: top, 11736 bottom: top + segHeight 11737 }); 11738 } 11739 return true; 11740 } 11741 else { 11742 return false; 11743 } 11744 } 11745 function canPlaceSegAt(seg, segHeight, top) { 11746 for (var col = seg.firstCol; col <= seg.lastCol; col++) { 11747 for (var _i = 0, _a = colPlacements[col]; _i < _a.length; _i++) { 11748 var placement = _a[_i]; 11749 if (top < placement.bottom && top + segHeight > placement.top) { // collide? 11750 return false; 11751 } 11752 } 11753 } 11754 return true; 11755 } 11756 // what does this do!? 11757 for (var instanceIdAndFirstCol in eventHeights) { 11758 if (!eventHeights[instanceIdAndFirstCol]) { 11759 segIsHidden[instanceIdAndFirstCol.split(':')[0]] = true; 11760 } 11761 } 11762 var segsByFirstCol = colPlacements.map(extractFirstColSegs); // operates on the sorted cols 11763 var segsByEachCol = colPlacements.map(function (placements, col) { 11764 var segs = extractAllColSegs(placements); 11765 segs = resliceDaySegs(segs, cellModels[col].date, col); 11766 return segs; 11767 }); 11768 return { 11769 segsByFirstCol: segsByFirstCol, 11770 segsByEachCol: segsByEachCol, 11771 segIsHidden: segIsHidden, 11772 segTops: segTops, 11773 segMarginTops: segMarginTops, 11774 moreCnts: moreCnts, 11775 moreTops: moreTops, 11776 paddingBottoms: paddingBottoms 11777 }; 11778 } 11779 function extractFirstColSegs(oneColPlacements, col) { 11780 var segs = []; 11781 for (var _i = 0, oneColPlacements_1 = oneColPlacements; _i < oneColPlacements_1.length; _i++) { 11782 var placement = oneColPlacements_1[_i]; 11783 if (placement.seg.firstCol === col) { 11784 segs.push(placement.seg); 11785 } 11786 } 11787 return segs; 11788 } 11789 function extractAllColSegs(oneColPlacements) { 11790 var segs = []; 11791 for (var _i = 0, oneColPlacements_2 = oneColPlacements; _i < oneColPlacements_2.length; _i++) { 11792 var placement = oneColPlacements_2[_i]; 11793 segs.push(placement.seg); 11794 } 11795 return segs; 11796 } 11797 function limitByMaxHeight(hiddenCnts, segIsHidden, colPlacements, maxContentHeight) { 11798 limitEvents(hiddenCnts, segIsHidden, colPlacements, true, function (placement) { 11799 return placement.bottom <= maxContentHeight; 11800 }); 11801 } 11802 function limitByMaxEvents(hiddenCnts, segIsHidden, colPlacements, dayMaxEvents) { 11803 limitEvents(hiddenCnts, segIsHidden, colPlacements, false, function (placement, levelIndex) { 11804 return levelIndex < dayMaxEvents; 11805 }); 11806 } 11807 function limitByMaxRows(hiddenCnts, segIsHidden, colPlacements, dayMaxEventRows) { 11808 limitEvents(hiddenCnts, segIsHidden, colPlacements, true, function (placement, levelIndex) { 11809 return levelIndex < dayMaxEventRows; 11810 }); 11811 } 11812 /* 11813 populates the given hiddenCnts/segIsHidden, which are supplied empty. 11814 TODO: return them instead 11815 */ 11816 function limitEvents(hiddenCnts, segIsHidden, colPlacements, moreLinkConsumesLevel, isPlacementInBounds) { 11817 var colCnt = hiddenCnts.length; 11818 var segIsVisible = {}; // TODO: instead, use segIsHidden with true/false? 11819 var visibleColPlacements = []; // will mirror colPlacements 11820 for (var col = 0; col < colCnt; col++) { 11821 visibleColPlacements.push([]); 11822 } 11823 for (var col = 0; col < colCnt; col++) { 11824 var placements = colPlacements[col]; 11825 var level = 0; 11826 for (var _i = 0, placements_2 = placements; _i < placements_2.length; _i++) { 11827 var placement = placements_2[_i]; 11828 if (isPlacementInBounds(placement, level)) { 11829 recordVisible(placement); 11830 } 11831 else { 11832 recordHidden(placement); 11833 } 11834 // only considered a level if the seg had height 11835 if (placement.top !== placement.bottom) { 11836 level++; 11837 } 11838 } 11839 } 11840 function recordVisible(placement) { 11841 var seg = placement.seg; 11842 var instanceId = seg.eventRange.instance.instanceId; 11843 if (!segIsVisible[instanceId]) { 11844 segIsVisible[instanceId] = true;
11845 for (var col = seg.firstCol; col <= seg.lastCol; col++) { 11846 visibleColPlacements[col].push(placement); 11847 } 11848 } 11849 } 11850 function recordHidden(placement) { 11851 var seg = placement.seg; 11852 var instanceId = seg.eventRange.instance.instanceId; 11853 if (!segIsHidden[instanceId]) { 11854 segIsHidden[instanceId] = true; 11855 for (var col = seg.firstCol; col <= seg.lastCol; col++) { 11856 var hiddenCnt = ++hiddenCnts[col]; 11857 if (moreLinkConsumesLevel && hiddenCnt === 1) { 11858 var lastVisiblePlacement = visibleColPlacements[col].pop(); 11859 if (lastVisiblePlacement) { 11860 recordHidden(lastVisiblePlacement); 11861 } 11862 } 11863 } 11864 } 11865 } 11866 } 11867 // Given the events within an array of segment objects, reslice them to be in a single day 11868 function resliceDaySegs(segs, dayDate, colIndex) { 11869 var dayStart = dayDate; 11870 var dayEnd = addDays(dayStart, 1); 11871 var dayRange = { start: dayStart, end: dayEnd }; 11872 var newSegs = []; 11873 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 11874 var seg = segs_2[_i]; 11875 var eventRange = seg.eventRange; 11876 var origRange = eventRange.range; 11877 var slicedRange = intersectRanges(origRange, dayRange); 11878 if (slicedRange) { 11879 newSegs.push(__assign(__assign({}, seg), { firstCol: colIndex, lastCol: colIndex, eventRange: { 11880 def: eventRange.def, 11881 ui: __assign(__assign({}, eventRange.ui), { durationEditable: false }), 11882 instance: eventRange.instance, 11883 range: slicedRange 11884 }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() })); 11885 } 11886 } 11887 return newSegs; 11888 } 11889 11890 var TableRow = /** @class */ (function (_super) { 11891 __extends(TableRow, _super); 11892 function TableRow() { 11893 var _this = _super !== null && _super.apply(this, arguments) || this; 11894 _this.cellElRefs = new RefMap(); // the <td> 11895 _this.frameElRefs = new RefMap(); // the fc-daygrid-day-frame 11896 _this.fgElRefs = new RefMap(); // the fc-daygrid-day-events 11897 _this.segHarnessRefs = new RefMap(); // indexed by "instanceId:firstCol" 11898 _this.rootElRef = createRef(); 11899 _this.state = { 11900 framePositions: null, 11901 maxContentHeight: null, 11902 segHeights: {} 11903 }; 11904 return _this; 11905 } 11906 TableRow.prototype.render = function () { 11907 var _this = this; 11908 var _a = this, props = _a.props, state = _a.state, context = _a.context; 11909 var colCnt = props.cells.length; 11910 var businessHoursByCol = splitSegsByFirstCol(props.businessHourSegs, colCnt); 11911 var bgEventSegsByCol = splitSegsByFirstCol(props.bgEventSegs, colCnt); 11912 var highlightSegsByCol = splitSegsByFirstCol(this.getHighlightSegs(), colCnt); 11913 var mirrorSegsByCol = splitSegsByFirstCol(this.getMirrorSegs(), colCnt); 11914 var _b = computeFgSegPlacement(props.cells, props.fgEventSegs, props.dayMaxEvents, props.dayMaxEventRows, state.segHeights, state.maxContentHeight, colCnt, context.options.eventOrder), paddingBottoms = _b.paddingBottoms, segsByFirstCol = _b.segsByFirstCol, segsByEachCol = _b.segsByEachCol, segIsHidden = _b.segIsHidden, segTops = _b.segTops, segMarginTops = _b.segMarginTops, moreCnts = _b.moreCnts, moreTops = _b.moreTops; 11915 var selectedInstanceHash = // TODO: messy way to compute this 11916 (props.eventDrag && props.eventDrag.affectedInstances) || 11917 (props.eventResize && props.eventResize.affectedInstances) || 11918 {}; 11919 return (createElement("tr", { ref: this.rootElRef }, 11920 props.renderIntro && props.renderIntro(), 11921 props.cells.map(function (cell, col) { 11922 var normalFgNodes = _this.renderFgSegs(segsByFirstCol[col], segIsHidden, segTops, segMarginTops, selectedInstanceHash, props.todayRange); 11923 var mirrorFgNodes = _this.renderFgSegs(mirrorSegsByCol[col], {}, segTops, // use same tops as real rendering 11924 {}, {}, props.todayRange, Boolean(props.eventDrag), Boolean(props.eventResize), false // date-selecting (because mirror is never drawn for date selection) 11925 ); 11926 return (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, extraHookProps: cell.extraHookProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, moreCnt: moreCnts[col], buildMoreLinkText: props.buildMoreLinkText, onMoreClick: props.onMoreClick, segIsHidden: segIsHidden, moreMarginTop: moreTops[col] /* rename */, segsByEachCol: segsByEachCol[col], fgPaddingBottom: paddingBottoms[col], fgContentElRef: _this.fgElRefs.createRef(cell.key), fgContent: ( // Fragment scopes the keys 11927 createElement(Fragment, null, 11928 createElement(Fragment, null, normalFgNodes), 11929 createElement(Fragment, null, mirrorFgNodes))), bgContent: ( // Fragment scopes the keys 11930 createElement(Fragment, null, 11931 _this.renderFillSegs(highlightSegsByCol[col], 'highlight'), 11932 _this.renderFillSegs(businessHoursByCol[col], 'non-business'), 11933 _this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))) })); 11934 }))); 11935 }; 11936 TableRow.prototype.componentDidMount = function () { 11937 this.updateSizing(true); 11938 }; 11939 TableRow.prototype.componentDidUpdate = function (prevProps, prevState) { 11940 var currentProps = this.props; 11941 this.updateSizing(!isPropsEqual(prevProps, currentProps)); 11942 }; 11943 TableRow.prototype.getHighlightSegs = function () { 11944 var props = this.props; 11945 if (props.eventDrag && props.eventDrag.segs.length) { // messy check 11946 return props.eventDrag.segs; 11947 } 11948 else if (props.eventResize && props.eventResize.segs.length) { // messy check 11949 return props.eventResize.segs; 11950 } 11951 else { 11952 return props.dateSelectionSegs; 11953 } 11954 }; 11955 TableRow.prototype.getMirrorSegs = function () { 11956 var props = this.props; 11957 if (props.eventResize && props.eventResize.segs.length) { // messy check 11958 return props.eventResize.segs; 11959 } 11960 else { 11961 return []; 11962 } 11963 }; 11964 TableRow.prototype.renderFgSegs = function (segs, segIsHidden, // does NOT mean display:hidden 11965 segTops, segMarginTops, selectedInstanceHash, todayRange, isDragging, isResizing, isDateSelecting) { 11966 var context = this.context; 11967 var eventSelection = this.props.eventSelection; 11968 var framePositions = this.state.framePositions; 11969 var defaultDisplayEventEnd = this.props.cells.length === 1; // colCnt === 1 11970 var nodes = []; 11971 if (framePositions) { 11972 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 11973 var seg = segs_1[_i]; 11974 var instanceId = seg.eventRange.instance.instanceId; 11975 var isMirror = isDragging || isResizing || isDateSelecting; 11976 var isSelected = selectedInstanceHash[instanceId]; 11977 var isInvisible = segIsHidden[instanceId] || isSelected; 11978 var isAbsolute = segIsHidden[instanceId] || isMirror || seg.firstCol !== seg.lastCol || !seg.isStart || !seg.isEnd; // TODO: simpler way? NOT DRY 11979 var marginTop = void 0; 11980 var top_1 = void 0; 11981 var left = void 0; 11982 var right = void 0; 11983 if (isAbsolute) { 11984 top_1 = segTops[instanceId]; 11985 if (context.isRtl) { 11986 right = 0; 11987 left = framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol]; 11988 } 11989 else { 11990 left = 0; 11991 right = framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol]; 11992 } 11993 } 11994 else { 11995 marginTop = segMarginTops[instanceId]; 11996 } 11997 /* 11998 known bug: events that are force to be list-item but span multiple days still take up space in later columns 11999 */ 12000 nodes.push(createElement("div", { className: 'fc-daygri
12000d-event-harness' + (isAbsolute ? ' fc-daygrid-event-harness-abs' : ''), key: instanceId, ref: isMirror ? null : this.segHarnessRefs.createRef(instanceId + ':' + seg.firstCol) /* in print mode when in mult cols, could collide */, style: { 12001 visibility: isInvisible ? 'hidden' : '', 12002 marginTop: marginTop || '', 12003 top: top_1 || '', 12004 left: left || '', 12005 right: right || '' 12006 } }, hasListItemDisplay(seg) ? 12007 createElement(TableListItemEvent, __assign({ seg: seg, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getSegMeta(seg, todayRange))) : 12008 createElement(TableBlockEvent, __assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getSegMeta(seg, todayRange))))); 12009 } 12010 } 12011 return nodes; 12012 }; 12013 TableRow.prototype.renderFillSegs = function (segs, fillType) { 12014 var isRtl = this.context.isRtl; 12015 var todayRange = this.props.todayRange; 12016 var framePositions = this.state.framePositions; 12017 var nodes = []; 12018 if (framePositions) { 12019 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 12020 var seg = segs_2[_i]; 12021 var leftRightCss = isRtl ? { 12022 right: 0, 12023 left: framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol] 12024 } : { 12025 left: 0, 12026 right: framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol], 12027 }; 12028 nodes.push(createElement("div", { key: buildEventRangeKey(seg.eventRange), className: 'fc-daygrid-bg-harness', style: leftRightCss }, fillType === 'bg-event' ? 12029 createElement(BgEvent, __assign({ seg: seg }, getSegMeta(seg, todayRange))) : 12030 renderFill(fillType))); 12031 } 12032 } 12033 return createElement.apply(void 0, __spreadArrays([Fragment, {}], nodes)); 12034 }; 12035 TableRow.prototype.updateSizing = function (isExternalSizingChange) { 12036 var _a = this, props = _a.props, frameElRefs = _a.frameElRefs; 12037 if (props.clientWidth !== null) { // positioning ready? 12038 if (isExternalSizingChange) { 12039 var frameEls = props.cells.map(function (cell) { return frameElRefs.currentMap[cell.key]; }); 12040 if (frameEls.length) { 12041 var originEl = this.rootElRef.current; 12042 this.setState({ 12043 framePositions: new PositionCache(originEl, frameEls, true, // isHorizontal 12044 false) 12045 }); 12046 } 12047 } 12048 var limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true; 12049 this.setState({ 12050 segHeights: this.computeSegHeights(), 12051 maxContentHeight: limitByContentHeight ? this.computeMaxContentHeight() : null 12052 }); 12053 } 12054 }; 12055 TableRow.prototype.computeSegHeights = function () { 12056 return mapHash(this.segHarnessRefs.currentMap, function (eventHarnessEl) { return (eventHarnessEl.getBoundingClientRect().height); }); 12057 }; 12058 TableRow.prototype.computeMaxContentHeight = function () { 12059 var firstKey = this.props.cells[0].key; 12060 var cellEl = this.cellElRefs.currentMap[firstKey]; 12061 var fcContainerEl = this.fgElRefs.currentMap[firstKey]; 12062 return cellEl.getBoundingClientRect().bottom - fcContainerEl.getBoundingClientRect().top; 12063 }; 12064 TableRow.prototype.getCellEls = function () { 12065 var elMap = this.cellElRefs.currentMap; 12066 return this.props.cells.map(function (cell) { return elMap[cell.key]; }); 12067 }; 12068 return TableRow; 12069 }(DateComponent)); 12070 TableRow.addStateEquality({ 12071 segHeights: isPropsEqual 12072 }); 12073 12074 var PADDING_FROM_VIEWPORT = 10; 12075 var SCROLL_DEBOUNCE = 10; 12076 var Popover = /** @class */ (function (_super) { 12077 __extends(Popover, _super); 12078 function Popover() { 12079 var _this = _super !== null && _super.apply(this, arguments) || this; 12080 _this.repositioner = new DelayedRunner(_this.updateSize.bind(_this)); 12081 _this.handleRootEl = function (el) { 12082 _this.rootEl = el; 12083 if (_this.props.elRef) { 12084 setRef(_this.props.elRef, el); 12085 } 12086 }; 12087 // Triggered when the user clicks *anywhere* in the document, for the autoHide feature 12088 _this.handleDocumentMousedown = function (ev) { 12089 var onClose = _this.props.onClose; 12090 // only hide the popover if the click happened outside the popover 12091 if (onClose && !_this.rootEl.contains(ev.target)) { 12092 onClose(); 12093 } 12094 }; 12095 _this.handleDocumentScroll = function () { 12096 _this.repositioner.request(SCROLL_DEBOUNCE); 12097 }; 12098 _this.handleCloseClick = function () { 12099 var onClose = _this.props.onClose; 12100 if (onClose) { 12101 onClose(); 12102 } 12103 }; 12104 return _this; 12105 } 12106 Popover.prototype.render = function () { 12107 var theme = this.context.theme; 12108 var props = this.props; 12109 var classNames = [ 12110 'fc-popover', 12111 theme.getClass('popover') 12112 ].concat(props.extraClassNames || []); 12113 return (createElement("div", __assign({ className: classNames.join(' ') }, props.extraAttrs, { ref: this.handleRootEl }), 12114 createElement("div", { className: 'fc-popover-header ' + theme.getClass('popoverHeader') }, 12115 createElement("span", { className: 'fc-popover-title' }, props.title), 12116 createElement("span", { className: 'fc-popover-close ' + theme.getIconClass('close'), onClick: this.handleCloseClick })), 12117 createElement("div", { className: 'fc-popover-body ' + theme.getClass('popoverContent') }, props.children))); 12118 }; 12119 Popover.prototype.componentDidMount = function () { 12120 document.addEventListener('mousedown', this.handleDocumentMousedown); 12121 document.addEventListener('scroll', this.handleDocumentScroll); 12122 this.updateSize(); 12123 }; 12124 Popover.prototype.componentWillUnmount = function () { 12125 document.removeEventListener('mousedown', this.handleDocumentMousedown); 12126 document.removeEventListener('scroll', this.handleDocumentScroll); 12127 }; 12128 // TODO: adjust on window resize 12129 /* 12130 NOTE: the popover is position:fixed, so coordinates are relative to the viewport 12131 NOTE: the PARENT calls this as well, on window resize. we would have wanted to use the repositioner, 12132 but need to ensure that all other components have updated size first (for alignmentEl) 12133 */ 12134 Popover.prototype.updateSize = function () { 12135 var _a = this.props, alignmentEl = _a.alignmentEl, topAlignmentEl = _a.topAlignmentEl; 12136 var rootEl = this.rootEl; 12137 if (!rootEl) { 12138 return;
12138 // not sure why this was null, but we shouldn't let external components call updateSize() anyway 12139 } 12140 var dims = rootEl.getBoundingClientRect(); // only used for width,height 12141 var alignment = alignmentEl.getBoundingClientRect(); 12142 var top = topAlignmentEl ? topAlignmentEl.getBoundingClientRect().top : alignment.top; 12143 top = Math.min(top, window.innerHeight - dims.height - PADDING_FROM_VIEWPORT); 12144 top = Math.max(top, PADDING_FROM_VIEWPORT); 12145 var left; 12146 if (this.context.isRtl) { 12147 left = alignment.right - dims.width; 12148 } 12149 else { 12150 left = alignment.left; 12151 } 12152 left = Math.min(left, window.innerWidth - dims.width - PADDING_FROM_VIEWPORT); 12153 left = Math.max(left, PADDING_FROM_VIEWPORT); 12154 applyStyle(rootEl, { top: top, left: left }); 12155 }; 12156 return Popover; 12157 }(BaseComponent)); 12158 12159 var MorePopover = /** @class */ (function (_super) { 12160 __extends(MorePopover, _super); 12161 function MorePopover() { 12162 var _this = _super !== null && _super.apply(this, arguments) || this; 12163 _this.handlePopoverEl = function (popoverEl) { 12164 _this.popoverEl = popoverEl; 12165 if (popoverEl) { 12166 _this.context.registerInteractiveComponent(_this, { 12167 el: popoverEl, 12168 useEventCenter: false 12169 }); 12170 } 12171 else { 12172 _this.context.unregisterInteractiveComponent(_this); 12173 } 12174 }; 12175 return _this; 12176 } 12177 MorePopover.prototype.render = function () { 12178 var _a = this.context, options = _a.options, dateEnv = _a.dateEnv; 12179 var props = this.props; 12180 var date = props.date, hiddenInstances = props.hiddenInstances, todayRange = props.todayRange, dateProfile = props.dateProfile, selectedInstanceId = props.selectedInstanceId; 12181 var title = dateEnv.format(date, options.dayPopoverFormat); 12182 return (createElement(DayCellRoot, { date: date, dateProfile: dateProfile, todayRange: todayRange, elRef: this.handlePopoverEl }, function (rootElRef, dayClassNames, dataAttrs) { return (createElement(Popover, { elRef: rootElRef, title: title, extraClassNames: ['fc-more-popover'].concat(dayClassNames), extraAttrs: dataAttrs, onClose: props.onCloseClick, alignmentEl: props.alignmentEl, topAlignmentEl: props.topAlignmentEl }, 12183 createElement(DayCellContent, { date: date, dateProfile: dateProfile, todayRange: todayRange }, function (innerElRef, innerContent) { return (innerContent && 12184 createElement("div", { className: 'fc-more-popover-misc', ref: innerElRef }, innerContent)); }), 12185 props.segs.map(function (seg) { 12186 var instanceId = seg.eventRange.instance.instanceId; 12187 return (createElement("div", { className: 'fc-daygrid-event-harness', key: instanceId, style: { 12188 visibility: hiddenInstances[instanceId] ? 'hidden' : '' 12189 } }, hasListItemDisplay(seg) ? 12190 createElement(TableListItemEvent, __assign({ seg: seg, isDragging: false, isSelected: instanceId === selectedInstanceId, defaultDisplayEventEnd: false }, getSegMeta(seg, todayRange))) : 12191 createElement(TableBlockEvent, __assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === selectedInstanceId, defaultDisplayEventEnd: false }, getSegMeta(seg, todayRange))))); 12192 }))); })); 12193 }; 12194 MorePopover.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) { 12195 var date = this.props.date; 12196 if (positionLeft < elWidth && positionTop < elHeight) { 12197 return { 12198 component: this, 12199 dateSpan: { 12200 allDay: true, 12201 range: { start: date, end: addDays(date, 1) } 12202 }, 12203 dayEl: this.popoverEl, 12204 rect: { 12205 left: 0, 12206 top: 0, 12207 right: elWidth, 12208 bottom: elHeight 12209 }, 12210 layer: 1 12211 }; 12212 } 12213 }; 12214 MorePopover.prototype.isPopover = function () { 12215 return true; // gross 12216 }; 12217 return MorePopover; 12218 }(DateComponent)); 12219 12220 var Table = /** @class */ (function (_super) { 12221 __extends(Table, _super); 12222 function Table() { 12223 var _this = _super !== null && _super.apply(this, arguments) || this; 12224 _this.splitBusinessHourSegs = memoize(splitSegsByRow); 12225 _this.splitBgEventSegs = memoize(splitSegsByRow); 12226 _this.splitFgEventSegs = memoize(splitSegsByRow); 12227 _this.splitDateSelectionSegs = memoize(splitSegsByRow); 12228 _this.splitEventDrag = memoize(splitInteractionByRow); 12229 _this.splitEventResize = memoize(splitInteractionByRow); 12230 _this.buildBuildMoreLinkText = memoize(buildBuildMoreLinkText); 12231 _this.rowRefs = new RefMap(); 12232 _this.state = { 12233 morePopoverState: null 12234 }; 12235 _this.handleRootEl = function (rootEl) { 12236 _this.rootEl = rootEl; 12237 setRef(_this.props.elRef, rootEl); 12238 }; 12239 _this.handleMoreLinkClick = function (arg) { 12240 var context = _this.context; 12241 var dateEnv = context.dateEnv; 12242 var clickOption = context.options.moreLinkClick; 12243 function segForPublic(seg) { 12244 var _a = seg.eventRange, def = _a.def, instance = _a.instance, range = _a.range; 12245 return { 12246 event: new EventApi(context, def, instance), 12247 start: dateEnv.toDate(range.start), 12248 end: dateEnv.toDate(range.end), 12249 isStart: seg.isStart, 12250 isEnd: seg.isEnd 12251 }; 12252 } 12253 if (typeof clickOption === 'function') { 12254 clickOption = clickOption({ 12255 date: dateEnv.toDate(arg.date), 12256 allDay: true, 12257 allSegs: arg.allSegs.map(segForPublic), 12258 hiddenSegs: arg.hiddenSegs.map(segForPublic), 12259 jsEvent: arg.ev, 12260 view: context.viewApi 12261 }); // hack to handle void 12262 } 12263 if (!clickOption || clickOption === 'popover') { 12264 _this.setState({ 12265 morePopoverState: __assign(__assign({}, arg), { currentFgEventSegs: _this.props.fgEventSegs }) 12266 }); 12267 } 12268 else if (typeof clickOption === 'string') { // a view n
12268ame 12269 context.calendarApi.zoomTo(arg.date, clickOption); 12270 } 12271 }; 12272 _this.handleMorePopoverClose = function () { 12273 _this.setState({ 12274 morePopoverState: null 12275 }); 12276 }; 12277 return _this; 12278 } 12279 Table.prototype.render = function () { 12280 var _this = this; 12281 var props = this.props; 12282 var dateProfile = props.dateProfile, dayMaxEventRows = props.dayMaxEventRows, dayMaxEvents = props.dayMaxEvents, expandRows = props.expandRows; 12283 var morePopoverState = this.state.morePopoverState; 12284 var rowCnt = props.cells.length; 12285 var businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt); 12286 var bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt); 12287 var fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt); 12288 var dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt); 12289 var eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt); 12290 var eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt); 12291 var buildMoreLinkText = this.buildBuildMoreLinkText(this.context.options.moreLinkText); 12292 var limitViaBalanced = dayMaxEvents === true || dayMaxEventRows === true; 12293 // if rows can't expand to fill fixed height, can't do balanced-height event limit 12294 // TODO: best place to normalize these options? 12295 if (limitViaBalanced && !expandRows) { 12296 limitViaBalanced = false; 12297 dayMaxEventRows = null; 12298 dayMaxEvents = null; 12299 } 12300 var classNames = [ 12301 'fc-daygrid-body', 12302 limitViaBalanced ? 'fc-daygrid-body-balanced' : 'fc-daygrid-body-unbalanced', 12303 expandRows ? '' : 'fc-daygrid-body-natural' // will height of one row depend on the others? 12304 ]; 12305 return (createElement("div", { className: classNames.join(' '), ref: this.handleRootEl, style: { 12306 // these props are important to give this wrapper correct dimensions for interactions 12307 // TODO: if we set it here, can we avoid giving to inner tables? 12308 width: props.clientWidth, 12309 minWidth: props.tableMinWidth 12310 } }, 12311 createElement(NowTimer, { unit: 'day' }, function (nowDate, todayRange) { return (createElement(Fragment, null, 12312 createElement("table", { className: 'fc-scrollgrid-sync-table', style: { 12313 width: props.clientWidth, 12314 minWidth: props.tableMinWidth, 12315 height: expandRows ? props.clientHeight : '' 12316 } }, 12317 props.colGroupNode, 12318 createElement("tbody", null, props.cells.map(function (cells, row) { return (createElement(TableRow, { ref: _this.rowRefs.createRef(row), key: cells.length 12319 ? cells[0].date.toISOString() /* best? or put key on cell? or use diff formatter? */ 12320 : row // in case there are no cells (like when resource view is loading) 12321 , showDayNumbers: rowCnt > 1, showWeekNumbers: props.showWeekNumbers, todayRange: todayRange, dateProfile: 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: dayMaxEvents, dayMaxEventRows: dayMaxEventRows, clientWidth: props.clientWidth, clientHeight: props.clientHeight, buildMoreLinkText: buildMoreLinkText, onMoreClick: _this.handleMoreLinkClick })); }))), 12322 (!props.forPrint && morePopoverState && morePopoverState.currentFgEventSegs === props.fgEventSegs) && // clear popover on event mod 12323 createElement(MorePopover, { date: morePopoverState.date, dateProfile: dateProfile, segs: morePopoverState.allSegs, alignmentEl: morePopoverState.dayEl, topAlignmentEl: rowCnt === 1 ? props.headerAlignElRef.current : null, onCloseClick: _this.handleMorePopoverClose, selectedInstanceId: props.eventSelection, hiddenInstances: // yuck 12324 (props.eventDrag ? props.eventDrag.affectedInstances : null) || 12325 (props.eventResize ? props.eventResize.affectedInstances : null) || 12326 {}, todayRange: todayRange }))); }))); 12327 }; 12328 // Hit System 12329 // ---------------------------------------------------------------------------------------------------- 12330 Table.prototype.prepareHits = function () { 12331 this.rowPositions = new PositionCache(this.rootEl, this.rowRefs.collect().map(function (rowObj) { return rowObj.getCellEls()[0]; }), // first cell el in each row. TODO: not optimal 12332 false, true // vertical 12333 ); 12334 this.colPositions = new PositionCache(this.rootEl, this.rowRefs.currentMap[0].getCellEls(), // cell els in first row 12335 true, // horizontal 12336 false); 12337 }; 12338 Table.prototype.positionToHit = function (leftPosition, topPosition) {
12339 var _a = this, colPositions = _a.colPositions, rowPositions = _a.rowPositions; 12340 var col = colPositions.leftToIndex(leftPosition); 12341 var row = rowPositions.topToIndex(topPosition); 12342 if (row != null && col != null) { 12343 return { 12344 row: row, 12345 col: col, 12346 dateSpan: { 12347 range: this.getCellRange(row, col), 12348 allDay: true 12349 }, 12350 dayEl: this.getCellEl(row, col), 12351 relativeRect: { 12352 left: colPositions.lefts[col], 12353 right: colPositions.rights[col], 12354 top: rowPositions.tops[row], 12355 bottom: rowPositions.bottoms[row] 12356 } 12357 }; 12358 } 12359 }; 12360 Table.prototype.getCellEl = function (row, col) { 12361 return this.rowRefs.currentMap[row].getCellEls()[col]; // TODO: not optimal 12362 }; 12363 Table.prototype.getCellRange = function (row, col) { 12364 var start = this.props.cells[row][col].date; 12365 var end = addDays(start, 1); 12366 return { start: start, end: end }; 12367 }; 12368 return Table; 12369 }(DateComponent)); 12370 function buildBuildMoreLinkText(moreLinkTextInput) { 12371 if (typeof moreLinkTextInput === 'function') { 12372 return moreLinkTextInput; 12373 } 12374 else { 12375 return function (num) { 12376 return "+" + num + " " + moreLinkTextInput; 12377 }; 12378 } 12379 } 12380 function isSegAllDay(seg) { 12381 return seg.eventRange.def.allDay; 12382 } 12383 12384 var DayTable = /** @class */ (function (_super) { 12385 __extends(DayTable, _super); 12386 function DayTable() { 12387 var _this = _super !== null && _super.apply(this, arguments) || this; 12388 _this.slicer = new DayTableSlicer(); 12389 _this.tableRef = createRef(); 12390 _this.handleRootEl = function (rootEl) { 12391 if (rootEl) { 12392 _this.context.registerInteractiveComponent(_this, { el: rootEl }); 12393 } 12394 else { 12395 _this.context.unregisterInteractiveComponent(_this); 12396 } 12397 }; 12398 return _this; 12399 } 12400 DayTable.prototype.render = function () { 12401 var _a = this, props = _a.props, context = _a.context; 12402 return (createElement(Table, __assign({ ref: this.tableRef, elRef: this.handleRootEl }, 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 }))); 12403 }; 12404 DayTable.prototype.prepareHits = function () { 12405 this.tableRef.current.prepareHits(); 12406 }; 12407 DayTable.prototype.queryHit = function (positionLeft, positionTop) { 12408 var rawHit = this.tableRef.current.positionToHit(positionLeft, positionTop); 12409 if (rawHit) { 12410 return { 12411 component: this, 12412 dateSpan: rawHit.dateSpan, 12413 dayEl: rawHit.dayEl, 12414 rect: { 12415 left: rawHit.relativeRect.left, 12416 right: rawHit.relativeRect.right, 12417 top: rawHit.relativeRect.top, 12418 bottom: rawHit.relativeRect.bottom 12419 }, 12420 layer: 0 12421 }; 12422 } 12423 }; 12424 return DayTable; 12425 }(DateComponent)); 12426 var DayTableSlicer = /** @class */ (function (_super) { 12427 __extends(DayTableSlicer, _super); 12428 function DayTableSlicer() { 12429 var _this = _super !== null && _super.apply(this, arguments) || this; 12430 _this.forceDayIfListItem = true; 12431 return _this; 12432 } 12433 DayTableSlicer.prototype.sliceRange = function (dateRange, dayTableModel) { 12434 return dayTableModel.sliceRange(dateRange); 12435 }; 12436 return DayTableSlicer; 12437 }(Slicer)); 12438 12439 var DayTableView = /** @class */ (function (_super) { 12440 __extends(DayTableView, _super); 12441 function DayTableView() { 12442 var _this = _super !== null && _super.apply(this, arguments) || this; 12443 _this.buildDayTableModel = memoize(buildDayTableModel); 12444 _this.headerRef = createRef(); 12445 _this.tableRef = createRef(); 12446 return _this; 12447 } 12448 DayTableView.prototype.render = function () { 12449 var _this = this; 12450 var _a = this.context, options = _a.options, dateProfileGenerator = _a.dateProfileGenerator; 12451 var props = this.props; 12452 var dayTableModel = this.buildDayTableModel(props.dateProfile, dateProfileGenerator); 12453 var headerContent = options.dayHeaders && 12454 createElement(DayHeader, { ref: this.headerRef, dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: dayTableModel.rowCnt === 1 }); 12455 var bodyContent = function (contentArg) { return (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 })); }; 12456 return options.dayMinWidth 12457 ? this.renderHScrollLayout(headerContent, bodyContent, dayTableModel.colCnt, options.dayMinWidth) 12458 : this.renderSimpleLayout(headerContent, bodyContent); 12459 }; 12460 return DayTableView; 12461 }(TableView)); 12462 function buildDayTableModel(dateProfile, dateProfileGenerator) {
12463 var daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator); 12464 return new DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit)); 12465 } 12466 12467 var TableDateProfileGenerator = /** @class */ (function (_super) { 12468 __extends(TableDateProfileGenerator, _super); 12469 function TableDateProfileGenerator() { 12470 return _super !== null && _super.apply(this, arguments) || this; 12471 } 12472 // Computes the date range that will be rendered. 12473 TableDateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) { 12474 var dateEnv = this.props.dateEnv; 12475 var renderRange = _super.prototype.buildRenderRange.call(this, currentRange, currentRangeUnit, isRangeAllDay); 12476 var start = renderRange.start; 12477 var end = renderRange.end; 12478 var endOfWeek; 12479 // year and month views should be aligned with weeks. this is already done for week 12480 if (/^(year|month)$/.test(currentRangeUnit)) { 12481 start = dateEnv.startOfWeek(start); 12482 // make end-of-week if not already 12483 endOfWeek = dateEnv.startOfWeek(end); 12484 if (endOfWeek.valueOf() !== end.valueOf()) { 12485 end = addWeeks(endOfWeek, 1); 12486 } 12487 } 12488 // ensure 6 weeks 12489 if (this.props.monthMode && 12490 this.props.fixedWeekCount) { 12491 var rowCnt = Math.ceil(// could be partial weeks due to hiddenDays 12492 diffWeeks(start, end)); 12493 end = addWeeks(end, 6 - rowCnt); 12494 } 12495 return { start: start, end: end }; 12496 }; 12497 return TableDateProfileGenerator; 12498 }(DateProfileGenerator)); 12499 12500 var OPTION_REFINERS = { 12501 moreLinkClick: identity, 12502 moreLinkClassNames: identity, 12503 moreLinkContent: identity, 12504 moreLinkDidMount: identity, 12505 moreLinkWillUnmount: identity, 12506 }; 12507 12508 var dayGridPlugin = createPlugin({ 12509 initialView: 'dayGridMonth', 12510 optionRefiners: OPTION_REFINERS, 12511 views: { 12512 dayGrid: { 12513 component: DayTableView, 12514 dateProfileGeneratorClass: TableDateProfileGenerator 12515 }, 12516 dayGridDay: { 12517 type: 'dayGrid', 12518 duration: { days: 1 } 12519 }, 12520 dayGridWeek: { 12521 type: 'dayGrid', 12522 duration: { weeks: 1 } 12523 }, 12524 dayGridMonth: { 12525 type: 'dayGrid', 12526 duration: { months: 1 }, 12527 monthMode: true, 12528 fixedWeekCount: true 12529 } 12530 } 12531 }); 12532 12533 var AllDaySplitter = /** @class */ (function (_super) { 12534 __extends(AllDaySplitter, _super); 12535 function AllDaySplitter() { 12536 return _super !== null && _super.apply(this, arguments) || this; 12537 } 12538 AllDaySplitter.prototype.getKeyInfo = function () { 12539 return { 12540 allDay: {}, 12541 timed: {} 12542 }; 12543 }; 12544 AllDaySplitter.prototype.getKeysForDateSpan = function (dateSpan) { 12545 if (dateSpan.allDay) { 12546 return ['allDay']; 12547 } 12548 else { 12549 return ['timed']; 12550 } 12551 }; 12552 AllDaySplitter.prototype.getKeysForEventDef = function (eventDef) { 12553 if (!eventDef.allDay) { 12554 return ['timed']; 12555 } 12556 else if (hasBgRendering(eventDef)) { 12557 return ['timed', 'allDay']; 12558 } 12559 else { 12560 return ['allDay']; 12561 } 12562 }; 12563 return AllDaySplitter; 12564 }(Splitter)); 12565 12566 var TimeColsSlatsCoords = /** @class */ (function () { 12567 function TimeColsSlatsCoords(positions, dateProfile, slatMetas) { 12568 this.positions = positions; 12569 this.dateProfile = dateProfile; 12570 this.slatMetas = slatMetas; 12571 } 12572 TimeColsSlatsCoords.prototype.safeComputeTop = function (date) { 12573 var dateProfile = this.dateProfile; 12574 if (rangeContainsMarker(dateProfile.currentRange, date)) { 12575 var startOfDayDate = startOfDay(date); 12576 var timeMs = date.valueOf() - startOfDayDate.valueOf(); 12577 if (timeMs >= asRoughMs(dateProfile.slotMinTime) && 12578 timeMs < asRoughMs(dateProfile.slotMaxTime)) { 12579 return this.computeTimeTop(createDuration(timeMs)); 12580 } 12581 } 12582 }; 12583 // Computes the top coordinate, relative to the bounds of the grid, of the given date. 12584 // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight. 12585 TimeColsSlatsCoords.prototype.computeDateTop = function (when, startOfDayDate) { 12586 if (!startOfDayDate) { 12587 startOfDayDate = startOfDay(when); 12588 } 12589 return this.computeTimeTop(createDuration(when.valueOf() - startOfDayDate.valueOf())); 12590 }; 12591 // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration). 12592 // This is a makeshify way to compute the time-top. Assumes all slatMetas dates are uniform. 12593 // Eventually allow computation with arbirary slat dates. 12594 TimeColsSlatsCoords.prototype.computeTimeTop = function (duration) { 12595 var _a = this, positions = _a.positions, dateProfile = _a.dateProfile, slatMetas = _a.slatMetas; 12596 var len = positions.els.length; 12597 var slotDurationMs = slatMetas[1].date.valueOf() - slatMetas[0].date.valueOf(); // we assume dates are uniform 12598 var slatCoverage = (duration.milliseconds - asRoughMs(dateProfile.slotMinTime)) / slotDurationMs; // floating-point value of # of slots covered 12599 var slatIndex; 12600 var slatRemainder; 12601 // compute a floating-point number for how many slats should be progressed through. 12602 // from 0 to number of slats (inclusive) 12603 // constrained because slotMinTime/slotMaxTime might be customized. 12604 slatCoverage = Math.max(0, slatCoverage); 12605 slatCoverage = Math.min(len, slatCoverage); 12606 // an integer index of the furthest whole slat 12607 // from 0 to number slats (*exclusive*, so len-1) 12608 slatIndex = Math.floor(slatCoverage); 12609 slatIndex = Math.min(slatIndex, len - 1); 12610 // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition. 12611 // could be 1.0 if slatCoverage is covering *all* the slots 12612 slatRemainder = slatCoverage - slatIndex; 12613 return positions.tops[slatIndex] + 12614 positions.getHeight(slatIndex) * slatRemainder; 12615 }; 12616 return TimeColsSlatsCoords; 12617 }()); 12618 12619 // potential nice values for the slot-duration and interval-duration 12620 // from largest to smallest 12621 var STOCK_SUB_DURATIONS = [ 12622 { hours: 1 }, 12623 { minutes: 30 }, 12624 { minutes: 15 }, 12625 { seconds: 30 }, 12626 { seconds: 15 } 12627 ]; 12628 /* 12629 for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL. 12630 */ 12631 var TimeColsSlats = /** @class */ (function (_super) { 12632 __extends(TimeColsSlats, _super); 12633 function TimeColsSlats() { 12634 var _this = _super !== null && _super.apply(this, arguments) || this; 12635 _this.rootElRef = createRef(); 12636 _this.slatElRefs = new RefMap(); 12637 return _this; 12638 } 12639 TimeColsSlats.prototype.render = function () { 12640 var _a = this, props = _a.props, context = _a.context; 12641 return (createElement("div", { className: 'fc-timegrid-slots', ref: this.rootElRef }, 12642 createElement("table", { className: context.theme.getClass('table'), style: { 12643 minWidth: props.tableMinWidth, 12644 width: props.clientWidth, 12645 height: props.minHeight 12646 } },
12647 props.tableColGroupNode /* relies on there only being a single <col> for the axis */, 12648 createElement(TimeColsSlatsBody, { slatElRefs: this.slatElRefs, axis: props.axis, slatMetas: props.slatMetas })))); 12649 }; 12650 TimeColsSlats.prototype.componentDidMount = function () { 12651 this.updateSizing(); 12652 }; 12653 TimeColsSlats.prototype.componentDidUpdate = function () { 12654 this.updateSizing(); 12655 }; 12656 TimeColsSlats.prototype.componentWillUnmount = function () { 12657 if (this.props.onCoords) { 12658 this.props.onCoords(null); 12659 } 12660 }; 12661 TimeColsSlats.prototype.updateSizing = function () { 12662 var props = this.props; 12663 if (props.onCoords && 12664 props.clientWidth !== null // means sizing has stabilized 12665 ) { 12666 var rootEl = this.rootElRef.current; 12667 if (rootEl.offsetHeight) { // not hidden by css 12668 props.onCoords(new TimeColsSlatsCoords(new PositionCache(this.rootElRef.current, collectSlatEls(this.slatElRefs.currentMap, props.slatMetas), false, true // vertical 12669 ), this.props.dateProfile, props.slatMetas)); 12670 } 12671 } 12672 }; 12673 return TimeColsSlats; 12674 }(BaseComponent)); 12675 function collectSlatEls(elMap, slatMetas) { 12676 return slatMetas.map(function (slatMeta) { return elMap[slatMeta.key]; }); 12677 } 12678 var TimeColsSlatsBody = /** @class */ (function (_super) { 12679 __extends(TimeColsSlatsBody, _super); 12680 function TimeColsSlatsBody() { 12681 return _super !== null && _super.apply(this, arguments) || this; 12682 } 12683 TimeColsSlatsBody.prototype.render = function () { 12684 var _a = this, props = _a.props, context = _a.context; 12685 var options = context.options; 12686 var slatElRefs = props.slatElRefs; 12687 return (createElement("tbody", null, props.slatMetas.map(function (slatMeta, i) { 12688 var hookProps = { 12689 time: slatMeta.time, 12690 date: context.dateEnv.toDate(slatMeta.date), 12691 view: context.viewApi 12692 }; 12693 var classNames = [ 12694 'fc-timegrid-slot', 12695 'fc-timegrid-slot-lane', 12696 slatMeta.isLabeled ? '' : 'fc-timegrid-slot-minor' 12697 ]; 12698 return (createElement("tr", { key: slatMeta.key, ref: slatElRefs.createRef(slatMeta.key) }, 12699 props.axis && 12700 createElement(TimeColsAxisCell, __assign({}, slatMeta)), 12701 createElement(RenderHook, { hookProps: hookProps, classNames: options.slotLaneClassNames, content: options.slotLaneContent, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount }, function (rootElRef, customClassNames, innerElRef, innerContent) { return (createElement("td", { ref: rootElRef, className: classNames.concat(customClassNames).join(' '), "data-time": slatMeta.isoTimeStr }, innerContent)); }))); 12702 }))); 12703 }; 12704 return TimeColsSlatsBody; 12705 }(BaseComponent)); 12706 var DEFAULT_SLAT_LABEL_FORMAT = createFormatter({ 12707 hour: 'numeric', 12708 minute: '2-digit', 12709 omitZeroMinute: true, 12710 meridiem: 'short' 12711 }); 12712 function TimeColsAxisCell(props) { 12713 var classNames = [ 12714 'fc-timegrid-slot', 12715 'fc-timegrid-slot-label', 12716 props.isLabeled ? 'fc-scrollgrid-shrink' : 'fc-timegrid-slot-minor' 12717 ]; 12718 return (createElement(ViewContextType.Consumer, null, function (context) { 12719 if (!props.isLabeled) { 12720 return (createElement("td", { className: classNames.join(' '), "data-time": props.isoTimeStr })); 12721 } 12722 else { 12723 var dateEnv = context.dateEnv, options = context.options, viewApi = context.viewApi; 12724 var labelFormat = // TODO: fully pre-parse 12725 options.slotLabelFormat == null ? DEFAULT_SLAT_LABEL_FORMAT : 12726 Array.isArray(options.slotLabelFormat) ? createFormatter(options.slotLabelFormat[0]) : 12727 createFormatter(options.slotLabelFormat); 12728 var hookProps = { 12729 level: 0, 12730 time: props.time, 12731 date: dateEnv.toDate(props.date), 12732 view: viewApi, 12733 text: dateEnv.format(props.date, labelFormat) 12734 }; 12735 return (createElement(RenderHook, { hookProps: hookProps, classNames: options.slotLabelClassNames, content: options.slotLabelContent, defaultContent: renderInnerContent$3, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, function (rootElRef, customClassNames, innerElRef, innerContent) { return (createElement("td", { ref: rootElRef, className: classNames.c
12735oncat(customClassNames).join(' '), "data-time": props.isoTimeStr }, 12736 createElement("div", { className: 'fc-timegrid-slot-label-frame fc-scrollgrid-shrink-frame' }, 12737 createElement("div", { className: 'fc-timegrid-slot-label-cushion fc-scrollgrid-shrink-cushion', ref: innerElRef }, innerContent)))); })); 12738 } 12739 })); 12740 } 12741 function renderInnerContent$3(props) { 12742 return props.text; 12743 } 12744 function buildSlatMetas(slotMinTime, slotMaxTime, explicitLabelInterval, slotDuration, dateEnv) { 12745 var dayStart = new Date(0); 12746 var slatTime = slotMinTime; 12747 var slatIterator = createDuration(0); 12748 var labelInterval = explicitLabelInterval || computeLabelInterval(slotDuration); 12749 var metas = []; 12750 while (asRoughMs(slatTime) < asRoughMs(slotMaxTime)) { 12751 var date = dateEnv.add(dayStart, slatTime); 12752 var isLabeled = wholeDivideDurations(slatIterator, labelInterval) !== null; 12753 metas.push({ 12754 date: date, 12755 time: slatTime, 12756 key: date.toISOString(), 12757 isoTimeStr: formatIsoTimeString(date), 12758 isLabeled: isLabeled 12759 }); 12760 slatTime = addDurations(slatTime, slotDuration); 12761 slatIterator = addDurations(slatIterator, slotDuration); 12762 } 12763 return metas; 12764 } 12765 // Computes an automatic value for slotLabelInterval 12766 function computeLabelInterval(slotDuration) { 12767 var i; 12768 var labelInterval; 12769 var slotsPerLabel; 12770 // find the smallest stock label interval that results in more than one slots-per-label 12771 for (i = STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) { 12772 labelInterval = createDuration(STOCK_SUB_DURATIONS[i]); 12773 slotsPerLabel = wholeDivideDurations(labelInterval, slotDuration);
12774 if (slotsPerLabel !== null && slotsPerLabel > 1) { 12775 return labelInterval; 12776 } 12777 } 12778 return slotDuration; // fall back 12779 } 12780 12781 var DEFAULT_WEEK_NUM_FORMAT$1 = createFormatter({ week: 'short' }); 12782 var AUTO_ALL_DAY_MAX_EVENT_ROWS = 5; 12783 var TimeColsView = /** @class */ (function (_super) { 12784 __extends(TimeColsView, _super); 12785 function TimeColsView() { 12786 var _this = _super !== null && _super.apply(this, arguments) || this; 12787 _this.allDaySplitter = new AllDaySplitter(); // for use by subclasses 12788 _this.headerElRef = createRef(); 12789 _this.rootElRef = createRef(); 12790 _this.scrollerElRef = createRef(); 12791 _this.state = { 12792 slatCoords: null 12793 }; 12794 _this.handleScrollTopRequest = function (scrollTop) { 12795 var scrollerEl = _this.scrollerElRef.current; 12796 if (scrollerEl) { // TODO: not sure how this could ever be null. weirdness with the reducer 12797 scrollerEl.scrollTop = scrollTop; 12798 } 12799 }; 12800 /* Header Render Methods 12801 ------------------------------------------------------------------------------------------------------------------*/ 12802 _this.renderHeadAxis = function (frameHeight) { 12803 if (frameHeight === void 0) { frameHeight = ''; } 12804 var options = _this.context.options; 12805 var dateProfile = _this.props.dateProfile; 12806 var range = dateProfile.renderRange; 12807 var dayCnt = diffDays(range.start, range.end); 12808 var navLinkAttrs = (options.navLinks && dayCnt === 1) // only do in day views (to avoid doing in week views that dont need it) 12809 ? { 'data-navlink': buildNavLinkData(range.start, 'week'), tabIndex: 0 } 12810 : {}; 12811 if (options.weekNumbers) { 12812 return (createElement(WeekNumberRoot, { date: range.start, defaultFormat: DEFAULT_WEEK_NUM_FORMAT$1 }, function (rootElRef, classNames, innerElRef, innerContent) { return (createElement("th", { ref: rootElRef, className: [ 12813 'fc-timegrid-axis', 12814 'fc-scrollgrid-shrink' 12815 ].concat(classNames).join(' ') }, 12816 createElement("div", { className: 'fc-timegrid-axis-frame fc-scrollgrid-shrink-frame fc-timegrid-axis-frame-liquid', style: { height: frameHeight } }, 12817 createElement("a", __assign({ ref: innerElRef, className: 'fc-timegrid-axis-cushion fc-scrollgrid-shrink-cushion fc-scrollgrid-sync-inner' }, navLinkAttrs), innerContent)))); })); 12818 } 12819 return (createElement("th", { className: 'fc-timegrid-axis' }, 12820 createElement("div", { className: 'fc-timegrid-axis-frame', style: { height: frameHeight } }))); 12821 }; 12822 /* Table Component Render Methods 12823 ------------------------------------------------------------------------------------------------------------------*/ 12824 // only a one-way height sync. we don't send the axis inner-content height to the DayGrid, 12825 // but DayGrid still needs to have classNames on inner elements in order to measure. 12826 _this.renderTableRowAxis = function (rowHeight) { 12827 var _a = _this.context, options = _a.options, viewApi = _a.viewApi; 12828 var hookProps = { 12829 text: options.allDayText, 12830 view: viewApi 12831 }; 12832 return ( 12833 // TODO: make reusable hook. used in list view too 12834 createElement(RenderHook, { hookProps: hookProps, classNames: options.allDayClassNames, content: options.allDayContent, defaultContent: renderAllDayInner, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }, function (rootElRef, classNames, innerElRef, innerContent) { return (createElement("td", { ref: rootElRef, className: [ 12835 'fc-timegrid-axis', 12836 'fc-scrollgrid-shrink' 12837 ].concat(classNames).join(' ') }, 12838 createElement("div", { className: 'fc-timegrid-axis-frame fc-scrollgrid-shrink-frame' + (rowHeight == null ? ' fc-timegrid-axis-frame-liquid' : ''), style: { height: rowHeight } }, 12839 createElement("span", { className: 'fc-timegrid-axis-cushion fc-scrollgrid-shrink-cushion fc-scrollgrid-sync-inner', ref: innerElRef }, innerContent)))); })); 12840 }; 12841 _this.handleSlatCoords = function (slatCoords) {
12842 _this.setState({ slatCoords: slatCoords }); 12843 }; 12844 return _this; 12845 } 12846 // rendering 12847 // ---------------------------------------------------------------------------------------------------- 12848 TimeColsView.prototype.renderSimpleLayout = function (headerRowContent, allDayContent, timeContent) { 12849 var _a = this, context = _a.context, props = _a.props; 12850 var sections = []; 12851 var stickyHeaderDates = getStickyHeaderDates(context.options); 12852 if (headerRowContent) { 12853 sections.push({ 12854 type: 'header', 12855 key: 'header', 12856 isSticky: stickyHeaderDates, 12857 chunk: { 12858 elRef: this.headerElRef, 12859 tableClassName: 'fc-col-header', 12860 rowContent: headerRowContent 12861 } 12862 }); 12863 } 12864 if (allDayContent) { 12865 sections.push({ 12866 type: 'body', 12867 key: 'all-day', 12868 chunk: { content: allDayContent } 12869 }); 12870 sections.push({ 12871 type: 'body', 12872 key: 'all-day-divider', 12873 outerContent: ( // TODO: rename to cellContent so don't need to define <tr>? 12874 createElement("tr", { className: 'fc-scrollgrid-section' }, 12875 createElement("td", { className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))) 12876 }); 12877 } 12878 sections.push({ 12879 type: 'body', 12880 key: 'body', 12881 liquid: true, 12882 expandRows: Boolean(context.options.expandRows), 12883 chunk: { 12884 scrollerElRef: this.scrollerElRef, 12885 content: timeContent 12886 } 12887 }); 12888 return (createElement(ViewRoot, { viewSpec: context.viewSpec, elRef: this.rootElRef }, function (rootElRef, classNames) { return (createElement("div", { className: ['fc-timegrid'].concat(classNames).join(' '), ref: rootElRef }, 12889 createElement(SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, cols: [{ width: 'shrink' }], sections: sections }))); })); 12890 }; 12891 TimeColsView.prototype.renderHScrollLayout = function (headerRowContent, allDayContent, timeContent, colCnt, dayMinWidth, slatMetas, slatCoords // yuck 12892 ) { 12893 var _this = this; 12894 var ScrollGrid = this.context.pluginHooks.scrollGridImpl; 12895 if (!ScrollGrid) { 12896 throw new Error('No ScrollGrid implementation'); 12897 } 12898 var _a = this, context = _a.context, props = _a.props; 12899 var stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options); 12900 var stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options); 12901 var sections = []; 12902 if (headerRowContent) { 12903 sections.push({ 12904 type: 'header', 12905 key: 'header', 12906 isSticky: stickyHeaderDates, 12907 syncRowHeights: true, 12908 chunks: [ 12909 { 12910 key: 'axis', 12911 rowContent: function (arg) { return (createElement("tr", null, _this.renderHeadAxis(arg.rowSyncHeights[0]))); } 12912 }, 12913 { 12914 key: 'cols', 12915 elRef: this.headerElRef, 12916 tableClassName: 'fc-col-header', 12917 rowContent: headerRowContent 12918 } 12919 ] 12920 }); 12921 } 12922 if (allDayContent) { 12923 sections.push({ 12924 type: 'body', 12925 key: 'all-day', 12926 syncRowHeights: true, 12927 chunks: [ 12928 { 12929 key: 'axis', 12930 rowContent: function (contentArg) { return (createElement("tr", null, _this.renderTableRowAxis(contentArg.rowSyncHeights[0]))); }, 12931 }, 12932 { 12933 key: 'cols', 12934 content: allDayContent 12935 } 12936 ] 12937 }); 12938 sections.push({ 12939 key: 'all-day-divider', 12940 type: 'body', 12941 outerContent: ( // TODO: rename to cellContent so don't need to define <tr>? 12942 createElement("tr", { className: 'fc-scrollgrid-section' }, 12943 createElement("td", { colSpan: 2, className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))) 12944 }); 12945 } 12946 var isNowIndicator = context.options.nowIndicator; 12947 sections.push({ 12948 type: 'body', 12949 key: 'body', 12950 liquid: true, 12951 expandRows: Boolean(context.options.expandRows), 12952 chunks: [ 12953 { 12954 key: 'axis', 12955 content: function (arg) { 12956 // TODO: make this now-indicator arrow more DRY with TimeColsContent 12957 return (createElement("div", { className: 'fc-timegrid-axis-chunk' }, 12958 createElement("table", { style: { height: arg.expandRows ? arg.clientHeight : '' } }, 12959 arg.tableColGroupNode, 12960 createElement("tbody", null, 12961 createElement(TimeBodyAxis, { slatMetas: slatMetas }))), 12962 createElement("div", { className: 'fc-timegrid-now-indicator-container' }, 12963 createElement(NowTimer, { unit: isNowIndicator ? 'minute' : 'day' /* hacky */ }, function (nowDate) { 12964 var nowIndicatorTop = isNowIndicator && 12965 slatCoords && 12966 slatCoords.safeComputeTop(nowDate); // might return void 12967 if (typeof nowIndicatorTop === 'number') { 12968 return (createElement(NowIndicatorRoot, { isAxis: true, date: nowDate }, function (rootElRef, classNames, innerElRef, innerContent) { return (createElement("div", { ref: rootElRef, className: ['fc-timegrid-now-indicator-arrow'].concat(classNames).join(' '), style: { top: nowIndicatorTop } }, innerContent)); })); 12969 } 12970 return null; 12971 })))); 12972 } 12973 }, 12974 { 12975 key: 'cols', 12976 scrollerElRef: this.scrollerElRef, 12977 content: timeContent 12978 } 12979 ] 12980 }); 12981 if (stickyFooterScrollbar) { 12982 sections.push({ 12983 key: 'footer', 12984 type: 'footer', 12985 isSticky: true, 12986 chunks: [ 12987 { 12988 key: 'axis', 12989 content: renderScrollShim 12990 }, 12991 { 12992 key: 'cols', 12993 content: renderScrollShim 12994 } 12995 ] 12996 }); 12997 } 12998 return (createElement(ViewRoot, { viewSpec: context.viewSpec, elRef: this.rootElRef }, function (rootElRef, classNames) { return (createElement("div", { className: ['fc-timegrid'].
12998concat(classNames).join(' '), ref: rootElRef }, 12999 createElement(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, colGroups: [ 13000 { width: 'shrink', cols: [{ width: 'shrink' }] }, 13001 { cols: [{ span: colCnt, minWidth: dayMinWidth }] } 13002 ], sections: sections }))); })); 13003 }; 13004 /* Dimensions 13005 ------------------------------------------------------------------------------------------------------------------*/ 13006 TimeColsView.prototype.getAllDayMaxEventProps = function () { 13007 var _a = this.context.options, dayMaxEvents = _a.dayMaxEvents, dayMaxEventRows = _a.dayMaxEventRows; 13008 if (dayMaxEvents === true || dayMaxEventRows === true) { // is auto? 13009 dayMaxEvents = undefined; 13010 dayMaxEventRows = AUTO_ALL_DAY_MAX_EVENT_ROWS; // make sure "auto" goes to a real number 13011 } 13012 return { dayMaxEvents: dayMaxEvents, dayMaxEventRows: dayMaxEventRows }; 13013 }; 13014 return TimeColsView; 13015 }(DateComponent)); 13016 function renderAllDayInner(hookProps) { 13017 return hookProps.text; 13018 } 13019 var TimeBodyAxis = /** @class */ (function (_super) { 13020 __extends(TimeBodyAxis, _super); 13021 function TimeBodyAxis() { 13022 return _super !== null && _super.apply(this, arguments) || this; 13023 } 13024 TimeBodyAxis.prototype.render = function () { 13025 return this.props.slatMetas.map(function (slatMeta) { return (createElement("tr", { key: slatMeta.key }, 13026 createElement(TimeColsAxisCell, __assign({}, slatMeta)))); }); 13027 }; 13028 return TimeBodyAxis; 13029 }(BaseComponent)); 13030 13031 function splitSegsByCol(segs, colCnt) { 13032 var segsByCol = []; 13033 var i; 13034 for (i = 0; i < colCnt; i++) { 13035 segsByCol.push([]); 13036 } 13037 if (segs) { 13038 for (i = 0; i < segs.length; i++) { 13039 segsByCol[segs[i].col].push(segs[i]); 13040 } 13041 } 13042 return segsByCol; 13043 } 13044 function splitInteractionByCol(ui, colCnt) { 13045 var byRow = []; 13046 if (!ui) { 13047 for (var i = 0; i < colCnt; i++) { 13048 byRow[i] = null; 13049 } 13050 } 13051 else { 13052 for (var i = 0; i < colCnt; i++) { 13053 byRow[i] = { 13054 affectedInstances: ui.affectedInstances, 13055 isEvent: ui.isEvent, 13056 segs: [] 13057 }; 13058 } 13059 for (var _i = 0, _a = ui.segs; _i < _a.length; _i++) { 13060 var seg = _a[_i]; 13061 byRow[seg.col].segs.push(seg); 13062 } 13063 } 13064 return byRow; 13065 } 13066 13067 // UNFORTUNATELY, assigns results to the top/bottom/level/forwardCoord/backwardCoord props of the actual segs. 13068 // TODO: return hash (by instanceId) of results 13069 function computeSegCoords(segs, dayDate, slatCoords, eventMinHeight, eventOrderSpecs) { 13070 computeSegVerticals(segs, dayDate, slatCoords, eventMinHeight); 13071 return computeSegHorizontals(segs, eventOrderSpecs); // requires top/bottom from computeSegVerticals 13072 } 13073 // For each segment in an array, computes and assigns its top and bottom properties 13074 function computeSegVerticals(segs, dayDate, slatCoords, eventMinHeight) { 13075 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 13076 var seg = segs_1[_i]; 13077 seg.top = slatCoords.computeDateTop(seg.start, dayDate); 13078 seg.bottom = Math.max(seg.top + (eventMinHeight || 0), // yuck 13079 slatCoords.computeDateTop(seg.end, dayDate)); 13080 } 13081 } 13082 // Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each. 13083 // Assumed the segs are already ordered. 13084 // NOTE: Also reorders the given array by date! 13085 function computeSegHorizontals(segs, eventOrderSpecs) { 13086 // IMPORTANT TO CLEAR OLD RESULTS :( 13087 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 13088 var seg = segs_2[_i]; 13089 seg.level = null; 13090 seg.forwardCoord = null; 13091 seg.backwardCoord = null; 13092 seg.forwardPressure = null; 13093 } 13094 segs = sortEventSegs(segs, eventOrderSpecs); 13095 var level0; 13096 var levels = buildSlotSegLevels(segs); 13097 computeForwardSlotSegs(levels); 13098 if ((level0 = levels[0])) { 13099 for (var _a = 0, level0_1 = level0; _a < level0_1.length; _a++) { 13100 var seg = level0_1[_a]; 13101 computeSlotSegPressures(seg); 13102 } 13103 for (var _b = 0, level0_2 = level0; _b < level0_2.length; _b++) { 13104 var seg = level0_2[_b]; 13105 computeSegForwardBack(seg, 0, 0, eventOrderSpecs); 13106 } 13107 } 13108 return segs; 13109 } 13110 // Builds an array of segments "levels". The first level will be the leftmost tier of segments if the calendar is 13111 // left-to-right, or the rightmost if the calendar is right-to-left. Assumes the segments are already ordered by date. 13112 function buildSlotSegLevels(segs) { 13113 var levels = []; 13114 var i; 13115 var seg; 13116 var j; 13117 for (i = 0; i < segs.length; i++) { 13118 seg = segs[i]; 13119 // go through all the levels and stop on the first level where there are no collisions 13120 for (j = 0; j < levels.length; j++) { 13121 if (!computeSlotSegCollisions(seg, levels[j]).length) { 13122 break; 13123 } 13124 } 13125 seg.level = j; 13126 (levels[j] || (levels[j] = [])).push(seg); 13127 } 13128 return levels; 13129 } 13130 // Find all the segments in `otherSegs` that vertically collide with `seg`. 13131 // Append into an optionally-supplied `results` array and return. 13132 function computeSlotSegCollisions(seg, otherSegs, results) { 13133 if (results === void 0) { results = []; } 13134 for (var i = 0; i < otherSegs.length; i++) { 13135 if (isSlotSegCollision(seg, otherSegs[i])) { 13136 results.push(otherSegs[i]); 13137 } 13138 } 13139 return results; 13140 } 13141 // Do these segments occupy the same vertical space? 13142 function isSlotSegCollision(seg1, seg2) { 13143 return seg1.bottom > seg2.top && seg1.top < seg2.bottom; 13144 } 13145 // For every segment, figure out the other segments that are in subsequent 13146 // levels that also occupy the same vertical space. Accumulate in seg.forwardSegs 13147 function computeForwardSlotSegs(levels) { 13148 var i; 13149 var level; 13150 var j; 13151 var seg; 13152 var k; 13153 for (i = 0; i < levels.length; i++) { 13154 level = levels[i]; 13155 for (j = 0; j < level.length; j++) { 13156 seg = level[j]; 13157 seg.forwardSegs = []; 13158 for (k = i + 1; k < levels.length; k++) { 13159 computeSlotSegCollisions(seg, levels[k], seg.forwardSegs); 13160 } 13161 } 13162 } 13163 } 13164 // Figure out which path forward (via seg.forwardSegs) results in the longest path until 13165 // the furthest edge is reached. The number of segments in this path will be seg.forwardPressure 13166 function computeSlotSegPressures(seg) { 13167 var forwardSegs = seg.forwardSegs; 13168 var forwardPressure = 0; 13169 var i; 13170 var forwardSeg; 13171 if (seg.forwardPressure == null) { // not already computed 13172 for (i = 0; i < forwardSegs.length; i++) { 13173 forwardSeg = forwardSegs[i]; 13174 // figure out the child's maximum forward path 13175 computeSlotSegPressures(forwardSeg); 13176 // either use the existing maximum, or use the child's forward pressure 13177 // plus one (for the forwardSeg itself) 13178 forwardPressure = Math.max(forwardPressure, 1 + forwardSeg.forwardPressure); 13179 } 13180 seg.forwardPressure = forwardPressure; 13181 } 13182 } 13183 // Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range 13184 // from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and 13185 // seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left. 13186 // 13187 // The segment might be part of a "series", which means consecutive segments with the same pressure 13188 // who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of 13189 // segments behind this one in the current series, and `seriesBackwardCoord` is the starting 13190 // coordinate of the first segment in the series. 13191 function computeSegForwardBack(seg, seriesBackwardPressure, seriesBackwardCoord, eventOrderSpecs) { 13192 var forwardSegs = seg.forwardSegs; 13193 var i; 13194 if (seg.forwardCoord == null) { // not already computed 13195 if (!forwardSegs.length) { 13196 // if there are no forward segments, this segment should butt up against the edge 13197 seg.forwardCoord = 1; 13198 } 13199 else { 13200 // sort highest pressure first 13201 sortForwardSegs(forwardSegs, eventOrderSpecs); 13202 // this segment's forwardCoord will be calculated from the backwardCoord of the 13203 // highest-pressure forward segment. 13204 computeSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord, eventOrderSpecs); 13205 seg.forwardCoord = forwardSegs[0].backwardCoord; 13206 } 13207 // calculate the backwardCoord from the forwardCoord. consider the series 13208 seg.backwardCoord = seg.forwardCoord - 13209 (seg.forwardCoord - seriesBackwardCoord) / // available width for series 13210 (seriesBackwardPressure + 1); // # of segments in the series
13211 // use this segment's coordinates to computed the coordinates of the less-pressurized 13212 // forward segments 13213 for (i = 0; i < forwardSegs.length; i++) { 13214 computeSegForwardBack(forwardSegs[i], 0, seg.forwardCoord, eventOrderSpecs); 13215 } 13216 } 13217 } 13218 function sortForwardSegs(forwardSegs, eventOrderSpecs) { 13219 var objs = forwardSegs.map(buildTimeGridSegCompareObj); 13220 var specs = [ 13221 // put higher-pressure first 13222 { field: 'forwardPressure', order: -1 }, 13223 // put segments that are closer to initial edge first (and favor ones with no coords yet) 13224 { field: 'backwardCoord', order: 1 } 13225 ].concat(eventOrderSpecs); 13226 objs.sort(function (obj0, obj1) { 13227 return compareByFieldSpecs(obj0, obj1, specs); 13228 }); 13229 return objs.map(function (c) { 13230 return c._seg; 13231 }); 13232 } 13233 function buildTimeGridSegCompareObj(seg) { 13234 var obj = buildSegCompareObj(seg); 13235 obj.forwardPressure = seg.forwardPressure; 13236 obj.backwardCoord = seg.backwardCoord; 13237 return obj; 13238 } 13239 13240 var DEFAULT_TIME_FORMAT = createFormatter({ 13241 hour: 'numeric', 13242 minute: '2-digit', 13243 meridiem: false 13244 }); 13245 var TimeColEvent = /** @class */ (function (_super) { 13246 __extends(TimeColEvent, _super); 13247 function TimeColEvent() { 13248 return _super !== null && _super.apply(this, arguments) || this; 13249 } 13250 TimeColEvent.prototype.render = function () { 13251 var classNames = [ 13252 'fc-timegrid-event', 13253 'fc-v-event' 13254 ]; 13255 if (this.props.isCondensed) { 13256 classNames.push('fc-timegrid-event-condensed'); 13257 } 13258 return (createElement(StandardEvent, __assign({}, this.props, { defaultTimeFormat: DEFAULT_TIME_FORMAT, extraClassNames: classNames }))); 13259 }; 13260 return TimeColEvent; 13261 }(BaseComponent)); 13262 13263 config.timeGridEventCondensedHeight = 30; 13264 var TimeCol = /** @class */ (function (_super) { 13265 __extends(TimeCol, _super); 13266 function TimeCol() { 13267 return _super !== null && _super.apply(this, arguments) || this; 13268 } 13269 TimeCol.prototype.render = function () { 13270 var _this = this; 13271 var _a = this, props = _a.props, context = _a.context; 13272 var isSelectMirror = context.options.selectMirror; 13273 var mirrorSegs = (props.eventDrag && props.eventDrag.segs) || 13274 (props.eventResize && props.eventResize.segs) || 13275 (isSelectMirror && props.dateSelectionSegs) || 13276 []; 13277 var interactionAffectedInstances = // TODO: messy way to compute this 13278 (props.eventDrag && props.eventDrag.affectedInstances) || 13279 (props.eventResize && props.eventResize.affectedInstances) || 13280 {}; 13281 return (createElement(DayCellRoot, { elRef: props.elRef, date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, extraHookProps: props.extraHookProps }, function (rootElRef, classNames, dataAttrs) { return (createElement("td", __assign({ ref: rootElRef, className: ['fc-timegrid-col'].concat(classNames, props.extraClassNames || []).join(' ') }, dataAttrs, props.extraDataAttrs), 13282 createElement("div", { className: 'fc-timegrid-col-frame' }, 13283 createElement("div", { className: 'fc-timegrid-col-bg' }, 13284 _this.renderFillSegs(props.businessHourSegs, 'non-business'), 13285 _this.renderFillSegs(props.bgEventSegs, 'bg-event'), 13286 _this.renderFillSegs(props.dateSelectionSegs, 'highlight')), 13287 createElement("div", { className: 'fc-timegrid-col-events' }, _this.renderFgSegs(props.fgEventSegs, interactionAffectedInstances)), 13288 createElement("div", { className: 'fc-timegrid-col-events' }, _this.renderFgSegs(mirrorSegs, {}, Boolean(props.eventDrag), Boolean(props.eventResize), Boolean(isSelectMirror) 13289 // TODO: pass in left/right instead of using only computeSegTopB
13289ottomCss 13290 )), 13291 createElement("div", { className: 'fc-timegrid-now-indicator-container' }, _this.renderNowIndicator(props.nowIndicatorSegs)), 13292 createElement(TimeColMisc, { date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, extraHookProps: props.extraHookProps })))); })); 13293 }; 13294 TimeCol.prototype.renderFgSegs = function (segs, segIsInvisible, isDragging, isResizing, isDateSelecting) { 13295 var props = this.props; 13296 if (props.forPrint) { 13297 return this.renderPrintFgSegs(segs); 13298 } 13299 else if (props.slatCoords) { 13300 return this.renderPositionedFgSegs(segs, segIsInvisible, isDragging, isResizing, isDateSelecting); 13301 } 13302 }; 13303 TimeCol.prototype.renderPrintFgSegs = function (segs) { 13304 var _a = this, props = _a.props, context = _a.context; 13305 // not DRY 13306 segs = sortEventSegs(segs, context.options.eventOrder); 13307 return segs.map(function (seg) { return (createElement("div", { className: 'fc-timegrid-event-harness', key: seg.eventRange.instance.instanceId }, 13308 createElement(TimeColEvent, __assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false, isCondensed: false }, getSegMeta(seg, props.todayRange, props.nowDate))))); }); 13309 }; 13310 TimeCol.prototype.renderPositionedFgSegs = function (segs, segIsInvisible, isDragging, isResizing, isDateSelecting) { 13311 var _this = this; 13312 var _a = this, context = _a.context, props = _a.props; 13313 // assigns TO THE SEGS THEMSELVES 13314 // also, receives resorted array 13315 segs = computeSegCoords(segs, props.date, props.slatCoords, context.options.eventMinHeight, context.options.eventOrder); 13316 return segs.map(function (seg) { 13317 var instanceId = seg.eventRange.instance.instanceId; 13318 var isMirror = isDragging || isResizing || isDateSelecting; 13319 var positionCss = isMirror ? __assign({ left: 0, right: 0 }, _this.computeSegTopBottomCss(seg)) : 13320 _this.computeFgSegPositionCss(seg); 13321 return (createElement("div", { className: 'fc-timegrid-event-harness' + (seg.level > 0 ? ' fc-timegrid-event-harness-inset' : ''), key: instanceId, style: __assign({ visibility: segIsInvisible[instanceId] ? 'hidden' : '' }, positionCss) }, 13322 createElement(TimeColEvent, __assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === props.eventSelection, isCondensed: (seg.bottom - seg.top) < config.timeGridEventCondensedHeight }, getSegMeta(seg, props.todayRange, props.nowDate))))); 13323 }); 13324 }; 13325 TimeCol.prototype.renderFillSegs = function (segs, fillType) { 13326 var _this = this; 13327 var _a = this, context = _a.context, props = _a.props; 13328 if (!props.slatCoords) { 13329 return; 13330 } 13331 // BAD: assigns TO THE SEGS THEMSELVES 13332 computeSegVerticals(segs, props.date, props.slatCoords, context.options.eventMinHeight); 13333 var children = segs.map(function (seg) { return (createElement("div", { key: buildEventRangeKey(seg.eventRange), className: 'fc-timegrid-bg-harness', style: _this.computeSegTopBottomCss(seg) }, fillType === 'bg-event' ? 13334 createElement(BgEvent, __assign({ seg: seg }, getSegMeta(seg, props.todayRange, props.nowDate))) : 13335 renderFill(fillType))); }); 13336 return createElement(Fragment, null, children); 13337 }; 13338 TimeCol.prototype.renderNowIndicator = function (segs) { 13339 var _a = this.props, slatCoords = _a.slatCoords, date = _a.date; 13340 if (!slatCoords) { 13341 return; 13342 } 13343 return segs.map(function (seg, i) { return (createElement(NowIndicatorRoot, { isAxis: false, date: date, key: i /* key doesn't matter. will only ever be one */ }, function (rootElRef, classNames, innerElRef, innerContent) { return (createElement("div", { ref: rootElRef, className: ['fc-timegrid-now-indicator-line'].concat(classNames).join(' '), style: { top: slatCoords.computeDateTop(seg.start, date) } }, innerContent)); })); }); 13344 }; 13345 TimeCol.prototype.computeFgSegPositionCss = function (seg) { 13346 var _a = this.context, isRtl = _a.isRtl, options = _a.options; 13347 var shouldOverlap = options.slotEventOverlap; 13348 var backwardCoord = seg.backwardCoord; // the left side if LTR. the right side if RTL. floating-point 13349 var forwardCoord = seg.forwardCoord; // the right side if LTR. the left side if RTL. floating-point 13350 var left; // amount of space from left edge, a fraction of the total width 13351 var right; // amount of space from right edge, a fraction of the total width 13352 if (shouldOverlap) { 13353 // double the width, but don't go beyond the maximum forward coordinate (1.0) 13354 forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2); 13355 } 13356 if (isRtl) { 13357 left = 1 - forwardCoord; 13358 right = backwardCoord; 13359 } 13360 else { 13361 left = backwardCoord; 13362 right = 1 - forwardCoord; 13363 } 13364 var props = { 13365 zIndex: seg.level + 1, 13366 left: left * 100 + '%', 13367 right: right * 100 + '%' 13368 }; 13369 if (shouldOverlap && seg.forwardPressure) { 13370 // add padding to the edge so that forward stacked events don't cover the resizer's icon 13371 props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width 13372 } 13373 return __assign(__assign({}
13373, props), this.computeSegTopBottomCss(seg)); 13374 }; 13375 TimeCol.prototype.computeSegTopBottomCss = function (seg) { 13376 return { 13377 top: seg.top, 13378 bottom: -seg.bottom 13379 }; 13380 }; 13381 return TimeCol; 13382 }(BaseComponent)); 13383 var TimeColMisc = /** @class */ (function (_super) { 13384 __extends(TimeColMisc, _super); 13385 function TimeColMisc() { 13386 return _super !== null && _super.apply(this, arguments) || this; 13387 } 13388 TimeColMisc.prototype.render = function () { 13389 var props = this.props; 13390 return (createElement(DayCellContent, { date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, extraHookProps: props.extraHookProps }, function (innerElRef, innerContent) { return (innerContent && 13391 createElement("div", { className: 'fc-timegrid-col-misc', ref: innerElRef }, innerContent)); })); 13392 }; 13393 return TimeColMisc; 13394 }(BaseComponent)); 13395 13396 var TimeColsContent = /** @class */ (function (_super) { 13397 __extends(TimeColsContent, _super); 13398 function TimeColsContent() { 13399 var _this = _super !== null && _super.apply(this, arguments) || this; 13400 _this.splitFgEventSegs = memoize(splitSegsByCol); 13401 _this.splitBgEventSegs = memoize(splitSegsByCol); 13402 _this.splitBusinessHourSegs = memoize(splitSegsByCol); 13403 _this.splitNowIndicatorSegs = memoize(splitSegsByCol); 13404 _this.splitDateSelectionSegs = memoize(splitSegsByCol); 13405 _this.splitEventDrag = memoize(splitInteractionByCol); 13406 _this.splitEventResize = memoize(splitInteractionByCol); 13407 _this.rootElRef = createRef(); 13408 _this.cellElRefs = new RefMap(); 13409 return _this; 13410 } 13411 TimeColsContent.prototype.render = function () { 13412 var _this = this; 13413 var _a = this, props = _a.props, context = _a.context; 13414 var nowIndicatorTop = context.options.nowIndicator && 13415 props.slatCoords && 13416 props.slatCoords.safeComputeTop(props.nowDate); // might return void 13417 var colCnt = props.cells.length; 13418 var fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, colCnt); 13419 var bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, colCnt); 13420 var businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, colCnt); 13421 var nowIndicatorSegsByRow = this.splitNowIndicatorSegs(props.nowIndicatorSegs, colCnt); 13422 var dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, colCnt); 13423 var eventDragByRow = this.splitEventDrag(props.eventDrag, colCnt); 13424 var eventResizeByRow = this.splitEventResize(props.eventResize, colCnt); 13425 return (createElement("div", { className: 'fc-timegrid-cols', ref: this.rootElRef }, 13426 createElement("table", { style: { 13427 minWidth: props.tableMinWidth, 13428 width: props.clientWidth 13429 } }, 13430 props.tableColGroupNode, 13431 createElement("tbody", null, 13432 createElement("tr", null, 13433 props.axis && 13434 createElement("td", { className: 'fc-timegrid-col fc-timegrid-axis' }, 13435 createElement("div", { className: 'fc-timegrid-col-frame' }, 13436 createElement("div", { className: 'fc-timegrid-now-indicator-container' }, typeof nowIndicatorTop === 'number' && 13437 createElement(NowIndicatorRoot, { isAxis: true, date: props.nowDate }, function (rootElRef, classNames, innerElRef, innerContent) { return (createElement("div", { ref: rootElRef, className: ['fc-timegrid-now-indicator-arrow'].concat(classNames).join(' '), style: { top: nowIndicatorTop } }, innerContent)); })))), 13438 props.cells.map(function (cell, i) { return (createElement(TimeCol, { key: cell.key, elRef: _this.cellElRefs.createRef(cell.key), dateProfile: props.dateProfile, date: cell.date, nowDate: props.nowDate, todayRange: props.todayRange, extraHookProps: cell.extraHookProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, 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 })); })))))); 13439 }; 13440 TimeColsContent.prototype.componentDidMount = function () { 13441 this.updateCoords(); 13442 }; 13443 TimeColsContent.prototype.componentDidUpdate = function () { 13444 this.updateCoords(); 13445 }; 13446 TimeColsContent.prototype.updateCoords = function () { 13447 var props = this.props; 13448 if (props.onColCoords && 13449 props.clientWidth !== null // means sizing has stabilized 13450 ) { 13451 props.onColCoords(new PositionCache(this.rootElRef.current, collectCellEls(this.cellElRefs.currentMap, props.cells), true, // horizontal 13452 false)); 13453 } 13454 }; 13455 return TimeColsContent; 13456 }(BaseComponent)); 13457 function collectCellEls(elMap, cells) { 13458 return cells.map(function (cell) { return elMap[cell.key]; }); 13459 } 13460 13461 /* A component that renders one or more columns of vertical time slots 13462 ----------------------------------------------------------------------------------------------------------------------*/ 13463 var TimeCols = /** @class */ (function (_super) { 13464 __extends(TimeCols, _super); 13465 function TimeCols() { 13466 var _this = _super !== null && _super.apply(this, arguments) || this; 13467 _this.processSlotOptions = memoize(processSlotOptions); 13468 _this.state = { 13469 slatCoords: null 13470 }; 13471 _this.handleScrollRequest = function (request) { 13472 var onScrollTopRequest = _this.props.onScrollTopRequest; 13473 var slatCoords = _this.state.slatCoords; 13474 if (onScrollTopRequest && slatCoords) { 13475 if (request.time) { 13476 var top_1 = slatCoords.computeTimeTop(request.time); 13477 top_1 = Math.ceil(top_1); // zoom can give weird floating-point values. rather scroll a little bit further 13478 if (top_1) { 13479 top_1++; 13480 } // to overcome top border that slots beyond the first have. looks better 13481 onScrollTopRequest(top_1); 13482 } 13483 return true; 13484 } 13485 }; 13486 _this.handleColCoords = function (colCoords) { 13487 _this.colCoords = colCoords; 13488 }; 13489 _this.handleSlatCoords = function (slatCoords) {
13490 _this.setState({ slatCoords: slatCoords }); 13491 if (_this.props.onSlatCoords) { 13492 _this.props.onSlatCoords(slatCoords); 13493 } 13494 }; 13495 return _this; 13496 } 13497 TimeCols.prototype.render = function () { 13498 var _a = this, props = _a.props, state = _a.state; 13499 return (createElement("div", { className: 'fc-timegrid-body', ref: props.rootElRef, style: { 13500 // these props are important to give this wrapper correct dimensions for interactions 13501 // TODO: if we set it here, can we avoid giving to inner tables? 13502 width: props.clientWidth, 13503 minWidth: props.tableMinWidth 13504 } }, 13505 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 /* axis depends on the colgroup's shrinking */, onCoords: this.handleSlatCoords }), 13506 createElement(TimeColsContent, { cells: props.cells, axis: props.axis, dateProfile: props.dateProfile, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bg
13506EventSegs, 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 }))); 13507 }; 13508 TimeCols.prototype.componentDidMount = function () { 13509 this.scrollResponder = this.context.createScrollResponder(this.handleScrollRequest); 13510 }; 13511 TimeCols.prototype.componentDidUpdate = function (prevProps) { 13512 this.scrollResponder.update(prevProps.dateProfile !== this.props.dateProfile); 13513 }; 13514 TimeCols.prototype.componentWillUnmount = function () { 13515 this.scrollResponder.detach(); 13516 }; 13517 TimeCols.prototype.positionToHit = function (positionLeft, positionTop) { 13518 var _a = this.context, dateEnv = _a.dateEnv, options = _a.options; 13519 var colCoords = this.colCoords; 13520 var dateProfile = this.props.dateProfile; 13521 var slatCoords = this.state.slatCoords; 13522 var _b = this.processSlotOptions(this.props.slotDuration, options.snapDuration), snapDuration = _b.snapDuration, snapsPerSlot = _b.snapsPerSlot; 13523 var colIndex = colCoords.leftToIndex(positionLeft); 13524 var slatIndex = slatCoords.positions.topToIndex(positionTop); 13525 if (colIndex != null && slatIndex != null) { 13526 var slatTop = slatCoords.positions.tops[slatIndex]; 13527 var slatHeight = slatCoords.positions.getHeight(slatIndex); 13528 var partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1 13529 var localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat 13530 var snapIndex = slatIndex * snapsPerSlot + localSnapIndex; 13531 var dayDate = this.props.cells[colIndex].date; 13532 var time = addDurations(dateProfile.slotMinTime, multiplyDuration(snapDuration, snapIndex)); 13533 var start = dateEnv.add(dayDate, time); 13534 var end = dateEnv.add(start, snapDuration); 13535 return { 13536 col: colIndex, 13537 dateSpan: { 13538 range: { start: start, end: end }, 13539 allDay: false 13540 }, 13541 dayEl: colCoords.els[colIndex], 13542 relativeRect: { 13543 left: colCoords.lefts[colIndex], 13544 right: colCoords.rights[colIndex], 13545 top: slatTop, 13546 bottom: slatTop + slatHeight 13547 } 13548 }; 13549 } 13550 }; 13551 return TimeCols; 13552 }(BaseComponent)); 13553 function processSlotOptions(slotDuration, snapDurationOverride) { 13554 var snapDuration = snapDurationOverride || slotDuration; 13555 var snapsPerSlot = wholeDivideDurations(slotDuration, snapDuration); 13556 if (snapsPerSlot === null) { 13557 snapDuration = slotDuration; 13558 snapsPerSlot = 1; 13559 // TODO: say warning? 13560 } 13561 return { snapDuration: snapDuration, snapsPerSlot: snapsPerSlot }; 13562 } 13563 13564 var DayTimeCols = /** @class */ (function (_super) { 13565 __extends(DayTimeCols, _super); 13566 function DayTimeCols() { 13567 var _this = _super !== null && _super.apply(this, arguments) || this; 13568 _this.buildDayRanges = memoize(buildDayRanges); 13569 _this.slicer = new DayTimeColsSlicer(); 13570 _this.timeColsRef = createRef(); 13571 _this.handleRootEl = function (rootEl) { 13572 if (rootEl) { 13573 _this.context.registerInteractiveComponent(_this, { el: rootEl }); 13574 } 13575 else { 13576 _this.context.unregisterInteractiveComponent(_this); 13577 } 13578 }; 13579 return _this; 13580 } 13581 DayTimeCols.prototype.render = function () { 13582 var _this = this; 13583 var _a = this, props = _a.props, context = _a.context; 13584 var dateProfile = props.dateProfile, dayTableModel = props.dayTableModel; 13585 var isNowIndicator = context.options.nowIndicator; 13586 var dayRanges = this.buildDayRanges(dayTableModel, dateProfile, context.dateEnv); 13587 // give it the first row of cells 13588 // TODO: would move this further down hierarchy, but sliceNowDate needs it 13589 return (createElement(NowTimer, { unit: isNowIndicator ? 'minute' : 'day' }, function (nowDate, todayRange) { return (createElement(TimeCols, __assign({ ref: _this.timeColsRef, rootElRef: _this.handleRootEl }, _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: n
13589owDate, nowIndicatorSegs: isNowIndicator && _this.slicer.sliceNowDate(nowDate, context, dayRanges), todayRange: todayRange, onScrollTopRequest: props.onScrollTopRequest, onSlatCoords: props.onSlatCoords }))); })); 13590 }; 13591 DayTimeCols.prototype.queryHit = function (positionLeft, positionTop) { 13592 var rawHit = this.timeColsRef.current.positionToHit(positionLeft, positionTop); 13593 if (rawHit) { 13594 return { 13595 component: this, 13596 dateSpan: rawHit.dateSpan, 13597 dayEl: rawHit.dayEl, 13598 rect: { 13599 left: rawHit.relativeRect.left, 13600 right: rawHit.relativeRect.right, 13601 top: rawHit.relativeRect.top, 13602 bottom: rawHit.relativeRect.bottom 13603 }, 13604 layer: 0 13605 }; 13606 } 13607 }; 13608 return DayTimeCols; 13609 }(DateComponent)); 13610 function buildDayRanges(dayTableModel, dateProfile, dateEnv) { 13611 var ranges = []; 13612 for (var _i = 0, _a = dayTableModel.headerDates; _i < _a.length; _i++) { 13613 var date = _a[_i]; 13614 ranges.push({ 13615 start: dateEnv.add(date, dateProfile.slotMinTime), 13616 end: dateEnv.add(date, dateProfile.slotMaxTime) 13617 }); 13618 } 13619 return ranges; 13620 } 13621 var DayTimeColsSlicer = /** @class */ (function (_super) { 13622 __extends(DayTimeColsSlicer, _super); 13623 function DayTimeColsSlicer() { 13624 return _super !== null && _super.apply(this, arguments) || this; 13625 } 13626 DayTimeColsSlicer.prototype.sliceRange = function (range, dayRanges) { 13627 var segs = []; 13628 for (var col = 0; col < dayRanges.length; col++) { 13629 var segRange = intersectRanges(range, dayRanges[col]); 13630 if (segRange) { 13631 segs.push({ 13632 start: segRange.start, 13633 end: segRange.end, 13634 isStart: segRange.start.valueOf() === range.start.valueOf(), 13635 isEnd: segRange.end.valueOf() === range.end.valueOf(), 13636 col: col 13637 }); 13638 } 13639 } 13640 return segs; 13641 }; 13642 return DayTimeColsSlicer; 13643 }(Slicer)); 13644 13645 var DayTimeColsView = /** @class */ (function (_super) { 13646 __extends(DayTimeColsView, _super); 13647 function DayTimeColsView() { 13648 var _this = _super !== null && _super.apply(this, arguments) || this; 13649 _this.buildTimeColsModel = memoize(buildTimeColsModel); 13650 _this.buildSlatMetas = memoize(buildSlatMetas); 13651 return _this; 13652 } 13653 DayTimeColsView.prototype.render = function () { 13654 var _this = this; 13655 var _a = this.context, options = _a.options, dateEnv = _a.dateEnv, dateProfileGenerator = _a.dateProfileGenerator; 13656 var props = this.props; 13657 var dateProfile = props.dateProfile;
13658 var dayTableModel = this.buildTimeColsModel(dateProfile, dateProfileGenerator); 13659 var splitProps = this.allDaySplitter.splitProps(props); 13660 var slatMetas = this.buildSlatMetas(dateProfile.slotMinTime, dateProfile.slotMaxTime, options.slotLabelInterval, options.slotDuration, dateEnv); 13661 var dayMinWidth = options.dayMinWidth; 13662 var hasAttachedAxis = !dayMinWidth; 13663 var hasDetachedAxis = dayMinWidth; 13664 var headerContent = options.dayHeaders && 13665 createElement(DayHeader, { dates: dayTableModel.headerDates, dateProfile: dateProfile, datesRepDistinctDays: true, renderIntro: hasAttachedAxis ? this.renderHeadAxis : null }); 13666 var allDayContent = (options.allDaySlot !== false) && (function (contentArg) { return (createElement(DayTable, __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()))); }); 13667 var timeGridContent = function (contentArg) { return (createElement(DayTimeCols, __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 }))); }; 13668 return hasDetachedAxis 13669 ? this.renderHScrollLayout(headerContent, allDayContent, timeGridContent, dayTableModel.colCnt, dayMinWidth, slatMetas, this.state.slatCoords) 13670 : this.renderSimpleLayout(headerContent, allDayContent, timeGridContent); 13671 }; 13672 return DayTimeColsView; 13673 }(TimeColsView));
13674 function buildTimeColsModel(dateProfile, dateProfileGenerator) { 13675 var daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator); 13676 return new DayTableModel(daySeries, false); 13677 } 13678 13679 var OPTION_REFINERS$1 = { 13680 allDaySlot: Boolean 13681 }; 13682 13683 var timeGridPlugin = createPlugin({ 13684 initialView: 'timeGridWeek', 13685 optionRefiners: OPTION_REFINERS$1, 13686 views: { 13687 timeGrid: { 13688 component: DayTimeColsView, 13689 usesMinMaxTime: true, 13690 allDaySlot: true, 13691 slotDuration: '00:30:00', 13692 slotEventOverlap: true // a bad name. confused with overlap/constraint system 13693 }, 13694 timeGridDay: { 13695 type: 'timeGrid', 13696 duration: { days: 1 } 13697 }, 13698 timeGridWeek: { 13699 type: 'timeGrid', 13700 duration: { weeks: 1 } 13701 } 13702 } 13703 }); 13704 13705 var ListViewHeaderRow = /** @class */ (function (_super) { 13706 __extends(ListViewHeaderRow, _super); 13707 function ListViewHeaderRow() { 13708 return _super !== null && _super.apply(this, arguments) || this; 13709 } 13710 ListViewHeaderRow.prototype.render = function () { 13711 var _a = this.props, dayDate = _a.dayDate, todayRange = _a.todayRange; 13712 var _b = this.context, theme = _b.theme, dateEnv = _b.dateEnv, options = _b.options, viewApi = _b.viewApi; 13713 var dayMeta = getDateMeta(dayDate, todayRange); 13714 var text = options.listDayFormat ? dateEnv.format(dayDate, options.listDayFormat) : ''; // will ever be falsy? 13715 var sideText = options.listDaySideFormat ? dateEnv.format(dayDate, options.listDaySideFormat) : ''; // will ever be falsy? also, BAD NAME "alt" 13716 var navLinkData = options.navLinks 13717 ? buildNavLinkData(dayDate) 13718 : null; 13719 var hookProps = __assign({ date: dateEnv.toDate(dayDate), view: viewApi, text: text, 13720 sideText: sideText, 13721 navLinkData: navLinkData }, dayMeta); 13722 var classNames = ['fc-list-day'].concat(getDayClassNames(dayMeta, theme)); 13723 // TODO: make a reusable HOC for dayHeader (used in daygrid/timegrid too) 13724 return (createElement(RenderHook, { hookProps: hookProps, classNames: options.dayHeaderClassNames, content: options.dayHeaderContent, defaultContent: renderInnerContent$4, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, function (rootElRef, customClassNames, innerElRef, innerContent) { return (createElement("tr", { ref: rootElRef, className: classNames.concat(customClassNames).join(' '), "data-date": formatDayString(dayDate) }, 13725 createElement("th", { colSpan: 3 }, 13726 createElement("div", { className: 'fc-list-day-cushion ' + theme.getClass('tableCellShaded'), ref: innerElRef }, innerContent)))); })); 13727 }; 13728 return ListViewHeaderRow; 13729 }(BaseComponent)); 13730 function renderInnerContent$4(props) { 13731 var navLinkAttrs = props.navLinkData // is there a type for this? 13732 ? { 'data-navlink': props.navLinkData, tabIndex: 0 } 13733 : {}; 13734 return (createElement(Fragment, null, 13735 props.text && 13736 createElement("a", __assign({ className: 'fc-list-day-text' }, navLinkAttrs), props.text), 13737 props.sideText && 13738 createElement("a", __assign({ className: 'fc-list-day-side-text' }, navLinkAttrs), props.sideText))); 13739 } 13740 13741 var DEFAULT_TIME_FORMAT$1 = createFormatter({ 13742 hour: 'numeric', 13743 minute: '2-digit', 13744 meridiem: 'short' 13745 }); 13746 var ListViewEventRow = /** @class */ (function (_super) { 13747 __extends(ListViewEventRow, _super); 13748 function ListViewEventRow() { 13749 return _super !== null && _super.apply(this, arguments) || this; 13750 } 13751 ListViewEventRow.prototype.render = function () { 13752 var _a = this, props = _a.props, context = _a.context; 13753 var seg = props.seg; 13754 var timeFormat = context.options.eventTimeFormat || DEFAULT_TIME_FORMAT$1; 13755 return (createElement(EventRoot, { seg: seg, timeText: '' /* BAD. because of all-day content */, disableDragging: true, disableResizing: true, defaultContent: renderEventInnerContent, isPast: props.isPast, isFuture: props.isFuture, isToday: props.isToday, isSelected: props.isSelected, isDragging: props.isDragging, isResizing: props.isResizing, isDateSelecting: props.isDateSelecting }, function (rootElRef, classNames, innerElRef, innerContent, hookProps) { return (createElement("tr", { className: ['fc-list-event', hookProps.event.url ? 'fc-event-forced-url' : ''].concat(classNames).join(' '), ref: rootElRef }, 13756 buildTimeContent(seg, timeFormat, context), 13757 createElement("td", { className: 'fc-list-event-graphic' }, 13758 createElement("span", { className: 'fc-list-event-dot', style: { borderColor: hookProps.borderColor || hookProps.backgroundColor } })), 13759 createElement("td", { className: 'fc-list-event-title', ref: innerElRef }, innerContent))); })); 13760 }; 13761 return ListViewEventRow; 13762 }(BaseComponent)); 13763 function renderEventInnerContent(props) { 13764 var event = props.event; 13765 var url = event.url; 13766 var anchorAttrs = url ? { href: url } : {}; 13767 return (createElement("a", __assign({}, anchorAttrs), event.title)); 13768 } 13769 function buildTimeContent(seg, timeFormat, context) { 13770 var options = context.options; 13771 if (options.displayEventTime !== false) { 13772 var eventDef = seg.eventRange.def; 13773 var eventInstance = seg.eventRange.instance; 13774 var doAllDay = false;
13775 var timeText = void 0; 13776 if (eventDef.allDay) { 13777 doAllDay = true; 13778 } 13779 else if (isMultiDayRange(seg.eventRange.range)) { // TODO: use (!isStart || !isEnd) instead? 13780 if (seg.isStart) { 13781 timeText = buildSegTimeText(seg, timeFormat, context, null, null, eventInstance.range.start, seg.end); 13782 } 13783 else if (seg.isEnd) { 13784 timeText = buildSegTimeText(seg, timeFormat, context, null, null, seg.start, eventInstance.range.end); 13785 } 13786 else { 13787 doAllDay = true; 13788 } 13789 } 13790 else { 13791 timeText = buildSegTimeText(seg, timeFormat, context); 13792 } 13793 if (doAllDay) { 13794 var hookProps = { 13795 text: context.options.allDayText, 13796 view: context.viewApi 13797 }; 13798 return (createElement(RenderHook, { hookProps: hookProps, classNames: options.allDayClassNames, content: options.allDayContent, defaultContent: renderAllDayInner$1, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }, function (rootElRef, classNames, innerElRef, innerContent) { return (createElement("td", { className: ['fc-list-event-time'].concat(classNames).join(' '), ref: rootElRef }, innerContent)); })); 13799 } 13800 else { 13801 return (createElement("td", { className: 'fc-list-event-time' }, timeText)); 13802 } 13803 } 13804 return null; 13805 } 13806 function renderAllDayInner$1(hookProps) { 13807 return hookProps.text; 13808 } 13809 13810 /* 13811 Responsible for the scroller, and forwarding event-related actions into the "grid". 13812 */ 13813 var ListView = /** @class */ (function (_super) { 13814 __extends(ListView, _super); 13815 function ListView() { 13816 var _this = _super !== null && _super.apply(this, arguments) || this; 13817 _this.computeDateVars = memoize(computeDateVars); 13818 _this.eventStoreToSegs = memoize(_this._eventStoreToSegs); 13819 _this.setRootEl = function (rootEl) { 13820 if (rootEl) { 13821 _this.context.registerInteractiveComponent(_this, { 13822 el: rootEl 13823 }); 13824 } 13825 else { 13826 _this.context.unregisterInteractiveComponent(_this); 13827 } 13828 }; 13829 return _this; 13830 } 13831 ListView.prototype.render = function () { 13832 var _this = this; 13833 var _a = this, props = _a.props, context = _a.context; 13834 var extraClassNames = [ 13835 'fc-list', 13836 context.theme.getClass('table'), 13837 context.options.stickyHeaderDates !== false ? 'fc-list-sticky' : '' 13838 ]; 13839 var _b = this.computeDateVars(props.dateProfile), dayDates = _b.dayDates, dayRanges = _b.dayRanges; 13840 var eventSegs = this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges); 13841 return (createElement(ViewRoot, { viewSpec: context.viewSpec, elRef: this.setRootEl }, function (rootElRef, classNames) { return (createElement("div", { ref: rootElRef, className: extraClassNames.concat(classNames).join(' ') }, 13842 createElement(Scroller, { liquid: !props.isHeightAuto, overflowX: props.isHeightAuto ? 'visible' : 'hidden', overflowY: props.isHeightAuto ? 'visible' : 'auto' }, eventSegs.length > 0 ? 13843 _this.renderSegList(eventSegs, dayDates) : 13844 _this.renderEmptyMessage()))); })); 13845 }; 13846 ListView.prototype.renderEmptyMessage = function () { 13847 var _a = this.context, options = _a.options, viewApi = _a.viewApi; 13848 var hookProps = { 13849 text: options.noEventsText, 13850 view: viewApi 13851 }; 13852 return (createElement(RenderHook, { hookProps: hookProps, classNames: options.noEventsClassNames, content: options.noEventsContent, defaultContent: renderNoEventsInner, didMount: options.noEventsDidMount, willUnmount: options.noEventsWillUnmount }, function (rootElRef, classNames, innerElRef, innerContent) { return (createElement("div", { className: ['fc-list-empty'].concat(classNames).join(' '), ref: rootElRef }, 13853 createElement("div", { className: 'fc-list-empty-cushion', ref: innerElRef }, innerContent))); })); 13854 }; 13855 ListView.prototype.renderSegList = function (allSegs, dayDates) { 13856 var _a = this.context, theme = _a.theme, options = _a.options; 13857 var segsByDay = groupSegsByDay(allSegs); // sparse array 13858 return (createElement(NowTimer, { unit: 'day' }, function (nowDate, todayRange) { 13859 var innerNodes = []; 13860 for (var dayIndex = 0; dayIndex < segsByDay.length; dayIndex++) { 13861 var daySegs = segsByDay[dayIndex]; 13862 if (daySegs) { // sparse array, so might be undefined 13863 var dayStr = dayDates[dayIndex].toISOString(); 13864 // append a day header 13865 innerNodes.push(createElement(ListViewHeaderRow, { key: dayStr, dayDate: dayDates[dayIndex], todayRange: todayRange })); 13866 daySegs = sortEventSegs(daySegs, options.eventOrder);
13867 for (var _i = 0, daySegs_1 = daySegs; _i < daySegs_1.length; _i++) { 13868 var seg = daySegs_1[_i]; 13869 innerNodes.push(createElement(ListViewEventRow, __assign({ key: dayStr + ':' + seg.eventRange.instance.instanceId /* are multiple segs for an instanceId */, seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false }, getSegMeta(seg, todayRange, nowDate)))); 13870 } 13871 } 13872 } 13873 return (createElement("table", { className: 'fc-list-table ' + theme.getClass('table') }, 13874 createElement("tbody", null, innerNodes))); 13875 })); 13876 }; 13877 ListView.prototype._eventStoreToSegs = function (eventStore, eventUiBases, dayRanges) { 13878 return this.eventRangesToSegs(sliceEventStore(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.context.options.nextDayThreshold).fg, dayRanges); 13879 }; 13880 ListView.prototype.eventRangesToSegs = function (eventRanges, dayRanges) { 13881 var segs = []; 13882 for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) { 13883 var eventRange = eventRanges_1[_i]; 13884 segs.push.apply(segs, this.eventRangeToSegs(eventRange, dayRanges)); 13885 } 13886 return segs; 13887 }; 13888 ListView.prototype.eventRangeToSegs = function (eventRange, dayRanges) { 13889 var dateEnv = this.context.dateEnv; 13890 var nextDayThreshold = this.context.options.nextDayThreshold; 13891 var range = eventRange.range; 13892 var allDay = eventRange.def.allDay; 13893 var dayIndex; 13894 var segRange; 13895 var seg; 13896 var segs = []; 13897 for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex++) { 13898 segRange = intersectRanges(range, dayRanges[dayIndex]); 13899 if (segRange) { 13900 seg = { 13901 component: this, 13902 eventRange: eventRange, 13903 start: segRange.start, 13904 end: segRange.end, 13905 isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(), 13906 isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(), 13907 dayIndex: dayIndex 13908 }; 13909 segs.push(seg); 13910 // detect when range won't go fully into the next day, 13911 // and mutate the latest seg to the be the end. 13912 if (!seg.isEnd && !allDay && 13913 dayIndex + 1 < dayRanges.length && 13914 range.end < 13915 dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) { 13916 seg.end = range.end; 13917 seg.isEnd = true; 13918 break; 13919 } 13920 } 13921 } 13922 return segs; 13923 }; 13924 return ListView; 13925 }(DateComponent)); 13926 function renderNoEventsInner(hookProps) { 13927 return hookProps.text; 13928 } 13929 function computeDateVars(dateProfile) { 13930 var dayStart = startOfDay(dateProfile.renderRange.start); 13931 var viewEnd = dateProfile.renderRange.end; 13932 var dayDates = []; 13933 var dayRanges = []; 13934 while (dayStart < viewEnd) { 13935 dayDates.push(dayStart); 13936 dayRanges.push({ 13937 start: dayStart, 13938 end: addDays(dayStart, 1) 13939 }); 13940 dayStart = addDays(dayStart, 1); 13941 } 13942 return { dayDates: dayDates, dayRanges: dayRanges }; 13943 } 13944 // Returns a sparse array of arrays, segs grouped by their dayIndex 13945 function groupSegsByDay(segs) { 13946 var segsByDay = []; // sparse array 13947 var i; 13948 var seg; 13949 for (i = 0; i < segs.length; i++) { 13950 seg = segs[i]; 13951 (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = [])) 13952 .push(seg); 13953 } 13954 return segsByDay; 13955 } 13956 13957 var OPTION_REFINERS$2 = { 13958 listDayFormat: createFalsableFormatter, 13959 listDaySideFormat: createFalsableFormatter, 13960 noEventsClassNames: identity, 13961 noEventsContent: identity, 13962 noEventsDidMount: identity, 13963 noEventsWillUnmount: identity 13964 // noEventsText is defined in base options 13965 }; 13966 function createFalsableFormatter(input) { 13967 return input === false ? null : createFormatter(input); 13968 } 13969 13970 var listPlugin = createPlugin({ 13971 optionRefiners: OPTION_REFINERS$2, 13972 views: { 13973 list: { 13974 component: ListView, 13975 buttonTextKey: 'list', 13976 listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' } // like "January 1, 2016" 13977 }, 13978 listDay: { 13979 type: 'list', 13980 duration: { days: 1 }, 13981 listDayFormat: { weekday: 'long' } // day-of-week is all we need. full date is probably in headerToolbar 13982 }, 13983 listWeek: { 13984 type: 'list', 13985 duration: { weeks: 1 }, 13986 listDayFormat: { weekday: 'long' }, 13987 listDaySideFormat: { month: 'long', day: 'numeric', year: 'numeric' } 13988 }, 13989 listMonth: { 13990 type: 'list', 13991 duration: { month: 1 }, 13992 listDaySideFormat: { weekday: 'long' } // day-of-week is nice-to-have 13993 }, 13994 listYear: { 13995 type: 'list', 13996 duration: { year: 1 }, 13997 listDaySideFormat: { weekday: 'long' } // day-of-week is nice-to-have 13998 } 13999 } 14000 }); 14001 14002 var BootstrapTheme = /** @class */ (function (_super) { 14003 __extends(BootstrapTheme, _super); 14004 function BootstrapTheme() { 14005 return _super !== null && _super.apply(this, arguments) || this; 14006 } 14007 return BootstrapTheme; 14008 }(Theme)); 14009 BootstrapTheme.prototype.classes = { 14010 root: 'fc-theme-bootstrap', 14011 table: 'table-bordered', 14012 tableCellShaded: 'table-active', 14013 buttonGroup: 'btn-group', 14014 button: 'btn btn-primary', 14015 buttonActive: 'active', 14016 popover: 'popover', 14017 popoverHeader: 'popover-header', 14018 popoverContent: 'popover-body' 14019 }; 14020 BootstrapTheme.prototype.baseIconClass = 'fa'; 14021 BootstrapTheme.prototype.iconClasses = { 14022 close: 'fa-times', 14023 prev: 'fa-chevron-left', 14024 next: 'fa-chevron-right', 14025 prevYear: 'fa-angle-double-left', 14026 nextYear: 'fa-angle-double-right' 14027 }; 14028 BootstrapTheme.prototype.rtlIconClasses = { 14029 prev: 'fa-chevron-right', 14030 next: 'fa-chevron-left', 14031 prevYear: 'fa-angle-double-right', 14032 nextYear: 'fa-angle-double-left' 14033 }; 14034 BootstrapTheme.prototype.iconOverrideOption = 'bootstrapFontAwesome';
14034 // TODO: make TS-friendly. move the option-processing into this plugin 14035 BootstrapTheme.prototype.iconOverrideCustomButtonOption = 'bootstrapFontAwesome'; 14036 BootstrapTheme.prototype.iconOverridePrefix = 'fa-'; 14037 var plugin = createPlugin({ 14038 themeClasses: { 14039 bootstrap: BootstrapTheme 14040 } 14041 }); 14042 14043 // rename this file to options.ts like other packages? 14044 var OPTION_REFINERS$3 = { 14045 googleCalendarApiKey: String 14046 }; 14047 14048 var EVENT_SOURCE_REFINERS$1 = { 14049 googleCalendarApiKey: String, 14050 googleCalendarId: String, 14051 googleCalendarApiBase: String, 14052 extraParams: identity 14053 }; 14054 14055 // TODO: expose somehow 14056 var API_BASE = 'https://www.googleapis.com/calendar/v3/calendars'; 14057 var eventSourceDef$3 = { 14058 parseMeta: function (refined) { 14059 var googleCalendarId = refined.googleCalendarId; 14060 if (!googleCalendarId && refined.url) { 14061 googleCalendarId = parseGoogleCalendarId(refined.url); 14062 } 14063 if (googleCalendarId) { 14064 return { 14065 googleCalendarId: googleCalendarId, 14066 googleCalendarApiKey: refined.googleCalendarApiKey, 14067 googleCalendarApiBase: refined.googleCalendarApiBase, 14068 extraParams: refined.extraParams 14069 }; 14070 } 14071 return null; 14072 }, 14073 fetch: function (arg, onSuccess, onFailure) { 14074 var _a = arg.context, dateEnv = _a.dateEnv, options = _a.options; 14075 var meta = arg.eventSource.meta; 14076 var apiKey = meta.googleCalendarApiKey || options.googleCalendarApiKey; 14077 if (!apiKey) { 14078 onFailure({ 14079 message: 'Specify a googleCalendarApiKey. See http://fullcalendar.io/docs/google_calendar/' 14080 }); 14081 } 14082 else { 14083 var url = buildUrl(meta); 14084 // TODO: make DRY with json-feed-event-source 14085 var extraParams = meta.extraParams; 14086 var extraParamsObj = typeof extraParams === 'function' ? extraParams() : extraParams; 14087 var requestParams_1 = buildRequestParams$1(arg.range, apiKey, extraParamsObj, dateEnv); 14088 requestJson('GET', url, requestParams_1, function (body, xhr) { 14089 if (body.error) { 14090 onFailure({ 14091 message: 'Google Calendar API: ' + body.error.message, 14092 errors: body.error.errors, 14093 xhr: xhr 14094 }); 14095 } 14096 else { 14097 onSuccess({ 14098 rawEvents: gcalItemsToRawEventDefs(body.items, requestParams_1.timeZone), 14099 xhr: xhr 14100 }); 14101 } 14102 }, function (message, xhr) { 14103 onFailure({ message: message, xhr: xhr }); 14104 }); 14105 } 14106 } 14107 }; 14108 function parseGoogleCalendarId(url) { 14109 var match; 14110 // detect if the ID was specified as a single string. 14111 // will match calendars like "[email protected]" in addition to person email calendars. 14112 if (/^[^/]+@([^/.]+\.)*(google|googlemail|gmail)\.com$/.test(url)) { 14113 return url; 14114 } 14115 else if ((match = /^https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/([^/]*)/.exec(url)) || 14116 (match = /^https?:\/\/www.google.com\/calendar\/feeds\/([^/]*)/.exec(url))) { 14117 return decodeURIComponent(match[1]); 14118 } 14119 } 14120 function buildUrl(meta) { 14121 var apiBase = meta.googleCalendarApiBase; 14122 if (!apiBase) { 14123 apiBase = API_BASE; 14124 } 14125 return apiBase + '/' + encodeURIComponent(meta.googleCalendarId) + '/events'; 14126 } 14127 function buildRequestParams$1(range, apiKey, extraParams, dateEnv) { 14128 var params; 14129 var startStr; 14130 var endStr; 14131 if (dateEnv.canComputeOffset) { 14132 // strings will naturally have offsets, which GCal needs 14133 startStr = dateEnv.formatIso(range.start); 14134 endStr = dateEnv.formatIso(range.end); 14135 } 14136 else {
14137 // when timezone isn't known, we don't know what the UTC offset should be, so ask for +/- 1 day 14138 // from the UTC day-start to guarantee we're getting all the events 14139 // (start/end will be UTC-coerced dates, so toISOString is okay) 14140 startStr = addDays(range.start, -1).toISOString(); 14141 endStr = addDays(range.end, 1).toISOString(); 14142 } 14143 params = __assign(__assign({}, (extraParams || {})), { key: apiKey, timeMin: startStr, timeMax: endStr, singleEvents: true, maxResults: 9999 }); 14144 if (dateEnv.timeZone !== 'local') { 14145 params.timeZone = dateEnv.timeZone; 14146 } 14147 return params; 14148 } 14149 function gcalItemsToRawEventDefs(items, gcalTimezone) { 14150 return items.map(function (item) { 14151 return gcalItemToRawEventDef(item, gcalTimezone); 14152 }); 14153 } 14154 function gcalItemToRawEventDef(item, gcalTimezone) { 14155 var url = item.htmlLink || null; 14156 // make the URLs for each event show times in the correct timezone 14157 if (url && gcalTimezone) { 14158 url = injectQsComponent(url, 'ctz=' + gcalTimezone); 14159 } 14160 return { 14161 id: item.id, 14162 title: item.summary, 14163 start: item.start.dateTime || item.start.date, 14164 end: item.end.dateTime || item.end.date, 14165 url: url, 14166 location: item.location, 14167 description: item.description 14168 }; 14169 } 14170 // Injects a string like "arg=value" into the querystring of a URL 14171 // TODO: move to a general util file? 14172 function injectQsComponent(url, component) { 14173 // inject it after the querystring but before the fragment 14174 return url.replace(/(\?.*?)?(#|$)/, function (whole, qs, hash) { 14175 return (qs ? qs + '&' : '?') + component + hash; 14176 }); 14177 } 14178 var googleCalendarPlugin = createPlugin({ 14179 eventSourceDefs: [eventSourceDef$3], 14180 optionRefiners: OPTION_REFINERS$3, 14181 eventSourceRefiners: EVENT_SOURCE_REFINERS$1 14182 }); 14183 14184 globalPlugins.push(interactionPlugin, dayGridPlugin, timeGridPlugin, listPlugin, plugin, googleCalendarPlugin); 14185 14186 exports.BASE_OPTION_DEFAULTS = BASE_OPTION_DEFAULTS; 14187 exports.BASE_OPTION_REFINERS = BASE_OPTION_REFINERS; 14188 exports.BaseComponent = BaseComponent; 14189 exports.BgEvent = BgEvent; 14190 exports.BootstrapTheme = BootstrapTheme; 14191 exports.Calendar = Calendar; 14192 exports.CalendarApi = CalendarApi; 14193 exports.CalendarContent = CalendarContent; 14194 exports.CalendarDataManager = CalendarDataManager; 14195 exports.CalendarDataProvider = CalendarDataProvider; 14196 exports.CalendarRoot = CalendarRoot; 14197 exports.Component = Component; 14198 exports.ContentHook = ContentHook; 14199 exports.CustomContentRenderContext = CustomContentRenderContext; 14200 exports.DateComponent = DateComponent; 14201 exports.DateEnv = DateEnv; 14202 exports.DateProfileGenerator = DateProfileGenerator; 14203 exports.DayCellContent = DayCellContent; 14204 exports.DayCellRoot = DayCellRoot; 14205 exports.DayGridView = DayTableView; 14206 exports.DayHeader = DayHeader;
14207 exports.DaySeriesModel = DaySeriesModel; 14208 exports.DayTable = DayTable; 14209 exports.DayTableModel = DayTableModel; 14210 exports.DayTableSlicer = DayTableSlicer; 14211 exports.DayTimeCols = DayTimeCols; 14212 exports.DayTimeColsSlicer = DayTimeColsSlicer; 14213 exports.DayTimeColsView = DayTimeColsView; 14214 exports.DelayedRunner = DelayedRunner; 14215 exports.Draggable = ExternalDraggable; 14216 exports.ElementDragging = ElementDragging; 14217 exports.ElementScrollController = ElementScrollController; 14218 exports.Emitter = Emitter; 14219 exports.EventApi = EventApi; 14220 exports.EventRoot = EventRoot; 14221 exports.EventSourceApi = EventSourceApi; 14222 exports.FeaturefulElementDragging = FeaturefulElementDragging; 14223 exports.Fragment = Fragment; 14224 exports.Interaction = Interaction; 14225 exports.ListView = ListView; 14226 exports.MountHook = MountHook; 14227 exports.NamedTimeZoneImpl = NamedTimeZoneImpl; 14228 exports.NowIndicatorRoot = NowIndicatorRoot; 14229 exports.NowTimer = NowTimer; 14230 exports.PointerDragging = PointerDragging; 14231 exports.PositionCache = PositionCache; 14232 exports.RefMap = RefMap; 14233 exports.RenderHook = RenderHook; 14234 exports.ScrollController = ScrollController; 14235 exports.ScrollResponder = ScrollResponder; 14236 exports.Scroller = Scroller; 14237 exports.SimpleScrollGrid = SimpleScrollGrid; 14238 exports.Slicer = Slicer; 14239 exports.Splitter = Splitter; 14240 exports.StandardEvent = StandardEvent; 14241 exports.Table = Table; 14242 exports.TableDateCell = TableDateCell; 14243 exports.TableDowCell = TableDowCell; 14244 exports.TableView = TableView; 14245 exports.Theme = Theme; 14246 exports.ThirdPartyDraggable = ThirdPartyDraggable; 14247 exports.TimeCols = TimeCols; 14248 exports.TimeColsSlatsCoords = TimeColsSlatsCoords; 14249 exports.TimeColsView = TimeColsView; 14250 exports.ViewApi = ViewApi; 14251 exports.ViewContextType = ViewContextType; 14252 exports.ViewRoot = ViewRoot; 14253 exports.WeekNumberRoot = WeekNumberRoot; 14254 exports.WindowScrollController = WindowScrollController; 14255 exports.addDays = addDays; 14256 exports.addDurations = addDurations; 14257 exports.addMs = addMs; 14258 exports.addWeeks = addWeeks; 14259 exports.allowContextMenu = allowContextMenu; 14260 exports.allowSelection = allowSelection; 14261 exports.applyMutationToEventStore = applyMutationToEventStore; 14262 exports.applyStyle = applyStyle; 14263 exports.applyStyleProp = applyStyleProp; 14264 exports.asCleanDays = asCleanDays; 14265 exports.asRoughMinutes = asRoughMinutes; 14266 exports.asRoughMs = asRoughMs; 14267 exports.asRoughSeconds = asRoughSeconds; 14268 exports.buildClassNameNormalizer = buildClassNameNormalizer; 14269 exports.buildDayRanges = buildDayRanges; 14270 exports.buildDayTableModel = buildDayTableModel; 14271 exports.buildEventApis = buildEventApis; 14272 exports.buildEventRangeKey = buildEventRangeKey; 14273 exports.buildHashFromArray = buildHashFromArray; 14274 exports.buildNavLinkData = buildNavLinkData; 14275 exports.buildSegCompareObj = buildSegCompareObj; 14276 exports.buildSegTimeText = buildSegTimeText; 14277 exports.buildSlatMetas = buildSlatMetas; 14278 exports.buildTimeColsModel = buildTimeColsModel; 14279 exports.collectFromHash = collectFromHash; 14280 exports.combineEventUis = combineEventUis; 14281 exports.compareByFieldSpec = compareByFieldSpec; 14282 exports.compareByFieldSpecs = compareByFieldSpecs; 14283 exports.compareNumbers = compareNumbers; 14284 exports.compareObjs = compareObjs; 14285 exports.computeEdges = computeEdges; 14286 exports.computeFallbackHeaderFormat = computeFallbackHeaderFormat; 14287 exports.computeHeightAndMargins = computeHeightAndMargins; 14288 exports.computeInnerRect = computeInnerRect; 14289 exports.computeRect = computeRect; 14290 exports.computeSegDraggable = computeSegDraggable; 14291 exports.computeSegEndResizable = computeSegEndResizable; 14292 exports.computeSegStartResizable = computeSegStartResizable; 14293 exports.computeShrinkWidth = computeShrinkWidth; 14294 exports.computeSmallestCellWidth = computeSmallestCellWidth; 14295 exports.computeVisibleDayRange = computeVisibleDayRange; 14296 exports.config = config; 14297 exports.constrainPoint = constrainPoint; 14298 exports.createContext = createContext$1; 14299 exports.createDuration = createDuration; 14300 exports.createElement = createElement; 14301 exports.createEmptyEventStore = createEmptyEventStore; 14302 exports.createEventInstance = createEventInstance; 14303 exports.createEventUi = createEventUi; 14304 exports.createFormatter = createFormatter; 14305 exports.createPlugin = createPlugin; 14306 exports.createRef = createRef; 14307 exports.diffDates = diffDates; 14308 exports.diffDayAndTime = diffDayAndTime; 14309 exports.diffDays = diffDays; 14310 exports.diffPoints = diffPoints; 14311 exports.diffWeeks = diffWeeks; 14312 exports.diffWholeDays = diffWholeDays; 14313 exports.diffWholeWeeks = diffWholeWeeks; 14314 exports.disableCursor = disableCursor; 14315 exports.elementClosest = elementClosest; 14316 exports.elementMatches = elementMatches; 14317 exports.enableCursor = enableCursor; 14318 exports.eventTupleToStore = eventTupleToStore; 14319 exports.filterEventStoreDefs = filterEventStoreDefs; 14320 exports.filterHash = filterHash; 14321 exports.findDirectChildren = findDirectChildren; 14322 exports.findElements = findElements; 14323 exports.flexibleCompare = flexibleCompare; 14324 exports.flushToDom = flushToDom$1; 14325 exports.formatDate = formatDate; 14326 exports.formatDayString = formatDayString; 14327 exports.formatIsoTimeString = formatIsoTimeString; 14328 exports.formatRange = formatRange; 14329 exports.getAllowYScrolling = getAllowYScrolling; 14330 exports.getCanVGrowWithinCell = getCanVGrowWithinCell; 14331 exports.getClippingParents = getClippingParents; 14332 exports.getDateMeta = getDateMeta; 14333 exports.getDayClassNames = getDayClassNames; 14334 exports.getDefaultEventEnd = getDefaultEventEnd; 14335 exports.getElSeg = getElSeg; 14336 exports.getEventClassNames = getEventClassNames; 14337 exports.getIsRtlScrollbarOnLeft = getIsRtlScrollbarOnLeft; 14338 exports.getRectCenter = getRectCenter; 14339 exports.getRelevantEvents = getRelevantEvents; 14340 exports.getScrollGridClassNames = getScrollGridClassNames;
14341 exports.getScrollbarWidths = getScrollbarWidths; 14342 exports.getSectionClassNames = getSectionClassNames; 14343 exports.getSectionHasLiquidHeight = getSectionHasLiquidHeight; 14344 exports.getSegMeta = getSegMeta; 14345 exports.getSlotClassNames = getSlotClassNames; 14346 exports.getStickyFooterScrollbar = getStickyFooterScrollbar; 14347 exports.getStickyHeaderDates = getStickyHeaderDates; 14348 exports.getUnequalProps = getUnequalProps; 14349 exports.globalLocales = globalLocales; 14350 exports.globalPlugins = globalPlugins; 14351 exports.greatestDurationDenominator = greatestDurationDenominator; 14352 exports.guid = guid; 14353 exports.hasBgRendering = hasBgRendering; 14354 exports.hasShrinkWidth = hasShrinkWidth; 14355 exports.identity = identity; 14356 exports.interactionSettingsStore = interactionSettingsStore; 14357 exports.interactionSettingsToStore = interactionSettingsToStore; 14358 exports.intersectRanges = intersectRanges; 14359 exports.intersectRects = intersectRects; 14360 exports.isArraysEqual = isArraysEqual; 14361 exports.isColPropsEqual = isColPropsEqual; 14362 exports.isDateSpansEqual = isDateSpansEqual; 14363 exports.isInt = isInt; 14364 exports.isInteractionValid = isInteractionValid; 14365 exports.isMultiDayRange = isMultiDayRange; 14366 exports.isPropsEqual = isPropsEqual; 14367 exports.isPropsValid = isPropsValid; 14368 exports.isValidDate = isValidDate; 14369 exports.listenBySelector = listenBySelector; 14370 exports.mapHash = mapHash; 14371 exports.memoize = memoize; 14372 exports.memoizeArraylike = memoizeArraylike; 14373 exports.memoizeHashlike = memoizeHashlike; 14374 exports.memoizeObjArg = memoizeObjArg; 14375 exports.mergeEventStores = mergeEventStores; 14376 exports.multiplyDuration = multiplyDuration; 14377 exports.padStart = padStart; 14378 exports.parseBusinessHours = parseBusinessHours; 14379 exports.parseClassNames = parseClassNames; 14380 exports.parseDragMeta = parseDragMeta; 14381 exports.parseEventDef = parseEventDef; 14382 exports.parseFieldSpecs = parseFieldSpecs; 14383 exports.parseMarker = parse; 14384 exports.pointInsideRect = pointInsideRect; 14385 exports.preventContextMenu = preventContextMenu; 14386 exports.preventDefault = preventDefault; 14387 exports.preventSelection = preventSelection; 14388 exports.rangeContainsMarker = rangeContainsMarker; 14389 exports.rangeContainsRange = rangeContainsRange; 14390 exports.rangesEqual = rangesEqual; 14391 exports.rangesIntersect = rangesIntersect; 14392 exports.refineEventDef = refineEventDef; 14393 exports.refineProps = refineProps; 14394 exports.removeElement = removeElement; 14395 exports.removeExact = removeExact; 14396 exports.render = render; 14397 exports.renderChunkContent = renderChunkContent; 14398 exports.renderFill = renderFill; 14399 exports.renderMicroColGroup = renderMicroColGroup; 14400 exports.renderScrollShim = renderScrollShim; 14401 exports.requestJson = requestJson; 14402 exports.sanitizeShrinkWidth = sanitizeShrinkWidth; 14403 exports.setElSeg = setElSeg; 14404 exports.setRef = setRef; 14405 exports.sliceEventStore = sliceEventStore; 14406 exports.sliceEvents = sliceEvents; 14407 exports.sortEventSegs = sortEventSegs; 14408 exports.startOfDay = startOfDay; 14409 exports.translateRect = translateRect; 14410 exports.triggerDateSelect = triggerDateSelect; 14411 exports.unpromisify = unpromisify; 14412 exports.version = version; 14413 exports.whenTransitionDone = whenTransitionDone; 14414 exports.wholeDivideDurations = wholeDivideDurations; 14415 14416 return exports; 14417 14418}({}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.