vendor: 11,814 bytes, lines 1-57
1/*! 2FullCalendar v5.5.1 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 (Object.prototype.hasOwnProperty.call(b, 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,o,r,f={},e=[],c=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function s(n,l){for(var u in l)n[u]=l[u];return n}function a(n){var l=n.parentNode;l&&l.removeChild(n);}function v(n,l,u){var i,t,o,r=arguments,f={};for(o in l)"key"==o?i=l[o]:"ref"==o?t=l[o]:f[o]=l[o];if(arguments.length>3)for(u=[u],o=3;o<arguments.length;o++)u.push(r[o]);if(null!=u&&(f.children=u),"function"==typeof n&&null!=n.defaultProps)for(o in n.defaultProps)void 0===f[o]&&(f[o]=n.defaultProps[o]);return h(n,f,i,t,null)}function h(l,u,i,t,o){var r={type:l,props:u,key:i,ref:t,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++n.__v:o};return null!=n.vnode&&n.vnode(r),r}function y(){return {current:null}}function p(n){return n.children}function d(n,l){this.props=n,this.context=l;}function _(n,l){if(null==l)return n.__?_(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?_(n):null}function w(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 w(n)}}function k(l){(!l.__d&&(l.__d=!0)&&u.push(l)&&!g.__r++||t!==n.debounceRendering)&&((t=n.debounceRendering)||i)(g);}function g(){for(var n;g.__r=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,o,r,f;n.__d&&(r=(o=(l=n).__v).__e,(f=l.__P)&&(u=[],(i=s({},o)).__v=o.__v+1,t=$(f,o,i,l.__n,void 0!==f.ownerSVGElement,null!=o.__h?[r]:null,u,null==r?_(o):r,o.__h),j(u,o),t!=r&&w(o)));});}function m(n,l,u,i,t,o,r,c,s,v){var y,d,w,k,g,m,b,A=i&&i.__k||e,P=A.length;for(s==f&&(s=null!=r?r[0]:P?_(i,0):null),u.__k=[],y=0;y<l.length;y++)if(null!=(k=u.__k[y]=null==(k=l[y])||"boolean"==typeof k?null:"string"==typeof k||"number"==typeof k?h(null,k,null,null,k):Array.isArray(k)?h(p,{children:k},null,null,null):null!=k.__e||null!=k.__c?h(k.type,k.props,k.key,null,k.__v):k)){if(k.__=u,k.__b=u.__b+1,null===(w=A[y])||w&&k.key==w.key&&k.type===w.type)A[y]=void 0;else for(d=0;d<P;d++){if((w=A[d])&&k.key==w.key&&k.type===w.type){A[d]=void 0;break}w=null;}g=$(n,k,w=w||f,t,o,r,c,s,v),(d=k.ref)&&w.ref!=d&&(b||(b=[]),w.ref&&b.push(w.ref,null,k),b.push(d,k.__c||g,k)),null!=g?(null==m&&(m=g),s=x(n,k,w,A,r,g,s),v||"option"!=u.type?"function"==typeof u.type&&(u.__d=s):n.value=""):s&&w.__e==s&&s.parentNode!=n&&(s=_(w));}if(u.__e=m,null!=r&&"function"!=typeof u.type)for(y=r.length;y--;)null!=r[y]&&a(r[y]);for(y=P;y--;)null!=A[y]&&L(A[y],A[y]);if(b)for(y=0;y<b.length;y++)I(b[y],b[++y],b[++y]);}function x(n,l,u,i,t,o,r){var f,e,c;if(void 0!==l.__d)f=l.__d,l.__d=void 0;else if(t==u||o!=r||null==o.parentNode)n:if(null==r||r.parentNode!==n)n.appendChild(o),f=null;else {for(e=r,c=0;(e=e.nextSibling)&&c<i.length;c+=2)if(e==o)break n;n.insertBefore(o,r),f=r;}return void 0!==f?f:o.nextSibling}function A(n,l,u,i,t){var o;for(o in u)"children"===o||"key"===o||o in l||C(n,o,null,u[o],i);for(o in l)t&&"function"!=typeof l[o]||"children"===o||"key"===o||"value"===o||"checked"===o||u[o]===l[o]||C(n,o,l[o],u[o],i);}function P(n,l,u){"-"===l[0]?n.setProperty(l,u):n[l]=null==u?"":"number"!=typeof u||c.test(l)?u:u+"px";}function C(n,l,u,i,t){var o,r,f;if(t&&"className"==l&&(l="class"),"style"===l)if("string"==typeof u)n.style.cssText=u;else {if("string"==typeof i&&(n.style.cssText=i=""),i)for(l in i)u&&l in u||P(n.style,l,"");if(u)for(l in u)i&&u[l]===i[l]||P(n.style,l,u[l]);}else "o"===l[0]&&"n"===l[1]?(o=l!==(l=l.replace(/Capture$/,"")),(r=l.toLowerCase())in n&&(l=r),l=l.slice(2),n.l||(n.l={}),n.l[l+o]=u,f=o?N:z,u?i||n.addEventListener(l,f,o):n.removeEventListener(l,f,o)):"list"!==l&&"tagName"!==l&&"form"!==l&&"type"!==l&&"size"!==l&&"download"!==l&&"href"!==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+!1](n.event?n.event(l):l);}function N(l){this.l[l.type+!0](n.event?n.event(l):l);}function T(n,l,u){var i,t;for(i=0;i<n.__k.length;i++)(t=n.__k[i])&&(t.__=n,t.__e&&("function"==typeof t.type&&t.__k.length>1&&T(t,l,u),l=x(u,t,t,n.__k,null,t.__e,l),"function"==typeof n.type&&(n.__d=l)));}function $(l,u,i,t,o,r,f,e,c){var a,v,h,y,_,w,k,g,b,x,A,P=u.type;if(void 0!==u.constructor)return null;null!=i.__h&&(c=i.__h,e=u.__e=i.__e,u.__h=null,r=[e]),(a=n.__b)&&a(u);try{n:if("function"==typeof P){if(g=u.props,b=(a=P.contextType)&&t[a.__c],x=a?b?b.props.value:a.__: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 d(g,x),v.constructor=P,v.render=M),b&&b.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=s({},v.__s)),s(v.__s,P.getDerivedStateFromProps(g,v.__s))),y=v.props,_=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!==y&&null!=v.componentWillReceiveProps&&v.componentWillReceiveProps(g,x),!v.__e&&null!=v.shouldComponentUpdate&&!1===v.shouldComponentUpdate(g,v.__s,x)||u.__v===i.__v){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),T(u,e,l);break n}null!=v.componentWillUpdate&&v.componentWillUpdate(g,v.__s,x),null!=v.componentDidUpdate&&v.__h.push(function(){v.componentDidUpdate(y,_,w);});}v.context=x,v.props=g,v.state=v.__s,(a=n.__r)&&a(u),v.__d=!1,v.__v=u,v.__P=l,a=v.render(v.props,v.state,v.context),v.state=v.__s,null!=v.getChildContext&&(t=s(s({},t),v.getChildContext())),h||null==v.getSnapshotBeforeUpdate||(w=v.getSnapshotBeforeUpdate(y,_)),A=null!=a&&a.type==p&&null==a.key?a.props.children:a,m(l,Array.isArray(A)?A:[A],u,i,t,o,r,f,e,c),v.base=u.__e,u.__h=null,v.__h.length&&f.push(v),k&&(v.__E=v.__=null),v.__e=!1;}else null==r&&u.__v===i.__v?(u.__k=i.__k,u.__e=i.__e):u.__e=H(i.__e,u,i,t,o,r,f,c);(a=n.diffed)&&a(u);}catch(l){u.__v=null,(c||null!=r)&&(u.__e=e,u.__h=!!c,r[r.indexOf(e)]=null),n.__e(l,u,i);}return u.__e}function j(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 H(n,l,u,i,t,o,r,c){var s,a,v,h,y,p=u.props,d=l.props;if(t="svg"===l.type||t,null!=o)for(s=0;s<o.length;s++)if(null!=(a=o[s])&&((null===l.type?3===a.nodeType:a.localName===l.type)||n==a)){n=a,o[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}),o=null,c=!1;}if(null===l.type)p===d||c&&n.data===d||(n.data=d);else {if(null!=o&&(o=e.slice.call(n.childNodes)),v=(p=u.props||f).dangerouslySetInnerHTML,h=d.dangerouslySetInnerHTML,!c){if(null!=o)for(p={},y=0;y<n.attributes.length;y++)p[n.attributes[y].name]=n.attributes[y].value;(h||v)&&(h&&(v&&h.__html==v.__html||h.__html===n.innerHTML)||(n.innerHTML=h&&h.__html||""));}A(n,d,p,t,c),h?l.__k=[]:(s=l.props.children,m(n,Array.isArray(s)?s:[s],l,u,i,"foreignObject"!==l.type&&t,o,r,f,c)),c||("value"in d&&void 0!==(s=d.value)&&(s!==n.value||"progress"===l.type&&!s)&&C(n,"value",s,p.value,!1),"checked"in d&&void 0!==(s=d.checked)&&s!==n.checked&&C(n,"checked",s,p.checked,!1));}return n}function I(l,u,i){try{"function"==typeof l?l(u):l.current=u;}catch(l){n.__e(l,i);}}function L(l,u,i){var t,o,r;if(n.unmount&&n.unmount(l),(t=l.ref)&&(t.current&&t.current!==l.__e||I(t,null,u)),i||"function"==typeof l.type||(i=null!=(o=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(r=0;r<t.length;r++)t[r]&&L(t[r],u,i);null!=o&&a(o);}function M(n,l,u){return this.constructor(n,u)}function O(l,u,i){var t,r,c;n.__&&n.__(l,u),r=(t=i===o)?null:i&&i.__k||u.__k,l=v(p,null,[l]),c=[],$(u,(t?u:i||u).__k=l,r||f,f,void 0!==u.ownerSVGElement,i&&!t?[i]:r?null:u.childNodes.length?e.slice.call(u.childNodes):null,c,i||f,t),j(c,l);}function B(n,l){var u={__c:l="__cC"+r++,__:n,Consumer:function(n,l){return n.children(l)},Provider:function(n,u,i){return this.getChildContext||(u=[],(i={})[l]=this,this.getChildContext=function(){return i},this.shouldComponentUpdate=function(n){this.props.value!==n.value&&u.some(k);},this.sub=function(n){u.push(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){u.splice(u.indexOf(n),1),l&&l.call(n);};}),n.children}};return u.Provider.__=u.Consumer.contextType=u}n={__e:function(n,l){for(var u,i,t,o=l.__h;l=l.__;)if((u=l.__c)&&!u.__)try{if((i=u.constructor)&&null!=i.getDerivedStateFromError&&(u.setState(i.getDerivedStateFromError(n)),t=u.__d),null!=u.componentDidCatch&&(u.componentDidCatch(n),t=u.__d),t)return l.__h=o,u.__E=u}catch(l){n=l;}throw n},__v:0},d.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=s({},this.state),"function"==typeof n&&(n=n(s({},u),this.props)),n&&s(u,n),null!=n&&this.__v&&(l&&this.__h.push(l),k(this));},d.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),k(this));},d.prototype.render=p,u=[],i="function"==typeof Promise?Promise.prototype.then.bind(Prom
57ise.resolve()):setTimeout,g.__r=0,o=f,r=0; 58 59 var globalObj = typeof globalThis !== 'undefined' ? globalThis : window; // // TODO: streamline when killing IE11 support 60 if (globalObj.FullCalendarVDom) { 61 console.warn('FullCalendar VDOM already loaded'); 62 } 63 else { 64 globalObj.FullCalendarVDom = { 65 Component: d, 66 createElement: v, 67 render: O, 68 createRef: y, 69 Fragment: p, 70 createContext: createContext, 71 flushToDom: flushToDom, 72 unmountComponentAtNode: unmountComponentAtNode, 73 }; 74 } 75 // HACKS... 76 // TODO: lock version 77 // TODO: link gh issues 78 function flushToDom() { 79 var oldDebounceRendering = n.debounceRendering; // orig 80 var callbackQ = []; 81 function execCallbackSync(callback) { 82 callbackQ.push(callback); 83 } 84 n.debounceRendering = execCallbackSync; 85 O(v(FakeComponent, {}), document.createElement('div')); 86 while (callbackQ.length) { 87 callbackQ.shift()(); 88 } 89 n.debounceRendering = oldDebounceRendering; 90 } 91 var FakeComponent = /** @class */ (function (_super) { 92 __extends(FakeComponent, _super); 93 function FakeComponent() { 94 return _super !== null && _super.apply(this, arguments) || this; 95 } 96 FakeComponent.prototype.render = function () { return v('div', {}); }; 97 FakeComponent.prototype.componentDidMount = function () { this.setState({}); }; 98 return FakeComponent; 99 }(d)); 100 function createContext(defaultValue) { 101 var ContextType = B(defaultValue); 102 var origProvider = ContextType.Provider; 103 ContextType.Provider = function () { 104 var _this = this; 105 var isNew = !this.getChildContext; 106 var children = origProvider.apply(this, arguments); // eslint-disable-line prefer-rest-params 107 if (isNew) { 108 var subs_1 = []; 109 this.shouldComponentUpdate = function (_props) { 110 if (_this.props.value !== _props.value) { 111 subs_1.forEach(function (c) { 112 c.context = _props.value; 113 c.forceUpdate(); 114 }); 115 } 116 }; 117 this.sub = function (c) { 118 subs_1.push(c); 119 var old = c.componentWillUnmount; 120 c.componentWillUnmount = function () { 121 subs_1.splice(subs_1.indexOf(c), 1); 122 old && old.call(c); 123 }; 124 }; 125 } 126 return children; 127 }; 128 return ContextType; 129 } 130 function unmountComponentAtNode(node) { 131 O(null, node); 132 } 133 134 // no public types yet. when there are, export from: 135 // import {} from './api-type-deps' 136 var EventSourceApi = /** @class */ (function () { 137 function EventSourceApi(context, internalEventSource) { 138 this.context = context; 139 this.internalEventSource = internalEventSource; 140 } 141 EventSourceApi.prototype.remove = function () { 142 this.context.dispatch({ 143 type: 'REMOVE_EVENT_SOURCE', 144 sourceId: this.internalEventSource.sourceId, 145 }); 146 }; 147 EventSourceApi.prototype.refetch = function () { 148 this.context.dispatch({ 149 type: 'FETCH_EVENT_SOURCES', 150 sourceIds: [this.internalEventSource.sourceId], 151 }); 152 }; 153 Object.defineProperty(EventSourceApi.prototype, "id", { 154 get: function () { 155 return this.internalEventSource.publicId; 156 }, 157 enumerable: false, 158 configurable: true 159 }); 160 Object.defineProperty(EventSourceApi.prototype, "url", { 161 get: function () { 162 return this.internalEventSource.meta.url; 163 }, 164 enumerable: false, 165 configurable: true 166 }); 167 Object.defineProperty(EventSourceApi.prototype, "format", { 168 get: function () { 169 return this.internalEventSource.meta.format; // TODO: bad. not guaranteed 170 }, 171 enumerable: false, 172 configurable: true 173 }); 174 return EventSourceApi; 175 }()); 176 177 function removeElement(el) { 178 if (el.parentNode) { 179 el.parentNode.removeChild(el); 180 } 181 } 182 // Querying 183 // ---------------------------------------------------------------------------------------------------------------- 184 function elementClosest(el, selector) { 185 if (el.closest) { 186 return el.closest(selector); 187 // really bad fallback for IE 188 // from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest 189 } 190 if (!document.documentElement.contains(el)) { 191 return null; 192 } 193 do { 194 if (elementMatches(el, selector)) { 195 return el; 196 } 197 el = (el.parentElement || el.parentNode); 198 } while (el !== null && el.nodeType === 1); 199 return null; 200 } 201 function elementMatches(el, selector) { 202 var method = el.matches || el.matchesSelector || el.msMatchesSelector; 203 return method.call(el, selector); 204 } 205 // accepts multiple subject els 206 // returns a real array. good for methods like forEach 207 // TODO: accept the document 208 function findElements(container, selector) { 209 var containers = container instanceof HTMLElement ? [container] : container; 210 var allMatches = []; 211 for (var i = 0; i < containers.length; i += 1) { 212 var matches = containers[i].querySelectorAll(selector); 213 for (var j = 0; j < matches.length; j += 1) { 214 allMatches.push(matches[j]); 215 } 216 } 217 return allMatches; 218 } 219 // accepts multiple subject els 220 // only queries direct child elements // TODO: rename to findDirectChildren! 221 function findDirectChildren(parent, selector) { 222 var parents = parent instanceof HTMLElement ? [parent] : parent; 223 var allMatches = []; 224 for (var i = 0; i < parents.length; i += 1) { 225 var childNodes = parents[i].children; // only ever elements 226 for (var j = 0; j < childNodes.length; j += 1) { 227 var childNode = childNodes[j]; 228 if (!selector || elementMatches(childNode, selector)) { 229 allMatches.push(childNode); 230 } 231 } 232 } 233 return allMatches; 234 } 235 // Style 236 // ---------------------------------------------------------------------------------------------------------------- 237 var PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i; 238 function applyStyle(el, props) { 239 for (var propName in props) { 240 applyStyleProp(el, propName, props[propName]); 241 } 242 } 243 function applyStyleProp(el, name, val) { 244 if (val == null) { 245 el.style[name] = ''; 246 } 247 else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) { 248 el.style[name] = val + "px"; 249 } 250 else { 251 el.style[name] = val; 252 } 253 } 254 255 // Stops a mouse/touch event from doing it's native browser action 256 function preventDefault(ev) { 257 ev.preventDefault(); 258 } 259 // Event Delegation 260 // ---------------------------------------------------------------------------------------------------------------- 261 function buildDelegationHandler(selector, handler) { 262 return function (ev) {
vendor: 15,134 bytes, lines 263-694
263 var matchedChild = elementClosest(ev.target, selector); 264 if (matchedChild) { 265 handler.call(matchedChild, ev, matchedChild); 266 } 267 }; 268 } 269 function listenBySelector(container, eventType, selector, handler) { 270 var attachedHandler = buildDelegationHandler(selector, handler); 271 container.addEventListener(eventType, attachedHandler); 272 return function () { 273 container.removeEventListener(eventType, attachedHandler); 274 }; 275 } 276 function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) { 277 var currentMatchedChild; 278 return listenBySelector(container, 'mouseover', selector, function (mouseOverEv, matchedChild) { 279 if (matchedChild !== currentMatchedChild) { 280 currentMatchedChild = matchedChild; 281 onMouseEnter(mouseOverEv, matchedChild); 282 var realOnMouseLeave_1 = function (mouseLeaveEv) { 283 currentMatchedChild = null; 284 onMouseLeave(mouseLeaveEv, matchedChild); 285 matchedChild.removeEventListener('mouseleave', realOnMouseLeave_1); 286 }; 287 // listen to the next mouseleave, and then unattach 288 matchedChild.addEventListener('mouseleave', realOnMouseLeave_1); 289 } 290 }); 291 } 292 // Animation 293 // ---------------------------------------------------------------------------------------------------------------- 294 var transitionEventNames = [ 295 'webkitTransitionEnd', 296 'otransitionend', 297 'oTransitionEnd', 298 'msTransitionEnd', 299 'transitionend', 300 ]; 301 // triggered only when the next single subsequent transition finishes 302 function whenTransitionDone(el, callback) { 303 var realCallback = function (ev) { 304 callback(ev); 305 transitionEventNames.forEach(function (eventName) { 306 el.removeEventListener(eventName, realCallback); 307 }); 308 }; 309 transitionEventNames.forEach(function (eventName) { 310 el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes 311 }); 312 } 313 314 var guidNumber = 0; 315 function guid() { 316 guidNumber += 1; 317 return String(guidNumber); 318 } 319 /* FullCalendar-specific DOM Utilities 320 ----------------------------------------------------------------------------------------------------------------------*/ 321 // Make the mouse cursor express that an event is not allowed in the current area 322 function disableCursor() { 323 document.body.classList.add('fc-not-allowed'); 324 } 325 // Returns the mouse cursor to its original look 326 function enableCursor() { 327 document.body.classList.remove('fc-not-allowed'); 328 } 329 /* Selection 330 ----------------------------------------------------------------------------------------------------------------------*/ 331 function preventSelection(el) { 332 el.classList.add('fc-unselectable'); 333 el.addEventListener('selectstart', preventDefault); 334 } 335 function allowSelection(el) { 336 el.classList.remove('fc-unselectable'); 337 el.removeEventListener('selectstart', preventDefault); 338 } 339 /* Context Menu 340 ----------------------------------------------------------------------------------------------------------------------*/ 341 function preventContextMenu(el) { 342 el.addEventListener('contextmenu', preventDefault); 343 } 344 function allowContextMenu(el) { 345 el.removeEventListener('contextmenu', preventDefault); 346 } 347 function parseFieldSpecs(input) { 348 var specs = []; 349 var tokens = []; 350 var i; 351 var token; 352 if (typeof input === 'string') { 353 tokens = input.split(/\s*,\s*/); 354 } 355 else if (typeof input === 'function') { 356 tokens = [input]; 357 } 358 else if (Array.isArray(input)) { 359 tokens = input; 360 } 361 for (i = 0; i < tokens.length; i += 1) { 362 token = tokens[i]; 363 if (typeof token === 'string') { 364 specs.push(token.charAt(0) === '-' ? 365 { field: token.substring(1), order: -1 } : 366 { field: token, order: 1 }); 367 } 368 else if (typeof token === 'function') { 369 specs.push({ func: token }); 370 } 371 } 372 return specs; 373 } 374 function compareByFieldSpecs(obj0, obj1, fieldSpecs) { 375 var i; 376 var cmp; 377 for (i = 0; i < fieldSpecs.length; i += 1) { 378 cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]); 379 if (cmp) { 380 return cmp; 381 } 382 } 383 return 0; 384 } 385 function compareByFieldSpec(obj0, obj1, fieldSpec) { 386 if (fieldSpec.func) { 387 return fieldSpec.func(obj0, obj1); 388 } 389 return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field]) 390 * (fieldSpec.order || 1); 391 } 392 function flexibleCompare(a, b) { 393 if (!a && !b) { 394 return 0; 395 } 396 if (b == null) { 397 return -1; 398 } 399 if (a == null) { 400 return 1; 401 } 402 if (typeof a === 'string' || typeof b === 'string') { 403 return String(a).localeCompare(String(b)); 404 } 405 return a - b; 406 } 407 /* String Utilities 408 ----------------------------------------------------------------------------------------------------------------------*/ 409 function padStart(val, len) { 410 var s = String(val); 411 return '000'.substr(0, len - s.length) + s; 412 } 413 /* Number Utilities 414 ----------------------------------------------------------------------------------------------------------------------*/ 415 function compareNumbers(a, b) { 416 return a - b; 417 } 418 function isInt(n) { 419 return n % 1 === 0; 420 } 421 /* FC-specific DOM dimension stuff 422 ----------------------------------------------------------------------------------------------------------------------*/ 423 function computeSmallestCellWidth(cellEl) { 424 var allWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-frame'); 425 var contentWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-cushion'); 426 if (!allWidthEl) { 427 throw new Error('needs fc-scrollgrid-shrink-frame className'); // TODO: use const 428 } 429 if (!contentWidthEl) { 430 throw new Error('needs fc-scrollgrid-shrink-cushion className'); 431 } 432 return cellEl.getBoundingClientRect().width - allWidthEl.getBoundingClientRect().width + // the cell padding+border 433 contentWidthEl.getBoundingClientRect().width; 434 } 435 436 var DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; 437 // Adding 438 function addWeeks(m, n) { 439 var a = dateToUtcArray(m); 440 a[2] += n * 7; 441 return arrayToUtcDate(a); 442 } 443 function addDays(m, n) { 444 var a = dateToUtcArray(m); 445 a[2] += n; 446 return arrayToUtcDate(a); 447 } 448 function addMs(m, n) { 449 var a = dateToUtcArray(m); 450 a[6] += n; 451 return arrayToUtcDate(a); 452 } 453 // Diffing (all return floats) 454 // TODO: why not use ranges? 455 function diffWeeks(m0, m1) { 456 return diffDays(m0, m1) / 7; 457 } 458 function diffDays(m0, m1) { 459 return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24); 460 } 461 function diffHours(m0, m1) { 462 return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60); 463 } 464 function diffMinutes(m0, m1) { 465 return (m1.valueOf() - m0.valueOf()) / (1000 * 60); 466 } 467 function diffSeconds(m0, m1) { 468 return (m1.valueOf() - m0.valueOf()) / 1000; 469 } 470 function diffDayAndTime(m0, m1) { 471 var m0day = startOfDay(m0); 472 var m1day = startOfDay(m1); 473 return { 474 years: 0, 475 months: 0, 476 days: Math.round(diffDays(m0day, m1day)), 477 milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()), 478 }; 479 } 480 // Diffing Whole Units 481 function diffWholeWeeks(m0, m1) { 482 var d = diffWholeDays(m0, m1); 483 if (d !== null && d % 7 === 0) { 484 return d / 7; 485 } 486 return null; 487 } 488 function diffWholeDays(m0, m1) { 489 if (timeAsMs(m0) === timeAsMs(m1)) { 490 return Math.round(diffDays(m0, m1)); 491 } 492 return null; 493 } 494 // Start-Of 495 function startOfDay(m) { 496 return arrayToUtcDate([ 497 m.getUTCFullYear(), 498 m.getUTCMonth(), 499 m.getUTCDate(), 500 ]); 501 } 502 function startOfHour(m) { 503 return arrayToUtcDate([ 504 m.getUTCFullYear(), 505 m.getUTCMonth(), 506 m.getUTCDate(), 507 m.getUTCHours(), 508 ]); 509 } 510 function startOfMinute(m) { 511 return arrayToUtcDate([ 512 m.getUTCFullYear(), 513 m.getUTCMonth(), 514 m.getUTCDate(), 515 m.getUTCHours(), 516 m.getUTCMinutes(), 517 ]); 518 } 519 function startOfSecond(m) { 520 return arrayToUtcDate([ 521 m.getUTCFullYear(), 522 m.getUTCMonth(), 523 m.getUTCDate(), 524 m.getUTCHours(), 525 m.getUTCMinutes(), 526 m.getUTCSeconds(), 527 ]); 528 } 529 // Week Computation 530 function weekOfYear(marker, dow, doy) { 531 var y = marker.getUTCFullYear(); 532 var w = weekOfGivenYear(marker, y, dow, doy); 533 if (w < 1) { 534 return weekOfGivenYear(marker, y - 1, dow, doy); 535 } 536 var nextW = weekOfGivenYear(marker, y + 1, dow, doy); 537 if (nextW >= 1) { 538 return Math.min(w, nextW); 539 } 540 return w; 541 } 542 function weekOfGivenYear(marker, year, dow, doy) { 543 var firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]); 544 var dayStart = startOfDay(marker); 545 var days = Math.round(diffDays(firstWeekStart, dayStart)); 546 return Math.floor(days / 7) + 1; // zero-indexed 547 } 548 // start-of-first-week - start-of-year 549 function firstWeekOffset(year, dow, doy) { 550 // first-week day -- which january is always in the first week (4 for iso, 1 for other) 551 var fwd = 7 + dow - doy; 552 // first-week day local weekday -- which local weekday is fwd 553 var fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7; 554 return -fwdlw + fwd - 1; 555 } 556 // Array Conversion 557 function dateToLocalArray(date) { 558 return [ 559 date.getFullYear(), 560 date.getMonth(), 561 date.getDate(), 562 date.getHours(), 563 date.getMinutes(), 564 date.getSeconds(), 565 date.getMilliseconds(), 566 ]; 567 } 568 function arrayToLocalDate(a) { 569 return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month 570 a[3] || 0, a[4] || 0, a[5] || 0); 571 } 572 function dateToUtcArray(date) { 573 return [ 574 date.getUTCFullYear(), 575 date.getUTCMonth(), 576 date.getUTCDate(), 577 date.getUTCHours(), 578 date.getUTCMinutes(), 579 date.getUTCSeconds(), 580 date.getUTCMilliseconds(), 581 ]; 582 } 583 function arrayToUtcDate(a) { 584 // according to web standards (and Safari), a month index is required. 585 // massage if only given a year. 586 if (a.length === 1) { 587 a = a.concat([0]); 588 } 589 return new Date(Date.UTC.apply(Date, a)); 590 } 591 // Other Utils 592 function isValidDate(m) { 593 return !isNaN(m.valueOf()); 594 } 595 function timeAsMs(m) { 596 return m.getUTCHours() * 1000 * 60 * 60 + 597 m.getUTCMinutes() * 1000 * 60 + 598 m.getUTCSeconds() * 1000 + 599 m.getUTCMilliseconds(); 600 } 601 602 function createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) { 603 return { 604 instanceId: guid(), 605 defId: defId, 606 range: range, 607 forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo, 608 forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo, 609 }; 610 } 611 612 var hasOwnProperty = Object.prototype.hasOwnProperty; 613 // Merges an array of objects into a single object. 614 // The second argument allows for an array of property names who's object values will be merged together. 615 function mergeProps(propObjs, complexPropsMap) { 616 var dest = {}; 617 if (complexPropsMap) { 618 for (var name_1 in complexPropsMap) { 619 var complexObjs = []; 620 // collect the trailing object values, stopping when a non-object is discovered 621 for (var i = propObjs.length - 1; i >= 0; i -= 1) { 622 var val = propObjs[i][name_1]; 623 if (typeof val === 'object' && val) { // non-null object 624 complexObjs.unshift(val); 625 } 626 else if (val !== undefined) { 627 dest[name_1] = val; // if there were no objects, this value will be used 628 break; 629 } 630 } 631 // if the trailing values were objects, use the merged value 632 if (complexObjs.length) { 633 dest[name_1] = mergeProps(complexObjs); 634 } 635 } 636 } 637 // copy values into the destination, going from last to first 638 for (var i = propObjs.length - 1; i >= 0; i -= 1) { 639 var props = propObjs[i]; 640 for (var name_2 in props) { 641 if (!(name_2 in dest)) { // if already assigned by previous props or complex props, don't reassign 642 dest[name_2] = props[name_2]; 643 } 644 } 645 } 646 return dest; 647 } 648 function filterHash(hash, func) { 649 var filtered = {}; 650 for (var key in hash) { 651 if (func(hash[key], key)) { 652 filtered[key] = hash[key]; 653 } 654 } 655 return filtered; 656 } 657 function mapHash(hash, func) { 658 var newHash = {}; 659 for (var key in hash) { 660 newHash[key] = func(hash[key], key); 661 } 662 return newHash; 663 } 664 function arrayToHash(a) { 665 var hash = {}; 666 for (var _i = 0, a_1 = a; _i < a_1.length; _i++) { 667 var item = a_1[_i]; 668 hash[item] = true; 669 } 670 return hash; 671 } 672 function buildHashFromArray(a, func) { 673 var hash = {}; 674 for (var i = 0; i < a.length; i += 1) { 675 var tuple = func(a[i], i); 676 hash[tuple[0]] = tuple[1]; 677 } 678 return hash; 679 } 680 function hashValuesToArray(obj) { 681 var a = []; 682 for (var key in obj) { 683 a.push(obj[key]); 684 } 685 return a; 686 } 687 function isPropsEqual(obj0, obj1) { 688 if (obj0 === obj1) { 689 return true; 690 } 691 for (var key in obj0) { 692 if (hasOwnProperty.call(obj0, key)) { 693 if (!(key in obj1)) { 694 return false;
695 } 696 } 697 } 698 for (var key in obj1) { 699 if (hasOwnProperty.call(obj1, key)) { 700 if (obj0[key] !== obj1[key]) { 701 return false; 702 } 703 } 704 } 705 return true; 706 } 707 function getUnequalProps(obj0, obj1) { 708 var keys = []; 709 for (var key in obj0) { 710 if (hasOwnProperty.call(obj0, key)) { 711 if (!(key in obj1)) { 712 keys.push(key); 713 } 714 } 715 } 716 for (var key in obj1) { 717 if (hasOwnProperty.call(obj1, key)) { 718 if (obj0[key] !== obj1[key]) { 719 keys.push(key); 720 } 721 } 722 } 723 return keys; 724 } 725 function compareObjs(oldProps, newProps, equalityFuncs) { 726 if (equalityFuncs === void 0) { equalityFuncs = {}; } 727 if (oldProps === newProps) { 728 return true; 729 } 730 for (var key in newProps) { 731 if (key in oldProps && isObjValsEqual(oldProps[key], newProps[key], equalityFuncs[key])) ; 732 else { 733 return false; 734 } 735 } 736 // check for props that were omitted in the new 737 for (var key in oldProps) { 738 if (!(key in newProps)) { 739 return false; 740 } 741 } 742 return true; 743 } 744 /* 745 assumed "true" equality for handler names like "onReceiveSomething" 746 */ 747 function isObjValsEqual(val0, val1, comparator) { 748 if (val0 === val1 || comparator === true) { 749 return true; 750 } 751 if (comparator) { 752 return comparator(val0, val1); 753 } 754 return false; 755 } 756 function collectFromHash(hash, startIndex, endIndex, step) { 757 if (startIndex === void 0) { startIndex = 0; } 758 if (step === void 0) { step = 1; } 759 var res = []; 760 if (endIndex == null) { 761 endIndex = Object.keys(hash).length; 762 } 763 for (var i = startIndex; i < endIndex; i += step) { 764 var val = hash[i]; 765 if (val !== undefined) { // will disregard undefined for sparse arrays 766 res.push(val); 767 } 768 } 769 return res; 770 } 771 772 function parseRecurring(refined, defaultAllDay, dateEnv, recurringTypes) { 773 for (var i = 0; i < recurringTypes.length; i += 1) { 774 var parsed = recurringTypes[i].parse(refined, dateEnv); 775 if (parsed) { 776 var allDay = refined.allDay; 777 if (allDay == null) { 778 allDay = defaultAllDay; 779 if (allDay == null) { 780 allDay = parsed.allDayGuess; 781 if (allDay == null) { 782 allDay = false; 783 } 784 } 785 } 786 return { 787 allDay: allDay, 788 duration: parsed.duration, 789 typeData: parsed.typeData, 790 typeId: i, 791 }; 792 } 793 } 794 return null; 795 } 796 function expandRecurring(eventStore, framingRange, context) { 797 var dateEnv = context.dateEnv, pluginHooks = context.pluginHooks, options = context.options; 798 var defs = eventStore.defs, instances = eventStore.instances; 799 // remove existing recurring instances 800 // TODO: bad. always expand events as a second step 801 instances = filterHash(instances, function (instance) { return !defs[instance.defId].recurringDef; }); 802 for (var defId in defs) { 803 var def = defs[defId]; 804 if (def.recurringDef) { 805 var duration = def.recurringDef.duration; 806 if (!duration) { 807 duration = def.allDay ? 808 options.defaultAllDayEventDuration : 809 options.defaultTimedEventDuration; 810 } 811 var starts = expandRecurringRanges(def, duration, framingRange, dateEnv, pluginHooks.recurringTypes); 812 for (var _i = 0, starts_1 = starts; _i < starts_1.length; _i++) { 813 var start = starts_1[_i]; 814 var instance = createEventInstance(defId, { 815 start: start, 816 end: dateEnv.add(start, duration), 817 }); 818 instances[instance.instanceId] = instance; 819 } 820 } 821 } 822 return { defs: defs, instances: instances }; 823 } 824 /* 825 Event MUST have a recurringDef 826 */ 827 function expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) { 828 var typeDef = recurringTypes[eventDef.recurringDef.typeId]; 829 var markers = typeDef.expand(eventDef.recurringDef.typeData, { 830 start: dateEnv.subtract(framingRange.start, duration), 831 end: framingRange.end, 832 }, dateEnv); 833 // the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to 834 if (eventDef.allDay) { 835 markers = markers.map(startOfDay); 836 } 837 return markers; 838 } 839 840 var INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];
vendor: 7,700 bytes, lines 841-1066
841 var PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/; 842 // Parsing and Creation 843 function createDuration(input, unit) { 844 var _a; 845 if (typeof input === 'string') { 846 return parseString(input); 847 } 848 if (typeof input === 'object' && input) { // non-null object 849 return parseObject(input); 850 } 851 if (typeof input === 'number') { 852 return parseObject((_a = {}, _a[unit || 'milliseconds'] = input, _a)); 853 } 854 return null; 855 } 856 function parseString(s) { 857 var m = PARSE_RE.exec(s); 858 if (m) { 859 var sign = m[1] ? -1 : 1; 860 return { 861 years: 0, 862 months: 0, 863 days: sign * (m[2] ? parseInt(m[2], 10) : 0), 864 milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours 865 (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes 866 (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds 867 (m[6] ? parseInt(m[6], 10) : 0) // ms 868 ), 869 }; 870 } 871 return null; 872 } 873 function parseObject(obj) { 874 var duration = { 875 years: obj.years || obj.year || 0, 876 months: obj.months || obj.month || 0, 877 days: obj.days || obj.day || 0, 878 milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours 879 (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes 880 (obj.seconds || obj.second || 0) * 1000 + // seconds 881 (obj.milliseconds || obj.millisecond || obj.ms || 0), 882 }; 883 var weeks = obj.weeks || obj.week; 884 if (weeks) { 885 duration.days += weeks * 7; 886 duration.specifiedWeeks = true; 887 } 888 return duration; 889 } 890 // Equality 891 function durationsEqual(d0, d1) { 892 return d0.years === d1.years && 893 d0.months === d1.months && 894 d0.days === d1.days && 895 d0.milliseconds === d1.milliseconds; 896 } 897 function asCleanDays(dur) { 898 if (!dur.years && !dur.months && !dur.milliseconds) { 899 return dur.days; 900 } 901 return 0; 902 } 903 // Simple Math 904 function addDurations(d0, d1) { 905 return { 906 years: d0.years + d1.years, 907 months: d0.months + d1.months, 908 days: d0.days + d1.days, 909 milliseconds: d0.milliseconds + d1.milliseconds, 910 }; 911 } 912 function subtractDurations(d1, d0) { 913 return { 914 years: d1.years - d0.years, 915 months: d1.months - d0.months, 916 days: d1.days - d0.days, 917 milliseconds: d1.milliseconds - d0.milliseconds, 918 }; 919 } 920 function multiplyDuration(d, n) { 921 return { 922 years: d.years * n, 923 months: d.months * n, 924 days: d.days * n, 925 milliseconds: d.milliseconds * n, 926 }; 927 } 928 // Conversions 929 // "Rough" because they are based on average-case Gregorian months/years 930 function asRoughYears(dur) { 931 return asRoughDays(dur) / 365; 932 } 933 function asRoughMonths(dur) { 934 return asRoughDays(dur) / 30; 935 } 936 function asRoughDays(dur) { 937 return asRoughMs(dur) / 864e5; 938 } 939 function asRoughMinutes(dur) { 940 return asRoughMs(dur) / (1000 * 60); 941 } 942 function asRoughSeconds(dur) { 943 return asRoughMs(dur) / 1000; 944 } 945 function asRoughMs(dur) { 946 return dur.years * (365 * 864e5) + 947 dur.months * (30 * 864e5) + 948 dur.days * 864e5 + 949 dur.milliseconds; 950 } 951 // Advanced Math 952 function wholeDivideDurations(numerator, denominator) { 953 var res = null; 954 for (var i = 0; i < INTERNAL_UNITS.length; i += 1) { 955 var unit = INTERNAL_UNITS[i]; 956 if (denominator[unit]) { 957 var localRes = numerator[unit] / denominator[unit]; 958 if (!isInt(localRes) || (res !== null && res !== localRes)) { 959 return null; 960 } 961 res = localRes; 962 } 963 else if (numerator[unit]) { 964 // needs to divide by something but can't! 965 return null; 966 } 967 } 968 return res; 969 } 970 function greatestDurationDenominator(dur) { 971 var ms = dur.milliseconds; 972 if (ms) { 973 if (ms % 1000 !== 0) { 974 return { unit: 'millisecond', value: ms }; 975 } 976 if (ms % (1000 * 60) !== 0) { 977 return { unit: 'second', value: ms / 1000 }; 978 } 979 if (ms % (1000 * 60 * 60) !== 0) { 980 return { unit: 'minute', value: ms / (1000 * 60) }; 981 } 982 if (ms) { 983 return { unit: 'hour', value: ms / (1000 * 60 * 60) }; 984 } 985 } 986 if (dur.days) { 987 if (dur.specifiedWeeks && dur.days % 7 === 0) { 988 return { unit: 'week', value: dur.days / 7 }; 989 } 990 return { unit: 'day', value: dur.days }; 991 } 992 if (dur.months) { 993 return { unit: 'month', value: dur.months }; 994 } 995 if (dur.years) { 996 return { unit: 'year', value: dur.years }; 997 } 998 return { unit: 'millisecond', value: 0 }; 999 } 1000 1001 // timeZoneOffset is in minutes 1002 function buildIsoString(marker, timeZoneOffset, stripZeroTime) { 1003 if (stripZeroTime === void 0) { stripZeroTime = false; } 1004 var s = marker.toISOString(); 1005 s = s.replace('.000', ''); 1006 if (stripZeroTime) { 1007 s = s.replace('T00:00:00Z', ''); 1008 } 1009 if (s.length > 10) { // time part wasn't stripped, can add timezone info 1010 if (timeZoneOffset == null) { 1011 s = s.replace('Z', ''); 1012 } 1013 else if (timeZoneOffset !== 0) { 1014 s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true)); 1015 } 1016 // otherwise, its UTC-0 and we want to keep the Z 1017 } 1018 return s; 1019 } 1020 // formats the date, but with no time part 1021 // TODO: somehow merge with buildIsoString and stripZeroTime 1022 // TODO: rename. omit "string" 1023 function formatDayString(marker) { 1024 return marker.toISOString().replace(/T.*$/, ''); 1025 } 1026 // TODO: use Date::toISOString and use everything after the T? 1027 function formatIsoTimeString(marker) { 1028 return padStart(marker.getUTCHours(), 2) + ':' + 1029 padStart(marker.getUTCMinutes(), 2) + ':' + 1030 padStart(marker.getUTCSeconds(), 2); 1031 } 1032 function formatTimeZoneOffset(minutes, doIso) { 1033 if (doIso === void 0) { doIso = false; } 1034 var sign = minutes < 0 ? '-' : '+'; 1035 var abs = Math.abs(minutes); 1036 var hours = Math.floor(abs / 60); 1037 var mins = Math.round(abs % 60); 1038 if (doIso) { 1039 return sign + padStart(hours, 2) + ":" + padStart(mins, 2); 1040 } 1041 return "GMT" + sign + hours + (mins ? ":" + padStart(mins, 2) : ''); 1042 } 1043 1044 // TODO: new util arrayify? 1045 function removeExact(array, exactVal) { 1046 var removeCnt = 0; 1047 var i = 0; 1048 while (i < array.length) { 1049 if (array[i] === exactVal) { 1050 array.splice(i, 1); 1051 removeCnt += 1; 1052 } 1053 else { 1054 i += 1; 1055 } 1056 } 1057 return removeCnt; 1058 } 1059 function isArraysEqual(a0, a1, equalityFunc) { 1060 if (a0 === a1) { 1061 return true; 1062 } 1063 var len = a0.length; 1064 var i; 1065 if (len !== a1.length) { // not array? or not same length? 1066 return false;
1067 } 1068 for (i = 0; i < len; i += 1) { 1069 if (!(equalityFunc ? equalityFunc(a0[i], a1[i]) : a0[i] === a1[i])) { 1070 return false; 1071 } 1072 } 1073 return true; 1074 } 1075 1076 function memoize(workerFunc, resEquality, teardownFunc) { 1077 var currentArgs; 1078 var currentRes; 1079 return function () { 1080 var newArgs = []; 1081 for (var _i = 0; _i < arguments.length; _i++) { 1082 newArgs[_i] = arguments[_i]; 1083 } 1084 if (!currentArgs) { 1085 currentRes = workerFunc.apply(this, newArgs); 1086 } 1087 else if (!isArraysEqual(currentArgs, newArgs)) { 1088 if (teardownFunc) { 1089 teardownFunc(currentRes); 1090 } 1091 var res = workerFunc.apply(this, newArgs); 1092 if (!resEquality || !resEquality(res, currentRes)) { 1093 currentRes = res; 1094 } 1095 } 1096 currentArgs = newArgs; 1097 return currentRes; 1098 }; 1099 } 1100 function memoizeObjArg(workerFunc, resEquality, teardownFunc) { 1101 var _this = this; 1102 var currentArg; 1103 var currentRes; 1104 return function (newArg) { 1105 if (!currentArg) { 1106 currentRes = workerFunc.call(_this, newArg); 1107 } 1108 else if (!isPropsEqual(currentArg, newArg)) { 1109 if (teardownFunc) { 1110 teardownFunc(currentRes); 1111 } 1112 var res = workerFunc.call(_this, newArg); 1113 if (!resEquality || !resEquality(res, currentRes)) { 1114 currentRes = res; 1115 } 1116 } 1117 currentArg = newArg; 1118 return currentRes; 1119 }; 1120 } 1121 function memoizeArraylike(// used at all? 1122 workerFunc, resEquality, teardownFunc) { 1123 var _this = this; 1124 var currentArgSets = []; 1125 var currentResults = []; 1126 return function (newArgSets) { 1127 var currentLen = currentArgSets.length; 1128 var newLen = newArgSets.length; 1129 var i = 0; 1130 for (; i < currentLen; i += 1) { 1131 if (!newArgSets[i]) { // one of the old sets no longer exists 1132 if (teardownFunc) { 1133 teardownFunc(currentResults[i]); 1134 } 1135 } 1136 else if (!isArraysEqual(currentArgSets[i], newArgSets[i])) { 1137 if (teardownFunc) { 1138 teardownFunc(currentResults[i]); 1139 } 1140 var res = workerFunc.apply(_this, newArgSets[i]); 1141 if (!resEquality || !resEquality(res, currentResults[i])) { 1142 currentResults[i] = res; 1143 } 1144 } 1145 } 1146 for (; i < newLen; i += 1) { 1147 currentResults[i] = workerFunc.apply(_this, newArgSets[i]); 1148 } 1149 currentArgSets = newArgSets; 1150 currentResults.splice(newLen); // remove excess 1151 return currentResults; 1152 }; 1153 } 1154 function memoizeHashlike(// used? 1155 workerFunc, resEquality, teardownFunc) { 1156 var _this = this; 1157 var currentArgHash = {}; 1158 var currentResHash = {}; 1159 return function (newArgHash) { 1160 var newResHash = {}; 1161 for (var key in newArgHash) { 1162 if (!currentResHash[key]) { 1163 newResHash[key] = workerFunc.apply(_this, newArgHash[key]); 1164 } 1165 else if (!isArraysEqual(currentArgHash[key], newArgHash[key])) { 1166 if (teardownFunc) { 1167 teardownFunc(currentResHash[key]); 1168 } 1169 var res = workerFunc.apply(_this, newArgHash[key]); 1170 newResHash[key] = (resEquality && resEquality(res, currentResHash[key])) 1171 ? currentResHash[key] 1172 : res; 1173 } 1174 else { 1175 newResHash[key] = currentResHash[key]; 1176 } 1177 } 1178 currentArgHash = newArgHash; 1179 currentResHash = newResHash; 1180 return newResHash; 1181 }; 1182 } 1183 1184 var EXTENDED_SETTINGS_AND_SEVERITIES = { 1185 week: 3, 1186 separator: 0, 1187 omitZeroMinute: 0, 1188 meridiem: 0, 1189 omitCommas: 0, 1190 }; 1191 var STANDARD_DATE_PROP_SEVERITIES = { 1192 timeZoneName: 7, 1193 era: 6, 1194 year: 5, 1195 month: 4, 1196 day: 2, 1197 weekday: 2, 1198 hour: 1, 1199 minute: 1, 1200 second: 1, 1201 }; 1202 var MERIDIEM_RE = /\s*([ap])\.?m\.?/i;
1202 // eats up leading spaces too 1203 var COMMA_RE = /,/g; // we need re for globalness 1204 var MULTI_SPACE_RE = /\s+/g; 1205 var LTR_RE = /\u200e/g; // control character 1206 var UTC_RE = /UTC|GMT/; 1207 var NativeFormatter = /** @class */ (function () { 1208 function NativeFormatter(formatSettings) { 1209 var standardDateProps = {}; 1210 var extendedSettings = {}; 1211 var severity = 0; 1212 for (var name_1 in formatSettings) { 1213 if (name_1 in EXTENDED_SETTINGS_AND_SEVERITIES) { 1214 extendedSettings[name_1] = formatSettings[name_1]; 1215 severity = Math.max(EXTENDED_SETTINGS_AND_SEVERITIES[name_1], severity); 1216 } 1217 else { 1218 standardDateProps[name_1] = formatSettings[name_1]; 1219 if (name_1 in STANDARD_DATE_PROP_SEVERITIES) { // TODO: what about hour12? no severity 1220 severity = Math.max(STANDARD_DATE_PROP_SEVERITIES[name_1], severity); 1221 } 1222 } 1223 } 1224 this.standardDateProps = standardDateProps; 1225 this.extendedSettings = extendedSettings; 1226 this.severity = severity; 1227 this.buildFormattingFunc = memoize(buildFormattingFunc); 1228 } 1229 NativeFormatter.prototype.format = function (date, context) { 1230 return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date); 1231 }; 1232 NativeFormatter.prototype.formatRange = function (start, end, context, betterDefaultSeparator) { 1233 var _a = this, standardDateProps = _a.standardDateProps, extendedSettings = _a.extendedSettings; 1234 var diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem); 1235 if (!diffSeverity) { 1236 return this.format(start, context); 1237 } 1238 var biggestUnitForPartial = diffSeverity; 1239 if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time 1240 (standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') && 1241 (standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') && 1242 (standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) { 1243 biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time 1244 } 1245 var full0 = this.format(start, context); 1246 var full1 = this.format(end, context); 1247 if (full0 === full1) { 1248 return full0; 1249 } 1250 var partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForPartial); 1251 var partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context); 1252 var partial0 = partialFormattingFunc(start); 1253 var partial1 = partialFormattingFunc(end); 1254 var insertion = findCommonInsertion(full0, partial0, full1, partial1); 1255 var separator = extendedSettings.separator || betterDefaultSeparator || context.defaultSeparator || ''; 1256 if (insertion) { 1257 return insertion.before + partial0 + separator + partial1 + insertion.after; 1258 } 1259 return full0 + separator + full1; 1260 }; 1261 NativeFormatter.prototype.getLargestUnit = function () { 1262 switch (this.severity) { 1263 case 7: 1264 case 6: 1265 case 5: 1266 return 'year'; 1267 case 4: 1268 return 'month'; 1269 case 3: 1270 return 'week'; 1271 case 2: 1272 return 'day'; 1273 default: 1274 return 'time'; // really? 1275 } 1276 }; 1277 return NativeFormatter; 1278 }()); 1279 function buildFormattingFunc(standardDateProps, extendedSettings, context) { 1280 var standardDatePropCnt = Object.keys(standardDateProps).length; 1281 if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') { 1282 return function (date) { return (formatTimeZoneOffset(date.timeZoneOffset)); }; 1283 } 1284 if (standardDatePropCnt === 0 && extendedSettings.week) { 1285 return function (date) { return (formatWeekNumber(context.computeWeekNumber(date.marker), context.weekText, context.locale, extendedSettings.week)); }; 1286 } 1287 return buildNativeFormattingFunc(standardDateProps, extendedSettings, context); 1288 } 1289 function buildNativeFormattingFunc(standardDateProps, extendedSettings, context) { 1290 standardDateProps = __assign({}, standardDateProps); // copy 1291 extendedSettings = __assign({}, extendedSettings); // copy 1292 sanitizeSettings(standardDateProps, extendedSettings); 1293 standardDateProps.timeZone = 'UTC';
1293 // we leverage the only guaranteed timeZone for our UTC markers 1294 var normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps); 1295 var zeroFormat; // needed? 1296 if (extendedSettings.omitZeroMinute) { 1297 var zeroProps = __assign({}, standardDateProps); 1298 delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings 1299 zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps); 1300 } 1301 return function (date) { 1302 var marker = date.marker; 1303 var format; 1304 if (zeroFormat && !marker.getUTCMinutes()) { 1305 format = zeroFormat; 1306 } 1307 else { 1308 format = normalFormat; 1309 } 1310 var s = format.format(marker); 1311 return postProcess(s, date, standardDateProps, extendedSettings, context); 1312 }; 1313 } 1314 function sanitizeSettings(standardDateProps, extendedSettings) { 1315 // deal with a browser inconsistency where formatting the timezone 1316 // requires that the hour/minute be present. 1317 if (standardDateProps.timeZoneName) { 1318 if (!standardDateProps.hour) { 1319 standardDateProps.hour = '2-digit'; 1320 } 1321 if (!standardDateProps.minute) { 1322 standardDateProps.minute = '2-digit'; 1323 } 1324 } 1325 // only support short timezone names 1326 if (standardDateProps.timeZoneName === 'long') { 1327 standardDateProps.timeZoneName = 'short'; 1328 } 1329 // if requesting to display seconds, MUST display minutes 1330 if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) { 1331 delete extendedSettings.omitZeroMinute; 1332 } 1333 } 1334 function postProcess(s, date, standardDateProps, extendedSettings, context) { 1335 s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes 1336 if (standardDateProps.timeZoneName === 'short') { 1337 s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ? 1338 'UTC' : // important to normalize for IE, which does "GMT" 1339 formatTimeZoneOffset(date.timeZoneOffset)); 1340 } 1341 if (extendedSettings.omitCommas) { 1342 s = s.replace(COMMA_RE, '').trim(); 1343 } 1344 if (extendedSettings.omitZeroMinute) { 1345 s = s.replace(':00', ''); // zeroFormat doesn't always achieve this 1346 } 1347 // ^ do anything that might create adjacent spaces before this point, 1348 // because MERIDIEM_RE likes to eat up loading spaces 1349 if (extendedSettings.meridiem === false) { 1350 s = s.replace(MERIDIEM_RE, '').trim(); 1351 } 1352 else if (extendedSettings.meridiem === 'narrow') { // a/p 1353 s = s.replace(MERIDIEM_RE, function (m0, m1) { return m1.toLocaleLowerCase(); }); 1354 } 1355 else if (extendedSettings.meridiem === 'short') { // am/pm 1356 s = s.replace(MERIDIEM_RE, function (m0, m1) { return m1.toLocaleLowerCase() + "m"; }); 1357 } 1358 else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase 1359 s = s.replace(MERIDIEM_RE, function (m0) { return m0.toLocaleLowerCase(); }); 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 if (typeof input === 'string') { 1518 return new CmdFormatter(input); 1519 } 1520 if (typeof input === 'function') { 1521 return new FuncFormatter(input); 1522 } 1523 return null; 1524 } 1525 1526 // base options 1527 // ------------ 1528 var BASE_OPTION_REFINERS = { 1529 navLinkDayClick: identity, 1530 navLinkWeekClick: identity, 1531 duration: createDuration, 1532 bootstrapFontAwesome: identity, 1533 buttonIcons: identity, 1534 customButtons: identity, 1535 defaultAllDayEventDuration: createDuration, 1536 defaultTimedEventDuration: createDuration, 1537 nextDayThreshold: createDuration, 1538 scrollTime: createDuration, 1539 slotMinTime: createDuration, 1540 slotMaxTime: createDuration, 1541 dayPopoverFormat: createFormatter, 1542 slotDuration: createDuration, 1543 snapDuration: createDuration, 1544 headerToolbar: identity, 1545 footerToolbar: identity, 1546 defaultRangeSeparator: String, 1547 titleRangeSeparator: String, 1548 forceEventDuration: Boolean, 1549 dayHeaders: Boolean, 1550 dayHeaderFormat: createFormatter, 1551 dayHeaderClassNames: identity, 1552 dayHeaderContent: identity, 1553 dayHeaderDidMount: identity, 1554 dayHeaderWillUnmount: identity, 1555 dayCellClassNames: identity, 1556 dayCellContent: identity, 1557 dayCellDidMount: identity, 1558 dayCellWillUnmount: identity, 1559 initialView: String, 1560 aspectRatio: Number, 1561 weekends: Boolean, 1562 weekNumberCalculation: identity, 1563 weekNumbers: Boolean, 1564 weekNumberClassNames: identity, 1565 weekNumberContent: identity, 1566 weekNumberDidMount: identity, 1567 weekNumberWillUnmount: identity, 1568 editable: Boolean, 1569 viewClassNames: identity, 1570 viewDidMount: identity, 1571 viewWillUnmount: identity, 1572 nowIndicator: Boolean, 1573 nowIndicatorClassNames: identity, 1574 nowIndicatorContent: identity, 1575 nowIndicatorDidMount: identity, 1576 nowIndicatorWillUnmount: identity, 1577 showNonCurrentDates: Boolean, 1578 lazyFetching: Boolean, 1579 startParam: String, 1580 endParam: String, 1581 timeZoneParam: String, 1582 timeZone: String, 1583 locales: identity, 1584 locale: identity, 1585 themeSystem: String, 1586 dragRevertDuration: Number, 1587 dragScroll: Boolean, 1588 allDayMaintainDuration: Boolean, 1589 unselectAuto: Boolean, 1590 dropAccept: identity, 1591 eventOrder: parseFieldSpecs, 1592 handleWindowResize: Boolean, 1593 windowResizeDelay: Number, 1594 longPressDelay: Number, 1595 eventDragMinDistance: Number, 1596 expandRows: Boolean, 1597 height: identity, 1598 contentHeight: identity, 1599 direction: String, 1600 weekNumberFormat: createFormatter, 1601 eventResizableFromStart: Boolean, 1602 displayEventTime: Boolean, 1603 displayEventEnd: Boolean, 1604 weekText: String, 1605 progressiveEventRendering: Boolean, 1606 businessHours: identity, 1607 initialDate: identity, 1608 now: identity, 1609 eventDataTransform: identity, 1610 stickyHeaderDates: identity, 1611 stickyFooterScrollbar: identity, 1612 viewHeight: identity, 1613 defaultAllDay: Boolean, 1614 eventSourceFailure: identity, 1615 eventSourceSuccess: identity, 1616 eventDisplay: String, 1617 eventStartEditable: Boolean, 1618 eventDurationEditable: Boolean, 1619 eventOverlap: identity, 1620 eventConstraint: identity, 1621 eventAllow: identity,
1622 eventBackgroundColor: String, 1623 eventBorderColor: String, 1624 eventTextColor: String, 1625 eventColor: String, 1626 eventClassNames: identity, 1627 eventContent: identity, 1628 eventDidMount: identity, 1629 eventWillUnmount: identity, 1630 selectConstraint: identity, 1631 selectOverlap: identity, 1632 selectAllow: identity, 1633 droppable: Boolean, 1634 unselectCancel: String, 1635 slotLabelFormat: identity, 1636 slotLaneClassNames: identity, 1637 slotLaneContent: identity, 1638 slotLaneDidMount: identity, 1639 slotLaneWillUnmount: identity, 1640 slotLabelClassNames: identity, 1641 slotLabelContent: identity, 1642 slotLabelDidMount: identity, 1643 slotLabelWillUnmount: identity, 1644 dayMaxEvents: identity, 1645 dayMaxEventRows: identity, 1646 dayMinWidth: Number, 1647 slotLabelInterval: createDuration, 1648 allDayText: String, 1649 allDayClassNames: identity, 1650 allDayContent: identity, 1651 allDayDidMount: identity, 1652 allDayWillUnmount: identity, 1653 slotMinWidth: Number, 1654 navLinks: Boolean, 1655 eventTimeFormat: createFormatter, 1656 rerenderDelay: Number, 1657 moreLinkText: identity, 1658 selectMinDistance: Number, 1659 selectable: Boolean, 1660 selectLongPressDelay: Number, 1661 eventLongPressDelay: Number, 1662 selectMirror: Boolean, 1663 eventMinHeight: Number, 1664 slotEventOverlap: Boolean, 1665 plugins: identity, 1666 firstDay: Number, 1667 dayCount: Number, 1668 dateAlignment: String, 1669 dateIncrement: createDuration, 1670 hiddenDays: identity, 1671 monthMode: Boolean, 1672 fixedWeekCount: Boolean, 1673 validRange: identity, 1674 visibleRange: identity, 1675 titleFormat: identity, 1676 // only used by list-view, but languages define the value, so we need it in base options 1677 noEventsText: String, 1678 }; 1679 // do NOT give a type here. need `typeof BASE_OPTION_DEFAULTS` to give real results. 1680 // raw values. 1681 var BASE_OPTION_DEFAULTS = { 1682 eventDisplay: 'auto', 1683 defaultRangeSeparator: ' - ', 1684 titleRangeSeparator: ' \u2013 ', 1685 defaultTimedEventDuration: '01:00:00', 1686 defaultAllDayEventDuration: { day: 1 }, 1687 forceEventDuration: false, 1688 nextDayThreshold: '00:00:00', 1689 dayHeaders: true, 1690 initialView: '', 1691 aspectRatio: 1.35, 1692 headerToolbar: { 1693 start: 'title', 1694 center: '', 1695 end: 'today prev,next', 1696 }, 1697 weekends: true, 1698 weekNumbers: false, 1699 weekNumberCalculation: 'local', 1700 editable: false, 1701 nowIndicator: false, 1702 scrollTime: '06:00:00', 1703 slotMinTime: '00:00:00', 1704 slotMaxTime: '24:00:00', 1705 showNonCurrentDates: true, 1706 lazyFetching: true, 1707 startParam: 'start', 1708 endParam: 'end', 1709 timeZoneParam: 'timeZone', 1710 timeZone: 'local', 1711 locales: [], 1712 locale: '', 1713 themeSystem: 'standard', 1714 dragRevertDuration: 500, 1715 dragScroll: true, 1716 allDayMaintainDuration: false, 1717 unselectAuto: true, 1718 dropAccept: '*', 1719 eventOrder: 'start,-duration,allDay,title', 1720 dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' }, 1721 handleWindowResize: true, 1722 windowResizeDelay: 100, 1723 longPressDelay: 1000, 1724 eventDragMinDistance: 5, 1725 expandRows: false, 1726 navLinks: false, 1727 selectable: false, 1728 }; 1729 // calendar listeners 1730 // ------------------ 1731 var CALENDAR_LISTENER_REFINERS = { 1732 datesSet: identity, 1733 eventsSet: identity, 1734 eventAdd: identity, 1735 eventChange: identity, 1736 eventRemove: identity, 1737 windowResize: identity, 1738 eventClick: identity, 1739 eventMouseEnter: identity, 1740 eventMouseLeave: identity, 1741 select: identity, 1742 unselect: identity, 1743 loading: identity, 1744 // internal 1745 _unmount: identity, 1746 _beforeprint: identity, 1747 _afterprint: identity, 1748 _noEventDrop: identity, 1749 _noEventResize: identity, 1750 _resize: identity, 1751 _scrollRequest: identity, 1752 }; 1753 // calendar-specific options 1754 // ------------------------- 1755 var CALENDAR_OPTION_REFINERS = { 1756 buttonText: identity, 1757 views: identity, 1758 plugins: identity, 1759 initialEvents: identity,
1760 events: identity, 1761 eventSources: identity, 1762 }; 1763 var COMPLEX_OPTION_COMPARATORS = { 1764 headerToolbar: isBoolComplexEqual, 1765 footerToolbar: isBoolComplexEqual, 1766 buttonText: isBoolComplexEqual, 1767 buttonIcons: isBoolComplexEqual, 1768 }; 1769 function isBoolComplexEqual(a, b) { 1770 if (typeof a === 'object' && typeof b === 'object' && a && b) { // both non-null objects 1771 return isPropsEqual(a, b); 1772 } 1773 return a === b; 1774 } 1775 // view-specific options 1776 // --------------------- 1777 var VIEW_OPTION_REFINERS = { 1778 type: String, 1779 component: identity, 1780 buttonText: String, 1781 buttonTextKey: String, 1782 dateProfileGeneratorClass: identity, 1783 usesMinMaxTime: Boolean, 1784 classNames: identity, 1785 content: identity, 1786 didMount: identity, 1787 willUnmount: identity, 1788 }; 1789 // util funcs 1790 // ---------------------------------------------------------------------------------------------------- 1791 function mergeRawOptions(optionSets) { 1792 return mergeProps(optionSets, COMPLEX_OPTION_COMPARATORS); 1793 } 1794 function refineProps(input, refiners) { 1795 var refined = {}; 1796 var extra = {}; 1797 for (var propName in refiners) { 1798 if (propName in input) { 1799 refined[propName] = refiners[propName](input[propName]); 1800 } 1801 } 1802 for (var propName in input) { 1803 if (!(propName in refiners)) { 1804 extra[propName] = input[propName]; 1805 } 1806 } 1807 return { refined: refined, extra: extra }; 1808 } 1809 function identity(raw) { 1810 return raw; 1811 } 1812 1813 function parseEvents(rawEvents, eventSource, context, allowOpenRange) { 1814 var eventStore = createEmptyEventStore(); 1815 var eventRefiners = buildEventRefiners(context); 1816 for (var _i = 0, rawEvents_1 = rawEvents; _i < rawEvents_1.length; _i++) { 1817 var rawEvent = rawEvents_1[_i]; 1818 var tuple = parseEvent(rawEvent, eventSource, context, allowOpenRange, eventRefiners); 1819 if (tuple) { 1820 eventTupleToStore(tuple, eventStore); 1821 } 1822 } 1823 return eventStore; 1824 } 1825 function eventTupleToStore(tuple, eventStore) { 1826 if (eventStore === void 0) { eventStore = createEmptyEventStore(); } 1827 eventStore.defs[tuple.def.defId] = tuple.def; 1828 if (tuple.instance) { 1829 eventStore.instances[tuple.instance.instanceId] = tuple.instance; 1830 } 1831 return eventStore; 1832 } 1833 // retrieves events that have the same groupId as the instance specified by `instanceId` 1834 // or they are the same as the instance. 1835 // why might instanceId not be in the store? an event from another calendar? 1836 function getRelevantEvents(eventStore, instanceId) { 1837 var instance = eventStore.instances[instanceId]; 1838 if (instance) { 1839 var def_1 = eventStore.defs[instance.defId]; 1840 // get events/instances with same group 1841 var newStore = filterEventStoreDefs(eventStore, function (lookDef) { return isEventDefsGrouped(def_1, lookDef); }); 1842 // add the original 1843 // TODO: wish we could use eventTupleToStore or something like it 1844 newStore.defs[def_1.defId] = def_1; 1845 newStore.instances[instance.instanceId] = instance; 1846 return newStore; 1847 } 1848 return createEmptyEventStore(); 1849 } 1850 function isEventDefsGrouped(def0, def1) { 1851 return Boolean(def0.groupId && def0.groupId === def1.groupId); 1852 } 1853 function createEmptyEventStore() { 1854 return { defs: {}, instances: {} }; 1855 } 1856 function mergeEventStores(store0, store1) { 1857 return { 1858 defs: __assign(__assign({}, store0.defs), store1.defs), 1859 instances: __assign(__assign({}, store0.instances), store1.instances), 1860 }; 1861 } 1862 function filterEventStoreDefs(eventStore, filterFunc) { 1863 var defs = filterHash(eventStore.defs, filterFunc); 1864 var instances = filterHash(eventStore.instances, function (instance) { return (defs[instance.defId] // still exists? 1865 ); }); 1866 return { defs: defs, instances: instances }; 1867 } 1868 function excludeSubEventStore(master, sub) { 1869 var defs = master.defs, instances = master.instances; 1870 var filteredDefs = {}; 1871 var filteredInstances = {}; 1872 for (var defId in defs) { 1873 if (!sub.defs[defId]) { // not explicitly excluded
vendor: 4,594 bytes, lines 1874-1992
1874 filteredDefs[defId] = defs[defId]; 1875 } 1876 } 1877 for (var instanceId in instances) { 1878 if (!sub.instances[instanceId] && // not explicitly excluded 1879 filteredDefs[instances[instanceId].defId] // def wasn't filtered away 1880 ) { 1881 filteredInstances[instanceId] = instances[instanceId]; 1882 } 1883 } 1884 return { 1885 defs: filteredDefs, 1886 instances: filteredInstances, 1887 }; 1888 } 1889 1890 function normalizeConstraint(input, context) { 1891 if (Array.isArray(input)) { 1892 return parseEvents(input, null, context, true); // allowOpenRange=true 1893 } 1894 if (typeof input === 'object' && input) { // non-null object 1895 return parseEvents([input], null, context, true); // allowOpenRange=true 1896 } 1897 if (input != null) { 1898 return String(input); 1899 } 1900 return null; 1901 } 1902 1903 function parseClassNames(raw) { 1904 if (Array.isArray(raw)) { 1905 return raw; 1906 } 1907 if (typeof raw === 'string') { 1908 return raw.split(/\s+/); 1909 } 1910 return []; 1911 } 1912 1913 // TODO: better called "EventSettings" or "EventConfig" 1914 // TODO: move this file into structs 1915 // TODO: separate constraint/overlap/allow, because selection uses only that, not other props 1916 var EVENT_UI_REFINERS = { 1917 display: String, 1918 editable: Boolean, 1919 startEditable: Boolean, 1920 durationEditable: Boolean, 1921 constraint: identity, 1922 overlap: identity, 1923 allow: identity, 1924 className: parseClassNames, 1925 classNames: parseClassNames, 1926 color: String, 1927 backgroundColor: String, 1928 borderColor: String, 1929 textColor: String, 1930 }; 1931 var EMPTY_EVENT_UI = { 1932 display: null, 1933 startEditable: null, 1934 durationEditable: null, 1935 constraints: [], 1936 overlap: null, 1937 allows: [], 1938 backgroundColor: '', 1939 borderColor: '', 1940 textColor: '', 1941 classNames: [], 1942 }; 1943 function createEventUi(refined, context) { 1944 var constraint = normalizeConstraint(refined.constraint, context); 1945 return { 1946 display: refined.display || null, 1947 startEditable: refined.startEditable != null ? refined.startEditable : refined.editable, 1948 durationEditable: refined.durationEditable != null ? refined.durationEditable : refined.editable, 1949 constraints: constraint != null ? [constraint] : [], 1950 overlap: refined.overlap != null ? refined.overlap : null, 1951 allows: refined.allow != null ? [refined.allow] : [], 1952 backgroundColor: refined.backgroundColor || refined.color || '', 1953 borderColor: refined.borderColor || refined.color || '', 1954 textColor: refined.textColor || '', 1955 classNames: (refined.className || []).concat(refined.classNames || []), 1956 }; 1957 } 1958 // TODO: prevent against problems with <2 args! 1959 function combineEventUis(uis) { 1960 return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI); 1961 } 1962 function combineTwoEventUis(item0, item1) { 1963 return { 1964 display: item1.display != null ? item1.display : item0.display, 1965 startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable, 1966 durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable, 1967 constraints: item0.constraints.concat(item1.constraints), 1968 overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap, 1969 allows: item0.allows.concat(item1.allows), 1970 backgroundColor: item1.backgroundColor || item0.backgroundColor, 1971 borderColor: item1.borderColor || item0.borderColor, 1972 textColor: item1.textColor || item0.textColor, 1973 classNames: item0.classNames.concat(item1.classNames), 1974 }; 1975 } 1976 1977 var EVENT_NON_DATE_REFINERS = { 1978 id: String, 1979 groupId: String, 1980 title: String, 1981 url: String, 1982 }; 1983 var EVENT_DATE_REFINERS = { 1984 start: identity, 1985 end: identity, 1986 date: identity, 1987 allDay: Boolean, 1988 }; 1989 var EVENT_REFINERS = __assign(__assign(__assign({}, EVENT_NON_DATE_REFINERS), EVENT_DATE_REFINERS), { extendedProps: identity }); 1990 function parseEvent(raw, eventSource, context, allowOpenRange, refiners) { 1991 if (refiners === void 0) { refiners = buildEventRefiners(context); } 1992 var _a = refineEventDef(raw, context, refiners), refined
1992= _a.refined, extra = _a.extra; 1993 var defaultAllDay = computeIsDefaultAllDay(eventSource, context); 1994 var recurringRes = parseRecurring(refined, defaultAllDay, context.dateEnv, context.pluginHooks.recurringTypes); 1995 if (recurringRes) { 1996 var def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', recurringRes.allDay, Boolean(recurringRes.duration), context); 1997 def.recurringDef = { 1998 typeId: recurringRes.typeId, 1999 typeData: recurringRes.typeData, 2000 duration: recurringRes.duration, 2001 }; 2002 return { def: def, instance: null }; 2003 } 2004 var singleRes = parseSingle(refined, defaultAllDay, context, allowOpenRange); 2005 if (singleRes) { 2006 var def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', singleRes.allDay, singleRes.hasEnd, context); 2007 var instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo); 2008 return { def: def, instance: instance }; 2009 } 2010 return null; 2011 } 2012 function refineEventDef(raw, context, refiners) { 2013 if (refiners === void 0) { refiners = buildEventRefiners(context); } 2014 return refineProps(raw, refiners); 2015 } 2016 function buildEventRefiners(context) { 2017 return __assign(__assign(__assign({}, EVENT_UI_REFINERS), EVENT_REFINERS), context.pluginHooks.eventRefiners); 2018 } 2019 /* 2020 Will NOT populate extendedProps with the leftover properties. 2021 Will NOT populate date-related props. 2022 */ 2023 function parseEventDef(refined, extra, sourceId, allDay, hasEnd, context) { 2024 var def = { 2025 title: refined.title || '', 2026 groupId: refined.groupId || '', 2027 publicId: refined.id || '', 2028 url: refined.url || '', 2029 recurringDef: null, 2030 defId: guid(), 2031 sourceId: sourceId, 2032 allDay: allDay, 2033 hasEnd: hasEnd, 2034 ui: createEventUi(refined, context), 2035 extendedProps: __assign(__assign({}, (refined.extendedProps || {})), extra), 2036 }; 2037 for (var _i = 0, _a = context.pluginHooks.eventDefMemberAdders; _i < _a.length; _i++) { 2038 var memberAdder = _a[_i]; 2039 __assign(def, memberAdder(refined)); 2040 } 2041 // help out EventApi from having user modify props 2042 Object.freeze(def.ui.classNames); 2043 Object.freeze(def.extendedProps); 2044 return def; 2045 } 2046 function parseSingle(refined, defaultAllDay, context, allowOpenRange) { 2047 var allDay = refined.allDay; 2048 var startMeta; 2049 var startMarker = null; 2050 var hasEnd = false; 2051 var endMeta; 2052 var endMarker = null; 2053 var startInput = refined.start != null ? refined.start : refined.date; 2054 startMeta = context.dateEnv.createMarkerMeta(startInput); 2055 if (startMeta) { 2056 startMarker = startMeta.marker; 2057 } 2058 else if (!allowOpenRange) { 2059 return null; 2060 } 2061 if (refined.end != null) { 2062 endMeta = context.dateEnv.createMarkerMeta(refined.end); 2063 } 2064 if (allDay == null) { 2065 if (defaultAllDay != null) { 2066 allDay = defaultAllDay; 2067 } 2068 else { 2069 // fall back to the date props LAST 2070 allDay = (!startMeta || startMeta.isTimeUnspecified) && 2071 (!endMeta || endMeta.isTimeUnspecified); 2072 } 2073 } 2074 if (allDay && startMarker) { 2075 startMarker = startOfDay(startMarker); 2076 } 2077 if (endMeta) { 2078 endMarker = endMeta.marker; 2079 if (allDay) { 2080 endMarker = startOfDay(endMarker); 2081 } 2082 if (startMarker && endMarker <= startMarker) { 2083 endMarker = null; 2084 } 2085 } 2086 if (endMarker) { 2087 hasEnd = true; 2088 } 2089 else if (!allowOpenRange) { 2090 hasEnd = context.options.forceEventDuration || false; 2091 endMarker = context.dateEnv.add(startMarker, allDay ? 2092 context.options.defaultAllDayEventDuration : 2093 context.options.defaultTimedEventDuration); 2094 } 2095 return { 2096 allDay: allDay, 2097 hasEnd: hasEnd, 2098 range: { start: startMarker, end: endMarker }, 2099 forcedStartTzo: startMeta ? startMeta.forcedTzo : null, 2100 forcedEndTzo: endMeta ? endMeta.forcedTzo : null, 2101 }; 2102 } 2103 function computeIsDefaultAllDay(eventSource, context) { 2104 var res = null; 2105 if (eventSource) { 2106 res = eventSource.defaultAllDay; 2107 } 2108 if (res == null) { 2109 res = context.options.defaultAllDay; 2110 } 2111 return res; 2112 } 2113 2114 /* Date stuff that doesn't belong in datelib core 2115 ----------------------------------------------------------------------------------------------------------------------*/ 2116 // given a timed range, computes an all-day range that has the same exact duration, 2117 // but whose start time is aligned with the start of the day. 2118 function computeAlignedDayRange(timedRange) { 2119 var dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1; 2120 var start = startOfDay(timedRange.start); 2121 var end = addDays(start, dayCnt); 2122 return { start: start, end: end }; 2123 } 2124 // given a timed range, computes an all-day range based on how for the end date bleeds into the next day 2125 // TODO: give nextDayThreshold a default arg 2126 function computeVisibleDayRange(timedRange, nextDayThreshold) { 2127 if (nextDayThreshold === void 0) { nextDayThreshold = createDuration(0); } 2128 var startDay = null; 2129 var endDay = null; 2130 if (timedRange.end) { 2131 endDay = startOfDay(timedRange.end); 2132 var endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay` 2133 // If the end time is actually inclusively part of the next day and is equal to or
vendor: 15,639 bytes, lines 2134-2509
2134 // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`. 2135 // Otherwise, leaving it as inclusive will cause it to exclude `endDay`. 2136 if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) { 2137 endDay = addDays(endDay, 1); 2138 } 2139 } 2140 if (timedRange.start) { 2141 startDay = startOfDay(timedRange.start); // the beginning of the day the range starts 2142 // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day. 2143 if (endDay && endDay <= startDay) { 2144 endDay = addDays(startDay, 1); 2145 } 2146 } 2147 return { start: startDay, end: endDay }; 2148 } 2149 // spans from one day into another? 2150 function isMultiDayRange(range) { 2151 var visibleRange = computeVisibleDayRange(range); 2152 return diffDays(visibleRange.start, visibleRange.end) > 1; 2153 } 2154 function diffDates(date0, date1, dateEnv, largeUnit) { 2155 if (largeUnit === 'year') { 2156 return createDuration(dateEnv.diffWholeYears(date0, date1), 'year'); 2157 } 2158 if (largeUnit === 'month') { 2159 return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month'); 2160 } 2161 return diffDayAndTime(date0, date1); // returns a duration 2162 } 2163 2164 function parseRange(input, dateEnv) { 2165 var start = null; 2166 var end = null; 2167 if (input.start) { 2168 start = dateEnv.createMarker(input.start); 2169 } 2170 if (input.end) { 2171 end = dateEnv.createMarker(input.end); 2172 } 2173 if (!start && !end) { 2174 return null; 2175 } 2176 if (start && end && end < start) { 2177 return null; 2178 } 2179 return { start: start, end: end }; 2180 } 2181 // SIDE-EFFECT: will mutate ranges. 2182 // Will return a new array result. 2183 function invertRanges(ranges, constraintRange) { 2184 var invertedRanges = []; 2185 var start = constraintRange.start; // the end of the previous range. the start of the new range 2186 var i; 2187 var dateRange; 2188 // ranges need to be in order. required for our date-walking algorithm 2189 ranges.sort(compareRanges); 2190 for (i = 0; i < ranges.length; i += 1) { 2191 dateRange = ranges[i]; 2192 // add the span of time before the event (if there is any) 2193 if (dateRange.start > start) { // compare millisecond time (skip any ambig logic) 2194 invertedRanges.push({ start: start, end: dateRange.start }); 2195 } 2196 if (dateRange.end > start) { 2197 start = dateRange.end; 2198 } 2199 } 2200 // add the span of time after the last event (if there is any) 2201 if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic) 2202 invertedRanges.push({ start: start, end: constraintRange.end }); 2203 } 2204 return invertedRanges; 2205 } 2206 function compareRanges(range0, range1) { 2207 return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first 2208 } 2209 function intersectRanges(range0, range1) { 2210 var start = range0.start, end = range0.end; 2211 var newRange = null; 2212 if (range1.start !== null) { 2213 if (start === null) { 2214 start = range1.start; 2215 } 2216 else { 2217 start = new Date(Math.max(start.valueOf(), range1.start.valueOf())); 2218 } 2219 } 2220 if (range1.end != null) { 2221 if (end === null) { 2222 end = range1.end; 2223 } 2224 else { 2225 end = new Date(Math.min(end.valueOf(), range1.end.valueOf())); 2226 } 2227 } 2228 if (start === null || end === null || start < end) { 2229 newRange = { start: start, end: end }; 2230 } 2231 return newRange; 2232 } 2233 function rangesEqual(range0, range1) { 2234 return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) && 2235 (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf()); 2236 } 2237 function rangesIntersect(range0, range1) { 2238 return (range0.end === null || range1.start === null || range0.end > range1.start) && 2239 (range0.start === null || range1.end === null || range0.start < range1.end); 2240 } 2241 function rangeContainsRange(outerRange, innerRange) { 2242 return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) && 2243 (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end)); 2244 } 2245 function rangeContainsMarker(range, date) { 2246 return (range.start === null || date >= range.start) && 2247 (range.end === null || date < range.end); 2248 } 2249 // If the given date is not within the given range, move it inside. 2250 // (If it's past the end, make it one millisecond before the end). 2251 function constrainMarkerToRange(date, range) { 2252 if (range.start != null && date < range.start) { 2253 return range.start; 2254 } 2255 if (range.end != null && date >= range.end) { 2256 return new Date(range.end.valueOf() - 1); 2257 } 2258 return date; 2259 } 2260 2261 /* 2262 Specifying nextDayThreshold signals that all-day ranges should be sliced. 2263 */ 2264 function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) { 2265 var inverseBgByGroupId = {}; 2266 var inverseBgByDefId = {}; 2267 var defByGroupId = {}; 2268 var bgRanges = []; 2269 var fgRanges = []; 2270 var eventUis = compileEventUis(eventStore.defs, eventUiBases); 2271 for (var defId in eventStore.defs) { 2272 var def = eventStore.defs[defId]; 2273 var ui = eventUis[def.defId]; 2274 if (ui.display === 'inverse-background') { 2275 if (def.groupId) { 2276 inverseBgByGroupId[def.groupId] = []; 2277 if (!defByGroupId[def.groupId]) { 2278 defByGroupId[def.groupId] = def; 2279 } 2280 } 2281 else { 2282 inverseBgByDefId[defId] = []; 2283 } 2284 } 2285 } 2286 for (var instanceId in eventStore.instances) { 2287 var instance = eventStore.instances[instanceId]; 2288 var def = eventStore.defs[instance.defId]; 2289 var ui = eventUis[def.defId]; 2290 var origRange = instance.range; 2291 var normalRange = (!def.allDay && nextDayThreshold) ? 2292 computeVisibleDayRange(origRange, nextDayThreshold) : 2293 origRange; 2294 var slicedRange = intersectRanges(normalRange, framingRange); 2295 if (slicedRange) { 2296 if (ui.display === 'inverse-background') { 2297 if (def.groupId) { 2298 inverseBgByGroupId[def.groupId].push(slicedRange); 2299 } 2300 else { 2301 inverseBgByDefId[instance.defId].push(slicedRange); 2302 } 2303 } 2304 else if (ui.display !== 'none') { 2305 (ui.display === 'background' ? bgRanges : fgRanges).push({ 2306 def: def, 2307 ui: ui, 2308 instance: instance, 2309 range: slicedRange, 2310 isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(), 2311 isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf(), 2312 }); 2313 } 2314 } 2315 } 2316 for (var groupId in inverseBgByGroupId) { // BY GROUP 2317 var ranges = inverseBgByGroupId[groupId]; 2318 var invertedRanges = invertRanges(ranges, framingRange); 2319 for (var _i = 0, invertedRanges_1 = invertedRanges; _i < invertedRanges_1.length; _i++) { 2320 var invertedRange = invertedRanges_1[_i]; 2321 var def = defByGroupId[groupId]; 2322 var ui = eventUis[def.defId]; 2323 bgRanges.push({ 2324 def: def, 2325 ui: ui, 2326 instance: null, 2327 range: invertedRange, 2328 isStart: false, 2329 isEnd: false, 2330 }); 2331 } 2332 } 2333 for (var defId in inverseBgByDefId) { 2334 var ranges = inverseBgByDefId[defId]; 2335 var invertedRanges = invertRanges(ranges, framingRange); 2336 for (var _a = 0, invertedRanges_2 = invertedRanges; _a < invertedRanges_2.length; _a++) { 2337 var invertedRange = invertedRanges_2[_a]; 2338 bgRanges.push({ 2339 def: eventStore.defs[defId], 2340 ui: eventUis[defId], 2341 instance: null, 2342 range: invertedRange, 2343 isStart: false, 2344 isEnd: false, 2345 }); 2346 } 2347 } 2348 return { bg: bgRanges, fg: fgRanges }; 2349 } 2350 function hasBgRendering(def) { 2351 return def.ui.display === 'background' || def.ui.display === 'inverse-background'; 2352 } 2353 function setElSeg(el, seg) { 2354 el.fcSeg = seg; 2355 } 2356 function getElSeg(el) { 2357 return el.fcSeg || 2358 el.parentNode.fcSeg || // for the harness 2359 null; 2360 } 2361 // event ui computation 2362 function compileEventUis(eventDefs, eventUiBases) { 2363 return mapHash(eventDefs, function (eventDef) { return compileEventUi(eventDef, eventUiBases); }); 2364 } 2365 function compileEventUi(eventDef, eventUiBases) { 2366 var uis = []; 2367 if (eventUiBases['']) { 2368 uis.push(eventUiBases['']); 2369 } 2370 if (eventUiBases[eventDef.defId]) { 2371 uis.push(eventUiBases[eventDef.defId]); 2372 } 2373 uis.push(eventDef.ui); 2374 return combineEventUis(uis); 2375 } 2376 function sortEventSegs(segs, eventOrderSpecs) { 2377 var objs = segs.map(buildSegCompareObj); 2378 objs.sort(function (obj0, obj1) { return compareByFieldSpecs(obj0, obj1, eventOrderSpecs); }); 2379 return objs.map(function (c) { return c._seg; }); 2380 } 2381 // returns a object with all primitive props that can be compared 2382 function buildSegCompareObj(seg) { 2383 var eventRange = seg.eventRange; 2384 var eventDef = eventRange.def; 2385 var range = eventRange.instance ? eventRange.instance.range : eventRange.range; 2386 var start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events 2387 var end = range.end ? range.end.valueOf() : 0; // " 2388 return __assign(__assign(__assign({}, eventDef.extendedProps), eventDef), { id: eventDef.publicId, start: start, 2389 end: end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg }); 2390 } 2391 function computeSegDraggable(seg, context) { 2392 var pluginHooks = context.pluginHooks; 2393 var transformers = pluginHooks.isDraggableTransformers; 2394 var _a = seg.eventRange, def = _a.def, ui = _a.ui; 2395 var val = ui.startEditable; 2396 for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) { 2397 var transformer = transformers_1[_i]; 2398 val = transformer(val, def, ui, context); 2399 } 2400 return val; 2401 } 2402 function computeSegStartResizable(seg, context) { 2403 return seg.isStart && seg.eventRange.ui.durationEditable && context.options.eventResizableFromStart; 2404 } 2405 function computeSegEndResizable(seg, context) { 2406 return seg.isEnd && seg.eventRange.ui.durationEditable; 2407 } 2408 function buildSegTimeText(seg, timeFormat, context, defaultDisplayEventTime, // defaults to true 2409 defaultDisplayEventEnd, // defaults to true 2410 startOverride, endOverride) { 2411 var dateEnv = context.dateEnv, options = context.options; 2412 var displayEventTime = options.displayEventTime, displayEventEnd = options.displayEventEnd; 2413 var eventDef = seg.eventRange.def; 2414 var eventInstance = seg.eventRange.instance; 2415 if (displayEventTime == null) { 2416 displayEventTime = defaultDisplayEventTime !== false; 2417 } 2418 if (displayEventEnd == null) { 2419 displayEventEnd = defaultDisplayEventEnd !== false; 2420 } 2421 if (displayEventTime && !eventDef.allDay && (seg.isStart || seg.isEnd)) { 2422 var segStart = startOverride || (seg.isStart ? eventInstance.range.start : (seg.start || seg.eventRange.range.start)); 2423 var segEnd = endOverride || (seg.isEnd ? eventInstance.range.end : (seg.end || seg.eventRange.range.end)); 2424 if (displayEventEnd && eventDef.hasEnd) { 2425 return dateEnv.formatRange(segStart, segEnd, timeFormat, { 2426 forcedStartTzo: startOverride ? null : eventInstance.forcedStartTzo, 2427 forcedEndTzo: endOverride ? null : eventInstance.forcedEndTzo, 2428 }); 2429 } 2430 return dateEnv.format(segStart, timeFormat, { 2431 forcedTzo: startOverride ? null : eventInstance.forcedStartTzo, 2432 }); 2433 } 2434 return ''; 2435 } 2436 function getSegMeta(seg, todayRange, nowDate) { 2437 var segRange = seg.eventRange.range; 2438 return { 2439 isPast: segRange.end < (nowDate || todayRange.start), 2440 isFuture: segRange.start >= (nowDate || todayRange.end), 2441 isToday: todayRange && rangeContainsMarker(todayRange, segRange.start), 2442 }; 2443 } 2444 function getEventClassNames(props) { 2445 var classNames = ['fc-event']; 2446 if (props.isMirror) { 2447 classNames.push('fc-event-mirror'); 2448 } 2449 if (props.isDraggable) { 2450 classNames.push('fc-event-draggable'); 2451 } 2452 if (props.isStartResizable || props.isEndResizable) { 2453 classNames.push('fc-event-resizable'); 2454 } 2455 if (props.isDragging) { 2456 classNames.push('fc-event-dragging'); 2457 } 2458 if (props.isResizing) { 2459 classNames.push('fc-event-resizing'); 2460 } 2461 if (props.isSelected) { 2462 classNames.push('fc-event-selected'); 2463 } 2464 if (props.isStart) { 2465 classNames.push('fc-event-start'); 2466 } 2467 if (props.isEnd) { 2468 classNames.push('fc-event-end'); 2469 } 2470 if (props.isPast) { 2471 classNames.push('fc-event-past'); 2472 } 2473 if (props.isToday) { 2474 classNames.push('fc-event-today'); 2475 } 2476 if (props.isFuture) { 2477 classNames.push('fc-event-future'); 2478 } 2479 return classNames; 2480 } 2481 function buildEventRangeKey(eventRange) { 2482 return eventRange.instance 2483 ? eventRange.instance.instanceId 2484 : eventRange.def.defId + ":" + eventRange.range.start.toISOString(); 2485 // inverse-background events don't have specific instances. TODO: better solution 2486 } 2487 2488 var STANDARD_PROPS = { 2489 start: identity, 2490 end: identity, 2491 allDay: Boolean, 2492 }; 2493 function parseDateSpan(raw, dateEnv, defaultDuration) { 2494 var span = parseOpenDateSpan(raw, dateEnv); 2495 var range = span.range; 2496 if (!range.start) { 2497 return null; 2498 } 2499 if (!range.end) { 2500 if (defaultDuration == null) { 2501 return null; 2502 } 2503 range.end = dateEnv.add(range.start, defaultDuration); 2504 } 2505 return span; 2506 } 2507 /* 2508 TODO: somehow combine with parseRange? 2509 Will return null if the start/end props were present but parsed invali
2509dly. 2510 */ 2511 function parseOpenDateSpan(raw, dateEnv) { 2512 var _a = refineProps(raw, STANDARD_PROPS), standardProps = _a.refined, extra = _a.extra; 2513 var startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null; 2514 var endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null; 2515 var allDay = standardProps.allDay; 2516 if (allDay == null) { 2517 allDay = (startMeta && startMeta.isTimeUnspecified) && 2518 (!endMeta || endMeta.isTimeUnspecified); 2519 } 2520 return __assign({ range: { 2521 start: startMeta ? startMeta.marker : null, 2522 end: endMeta ? endMeta.marker : null, 2523 }, allDay: allDay }, extra); 2524 } 2525 function isDateSpansEqual(span0, span1) { 2526 return rangesEqual(span0.range, span1.range) && 2527 span0.allDay === span1.allDay && 2528 isSpanPropsEqual(span0, span1); 2529 } 2530 // the NON-DATE-RELATED props 2531 function isSpanPropsEqual(span0, span1) { 2532 for (var propName in span1) { 2533 if (propName !== 'range' && propName !== 'allDay') { 2534 if (span0[propName] !== span1[propName]) { 2535 return false; 2536 } 2537 } 2538 } 2539 // are there any props that span0 has that span1 DOESN'T have? 2540 // both have range/allDay, so no need to special-case. 2541 for (var propName in span0) { 2542 if (!(propName in span1)) { 2543 return false; 2544 } 2545 } 2546 return true; 2547 } 2548 function buildDateSpanApi(span, dateEnv) { 2549 return __assign(__assign({}, buildRangeApi(span.range, dateEnv, span.allDay)), { allDay: span.allDay }); 2550 } 2551 function buildRangeApiWithTimeZone(range, dateEnv, omitTime) { 2552 return __assign(__assign({}, buildRangeApi(range, dateEnv, omitTime)), { timeZone: dateEnv.timeZone }); 2553 } 2554 function buildRangeApi(range, dateEnv, omitTime) { 2555 return { 2556 start: dateEnv.toDate(range.start), 2557 end: dateEnv.toDate(range.end), 2558 startStr: dateEnv.formatIso(range.start, { omitTime: omitTime }), 2559 endStr: dateEnv.formatIso(range.end, { omitTime: omitTime }), 2560 }; 2561 } 2562 function fabricateEventRange(dateSpan, eventUiBases, context) { 2563 var res = refineEventDef({ editable: false }, context); 2564 var def = parseEventDef(res.refined, res.extra, '', // sourceId 2565 dateSpan.allDay, true, // hasEnd 2566 context); 2567 return { 2568 def: def, 2569 ui: compileEventUi(def, eventUiBases), 2570 instance: createEventInstance(def.defId, dateSpan.range), 2571 range: dateSpan.range, 2572 isStart: true, 2573 isEnd: true, 2574 }; 2575 } 2576 2577 function triggerDateSelect(selection, pev, context) { 2578 context.emitter.trigger('select', __assign(__assign({}, buildDateSpanApiWithContext(selection, context)), { jsEvent: pev ? pev.origEvent : null, view: context.viewApi || context.calendarApi.view })); 2579 } 2580 function triggerDateUnselect(pev, context) { 2581 context.emitter.trigger('unselect', { 2582 jsEvent: pev ? pev.origEvent : null, 2583 view: context.viewApi || context.calendarApi.view, 2584 }); 2585 } 2586 function buildDateSpanApiWithContext(dateSpan, context) { 2587 var props = {}; 2588 for (var _i = 0, _a = context.pluginHooks.dateSpanTransforms; _i < _a.length; _i++) { 2589 var transform = _a[_i]; 2590 __assign(props, transform(dateSpan, context)); 2591 } 2592 __assign(props, buildDateSpanApi(dateSpan, context.dateEnv)); 2593 return props; 2594 } 2595 // Given an event's allDay status and start date, return what its fallback end date should be. 2596 // TODO: rename to computeDefaultEventEnd 2597 function getDefaultEventEnd(allDay, marker, context) { 2598 var dateEnv = context.dateEnv, options = context.options; 2599 var end = marker; 2600 if (allDay) { 2601 end = startOfDay(end); 2602 end = dateEnv.add(end, options.defaultAllDayEventDuration); 2603 } 2604 else { 2605 end = dateEnv.add(end, options.defaultTimedEventDuration); 2606 } 2607 return end; 2608 } 2609 2610 // applies the mutation to ALL defs/instances within the event store 2611 function applyMutationToEventStore(eventStore, eventConfigBase, mutation, context) { 2612 var eventConfigs = compileEventUis(eventStore.defs, eventConfigBase); 2613 var dest = createEmptyEventStore(); 2614 for (var defId in eventStore.defs) { 2615 var def = eventStore.defs[defId]; 2616 dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, context); 2617 } 2618 for (var instanceId in eventStore.instances) { 2619 var instance = eventStore.instances[instanceId]; 2620 var def = dest.defs[instance.defId]; // important to grab the newly modified def 2621 dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, context); 2622 } 2623 return dest; 2624 } 2625 function applyMutationToEventDef(eventDef, eventConfig, mutation, context) { 2626 var standardProps = mutation.standardProps || {}; 2627 // if hasEnd has not been specified, guess a good value based on deltas. 2628 // if duration will change, there's no way the default duration will persist, 2629 // and thus, we need to mark the event as having a real end 2630 if (standardProps.hasEnd == null && 2631 eventConfig.durationEditable && 2632 (mutation.startDelta || mutation.endDelta)) { 2633 standardProps.hasEnd = true; // TODO: is this mutation okay? 2634 } 2635 var copy = __assign(__assign(__assign({}, eventDef), standardProps), { ui: __assign(__assign({}, eventDef.ui), standardProps.ui) }); 2636 if (mutation.extendedProps) { 2637 copy.extendedProps = __assign(__assign({}, copy.extendedProps), mutation.extendedProps); 2638 } 2639 for (var _i = 0, _a = context.pluginHooks.eventDefMutationAppliers; _i < _a.length; _i++) { 2640 var applier = _a[_i]; 2641 applier(copy, mutation, context); 2642 } 2643 if (!copy.hasEnd && context.options.forceEventDuration) { 2644 copy.hasEnd = true; 2645 } 2646 return copy; 2647 } 2648 function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef 2649 eventConfig, mutation, context) { 2650 var dateEnv = context.dateEnv; 2651 var forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true; 2652 var clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false; 2653 var copy = __assign({}, eventInstance); 2654 if (forceAllDay) { 2655 copy.range = computeAlignedDayRange(copy.range); 2656 } 2657 if (mutation.datesDelta && eventConfig.startEditable) { 2658 copy.range = { 2659 start: dateEnv.add(copy.range.start, mutation.datesDelta), 2660 end: dateEnv.add(copy.range.end, mutation.datesDelta), 2661 }; 2662 } 2663 if (mutation.startDelta && eventConfig.durationEditable) { 2664 copy.range = { 2665 start: dateEnv.add(copy.range.start, mutation.startDelta), 2666 end: copy.range.end, 2667 }; 2668 } 2669 if (mutation.endDelta && eventConfig.durationEditable) { 2670 copy.range = { 2671 start: copy.range.start, 2672 end: dateEnv.add(copy.range.end, mutation.endDelta), 2673 }; 2674 } 2675 if (clearEnd) { 2676 copy.range = { 2677 start: copy.range.start, 2678 end: getDefaultEventEnd(eventDef.allDay, copy.range.start, context), 2679 }; 2680 } 2681 // in case event was all-day but the supplied deltas were not 2682 // better util for this? 2683 if (eventDef.allDay) { 2684 copy.range = { 2685 start: startOfDay(copy.range.start), 2686 end: startOfDay(copy.range.end), 2687 }; 2688 } 2689 // handle invalid durations 2690 if (copy.range.end < copy.range.start) { 2691 copy.range.end = getDefaultEventEnd(eventDef.allDay, copy.range.start, context); 2692 } 2693 return copy; 2694 } 2695 2696 // no public types yet. when there are, export from: 2697 // import {} from './api-type-deps' 2698 var ViewApi = /** @class */ (function () { 2699 function ViewApi(type, getCurrentData, dateEnv) { 2700 this.type = type; 2701 this.getCurrentData = getCurrentData; 2702 this.dateEnv = dateEnv; 2703 } 2704 Object.defineProperty(ViewApi.prototype, "calendar", { 2705 get: function () { 2706 return this.getCurrentData().calendarApi; 2707 }, 2708 enumerable: false, 2709 configurable: true 2710 }); 2711 Object.defineProperty(ViewApi.prototype, "title", { 2712 get: function () { 2713 return this.getCurrentData().viewTitle; 2714 }, 2715 enumerable: false, 2716 configurable: true 2717 }); 2718 Object.defineProperty(ViewApi.prototype, "activeStart", { 2719 get: function () { 2720 return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.start); 2721 }, 2722 enumerable: false, 2723 configurable: true 2724 }); 2725 Object.defineProperty(ViewApi.prototype, "activeEnd", { 2726 get: function () { 2727 return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.end); 2728 }, 2729 enumerable: false, 2730 configurable: true 2731 }); 2732 Object.defineProperty(ViewApi.prototype, "currentStart", { 2733 get: function () { 2734 return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.start); 2735 }, 2736 enumerable: false, 2737 configurable: true 2738 }); 2739 Object.defineProperty(ViewApi.prototype, "currentEnd", { 2740 get: function () { 2741 return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.end); 2742 }, 2743 enumerable: false, 2744 configurable: true 2745 }); 2746 ViewApi.prototype.getOption = function (name) { 2747 return this.getCurrentData().options[name]; // are the view-specific options 2748 }; 2749 return ViewApi; 2750 }()); 2751 2752 var EVENT_SOURCE_REFINERS = { 2753 id: String, 2754 defaultAllDay: Boolean, 2755 url: String, 2756 format: String,
2757 events: identity, 2758 eventDataTransform: identity, 2759 // for any network-related sources 2760 success: identity, 2761 failure: identity, 2762 }; 2763 function parseEventSource(raw, context, refiners) { 2764 if (refiners === void 0) { refiners = buildEventSourceRefiners(context); } 2765 var rawObj; 2766 if (typeof raw === 'string') { 2767 rawObj = { url: raw }; 2768 } 2769 else if (typeof raw === 'function' || Array.isArray(raw)) { 2770 rawObj = { events: raw }; 2771 } 2772 else if (typeof raw === 'object' && raw) { // not null 2773 rawObj = raw; 2774 } 2775 if (rawObj) { 2776 var _a = refineProps(rawObj, refiners), refined = _a.refined, extra = _a.extra; 2777 var metaRes = buildEventSourceMeta(refined, context); 2778 if (metaRes) { 2779 return { 2780 _raw: raw, 2781 isFetching: false, 2782 latestFetchId: '', 2783 fetchRange: null, 2784 defaultAllDay: refined.defaultAllDay, 2785 eventDataTransform: refined.eventDataTransform, 2786 success: refined.success, 2787 failure: refined.failure, 2788 publicId: refined.id || '', 2789 sourceId: guid(), 2790 sourceDefId: metaRes.sourceDefId, 2791 meta: metaRes.meta, 2792 ui: createEventUi(refined, context), 2793 extendedProps: extra, 2794 }; 2795 } 2796 } 2797 return null; 2798 } 2799 function buildEventSourceRefiners(context) { 2800 return __assign(__assign(__assign({}, EVENT_UI_REFINERS), EVENT_SOURCE_REFINERS), context.pluginHooks.eventSourceRefiners); 2801 } 2802 function buildEventSourceMeta(raw, context) { 2803 var defs = context.pluginHooks.eventSourceDefs; 2804 for (var i = defs.length - 1; i >= 0; i -= 1) { // later-added plugins take precedence 2805 var def = defs[i]; 2806 var meta = def.parseMeta(raw); 2807 if (meta) { 2808 return { sourceDefId: i, meta: meta }; 2809 } 2810 } 2811 return null; 2812 } 2813 2814 function reduceCurrentDate(currentDate, action) { 2815 switch (action.type) { 2816 case 'CHANGE_DATE': 2817 return action.dateMarker; 2818 default: 2819 return currentDate; 2820 } 2821 } 2822 function getInitialDate(options, dateEnv) { 2823 var initialDateInput = options.initialDate; 2824 // compute the initial ambig-timezone date 2825 if (initialDateInput != null) { 2826 return dateEnv.createMarker(initialDateInput); 2827 } 2828 return getNow(options.now, dateEnv); // getNow already returns unzoned 2829 } 2830 function getNow(nowInput, dateEnv) { 2831 if (typeof nowInput === 'function') { 2832 nowInput = nowInput(); 2833 } 2834 if (nowInput == null) { 2835 return dateEnv.createNowMarker(); 2836 } 2837 return dateEnv.createMarker(nowInput); 2838 } 2839 2840 var CalendarApi = /** @class */ (function () { 2841 function CalendarApi() { 2842 } 2843 CalendarApi.prototype.getCurrentData = function () { 2844 return this.currentDataManager.getCurrentData(); 2845 }; 2846 CalendarApi.prototype.dispatch = function (action) { 2847 return this.currentDataManager.dispatch(action); 2848 }; 2849 Object.defineProperty(CalendarApi.prototype, "view", { 2850 get: function () { return this.getCurrentData().viewApi; } // for public API 2851 , 2852 enumerable: false, 2853 configurable: true 2854 }); 2855 CalendarApi.prototype.batchRendering = function (callback) { 2856 callback(); 2857 }; 2858 CalendarApi.prototype.updateSize = function () { 2859 this.trigger('_resize', true); 2860 }; 2861 // Options 2862 // ----------------------------------------------------------------------------------------------------------------- 2863 CalendarApi.prototype.setOption = function (name, val) { 2864 this.dispatch({ 2865 type: 'SET_OPTION', 2866 optionName: name, 2867 rawOptionValue: val, 2868 }); 2869 }; 2870 CalendarApi.prototype.getOption = function (name) { 2871 return this.currentDataManager.currentCalendarOptionsInput[name]; 2872 }; 2873 CalendarApi.prototype.getAvailableLocaleCodes = function () { 2874 return Object.keys(this.getCurrentData().availableRawLocales); 2875 }; 2876 // Trigger 2877 // ----------------------------------------------------------------------------------------------------------------- 2878 CalendarApi.prototype.on = function (handlerName, handler) { 2879 var currentDataManager = this.currentDataManager; 2880 if (currentDataManager.currentCalendarOptionsRefiners[handlerName]) { 2881 currentDataManager.emitter.on(handlerName, handler); 2882 } 2883 else { 2884 console.warn("Unknown listener name '" + handlerName + "'"); 2885 } 2886 }; 2887 CalendarApi.prototype.off = function (handlerName, handler) { 2888 this.currentDataManager.emitter.off(handlerName, handler); 2889 }; 2890 // not meant for public use 2891 CalendarApi.prototype.trigger = function (handlerName) { 2892 var _a; 2893 var args = []; 2894 for (var _i = 1; _i < arguments.length; _i++) { 2895 args[_i - 1] = arguments[_i]; 2896 } 2897 (_a = this.currentDataManager.emitter).trigger.apply(_a, __spreadArrays([handlerName], args)); 2898 }; 2899 // View 2900 // ----------------------------------------------------------------------------------------------------------------- 2901 CalendarApi.prototype.changeView = function (viewType, dateOrRange) { 2902 var _this = this; 2903 this.batchRendering(function () { 2904 _this.unselect(); 2905 if (dateOrRange) { 2906 if (dateOrRange.start && dateOrRange.end) { // a range 2907 _this.dispatch({ 2908 type: 'CHANGE_VIEW_TYPE', 2909 viewType: viewType, 2910 }); 2911 _this.dispatch({ 2912 type: 'SET_OPTION', 2913 optionName: 'visibleRange', 2914 rawOptionValue: dateOrRange, 2915 }); 2916 } 2917 else { 2918 var dateEnv = _this.getCurrentData().dateEnv; 2919 _this.dispatch({ 2920 type: 'CHANGE_VIEW_TYPE', 2921 viewType: viewType, 2922 dateMarker: dateEnv.createMarker(dateOrRange), 2923 }); 2924 } 2925 } 2926 else { 2927 _this.dispatch({ 2928 type: 'CHANGE_VIEW_TYPE', 2929 viewType: viewType, 2930 }); 2931 } 2932 }); 2933 };
2934 // Forces navigation to a view for the given date. 2935 // `viewType` can be a specific view name or a generic one like "week" or "day". 2936 // needs to change 2937 CalendarApi.prototype.zoomTo = function (dateMarker, viewType) { 2938 var state = this.getCurrentData(); 2939 var spec; 2940 viewType = viewType || 'day'; // day is default zoom 2941 spec = state.viewSpecs[viewType] || this.getUnitViewSpec(viewType); 2942 this.unselect(); 2943 if (spec) { 2944 this.dispatch({ 2945 type: 'CHANGE_VIEW_TYPE', 2946 viewType: spec.type, 2947 dateMarker: dateMarker, 2948 }); 2949 } 2950 else { 2951 this.dispatch({ 2952 type: 'CHANGE_DATE', 2953 dateMarker: dateMarker, 2954 }); 2955 } 2956 }; 2957 // Given a duration singular unit, like "week" or "day", finds a matching view spec. 2958 // Preference is given to views that have corresponding buttons. 2959 CalendarApi.prototype.getUnitViewSpec = function (unit) { 2960 var _a = this.getCurrentData(), viewSpecs = _a.viewSpecs, toolbarConfig = _a.toolbarConfig; 2961 var viewTypes = [].concat(toolbarConfig.viewsWithButtons); 2962 var i; 2963 var spec; 2964 for (var viewType in viewSpecs) { 2965 viewTypes.push(viewType); 2966 } 2967 for (i = 0; i < viewTypes.length; i += 1) { 2968 spec = viewSpecs[viewTypes[i]]; 2969 if (spec) { 2970 if (spec.singleUnit === unit) { 2971 return spec; 2972 } 2973 } 2974 } 2975 return null; 2976 }; 2977 // Current Date 2978 // ----------------------------------------------------------------------------------------------------------------- 2979 CalendarApi.prototype.prev = function () { 2980 this.unselect(); 2981 this.dispatch({ type: 'PREV' }); 2982 }; 2983 CalendarApi.prototype.next = function () { 2984 this.unselect(); 2985 this.dispatch({ type: 'NEXT' }); 2986 }; 2987 CalendarApi.prototype.prevYear = function () { 2988 var state = this.getCurrentData(); 2989 this.unselect(); 2990 this.dispatch({ 2991 type: 'CHANGE_DATE', 2992 dateMarker: state.dateEnv.addYears(state.currentDate, -1), 2993 }); 2994 }; 2995 CalendarApi.prototype.nextYear = function () { 2996 var state = this.getCurrentData(); 2997 this.unselect(); 2998 this.dispatch({ 2999 type: 'CHANGE_DATE', 3000 dateMarker: state.dateEnv.addYears(state.currentDate, 1), 3001 }); 3002 }; 3003 CalendarApi.prototype.today = function () { 3004 var state = this.getCurrentData(); 3005 this.unselect(); 3006 this.dispatch({ 3007 type: 'CHANGE_DATE', 3008 dateMarker: getNow(state.calendarOptions.now, state.dateEnv), 3009 }); 3010 }; 3011 CalendarApi.prototype.gotoDate = function (zonedDateInput) { 3012 var state = this.getCurrentData(); 3013 this.unselect(); 3014 this.dispatch({ 3015 type: 'CHANGE_DATE', 3016 dateMarker: state.dateEnv.createMarker(zonedDateInput), 3017 }); 3018 }; 3019 CalendarApi.prototype.incrementDate = function (deltaInput) { 3020 var state = this.getCurrentData(); 3021 var delta = createDuration(deltaInput); 3022 if (delta) { // else, warn about invalid input? 3023 this.unselect(); 3024 this.dispatch({ 3025 type: 'CHANGE_DATE', 3026 dateMarker: state.dateEnv.add(state.currentDate, delta), 3027 }); 3028 } 3029 }; 3030 // for external API 3031 CalendarApi.prototype.getDate = function () { 3032 var state = this.getCurrentData(); 3033 return state.dateEnv.toDate(state.currentDate); 3034 }; 3035 // Date Formatting Utils 3036 // ----------------------------------------------------------------------------------------------------------------- 3037 CalendarApi.prototype.formatDate = function (d, formatter) { 3038 var dateEnv = this.getCurrentData().dateEnv; 3039 return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter)); 3040 }; 3041 // `settings` is for formatter AND isEndExclusive 3042 CalendarApi.prototype.formatRange = function (d0, d1, settings) { 3043 var dateEnv = this.getCurrentData().dateEnv; 3044 return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings), settings); 3045 }; 3046 CalendarApi.prototype.formatIso = function (d, omitTime) { 3047 var dateEnv = this.getCurrentData().dateEnv; 3048 return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime: omitTime }); 3049 }; 3050 // Date Selection / Event Selection / DayClick 3051 // ----------------------------------------------------------------------------------------------------------------- 3052 // this public method receives start/end dates in any format, with any timezone 3053 // NOTE: args were changed from v3 3054 CalendarApi.prototype.select = function (dateOrObj, endDate) { 3055 var selectionInput; 3056 if (endDate == null) { 3057 if (dateOrObj.start != null) { 3058 selectionInput = dateOrObj; 3059 } 3060 else { 3061 selectionInput = { 3062 start: dateOrObj, 3063 end: null, 3064 }; 3065 } 3066 } 3067 else { 3068 selectionInput = { 3069 start: dateOrObj, 3070 end: endDate, 3071 }; 3072 } 3073 var state = this.getCurrentData(); 3074 var selection = parseDateSpan(selectionInput, state.dateEnv, createDuration({ days: 1 })); 3075 if (selection) { // throw parse error otherwise? 3076 this.dispatch({ type: 'SELECT_DATES', selection: selection }); 3077 triggerDateSelect(selection, null, state); 3078 } 3079 }; 3080 // public method 3081 CalendarApi.prototype.unselect = function (pev) { 3082 var state = this.getCurrentData(); 3083 if (state.dateSelection) { 3084 this.dispatch({ type: 'UNSELECT_DATES' }); 3085 triggerDateUnselect(pev, state); 3086 } 3087 }; 3088 // Public Events API 3089 // ----------------------------------------------------------------------------------------------------------------- 3090 CalendarApi.prototype.addEvent = function (eventInput, sourceIn
3090put) { 3091 if (eventInput instanceof EventApi) { 3092 var def = eventInput._def; 3093 var instance = eventInput._instance; 3094 var currentData = this.getCurrentData(); 3095 // not already present? don't want to add an old snapshot 3096 if (!currentData.eventStore.defs[def.defId]) { 3097 this.dispatch({ 3098 type: 'ADD_EVENTS', 3099 eventStore: eventTupleToStore({ def: def, instance: instance }), 3100 }); 3101 this.triggerEventAdd(eventInput); 3102 } 3103 return eventInput; 3104 } 3105 var state = this.getCurrentData(); 3106 var eventSource; 3107 if (sourceInput instanceof EventSourceApi) { 3108 eventSource = sourceInput.internalEventSource; 3109 } 3110 else if (typeof sourceInput === 'boolean') { 3111 if (sourceInput) { // true. part of the first event source 3112 eventSource = hashValuesToArray(state.eventSources)[0]; 3113 } 3114 } 3115 else if (sourceInput != null) { // an ID. accepts a number too 3116 var sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function 3117 if (!sourceApi) { 3118 console.warn("Could not find an event source with ID \"" + sourceInput + "\""); // TODO: test 3119 return null; 3120 } 3121 eventSource = sourceApi.internalEventSource; 3122 } 3123 var tuple = parseEvent(eventInput, eventSource, state, false); 3124 if (tuple) { 3125 var newEventApi = new EventApi(state, tuple.def, tuple.def.recurringDef ? null : tuple.instance); 3126 this.dispatch({ 3127 type: 'ADD_EVENTS', 3128 eventStore: eventTupleToStore(tuple), 3129 }); 3130 this.triggerEventAdd(newEventApi); 3131 return newEventApi; 3132 } 3133 return null; 3134 }; 3135 CalendarApi.prototype.triggerEventAdd = function (eventApi) { 3136 var _this = this; 3137 var emitter = this.getCurrentData().emitter; 3138 emitter.trigger('eventAdd', { 3139 event: eventApi, 3140 relatedEvents: [], 3141 revert: function () { 3142 _this.dispatch({ 3143 type: 'REMOVE_EVENTS', 3144 eventStore: eventApiToStore(eventApi), 3145 }); 3146 }, 3147 }); 3148 }; 3149 // TODO: optimize 3150 CalendarApi.prototype.getEventById = function (id) { 3151 var state = this.getCurrentData(); 3152 var _a = state.eventStore, defs = _a.defs, instances = _a.instances; 3153 id = String(id); 3154 for (var defId in defs) { 3155 var def = defs[defId]; 3156 if (def.publicId === id) { 3157 if (def.recurringDef) { 3158 return new EventApi(state, def, null); 3159 } 3160 for (var instanceId in instances) { 3161 var instance = instances[instanceId]; 3162 if (instance.defId === def.defId) { 3163 return new EventApi(state, def, instance); 3164 } 3165 } 3166 } 3167 } 3168 return null; 3169 }; 3170 CalendarApi.prototype.getEvents = function () { 3171 var currentData = this.getCurrentData(); 3172 return buildEventApis(currentData.eventStore, currentData); 3173 }; 3174 CalendarApi.prototype.removeAllEvents = function () { 3175 this.dispatch({ type: 'REMOVE_ALL_EVENTS' }); 3176 }; 3177 // Public Event Sources API 3178 // ----------------------------------------------------------------------------------------------------------------- 3179 CalendarApi.prototype.getEventSources = function () { 3180 var state = this.getCurrentData(); 3181 var sourceHash = state.eventSources; 3182 var sourceApis = []; 3183 for (var internalId in sourceHash) { 3184 sourceApis.push(new EventSourceApi(state, sourceHash[internalId])); 3185 } 3186 return sourceApis; 3187 }; 3188 CalendarApi.prototype.getEventSourceById = function (id) { 3189 var state = this.getCurrentData(); 3190 var sourceHash = state.eventSources; 3191 id = String(id); 3192 for (var sourceId in sourceHash) { 3193 if (sourceHash[sourceId].publicId === id) { 3194 return new EventSourceApi(state, sourceHash[sourceId]); 3195 } 3196 } 3197 return null; 3198 }; 3199 CalendarApi.prototype.addEventSource = function (sourceInput) { 3200 var state = this.getCurrentData(); 3201 if (sourceInput instanceof EventSourceApi) { 3202 // not already present? don't want to add an old snapshot
3203 if (!state.eventSources[sourceInput.internalEventSource.sourceId]) { 3204 this.dispatch({ 3205 type: 'ADD_EVENT_SOURCES', 3206 sources: [sourceInput.internalEventSource], 3207 }); 3208 } 3209 return sourceInput; 3210 } 3211 var eventSource = parseEventSource(sourceInput, state); 3212 if (eventSource) { // TODO: error otherwise? 3213 this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] }); 3214 return new EventSourceApi(state, eventSource); 3215 } 3216 return null; 3217 }; 3218 CalendarApi.prototype.removeAllEventSources = function () { 3219 this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' }); 3220 }; 3221 CalendarApi.prototype.refetchEvents = function () { 3222 this.dispatch({ type: 'FETCH_EVENT_SOURCES' }); 3223 }; 3224 // Scroll 3225 // ----------------------------------------------------------------------------------------------------------------- 3226 CalendarApi.prototype.scrollToTime = function (timeInput) { 3227 var time = createDuration(timeInput); 3228 if (time) { 3229 this.trigger('_scrollRequest', { time: time }); 3230 } 3231 }; 3232 return CalendarApi; 3233 }()); 3234 3235 var EventApi = /** @class */ (function () { 3236 // instance will be null if expressing a recurring event that has no current instances, 3237 // OR if trying to validate an incoming external event that has no dates assigned 3238 function EventApi(context, def, instance) { 3239 this._context = context; 3240 this._def = def; 3241 this._instance = instance || null; 3242 } 3243 /* 3244 TODO: make event struct more responsible for this 3245 */ 3246 EventApi.prototype.setProp = function (name, val) { 3247 var _a, _b; 3248 if (name in EVENT_DATE_REFINERS) { 3249 console.warn('Could not set date-related prop \'name\'. Use one of the date-related methods instead.'); 3250 } 3251 else if (name in EVENT_NON_DATE_REFINERS) { 3252 val = EVENT_NON_DATE_REFINERS[name](val); 3253 this.mutate({ 3254 standardProps: (_a = {}, _a[name] = val, _a), 3255 }); 3256 } 3257 else if (name in EVENT_UI_REFINERS) { 3258 var ui = EVENT_UI_REFINERS[name](val); 3259 if (name === 'color') { 3260 ui = { backgroundColor: val, borderColor: val }; 3261 } 3262 else if (name === 'editable') { 3263 ui = { startEditable: val, durationEditable: val }; 3264 } 3265 else { 3266 ui = (_b = {}, _b[name] = val, _b); 3267 } 3268 this.mutate({ 3269 standardProps: { ui: ui }, 3270 }); 3271 } 3272 else { 3273 console.warn("Could not set prop '" + name + "'. Use setExtendedProp instead."); 3274 } 3275 }; 3276 EventApi.prototype.setExtendedProp = function (name, val) { 3277 var _a; 3278 this.mutate({ 3279 extendedProps: (_a = {}, _a[name] = val, _a), 3280 }); 3281 }; 3282 EventApi.prototype.setStart = function (startInput, options) { 3283 if (options === void 0) { options = {}; } 3284 var dateEnv = this._context.dateEnv; 3285 var start = dateEnv.createMarker(startInput); 3286 if (start && this._instance) { // TODO: warning if parsed bad 3287 var instanceRange = this._instance.range; 3288 var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!? 3289 if (options.maintainDuration) { 3290 this.mutate({ datesDelta: startDelta }); 3291 } 3292 else { 3293 this.mutate({ startDelta: startDelta }); 3294 } 3295 } 3296 }; 3297 EventApi.prototype.setEnd = function (endInput, options) { 3298 if (options === void 0) { options = {}; } 3299 var dateEnv = this._context.dateEnv; 3300 var end; 3301 if (endInput != null) { 3302 end = dateEnv.createMarker(endInput); 3303 if (!end) { 3304 return; // TODO: warning if parsed bad 3305 } 3306 } 3307 if (this._instance) { 3308 if (end) { 3309 var endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity); 3310 this.mutate({ endDelta: endDelta }); 3311 } 3312 else { 3313 this.mutate({ standardProps: { hasEnd: false } }); 3314 } 3315 } 3316 }; 3317 EventApi.prototype.setDates = function (startInput, endInput, options) { 3318 if (options === void 0) { options = {}; } 3319 var dateEnv = this._context.dateEnv; 3320 var standardProps = { allDay: options.allDay }; 3321 var start = dateEnv.createMarker(startInput); 3322 var end; 3323 if (!start) { 3324 return; // TODO: warning if parsed bad 3325 } 3326 if (endInput != null) { 3327 end = dateEnv.createMarker(endInput); 3328 if (!end) { // TODO: warning if parsed bad 3329 return; 3330 } 3331 } 3332 if (this._instance) { 3333 var instanceRange = this._instance.range; 3334 // when computing the diff for an event being converted to all-day, 3335 // compute diff off of the all-day values the way event-mutation does. 3336 if (options.allDay === true) { 3337 instanceRange = computeAlignedDayRange(instanceRange); 3338 } 3339 var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); 3340 if (end) { 3341 var endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity); 3342 if (durationsEqual(startDelta, endDelta)) { 3343 this.mutate({ datesDelta: startDelta, standardProps: standardProps }); 3344 } 3345 else { 3346 this.mutate({ startDelta: startDelta, endDelta: endDelta, standardProps: standardProps }); 3347 } 3348 } 3349 else { // means "clear the end" 3350 standardProps.hasEnd = false;
3351 this.mutate({ datesDelta: startDelta, standardProps: standardProps }); 3352 } 3353 } 3354 }; 3355 EventApi.prototype.moveStart = function (deltaInput) { 3356 var delta = createDuration(deltaInput); 3357 if (delta) { // TODO: warning if parsed bad 3358 this.mutate({ startDelta: delta }); 3359 } 3360 }; 3361 EventApi.prototype.moveEnd = function (deltaInput) { 3362 var delta = createDuration(deltaInput); 3363 if (delta) { // TODO: warning if parsed bad 3364 this.mutate({ endDelta: delta }); 3365 } 3366 }; 3367 EventApi.prototype.moveDates = function (deltaInput) { 3368 var delta = createDuration(deltaInput); 3369 if (delta) { // TODO: warning if parsed bad 3370 this.mutate({ datesDelta: delta }); 3371 } 3372 }; 3373 EventApi.prototype.setAllDay = function (allDay, options) { 3374 if (options === void 0) { options = {}; } 3375 var standardProps = { allDay: allDay }; 3376 var maintainDuration = options.maintainDuration; 3377 if (maintainDuration == null) { 3378 maintainDuration = this._context.options.allDayMaintainDuration; 3379 } 3380 if (this._def.allDay !== allDay) { 3381 standardProps.hasEnd = maintainDuration; 3382 } 3383 this.mutate({ standardProps: standardProps }); 3384 }; 3385 EventApi.prototype.formatRange = function (formatInput) { 3386 var dateEnv = this._context.dateEnv; 3387 var instance = this._instance; 3388 var formatter = createFormatter(formatInput); 3389 if (this._def.hasEnd) { 3390 return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, { 3391 forcedStartTzo: instance.forcedStartTzo, 3392 forcedEndTzo: instance.forcedEndTzo, 3393 }); 3394 } 3395 return dateEnv.format(instance.range.start, formatter, { 3396 forcedTzo: instance.forcedStartTzo, 3397 }); 3398 }; 3399 EventApi.prototype.mutate = function (mutation) { 3400 var instance = this._instance; 3401 if (instance) { 3402 var def = this._def; 3403 var context_1 = this._context; 3404 var eventStore_1 = context_1.getCurrentData().eventStore; 3405 var relevantEvents = getRelevantEvents(eventStore_1, instance.instanceId); 3406 var eventConfigBase = { 3407 '': { 3408 display: '', 3409 startEditable: true, 3410 durationEditable: true, 3411 constraints: [], 3412 overlap: null, 3413 allows: [], 3414 backgroundColor: '', 3415 borderColor: '', 3416 textColor: '', 3417 classNames: [], 3418 }, 3419 }; 3420 relevantEvents = applyMutationToEventStore(relevantEvents, eventConfigBase, mutation, context_1); 3421 var oldEvent = new EventApi(context_1, def, instance); // snapshot 3422 this._def = relevantEvents.defs[def.defId]; 3423 this._instance = relevantEvents.instances[instance.instanceId]; 3424 context_1.dispatch({ 3425 type: 'MERGE_EVENTS', 3426 eventStore: relevantEvents, 3427 }); 3428 context_1.emitter.trigger('eventChange', { 3429 oldEvent: oldEvent, 3430 event: this, 3431 relatedEvents: buildEventApis(relevantEvents, context_1, instance), 3432 revert: function () { 3433 context_1.dispatch({ 3434 type: 'RESET_EVENTS', 3435 eventStore: eventStore_1, 3436 }); 3437 }, 3438 }); 3439 } 3440 }; 3441 EventApi.prototype.remove = function () { 3442 var context = this._context; 3443 var asStore = eventApiToStore(this); 3444 context.dispatch({
3445 type: 'REMOVE_EVENTS', 3446 eventStore: asStore, 3447 }); 3448 context.emitter.trigger('eventRemove', { 3449 event: this, 3450 relatedEvents: [], 3451 revert: function () { 3452 context.dispatch({ 3453 type: 'MERGE_EVENTS', 3454 eventStore: asStore, 3455 }); 3456 }, 3457 }); 3458 }; 3459 Object.defineProperty(EventApi.prototype, "source", { 3460 get: function () { 3461 var sourceId = this._def.sourceId; 3462 if (sourceId) { 3463 return new EventSourceApi(this._context, this._context.getCurrentData().eventSources[sourceId]); 3464 } 3465 return null; 3466 }, 3467 enumerable: false, 3468 configurable: true 3469 }); 3470 Object.defineProperty(EventApi.prototype, "start", { 3471 get: function () { 3472 return this._instance ? 3473 this._context.dateEnv.toDate(this._instance.range.start) : 3474 null; 3475 }, 3476 enumerable: false, 3477 configurable: true 3478 }); 3479 Object.defineProperty(EventApi.prototype, "end", { 3480 get: function () { 3481 return (this._instance && this._def.hasEnd) ? 3482 this._context.dateEnv.toDate(this._instance.range.end) : 3483 null; 3484 }, 3485 enumerable: false, 3486 configurable: true 3487 }); 3488 Object.defineProperty(EventApi.prototype, "startStr", { 3489 get: function () { 3490 var instance = this._instance; 3491 if (instance) { 3492 return this._context.dateEnv.formatIso(instance.range.start, { 3493 omitTime: this._def.allDay, 3494 forcedTzo: instance.forcedStartTzo, 3495 }); 3496 } 3497 return ''; 3498 }, 3499 enumerable: false, 3500 configurable: true 3501 }); 3502 Object.defineProperty(EventApi.prototype, "endStr", { 3503 get: function () { 3504 var instance = this._instance; 3505 if (instance && this._def.hasEnd) { 3506 return this._context.dateEnv.formatIso(instance.range.end, { 3507 omitTime: this._def.allDay, 3508 forcedTzo: instance.forcedEndTzo, 3509 }); 3510 } 3511 return ''; 3512 }, 3513 enumerable: false, 3514 configurable: true 3515 }); 3516 Object.defineProperty(EventApi.prototype, "id", { 3517 // computable props that all access the def
3518 // TODO: find a TypeScript-compatible way to do this at scale 3519 get: function () { return this._def.publicId; }, 3520 enumerable: false, 3521 configurable: true 3522 }); 3523 Object.defineProperty(EventApi.prototype, "groupId", { 3524 get: function () { return this._def.groupId; }, 3525 enumerable: false, 3526 configurable: true 3527 }); 3528 Object.defineProperty(EventApi.prototype, "allDay", { 3529 get: function () { return this._def.allDay; }, 3530 enumerable: false, 3531 configurable: true 3532 }); 3533 Object.defineProperty(EventApi.prototype, "title", { 3534 get: function () { return this._def.title; }, 3535 enumerable: false, 3536 configurable: true 3537 }); 3538 Object.defineProperty(EventApi.prototype, "url", { 3539 get: function () { return this._def.url; }, 3540 enumerable: false, 3541 configurable: true 3542 }); 3543 Object.defineProperty(EventApi.prototype, "display", { 3544 get: function () { return this._def.ui.display || 'auto'; } // bad. just normalize the type earlier 3545 , 3546 enumerable: false, 3547 configurable: true 3548 }); 3549 Object.defineProperty(EventApi.prototype, "startEditable", { 3550 get: function () { return this._def.ui.startEditable; }, 3551 enumerable: false, 3552 configurable: true 3553 }); 3554 Object.defineProperty(EventApi.prototype, "durationEditable", { 3555 get: function () { return this._def.ui.durationEditable; }, 3556 enumerable: false, 3557 configurable: true 3558 }); 3559 Object.defineProperty(EventApi.prototype, "constraint", { 3560 get: function () { return this._def.ui.constraints[0] || null; }, 3561 enumerable: false, 3562 configurable: true 3563 }); 3564 Object.defineProperty(EventApi.prototype, "overlap", { 3565 get: function () { return this._def.ui.overlap; }, 3566 enumerable: false, 3567 configurable: true 3568 }); 3569 Object.defineProperty(EventApi.prototype, "allow", { 3570 get: function () { return this._def.ui.allows[0] || null; }, 3571 enumerable: false, 3572 configurable: true 3573 }); 3574 Object.defineProperty(EventApi.prototype, "backgroundColor", { 3575 get: function () { return this._def.ui.backgroundColor; }, 3576 enumerable: false, 3577 configurable: true 3578 }); 3579 Object.defineProperty(EventApi.prototype, "borderColor", { 3580 get: function () { return this._def.ui.borderColor; }, 3581 enumerable: false, 3582 configurable: true 3583 }); 3584 Object.defineProperty(EventApi.prototype, "textColor", { 3585 get: function () { return this._def.ui.textColor; }, 3586 enumerable: false, 3587 configurable: true 3588 }); 3589 Object.defineProperty(EventApi.prototype, "classNames", { 3590 // NOTE: user can't modify these because Object.freeze was called in event-def parsing 3591 get: function () { return this._def.ui.classNames; }, 3592 enumerable: false, 3593 configurable: true 3594 }); 3595 Object.defineProperty(EventApi.prototype, "extendedProps", { 3596 get: function () { return this._def.extendedProps; }, 3597 enumerable: false, 3598 configurable: true 3599 }); 3600 EventApi.prototype.toPlainObject = function (settings) { 3601 if (settings === void 0) { settings = {}; } 3602 var def = this._def; 3603 var ui = def.ui; 3604 var _a = this, startStr = _a.startStr, endStr = _a.endStr; 3605 var res = {}; 3606 if (def.title) { 3607 res.title = def.title; 3608 } 3609 if (startStr) { 3610 res.start = startStr; 3611 } 3612 if (endStr) { 3613 res.end = endStr; 3614 } 3615 if (def.publicId) { 3616 res.id = def.publicId; 3617 } 3618 if (def.groupId) { 3619 res.groupId = def.groupId; 3620 } 3621 if (def.url) { 3622 res.url = def.url; 3623 } 3624 if (ui.display && ui.display !== 'auto') { 3625 res.display = ui.display; 3626 } 3627 // TODO: what about recurring-event properties??? 3628 // TODO: include startEditable/durationEditable/constraint/overlap/allow 3629 if (settings.collapseColor && ui.backgroundColor && ui.backgroundColor === ui.borderColor) { 3630 res.color = ui.backgroundColor; 3631 } 3632 else { 3633 if (ui.backgroundColor) { 3634 res.backgroundColor = ui.backgroundColor; 3635 } 3636 if (ui.borderColor) { 3637 res.borderColor = ui.borderColor; 3638 } 3639 } 3640 if (ui.textColor) { 3641 res.textColor = ui.textColor; 3642 } 3643 if (ui.classNames.length) { 3644 res.classNames = ui.classNames; 3645 } 3646 if (Object.keys(def.extendedProps).length) { 3647 if (settings.collapseExtendedProps) { 3648 __assign(res, def.extendedProps); 3649 } 3650 else { 3651 res.extendedProps = def.extendedProps; 3652 } 3653 } 3654 return res; 3655 }; 3656 EventApi.prototype.toJSON = function () { 3657 return this.toPlainObject(); 3658 }; 3659 return EventApi; 3660 }()); 3661 function eventApiToStore(eventApi) { 3662 var _a, _b; 3663 var def = eventApi._def; 3664 var instance = eventApi._instance; 3665 return { 3666 defs: (_a = {}, _a[def.defId] = def, _a), 3667 instances: instance 3668 ? (_b = {}, _b[instance.instanceId] = instance, _b) : {}, 3669 }; 3670 } 3671 function buildEventApis(eventStore, context, excludeInstance) { 3672 var defs = eventStore.defs, instances = eventStore.instances; 3673 var eventApis = []; 3674 var excludeInstanceId = excludeInstance ? excludeInstance.instanceId : ''; 3675 for (var id in instances) { 3676 var instance = instances[id]; 3677 var def = defs[instance.defId]; 3678 if (instance.instanceId !== excludeInstanceId) { 3679 eventApis.push(new EventApi(context, def, instance)); 3680 } 3681 } 3682 return eventApis; 3683 } 3684 3685 var calendarSystemClassMap = {}; 3686 function registerCalendarSystem(name, theClass) { 3687 calendarSystemClassMap[name] = theClass; 3688 } 3689 function createCalendarSystem(name) { 3690 return new calendarSystemClassMap[name](); 3691 } 3692 var GregorianCalendarSystem = /** @class */ (function () { 3693 function GregorianCalendarSystem() { 3694 } 3695 GregorianCalendarSystem.prototype.getMarkerYear = function (d) { 3696 return d.getUTCFullYear(); 3697 }; 3698 GregorianCalendarSystem.prototype.getMarkerMonth = function (d) { 3699 return d.getUTCMonth(); 3700 }; 3701 GregorianCalendarSystem.prototype.getMarkerDay = function (d) { 3702 return d.getUTCDate(); 3703 }; 3704 GregorianCalendarSystem.prototype.arrayToMarker = function (arr) { 3705 return arrayToUtcDate(arr); 3706 }; 3707 GregorianCalendarSystem.prototype.markerToArray = function (marker) { 3708 return dateToUtcArray(marker); 3709 }; 3710 return GregorianCalendarSystem; 3711 }()); 3712 registerCalendarSystem('gregory', GregorianCalendarSystem); 3713 3714 var ISO_RE = /^\s*(\d{4})(-?(\d{2})(-?(\d{2})([T ](\d{2}):?(\d{2})(:?(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/; 3715 function parse(str) { 3716 var m = ISO_RE.exec(str); 3717 if (m) { 3718 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)); 3719 if (isValidDate(marker)) { 3720 var timeZoneOffset = null; 3721 if (m[13]) { 3722 timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 + 3723 Number(m[18] || 0)); 3724 } 3725 return { 3726 marker: marker, 3727 isTimeUnspecified: !m[6], 3728 timeZoneOffset: timeZoneOffset, 3729 }; 3730 } 3731 } 3732 return null; 3733 } 3734 3735 var DateEnv = /** @class */ (function () { 3736 function DateEnv(settings) { 3737 var timeZone = this.timeZone = settings.timeZone; 3738 var isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC'; 3739 if (settings.namedTimeZoneImpl && isNamedTimeZone) { 3740 this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone); 3741 } 3742 this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl); 3743 this.calendarSystem = createCalendarSystem(settings.calendarSystem); 3744 this.locale = settings.locale; 3745 this.weekDow = settings.locale.week.dow; 3746 this.weekDoy = settings.locale.week.doy; 3747 if (settings.weekNumberCalculation === 'ISO') { 3748 this.weekDow = 1; 3749 this.weekDoy = 4; 3750 } 3751 if (typeof settings.firstDay === 'number') { 3752 this.weekDow = settings.firstDay; 3753 } 3754 if (typeof settings.weekNumberCalculation === 'function') {
vendor: 16,384 bytes, lines 3755-4166
3755 this.weekNumberFunc = settings.weekNumberCalculation; 3756 } 3757 this.weekText = settings.weekText != null ? settings.weekText : settings.locale.options.weekText; 3758 this.cmdFormatter = settings.cmdFormatter; 3759 this.defaultSeparator = settings.defaultSeparator; 3760 } 3761 // Creating / Parsing 3762 DateEnv.prototype.createMarker = function (input) { 3763 var meta = this.createMarkerMeta(input); 3764 if (meta === null) { 3765 return null; 3766 } 3767 return meta.marker; 3768 }; 3769 DateEnv.prototype.createNowMarker = function () { 3770 if (this.canComputeOffset) { 3771 return this.timestampToMarker(new Date().valueOf()); 3772 } 3773 // if we can't compute the current date val for a timezone, 3774 // better to give the current local date vals than UTC 3775 return arrayToUtcDate(dateToLocalArray(new Date())); 3776 }; 3777 DateEnv.prototype.createMarkerMeta = function (input) { 3778 if (typeof input === 'string') { 3779 return this.parse(input); 3780 } 3781 var marker = null; 3782 if (typeof input === 'number') { 3783 marker = this.timestampToMarker(input); 3784 } 3785 else if (input instanceof Date) { 3786 input = input.valueOf(); 3787 if (!isNaN(input)) { 3788 marker = this.timestampToMarker(input); 3789 } 3790 } 3791 else if (Array.isArray(input)) { 3792 marker = arrayToUtcDate(input); 3793 } 3794 if (marker === null || !isValidDate(marker)) { 3795 return null; 3796 } 3797 return { marker: marker, isTimeUnspecified: false, forcedTzo: null }; 3798 }; 3799 DateEnv.prototype.parse = function (s) { 3800 var parts = parse(s); 3801 if (parts === null) { 3802 return null; 3803 } 3804 var marker = parts.marker; 3805 var forcedTzo = null; 3806 if (parts.timeZoneOffset !== null) { 3807 if (this.canComputeOffset) { 3808 marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000); 3809 } 3810 else { 3811 forcedTzo = parts.timeZoneOffset; 3812 } 3813 } 3814 return { marker: marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo: forcedTzo }; 3815 }; 3816 // Accessors 3817 DateEnv.prototype.getYear = function (marker) { 3818 return this.calendarSystem.getMarkerYear(marker); 3819 }; 3820 DateEnv.prototype.getMonth = function (marker) { 3821 return this.calendarSystem.getMarkerMonth(marker); 3822 }; 3823 // Adding / Subtracting 3824 DateEnv.prototype.add = function (marker, dur) { 3825 var a = this.calendarSystem.markerToArray(marker); 3826 a[0] += dur.years; 3827 a[1] += dur.months; 3828 a[2] += dur.days; 3829 a[6] += dur.milliseconds; 3830 return this.calendarSystem.arrayToMarker(a); 3831 }; 3832 DateEnv.prototype.subtract = function (marker, dur) { 3833 var a = this.calendarSystem.markerToArray(marker); 3834 a[0] -= dur.years; 3835 a[1] -= dur.months; 3836 a[2] -= dur.days; 3837 a[6] -= dur.milliseconds; 3838 return this.calendarSystem.arrayToMarker(a); 3839 }; 3840 DateEnv.prototype.addYears = function (marker, n) { 3841 var a = this.calendarSystem.markerToArray(marker); 3842 a[0] += n; 3843 return this.calendarSystem.arrayToMarker(a); 3844 }; 3845 DateEnv.prototype.addMonths = function (marker, n) { 3846 var a = this.calendarSystem.markerToArray(marker); 3847 a[1] += n; 3848 return this.calendarSystem.arrayToMarker(a); 3849 }; 3850 // Diffing Whole Units 3851 DateEnv.prototype.diffWholeYears = function (m0, m1) { 3852 var calendarSystem = this.calendarSystem; 3853 if (timeAsMs(m0) === timeAsMs(m1) && 3854 calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) && 3855 calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) { 3856 return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0); 3857 } 3858 return null; 3859 }; 3860 DateEnv.prototype.diffWholeMonths = function (m0, m1) { 3861 var calendarSystem = this.calendarSystem; 3862 if (timeAsMs(m0) === timeAsMs(m1) && 3863 calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) { 3864 return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) + 3865 (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12; 3866 } 3867 return null; 3868 }; 3869 // Range / Duration 3870 DateEnv.prototype.greatestWholeUnit = function (m0, m1) { 3871 var n = this.diffWholeYears(m0, m1); 3872 if (n !== null) { 3873 return { unit: 'year', value: n }; 3874 } 3875 n = this.diffWholeMonths(m0, m1); 3876 if (n !== null) { 3877 return { unit: 'month', value: n }; 3878 } 3879 n = diffWholeWeeks(m0, m1); 3880 if (n !== null) { 3881 return { unit: 'week', value: n }; 3882 } 3883 n = diffWholeDays(m0, m1); 3884 if (n !== null) { 3885 return { unit: 'day', value: n }; 3886 } 3887 n = diffHours(m0, m1); 3888 if (isInt(n)) { 3889 return { unit: 'hour', value: n }; 3890 } 3891 n = diffMinutes(m0, m1); 3892 if (isInt(n)) { 3893 return { unit: 'minute', value: n }; 3894 } 3895 n = diffSeconds(m0, m1); 3896 if (isInt(n)) { 3897 return { unit: 'second', value: n }; 3898 } 3899 return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() }; 3900 }; 3901 DateEnv.prototype.countDurationsBetween = function (m0, m1, d) { 3902 // TODO: can use greatestWholeUnit 3903 var diff; 3904 if (d.years) { 3905 diff = this.diffWholeYears(m0, m1); 3906 if (diff !== null) { 3907 return diff / asRoughYears(d); 3908 } 3909 } 3910 if (d.months) { 3911 diff = this.diffWholeMonths(m0, m1); 3912 if (diff !== null) { 3913 return diff / asRoughMonths(d); 3914 } 3915 } 3916 if (d.days) { 3917 diff = diffWholeDays(m0, m1); 3918 if (diff !== null) { 3919 return diff / asRoughDays(d); 3920 } 3921 } 3922 return (m1.valueOf() - m0.valueOf()) / asRoughMs(d); 3923 }; 3924 // Start-Of 3925 // these DON'T return zoned-dates. only UTC start-of dates 3926 DateEnv.prototype.startOf = function (m, unit) { 3927 if (unit === 'year') { 3928 return this.startOfYear(m); 3929 } 3930 if (unit === 'month') { 3931 return this.startOfMonth(m); 3932 } 3933 if (unit === 'week') { 3934 return this.startOfWeek(m); 3935 } 3936 if (unit === 'day') { 3937 return startOfDay(m); 3938 } 3939 if (unit === 'hour') { 3940 return startOfHour(m); 3941 } 3942 if (unit === 'minute') { 3943 return startOfMinute(m); 3944 } 3945 if (unit === 'second') { 3946 return startOfSecond(m); 3947 } 3948 return null; 3949 }; 3950 DateEnv.prototype.startOfYear = function (m) { 3951 return this.calendarSystem.arrayToMarker([ 3952 this.calendarSystem.getMarkerYear(m), 3953 ]); 3954 }; 3955 DateEnv.prototype.startOfMonth = function (m) { 3956 return this.calendarSystem.arrayToMarker([ 3957 this.calendarSystem.getMarkerYear(m), 3958 this.calendarSystem.getMarkerMonth(m), 3959 ]); 3960 }; 3961 DateEnv.prototype.startOfWeek = function (m) { 3962 return this.calendarSystem.arrayToMarker([ 3963 this.calendarSystem.getMarkerYear(m), 3964 this.calendarSystem.getMarkerMonth(m), 3965 m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7), 3966 ]); 3967 }; 3968 // Week Number 3969 DateEnv.prototype.computeWeekNumber = function (marker) { 3970 if (this.weekNumberFunc) { 3971 return this.weekNumberFunc(this.toDate(marker)); 3972 } 3973 return weekOfYear(marker, this.weekDow, this.weekDoy); 3974 }; 3975 // TODO: choke on timeZoneName: long 3976 DateEnv.prototype.format = function (marker, formatter, dateOptions) { 3977 if (dateOptions === void 0) { dateOptions = {}; } 3978 return formatter.format({ 3979 marker: marker, 3980 timeZoneOffset: dateOptions.forcedTzo != null ? 3981 dateOptions.forcedTzo : 3982 this.offsetForMarker(marker), 3983 }, this); 3984 }; 3985 DateEnv.prototype.formatRange = function (start, end, formatter, dateOptions) { 3986 if (dateOptions === void 0) { dateOptions = {}; } 3987 if (dateOptions.isEndExclusive) { 3988 end = addMs(end, -1); 3989 } 3990 return formatter.formatRange({ 3991 marker: start, 3992 timeZoneOffset: dateOptions.forcedStartTzo != null ? 3993 dateOptions.forcedStartTzo : 3994 this.offsetForMarker(start), 3995 }, { 3996 marker: end, 3997 timeZoneOffset: dateOptions.forcedEndTzo != null ? 3998 dateOptions.forcedEndTzo : 3999 this.offsetForMarker(end), 4000 }, this, dateOptions.defaultSeparator); 4001 }; 4002 /* 4003 DUMB: the omitTime arg is dumb. if we omit the time, we want to omit the timezone offset. and if we do that, 4004 might as well use buildIsoString or some other util directly 4005 */ 4006 DateEnv.prototype.formatIso = function (marker, extraOptions) { 4007 if (extraOptions === void 0) { extraOptions = {}; } 4008 var timeZoneOffset = null; 4009 if (!extraOptions.omitTimeZoneOffset) { 4010 if (extraOptions.forcedTzo != null) { 4011 timeZoneOffset = extraOptions.forcedTzo; 4012 } 4013 else { 4014 timeZoneOffset = this.offsetForMarker(marker); 4015 } 4016 } 4017 return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime); 4018 }; 4019 // TimeZone 4020 DateEnv.prototype.timestampToMarker = function (ms) { 4021 if (this.timeZone === 'local') { 4022 return arrayToUtcDate(dateToLocalArray(new Date(ms))); 4023 } 4024 if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) { 4025 return new Date(ms); 4026 } 4027 return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms)); 4028 }; 4029 DateEnv.prototype.offsetForMarker = function (m) { 4030 if (this.timeZone === 'local') { 4031 return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset 4032 } 4033 if (this.timeZone === 'UTC') { 4034 return 0; 4035 } 4036 if (this.namedTimeZoneImpl) { 4037 return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)); 4038 } 4039 return null; 4040 }; 4041 // Conversion 4042 DateEnv.prototype.toDate = function (m, forcedTzo) { 4043 if (this.timeZone === 'local') { 4044 return arrayToLocalDate(dateToUtcArray(m)); 4045 } 4046 if (this.timeZone === 'UTC') { 4047 return new Date(m.valueOf()); // make sure it's a copy 4048 } 4049 if (!this.namedTimeZoneImpl) { 4050 return new Date(m.valueOf() - (forcedTzo || 0)); 4051 } 4052 return new Date(m.valueOf() - 4053 this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60); 4054 }; 4055 return DateEnv; 4056 }()); 4057 4058 var globalLocales = []; 4059 4060 var RAW_EN_LOCALE = { 4061 code: 'en', 4062 week: { 4063 dow: 0, 4064 doy: 4, 4065 }, 4066 direction: 'ltr', 4067 buttonText: { 4068 prev: 'prev', 4069 next: 'next', 4070 prevYear: 'prev year', 4071 nextYear: 'next year', 4072 year: 'year', 4073 today: 'today', 4074 month: 'month', 4075 week: 'week', 4076 day: 'day', 4077 list: 'list', 4078 }, 4079 weekText: 'W', 4080 allDayText: 'all-day', 4081 moreLinkText: 'more', 4082 noEventsText: 'No events to display', 4083 }; 4084 function organizeRawLocales(explicitRawLocales) { 4085 var defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en'; 4086 var allRawLocales = globalLocales.concat(explicitRawLocales); 4087 var rawLocaleMap = { 4088 en: RAW_EN_LOCALE, 4089 }; 4090 for (var _i = 0, allRawLocales_1 = allRawLocales; _i < allRawLocales_1.length; _i++) { 4091 var rawLocale = allRawLocales_1[_i]; 4092 rawLocaleMap[rawLocale.code] = rawLocale; 4093 } 4094 return { 4095 map: rawLocaleMap, 4096 defaultCode: defaultCode, 4097 }; 4098 } 4099 function buildLocale(inputSingular, available) { 4100 if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) { 4101 return parseLocale(inputSingular.code, [inputSingular.code], inputSingular); 4102 } 4103 return queryLocale(inputSingular, available); 4104 } 4105 function queryLocale(codeArg, available) { 4106 var codes = [].concat(codeArg || []); // will convert to array 4107 var raw = queryRawLocale(codes, available) || RAW_EN_LOCALE; 4108 return parseLocale(codeArg, codes, raw); 4109 } 4110 function queryRawLocale(codes, available) { 4111 for (var i = 0; i < codes.length; i += 1) { 4112 var parts = codes[i].toLocaleLowerCase().split('-'); 4113 for (var j = parts.length; j > 0; j -= 1) { 4114 var simpleId = parts.slice(0, j).join('-'); 4115 if (available[simpleId]) { 4116 return available[simpleId]; 4117 } 4118 } 4119 } 4120 return null; 4121 } 4122 function parseLocale(codeArg, codes, raw) { 4123 var merged = mergeProps([RAW_EN_LOCALE, raw], ['buttonText']); 4124 delete merged.code; // don't want this part of the options 4125 var week = merged.week; 4126 delete merged.week; 4127 return { 4128 codeArg: codeArg, 4129 codes: codes, 4130 week: week, 4131 simpleNumberFormat: new Intl.NumberFormat(codeArg), 4132 options: merged, 4133 }; 4134 } 4135 4136 function formatDate(dateInput, options) { 4137 if (options === void 0) { options = {}; } 4138 var dateEnv = buildDateEnv(options); 4139 var formatter = createFormatter(options); 4140 var dateMeta = dateEnv.createMarkerMeta(dateInput); 4141 if (!dateMeta) { // TODO: warning? 4142 return ''; 4143 } 4144 return dateEnv.format(dateMeta.marker, formatter, { 4145 forcedTzo: dateMeta.forcedTzo, 4146 }); 4147 } 4148 function formatRange(startInput, endInput, options) { 4149 var dateEnv = buildDateEnv(typeof options === 'object' && options ? options : {}); // pass in if non-null object 4150 var formatter = createFormatter(options); 4151 var startMeta = dateEnv.createMarkerMeta(startInput); 4152 var endMeta = dateEnv.createMarkerMeta(endInput); 4153 if (!startMeta || !endMeta) { // TODO: warning? 4154 return ''; 4155 } 4156 return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, { 4157 forcedStartTzo: startMeta.forcedTzo, 4158 forcedEndTzo: endMeta.forcedTzo, 4159 isEndExclusive: options.isEndExclusive, 4160 defaultSeparator: BASE_OPTION_DEFAULTS.defaultRangeSeparator, 4161 }); 4162 } 4163 // TODO: more DRY and optimized 4164 function buildDateEnv(settings) { 4165 var locale = buildLocale(settings.locale || 'en', organizeRawLocales([]).map); // TODO: don't hardcode 'en' everywhere 4166 return new DateEnv(__assign(__assign({ timeZone: BASE_OPTION_DEFAULTS.timeZone, calendarSy
4166stem: 'gregory' }, settings), { locale: locale })); 4167 } 4168 4169 var DEF_DEFAULTS = { 4170 startTime: '09:00', 4171 endTime: '17:00', 4172 daysOfWeek: [1, 2, 3, 4, 5], 4173 display: 'inverse-background', 4174 classNames: 'fc-non-business', 4175 groupId: '_businessHours', 4176 }; 4177 /* 4178 TODO: pass around as EventDefHash!!! 4179 */ 4180 function parseBusinessHours(input, context) { 4181 return parseEvents(refineInputs(input), null, context); 4182 } 4183 function refineInputs(input) { 4184 var rawDefs; 4185 if (input === true) { 4186 rawDefs = [{}]; // will get DEF_DEFAULTS verbatim 4187 } 4188 else if (Array.isArray(input)) { 4189 // if specifying an array, every sub-definition NEEDS a day-of-week 4190 rawDefs = input.filter(function (rawDef) { return rawDef.daysOfWeek; }); 4191 } 4192 else if (typeof input === 'object' && input) { // non-null object 4193 rawDefs = [input]; 4194 } 4195 else { // is probably false 4196 rawDefs = []; 4197 } 4198 rawDefs = rawDefs.map(function (rawDef) { return (__assign(__assign({}, DEF_DEFAULTS), rawDef)); }); 4199 return rawDefs; 4200 } 4201 4202 function pointInsideRect(point, rect) { 4203 return point.left >= rect.left && 4204 point.left < rect.right && 4205 point.top >= rect.top && 4206 point.top < rect.bottom; 4207 } 4208 // Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false 4209 function intersectRects(rect1, rect2) { 4210 var res = { 4211 left: Math.max(rect1.left, rect2.left), 4212 right: Math.min(rect1.right, rect2.right), 4213 top: Math.max(rect1.top, rect2.top), 4214 bottom: Math.min(rect1.bottom, rect2.bottom), 4215 }; 4216 if (res.left < res.right && res.top < res.bottom) { 4217 return res; 4218 } 4219 return false; 4220 } 4221 function translateRect(rect, deltaX, deltaY) { 4222 return { 4223 left: rect.left + deltaX, 4224 right: rect.right + deltaX, 4225 top: rect.top + deltaY, 4226 bottom: rect.bottom + deltaY, 4227 }; 4228 } 4229 // Returns a new point that will have been moved to reside within the given rectangle 4230 function constrainPoint(point, rect) { 4231 return { 4232 left: Math.min(Math.max(point.left, rect.left), rect.right), 4233 top: Math.min(Math.max(point.top, rect.top), rect.bottom), 4234 }; 4235 } 4236 // Returns a point that is the center of the given rectangle 4237 function getRectCenter(rect) { 4238 return { 4239 left: (rect.left + rect.right) / 2, 4240 top: (rect.top + rect.bottom) / 2, 4241 }; 4242 } 4243 // Subtracts point2's coordinates from point1's coordinates, returning a delta 4244 function diffPoints(point1, point2) { 4245 return { 4246 left: point1.left - point2.left, 4247 top: point1.top - point2.top, 4248 }; 4249 } 4250 4251 var canVGrowWithinCell; 4252 function getCanVGrowWithinCell() { 4253 if (canVGrowWithinCell == null) { 4254 canVGrowWithinCell = computeCanVGrowWithinCell(); 4255 } 4256 return canVGrowWithinCell; 4257 } 4258 function computeCanVGrowWithinCell() { 4259 // for SSR, because this function is call immediately at top-level 4260 // TODO: just make this logic execute top-level, immediately, instead of doing lazily 4261 if (typeof document === 'undefined') { 4262 return true; 4263 } 4264 var el = document.createElement('div'); 4265 el.style.position = 'absolute'; 4266 el.style.top = '0px'; 4267 el.style.left = '0px'; 4268 el.innerHTML = '<table><tr><td><div></div></td></tr></table>'; 4269 el.querySelector('table').style.height = '100px'; 4270 el.querySelector('div').style.height = '100%'; 4271 document.body.appendChild(el); 4272 var div = el.querySelector('div'); 4273 var possible = div.offsetHeight > 0; 4274 document.body.removeChild(el); 4275 return possible; 4276 } 4277 4278 var EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere 4279 var Splitter = /** @class */ (function () { 4280 function Splitter() {
4281 this.getKeysForEventDefs = memoize(this._getKeysForEventDefs); 4282 this.splitDateSelection = memoize(this._splitDateSpan); 4283 this.splitEventStore = memoize(this._splitEventStore); 4284 this.splitIndividualUi = memoize(this._splitIndividualUi); 4285 this.splitEventDrag = memoize(this._splitInteraction); 4286 this.splitEventResize = memoize(this._splitInteraction); 4287 this.eventUiBuilders = {}; // TODO: typescript protection 4288 } 4289 Splitter.prototype.splitProps = function (props) { 4290 var _this = this; 4291 var keyInfos = this.getKeyInfo(props); 4292 var defKeys = this.getKeysForEventDefs(props.eventStore); 4293 var dateSelections = this.splitDateSelection(props.dateSelection); 4294 var individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases* 4295 var eventStores = this.splitEventStore(props.eventStore, defKeys); 4296 var eventDrags = this.splitEventDrag(props.eventDrag); 4297 var eventResizes = this.splitEventResize(props.eventResize); 4298 var splitProps = {}; 4299 this.eventUiBuilders = mapHash(keyInfos, function (info, key) { return _this.eventUiBuilders[key] || memoize(buildEventUiForKey); }); 4300 for (var key in keyInfos) { 4301 var keyInfo = keyInfos[key]; 4302 var eventStore = eventStores[key] || EMPTY_EVENT_STORE; 4303 var buildEventUi = this.eventUiBuilders[key]; 4304 splitProps[key] = { 4305 businessHours: keyInfo.businessHours || props.businessHours, 4306 dateSelection: dateSelections[key] || null, 4307 eventStore: eventStore, 4308 eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]), 4309 eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '', 4310 eventDrag: eventDrags[key] || null, 4311 eventResize: eventResizes[key] || null, 4312 }; 4313 } 4314 return splitProps; 4315 }; 4316 Splitter.prototype._splitDateSpan = function (dateSpan) { 4317 var dateSpans = {}; 4318 if (dateSpan) { 4319 var keys = this.getKeysForDateSpan(dateSpan); 4320 for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { 4321 var key = keys_1[_i]; 4322 dateSpans[key] = dateSpan; 4323 } 4324 } 4325 return dateSpans; 4326 }; 4327 Splitter.prototype._getKeysForEventDefs = function (eventStore) { 4328 var _this = this; 4329 return mapHash(eventStore.defs, function (eventDef) { return _this.getKeysForEventDef(eventDef); }); 4330 }; 4331 Splitter.prototype._splitEventStore = function (eventStore, defKeys) { 4332 var defs = eventStore.defs, instances = eventStore.instances; 4333 var splitStores = {}; 4334 for (var defId in defs) { 4335 for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) { 4336 var key = _a[_i]; 4337 if (!splitStores[key]) { 4338 splitStores[key] = createEmptyEventStore(); 4339 } 4340 splitStores[key].defs[defId] = defs[defId]; 4341 } 4342 } 4343 for (var instanceId in instances) { 4344 var instance = instances[instanceId]; 4345 for (var _b = 0, _c = defKeys[instance.defId]; _b < _c.length; _b++) { 4346 var key = _c[_b]; 4347 if (splitStores[key]) { // must have already been created 4348 splitStores[key].instances[instanceId] = instance; 4349 } 4350 } 4351 } 4352 return splitStores; 4353 }; 4354 Splitter.prototype._splitIndividualUi = function (eventUiBases, defKeys) { 4355 var splitHashes = {}; 4356 for (var defId in eventUiBases) { 4357 if (defId) { // not the '' key 4358 for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) { 4359 var key = _a[_i]; 4360 if (!splitHashes[key]) { 4361 splitHashes[key] = {}; 4362 } 4363 splitHashes[key][defId] = eventUiBases[defId]; 4364 } 4365 } 4366 } 4367 return splitHashes; 4368 }; 4369 Splitter.prototype._splitInteraction = function (interaction) { 4370 var splitStates = {}; 4371 if (interaction) { 4372 var affectedStores_1 = this._splitEventStore(interaction.affectedEvents, this._getKeys
4372ForEventDefs(interaction.affectedEvents)); 4373 // can't rely on defKeys because event data is mutated 4374 var mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents); 4375 var mutatedStores_1 = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId); 4376 var populate = function (key) { 4377 if (!splitStates[key]) { 4378 splitStates[key] = { 4379 affectedEvents: affectedStores_1[key] || EMPTY_EVENT_STORE, 4380 mutatedEvents: mutatedStores_1[key] || EMPTY_EVENT_STORE, 4381 isEvent: interaction.isEvent, 4382 }; 4383 } 4384 }; 4385 for (var key in affectedStores_1) { 4386 populate(key); 4387 } 4388 for (var key in mutatedStores_1) { 4389 populate(key); 4390 } 4391 } 4392 return splitStates; 4393 }; 4394 return Splitter; 4395 }()); 4396 function buildEventUiForKey(allUi, eventUiForKey, individualUi) { 4397 var baseParts = []; 4398 if (allUi) { 4399 baseParts.push(allUi); 4400 } 4401 if (eventUiForKey) { 4402 baseParts.push(eventUiForKey); 4403 } 4404 var stuff = { 4405 '': combineEventUis(baseParts), 4406 }; 4407 if (individualUi) { 4408 __assign(stuff, individualUi); 4409 } 4410 return stuff; 4411 } 4412 4413 function getDateMeta(date, todayRange, nowDate, dateProfile) { 4414 return { 4415 dow: date.getUTCDay(), 4416 isDisabled: Boolean(dateProfile && !rangeContainsMarker(dateProfile.activeRange, date)), 4417 isOther: Boolean(dateProfile && !rangeContainsMarker(dateProfile.currentRange, date)), 4418 isToday: Boolean(todayRange && rangeContainsMarker(todayRange, date)), 4419 isPast: Boolean(nowDate ? (date < nowDate) : todayRange ? (date < todayRange.start) : false), 4420 isFuture: Boolean(nowDate ? (date > nowDate) : todayRange ? (date >= todayRange.end) : false), 4421 }; 4422 } 4423 function getDayClassNames(meta, theme) { 4424 var classNames = [ 4425 'fc-day', 4426 "fc-day-" + DAY_IDS[meta.dow], 4427 ]; 4428 if (meta.isDisabled) { 4429 classNames.push('fc-day-disabled'); 4430 } 4431 else { 4432 if (meta.isToday) { 4433 classNames.push('fc-day-today'); 4434 classNames.push(theme.getClass('today')); 4435 } 4436 if (meta.isPast) { 4437 classNames.push('fc-day-past'); 4438 } 4439 if (meta.isFuture) { 4440 classNames.push('fc-day-future'); 4441 } 4442 if (meta.isOther) { 4443 classNames.push('fc-day-other'); 4444 } 4445 } 4446 return classNames; 4447 } 4448 function getSlotClassNames(meta, theme) { 4449 var classNames = [ 4450 'fc-slot', 4451 "fc-slot-" + DAY_IDS[meta.dow], 4452 ]; 4453 if (meta.isDisabled) { 4454 classNames.push('fc-slot-disabled'); 4455 } 4456 else { 4457 if (meta.isToday) { 4458 classNames.push('fc-slot-today'); 4459 classNames.push(theme.getClass('today')); 4460 } 4461 if (meta.isPast) { 4462 classNames.push('fc-slot-past'); 4463 } 4464 if (meta.isFuture) { 4465 classNames.push('fc-slot-future'); 4466 } 4467 } 4468 return classNames; 4469 } 4470 4471 function buildNavLinkData(date, type) { 4472 if (type === void 0) { type = 'day'; } 4473 return JSON.stringify({ 4474 date: formatDayString(date), 4475 type: type, 4476 }); 4477 } 4478 4479 var _isRtlScrollbarOnLeft = null; 4480 function getIsRtlScrollbarOnLeft() { 4481 if (_isRtlScrollbarOnLeft === null) { 4482 _isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft(); 4483 } 4484 return _isRtlScrollbarOnLeft; 4485 } 4486 function computeIsRtlScrollbarOnLeft() { 4487 var outerEl = document.createElement('div'); 4488 applyStyle(outerEl, { 4489 position: 'absolute', 4490 top: -1000, 4491 left: 0, 4492 border: 0, 4493 padding: 0, 4494 overflow: 'scroll', 4495 direction: 'rtl', 4496 }); 4497 outerEl.innerHTML = '<div></div>'; 4498 document.body.appendChild(outerEl); 4499 var innerEl = outerEl.firstChild; 4500 var res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left; 4501 removeElement(outerEl); 4502 return res; 4503 } 4504 4505 var _scrollbarWidths; 4506 function getScrollbarWidths() { 4507 if (!_scrollbarWidths) {
4508 _scrollbarWidths = computeScrollbarWidths(); 4509 } 4510 return _scrollbarWidths; 4511 } 4512 function computeScrollbarWidths() { 4513 var el = document.createElement('div'); 4514 el.style.overflow = 'scroll'; 4515 el.style.position = 'absolute'; 4516 el.style.top = '-9999px'; 4517 el.style.left = '-9999px'; 4518 document.body.appendChild(el); 4519 var res = computeScrollbarWidthsForEl(el); 4520 document.body.removeChild(el); 4521 return res; 4522 } 4523 // WARNING: will include border 4524 function computeScrollbarWidthsForEl(el) { 4525 return { 4526 x: el.offsetHeight - el.clientHeight, 4527 y: el.offsetWidth - el.clientWidth, 4528 }; 4529 } 4530 4531 function computeEdges(el, getPadding) { 4532 if (getPadding === void 0) { getPadding = false; } 4533 var computedStyle = window.getComputedStyle(el); 4534 var borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0; 4535 var borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0; 4536 var borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0; 4537 var borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0; 4538 var badScrollbarWidths = computeScrollbarWidthsForEl(el); // includes border! 4539 var scrollbarLeftRight = badScrollbarWidths.y - borderLeft - borderRight; 4540 var scrollbarBottom = badScrollbarWidths.x - borderTop - borderBottom; 4541 var res = { 4542 borderLeft: borderLeft, 4543 borderRight: borderRight, 4544 borderTop: borderTop, 4545 borderBottom: borderBottom, 4546 scrollbarBottom: scrollbarBottom, 4547 scrollbarLeft: 0, 4548 scrollbarRight: 0, 4549 }; 4550 if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side? 4551 res.scrollbarLeft = scrollbarLeftRight; 4552 } 4553 else { 4554 res.scrollbarRight = scrollbarLeftRight; 4555 } 4556 if (getPadding) { 4557 res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0; 4558 res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0; 4559 res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0; 4560 res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0; 4561 } 4562 return res; 4563 } 4564 function computeInnerRect(el, goWithinPadding, doFromWindowViewport) { 4565 if (goWithinPadding === void 0) { goWithinPadding = false; } 4566 var outerRect = doFromWindowViewport ? el.getBoundingClientRect() : computeRect(el); 4567 var edges = computeEdges(el, goWithinPadding); 4568 var res = { 4569 left: outerRect.left + edges.borderLeft + edges.scrollbarLeft, 4570 right: outerRect.right - edges.borderRight - edges.scrollbarRight, 4571 top: outerRect.top + edges.borderTop, 4572 bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom, 4573 }; 4574 if (goWithinPadding) { 4575 res.left += edges.paddingLeft; 4576 res.right -= edges.paddingRight; 4577 res.top += edges.paddingTop; 4578 res.bottom -= edges.paddingBottom; 4579 } 4580 return res; 4581 } 4582 function computeRect(el) { 4583 var rect = el.getBoundingClientRect(); 4584 return { 4585 left: rect.left + window.pageXOffset, 4586 top: rect.top + window.pageYOffset, 4587 right: rect.right + window.pageXOffset, 4588 bottom: rect.bottom + window.pageYOffset, 4589 }; 4590 } 4591 function computeHeightAndMargins(el) { 4592 return el.getBoundingClientRect().height + computeVMargins(el); 4593 } 4594 function computeVMargins(el) { 4595 var computed = window.getComputedStyle(el); 4596 return parseInt(computed.marginTop, 10) + 4597 parseInt(computed.marginBottom, 10); 4598 } 4599 // does not return window 4600 function getClippingParents(el) { 4601 var parents = []; 4602 while (el instanceof HTMLElement) { // will stop when gets to document or null 4603 var computedStyle = window.getComputedStyle(el); 4604 if (computedStyle.position === 'fixed') { 4605 break; 4606 } 4607 if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) { 4608 parents.push(el); 4609 } 4610 el = el.parentNode; 4611 } 4612 return parents; 4613 } 4614 4615 // given a function that resolves a result asynchronously. 4616 // the function can either call passed-in success and failure callbacks, 4617 // or it can return a promise. 4618 // if you need to pass additional params to func, bind them first. 4619 function unpromisify(func, success, failure) { 4620 // guard against success/failure callbacks being called more than once 4621 // and guard against a promise AND callback being used together. 4622 var isResolved = false;
4623 var wrappedSuccess = function () { 4624 if (!isResolved) { 4625 isResolved = true; 4626 success.apply(this, arguments); // eslint-disable-line prefer-rest-params 4627 } 4628 }; 4629 var wrappedFailure = function () { 4630 if (!isResolved) { 4631 isResolved = true; 4632 if (failure) { 4633 failure.apply(this, arguments); // eslint-disable-line prefer-rest-params 4634 } 4635 } 4636 }; 4637 var res = func(wrappedSuccess, wrappedFailure); 4638 if (res && typeof res.then === 'function') { 4639 res.then(wrappedSuccess, wrappedFailure); 4640 } 4641 } 4642 4643 var Emitter = /** @class */ (function () { 4644 function Emitter() { 4645 this.handlers = {}; 4646 this.thisContext = null; 4647 } 4648 Emitter.prototype.setThisContext = function (thisContext) { 4649 this.thisContext = thisContext; 4650 }; 4651 Emitter.prototype.setOptions = function (options) { 4652 this.options = options; 4653 }; 4654 Emitter.prototype.on = function (type, handler) { 4655 addToHash(this.handlers, type, handler); 4656 }; 4657 Emitter.prototype.off = function (type, handler) { 4658 removeFromHash(this.handlers, type, handler); 4659 }; 4660 Emitter.prototype.trigger = function (type) { 4661 var args = []; 4662 for (var _i = 1; _i < arguments.length; _i++) { 4663 args[_i - 1] = arguments[_i]; 4664 } 4665 var attachedHandlers = this.handlers[type] || []; 4666 var optionHandler = this.options && this.options[type]; 4667 var handlers = [].concat(optionHandler || [], attachedHandlers); 4668 for (var _a = 0, handlers_1 = handlers; _a < handlers_1.length; _a++) { 4669 var handler = handlers_1[_a]; 4670 handler.apply(this.thisContext, args); 4671 } 4672 }; 4673 Emitter.prototype.hasHandlers = function (type) { 4674 return (this.handlers[type] && this.handlers[type].length) || 4675 (this.options && this.options[type]); 4676 }; 4677 return Emitter; 4678 }()); 4679 function addToHash(hash, type, handler) { 4680 (hash[type] || (hash[type] = [])) 4681 .push(handler); 4682 } 4683 function removeFromHash(hash, type, handler) { 4684 if (handler) { 4685 if (hash[type]) { 4686 hash[type] = hash[type].filter(function (func) { return func !== handler; }); 4687 } 4688 } 4689 else { 4690 delete hash[type]; // remove all handler funcs for this type 4691 } 4692 } 4693 4694 /* 4695 Records offset information for a set of elements, relative to an origin element. 4696 Can record the left/right OR the top/bottom OR both. 4697 Provides methods for querying the cache by position. 4698 */ 4699 var PositionCache = /** @class */ (function () { 4700 function PositionCache(originEl, els, isHorizontal, isVertical) { 4701 this.els = els; 4702 var originClientRect = this.originClientRect = originEl.getBoundingClientRect(); // relative to viewport top-left 4703 if (isHorizontal) { 4704 this.buildElHorizontals(originClientRect.left); 4705 } 4706 if (isVertical) { 4707 this.buildElVerticals(originClientRect.top); 4708 } 4709 } 4710 // Populates the left/right internal coordinate arrays 4711 PositionCache.prototype.buildElHorizontals = function (originClientLeft) { 4712 var lefts = []; 4713 var rights = []; 4714 for (var _i = 0, _a = this.els; _i < _a.length; _i++) { 4715 var el = _a[_i]; 4716 var rect = el.getBoundingClientRect(); 4717 lefts.push(rect.left - originClientLeft); 4718 rights.push(rect.right - originClientLeft); 4719 } 4720 this.lefts = lefts; 4721 this.rights = rights; 4722 }; 4723 // Populates the top/bottom internal coordinate arrays 4724 PositionCache.prototype.buildElVerticals = function (originClientTop) { 4725 var tops = []; 4726 var bottoms = []; 4727 for (var _i = 0, _a = this.els; _i < _a.length; _i++) { 4728 var el = _a[_i]; 4729 var rect = el.getBoundingClientRect(); 4730 tops.push(rect.top - originClientTop); 4731 bottoms.push(rect.bottom - originClientTop); 4732 } 4733 this.tops = tops; 4734 this.bottoms = bottoms; 4735 }; 4736 // Given a left offset (from document left), returns the index of the el that it horizontally intersects. 4737 // If no intersection is made, returns undefined. 4738 PositionCache.prototype.leftToIndex = function (leftPosition) { 4739 var _a = this, lefts = _a.lefts, rights = _a.rights; 4740 var len = lefts.length; 4741 var i; 4742 for (i = 0; i < len; i += 1) { 4743 if (leftPosition >= lefts[i] && leftPosition < rights[i]) { 4744 return i; 4745 } 4746 } 4747 return undefined; // TODO: better 4748 }; 4749 // Given a top offset (from document top), returns the index of the el that it vertically intersects. 4750 // If no intersection is made, returns undefined. 4751 PositionCache.prototype.topToIndex = function (topPosition) { 4752 var _a = this, tops = _a.tops, bottoms = _a.bottoms; 4753 var len = tops.length; 4754 var i; 4755 for (i = 0; i < len; i += 1) { 4756 if (topPosition >= tops[i] && topPosition < bottoms[i]) { 4757 return i; 4758 } 4759 } 4760 return undefined; // TODO: better 4761 }; 4762 // Gets the width of the element at the given index 4763 PositionCache.prototype.getWidth = function (leftIndex) { 4764 return this.rights[leftIndex] - this.lefts[leftIndex]; 4765 }; 4766 // Gets the height of the element at the given index 4767 PositionCache.prototype.getHeight = function (topIndex) { 4768 return this.bottoms[topIndex] - this.tops[topIndex]; 4769 }; 4770 return PositionCache; 4771 }()); 4772
4773 /* eslint max-classes-per-file: "off" */ 4774 /* 4775 An object for getting/setting scroll-related information for an element. 4776 Internally, this is done very differently for window versus DOM element, 4777 so this object serves as a common interface. 4778 */ 4779 var ScrollController = /** @class */ (function () { 4780 function ScrollController() { 4781 } 4782 ScrollController.prototype.getMaxScrollTop = function () { 4783 return this.getScrollHeight() - this.getClientHeight(); 4784 }; 4785 ScrollController.prototype.getMaxScrollLeft = function () { 4786 return this.getScrollWidth() - this.getClientWidth(); 4787 }; 4788 ScrollController.prototype.canScrollVertically = function () { 4789 return this.getMaxScrollTop() > 0; 4790 }; 4791 ScrollController.prototype.canScrollHorizontally = function () { 4792 return this.getMaxScrollLeft() > 0; 4793 }; 4794 ScrollController.prototype.canScrollUp = function () { 4795 return this.getScrollTop() > 0; 4796 }; 4797 ScrollController.prototype.canScrollDown = function () { 4798 return this.getScrollTop() < this.getMaxScrollTop(); 4799 }; 4800 ScrollController.prototype.canScrollLeft = function () { 4801 return this.getScrollLeft() > 0; 4802 }; 4803 ScrollController.prototype.canScrollRight = function () { 4804 return this.getScrollLeft() < this.getMaxScrollLeft(); 4805 }; 4806 return ScrollController; 4807 }()); 4808 var ElementScrollController = /** @class */ (function (_super) { 4809 __extends(ElementScrollController, _super); 4810 function ElementScrollController(el) { 4811 var _this = _super.call(this) || this; 4812 _this.el = el; 4813 return _this; 4814 } 4815 ElementScrollController.prototype.getScrollTop = function () { 4816 return this.el.scrollTop; 4817 }; 4818 ElementScrollController.prototype.getScrollLeft = function () { 4819 return this.el.scrollLeft; 4820 }; 4821 ElementScrollController.prototype.setScrollTop = function (top) { 4822 this.el.scrollTop = top; 4823 }; 4824 ElementScrollController.prototype.setScrollLeft = function (left) { 4825 this.el.scrollLeft = left; 4826 }; 4827 ElementScrollController.prototype.getScrollWidth = function () { 4828 return this.el.scrollWidth; 4829 }; 4830 ElementScrollController.prototype.getScrollHeight = function () { 4831 return this.el.scrollHeight; 4832 }; 4833 ElementScrollController.prototype.getClientHeight = function () { 4834 return this.el.clientHeight; 4835 }; 4836 ElementScrollController.prototype.getClientWidth = function () { 4837 return this.el.clientWidth; 4838 }; 4839 return ElementScrollController; 4840 }(ScrollController)); 4841 var WindowScrollController = /** @class */ (function (_super) { 4842 __extends(WindowScrollController, _super); 4843 function WindowScrollController() { 4844 return _super !== null && _super.apply(this, arguments) || this; 4845 } 4846 WindowScrollController.prototype.getScrollTop = function () { 4847 return window.pageYOffset; 4848 }; 4849 WindowScrollController.prototype.getScrollLeft = function () { 4850 return window.pageXOffset; 4851 }; 4852 WindowScrollController.prototype.setScrollTop = function (n) { 4853 window.scroll(window.pageXOffset, n); 4854 }; 4855 WindowScrollController.prototype.setScrollLeft = function (n) { 4856 window.scroll(n, window.pageYOffset); 4857 }; 4858 WindowScrollController.prototype.getScrollWidth = function () { 4859 return document.documentElement.scrollWidth; 4860 }; 4861 WindowScrollController.prototype.getScrollHeight = function () { 4862 return document.documentElement.scrollHeight; 4863 }; 4864 WindowScrollController.prototype.getClientHeight = function () { 4865 return document.documentElement.clientHeight; 4866 }; 4867 WindowScrollController.prototype.getClientWidth = function () { 4868 return document.documentElement.clientWidth; 4869 }; 4870 return WindowScrollController; 4871 }(ScrollController)); 4872 4873 var Theme = /** @class */ (function () { 4874 function Theme(calendarOptions) { 4875 if (this.iconOverrideOption) { 4876 this.setIconOverride(calendarOptions[this.iconOverrideOption]); 4877 } 4878 } 4879 Theme.prototype.setIconOverride = function (iconOverrideHash) { 4880 var iconClassesCopy; 4881 var buttonName; 4882 if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object 4883 iconClassesCopy = __assign({}, this.iconClasses); 4884 for (buttonName in iconOverrideHash) { 4885 iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]); 4886 } 4887 this.iconClasses = iconClassesCopy; 4888 } 4889 else if (iconOverrideHash === false) { 4890 this.iconClasses = {}; 4891 } 4892 }; 4893 Theme.prototype.applyIconOverridePrefix = function (className) { 4894 var prefix = this.iconOverridePrefix; 4895 if (prefix && className.indexOf(prefix) !== 0) { // if not already present 4896 className = prefix + className; 4897 } 4898 return className; 4899 }; 4900 Theme.prototype.getClass = function (key) { 4901 return this.classes[key] || ''; 4902 }; 4903 Theme.prototype.getIconClass = function (buttonName, isRtl) { 4904 var className; 4905 if (isRtl && this.rtlIconClasses) { 4906 className = this.rtlIconClasses[buttonName] || this.iconClasses[buttonName]; 4907 } 4908 else { 4909 className = this.iconClasses[buttonName]; 4910 } 4911 if (className) { 4912 return this.baseIconClass + " " + className; 4913 } 4914 return ''; 4915 }; 4916 Theme.prototype.getCustomButtonIconClass = function (customButtonProps) { 4917 var className; 4918 if (this.iconOverrideCustomButtonOption) { 4919 className = customButtonProps[this.iconOverrideCustomButtonOption]; 4920 if (className) { 4921 return this.baseIconClass + " " + this.applyIconOverridePrefix(className); 4922 } 4923 } 4924 return ''; 4925 }; 4926 return Theme; 4927 }()); 4928 Theme.prototype.classes = {}; 4929 Theme.prototype.iconClasses = {}; 4930 Theme.prototype.baseIconClass = ''; 4931 Theme.prototype.iconOverridePrefix = ''; 4932 4933 /// <reference types="@fullcalendar/core-preact" /> 4934 if (typeof FullCalendarVDom === 'undefined') { 4935 throw new Error('Please import the top-level fullcalendar lib before attempting to import a plugin.'); 4936 } 4937 var Component = FullCalendarVDom.Component; 4938 var createElement = FullCalendarVDom.createElement; 4939 var render = FullCalendarVDom.render; 4940 var createRef = FullCalendarVDom.createRef; 4941 var Fragment = FullCalendarVDom.Fragment; 4942 var createContext$1 = FullCalendarVDom.createContext; 4943 var flushToDom$1 = FullCalendarVDom.flushToDom; 4944 var unmountComponentAtNode$1 = FullCalendarVDom.unmountComponentAtNode; 4945 4946 var ScrollResponder = /** @class */ (function () { 4947 function ScrollResponder(execFunc, emitter, scrollTime) { 4948 var _this = this; 4949 this.execFunc = execFunc; 4950 this.emitter = emitter; 4951 this.scrollTime = scrollTime; 4952 this.handleScrollRequest = function (request) { 4953 _this.queuedRequest = __assign({}, _this.queuedRequest || {}, request); 4954 _this.drain(); 4955 }; 4956 emitter.on('_scrollRequest', this.handleScrollRequest); 4957 this.fireInitialScroll(); 4958 } 4959 ScrollResponder.prototype.detach = function () { 4960 this.emitter.off('_scrollRequest', this.handleScrollRequest); 4961 }; 4962 ScrollResponder.prototype.update = function (isDatesNew) { 4963 if (isDatesNew) { 4964 this.fireInitialScroll(); // will drain 4965 } 4966 else { 4967 this.drain(); 4968 } 4969 }; 4970 ScrollResponder.prototype.fireInitialScroll = function () { 4971 this.handleScrollRequest({ 4972 time: this.scrollTime, 4973 }); 4974 };
4975 ScrollResponder.prototype.drain = function () { 4976 if (this.queuedRequest && this.execFunc(this.queuedRequest)) { 4977 this.queuedRequest = null; 4978 } 4979 }; 4980 return ScrollResponder; 4981 }()); 4982 4983 var ViewContextType = createContext$1({}); // for Components 4984 function buildViewContext(viewSpec, viewApi, viewOptions, dateProfileGenerator, dateEnv, theme, pluginHooks, dispatch, getCurrentData, emitter, calendarApi, registerInteractiveComponent, unregisterInteractiveComponent) { 4985 return { 4986 dateEnv: dateEnv, 4987 options: viewOptions, 4988 pluginHooks: pluginHooks, 4989 emitter: emitter, 4990 dispatch: dispatch, 4991 getCurrentData: getCurrentData, 4992 calendarApi: calendarApi, 4993 viewSpec: viewSpec, 4994 viewApi: viewApi, 4995 dateProfileGenerator: dateProfileGenerator, 4996 theme: theme, 4997 isRtl: viewOptions.direction === 'rtl', 4998 addResizeHandler: function (handler) { 4999 emitter.on('_resize', handler); 5000 }, 5001 removeResizeHandler: function (handler) { 5002 emitter.off('_resize', handler); 5003 }, 5004 createScrollResponder: function (execFunc) { 5005 return new ScrollResponder(execFunc, emitter, createDuration(viewOptions.scrollTime)); 5006 }, 5007 registerInteractiveComponent: registerInteractiveComponent, 5008 unregisterInteractiveComponent: unregisterInteractiveComponent, 5009 }; 5010 } 5011 5012 /* eslint max-classes-per-file: off */ 5013 var PureComponent = /** @class */ (function (_super) { 5014 __extends(PureComponent, _super); 5015 function PureComponent() { 5016 return _super !== null && _super.apply(this, arguments) || this; 5017 } 5018 PureComponent.prototype.shouldComponentUpdate = function (nextProps, nextState) { 5019 if (this.debug) { 5020 // eslint-disable-next-line no-console 5021 console.log(getUnequalProps(nextProps, this.props), getUnequalProps(nextState, this.state)); 5022 } 5023 return !compareObjs(this.props, nextProps, this.propEquality) || 5024 !compareObjs(this.state, nextState, this.stateEquality); 5025 }; 5026 PureComponent.addPropsEquality = addPropsEquality; 5027 PureComponent.addStateEquality = addStateEquality; 5028 PureComponent.contextType = ViewContextType; 5029 return PureComponent; 5030 }(Component)); 5031 PureComponent.prototype.propEquality = {}; 5032 PureComponent.prototype.stateEquality = {}; 5033 var BaseComponent = /** @class */ (function (_super) { 5034 __extends(BaseComponent, _super); 5035 function BaseComponent() { 5036 return _super !== null && _super.apply(this, arguments) || this; 5037 } 5038 BaseComponent.contextType = ViewContextType; 5039 return BaseComponent; 5040 }(PureComponent)); 5041 function addPropsEquality(propEquality) { 5042 var hash = Object.create(this.prototype.propEquality); 5043 __assign(hash, propEquality); 5044 this.prototype.propEquality = hash; 5045 } 5046 function addStateEquality(stateEquality) { 5047 var hash = Object.create(this.prototype.stateEquality); 5048 __assign(hash, stateEquality); 5049 this.prototype.stateEquality = hash; 5050 } 5051 // use other one 5052 function setRef(ref, current) { 5053 if (typeof ref === 'function') { 5054 ref(current); 5055 } 5056 else if (ref) { 5057 // see https://github.com/facebook/react/issues/13029 5058 ref.current = current; 5059 } 5060 } 5061 5062 function reduceEventStore(eventStore, action, eventSources, dateProfile, context) { 5063 switch (action.type) { 5064 case 'RECEIVE_EVENTS': // raw 5065 return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, context); 5066 case 'ADD_EVENTS': // already parsed, but not expanded 5067 return addEvent(eventStore, action.eventStore, // new ones 5068 dateProfile ? dateProfile.activeRange : null, context); 5069 case 'RESET_EVENTS': 5070 return action.eventStore; 5071 case 'MERGE_EVENTS': // already parsed and expanded 5072 return mergeEventStores(eventStore, action.eventStore); 5073 case 'PREV': // TODO: how do we track all actions that affect dateProfile :( 5074 case 'NEXT': 5075 case 'CHANGE_DATE': 5076 case 'CHANGE_VIEW_TYPE': 5077 if (dateProfile) { 5078 return expandRecurring(eventStore, dateProfile.activeRange, context); 5079 } 5080 return eventStore;
5081 case 'REMOVE_EVENTS': 5082 return excludeSubEventStore(eventStore, action.eventStore); 5083 case 'REMOVE_EVENT_SOURCE': 5084 return excludeEventsBySourceId(eventStore, action.sourceId); 5085 case 'REMOVE_ALL_EVENT_SOURCES': 5086 return filterEventStoreDefs(eventStore, function (eventDef) { return (!eventDef.sourceId // only keep events with no source id 5087 ); }); 5088 case 'REMOVE_ALL_EVENTS': 5089 return createEmptyEventStore(); 5090 default: 5091 return eventStore; 5092 } 5093 } 5094 function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, context) { 5095 if (eventSource && // not already removed 5096 fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources 5097 ) { 5098 var subset = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context); 5099 if (fetchRange) { 5100 subset = expandRecurring(subset, fetchRange, context); 5101 } 5102 return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset); 5103 } 5104 return eventStore; 5105 } 5106 function transformRawEvents(rawEvents, eventSource, context) { 5107 var calEachTransform = context.options.eventDataTransform; 5108 var sourceEachTransform = eventSource ? eventSource.eventDataTransform : null; 5109 if (sourceEachTransform) { 5110 rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform); 5111 } 5112 if (calEachTransform) { 5113 rawEvents = transformEachRawEvent(rawEvents, calEachTransform); 5114 } 5115 return rawEvents; 5116 } 5117 function transformEachRawEvent(rawEvents, func) { 5118 var refinedEvents; 5119 if (!func) { 5120 refinedEvents = rawEvents; 5121 } 5122 else { 5123 refinedEvents = []; 5124 for (var _i = 0, rawEvents_1 = rawEvents; _i < rawEvents_1.length; _i++) { 5125 var rawEvent = rawEvents_1[_i]; 5126 var refinedEvent = func(rawEvent); 5127 if (refinedEvent) { 5128 refinedEvents.push(refinedEvent); 5129 } 5130 else if (refinedEvent == null) { 5131 refinedEvents.push(rawEvent); 5132 } // if a different falsy value, do nothing 5133 } 5134 } 5135 return refinedEvents; 5136 } 5137 function addEvent(eventStore, subset, expandRange, context) { 5138 if (expandRange) { 5139 subset = expandRecurring(subset, expandRange, context); 5140 } 5141 return mergeEventStores(eventStore, subset); 5142 } 5143 function rezoneEventStoreDates(eventStore, oldDateEnv, newDateEnv) { 5144 var defs = eventStore.defs; 5145 var instances = mapHash(eventStore.instances, function (instance) { 5146 var def = defs[instance.defId]; 5147 if (def.allDay || def.recurringDef) { 5148 return instance; // isn't dependent on timezone 5149 } 5150 return __assign(__assign({}, instance), { range: { 5151 start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)), 5152 end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo)), 5153 }, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo }); 5154 }); 5155 return { defs: defs, instances: instances }; 5156 } 5157 function excludeEventsBySourceId(eventStore, sourceId) { 5158 return filterEventStoreDefs(eventStore, function (eventDef) { return eventDef.sourceId !== sourceId; }); 5159 } 5160 // QUESTION: why not just return instances? do a general object-property-exclusion util 5161 function excludeInstances(eventStore, removals) { 5162 return { 5163 defs: eventStore.defs, 5164 instances: filterHash(eventStore.instances, function (instance) { return !removals[instance.instanceId]; }), 5165 }; 5166 } 5167 5168 // high-level segmenting-aware tester functions 5169 // ------------------------------------------------------------------------------------------------------------------------ 5170 function isInteractionValid(interaction, context) { 5171 return isNewPropsValid({ eventDrag: interaction }, context); // HACK: the eventDrag props is used for ALL interactions 5172 } 5173 function isDateSelectionValid(dateSelection, context) { 5174 return isNewPropsValid({ dateSelection: dateSelection }, context); 5175 } 5176 function isNewPropsValid(newProps, context) { 5177 var calendarState = context.getCurrentData(); 5178 var props = __assign({ businessHours: calendarState.businessHours, dateSelection: '', eventStore: calendarState.eventStore, eventUiBases: calendarState.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps); 5179 return (context.pluginHooks.isPropsValid || isPropsValid)(props, context); 5180 } 5181 function isPropsValid(state, context, dateSpanMeta, filterConfig) {
5182 if (dateSpanMeta === void 0) { dateSpanMeta = {}; } 5183 if (state.eventDrag && !isInteractionPropsValid(state, context, dateSpanMeta, filterConfig)) { 5184 return false; 5185 } 5186 if (state.dateSelection && !isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig)) { 5187 return false; 5188 } 5189 return true; 5190 } 5191 // Moving Event Validation 5192 // ------------------------------------------------------------------------------------------------------------------------ 5193 function isInteractionPropsValid(state, context, dateSpanMeta, filterConfig) { 5194 var currentState = context.getCurrentData(); 5195 var interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions 5196 var subjectEventStore = interaction.mutatedEvents; 5197 var subjectDefs = subjectEventStore.defs; 5198 var subjectInstances = subjectEventStore.instances; 5199 var subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ? 5200 state.eventUiBases : 5201 { '': currentState.selectionConfig }); 5202 if (filterConfig) { 5203 subjectConfigs = mapHash(subjectConfigs, filterConfig); 5204 } 5205 // exclude the subject events. TODO: exclude defs too? 5206 var otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances); 5207 var otherDefs = otherEventStore.defs; 5208 var otherInstances = otherEventStore.instances; 5209 var otherConfigs = compileEventUis(otherDefs, state.eventUiBases); 5210 for (var subjectInstanceId in subjectInstances) { 5211 var subjectInstance = subjectInstances[subjectInstanceId]; 5212 var subjectRange = subjectInstance.range; 5213 var subjectConfig = subjectConfigs[subjectInstance.defId]; 5214 var subjectDef = subjectDefs[subjectInstance.defId]; 5215 // constraint 5216 if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, context)) { 5217 return false; 5218 } 5219 // overlap 5220 var eventOverlap = context.options.eventOverlap; 5221 var eventOverlapFunc = typeof eventOverlap === 'function' ? eventOverlap : null; 5222 for (var otherInstanceId in otherInstances) { 5223 var otherInstance = otherInstances[otherInstanceId]; 5224 // intersect! evaluate 5225 if (rangesIntersect(subjectRange, otherInstance.range)) { 5226 var otherOverlap = otherConfigs[otherInstance.defId].overlap; 5227 // consider the other event's overlap. only do this if the subject event is a "real" event 5228 if (otherOverlap === false && interaction.isEvent) { 5229 return false; 5230 } 5231 if (subjectConfig.overlap === false) { 5232 return false; 5233 } 5234 if (eventOverlapFunc && !eventOverlapFunc(new EventApi(context, otherDefs[otherInstance.defId], otherInstance), // still event 5235 new EventApi(context, subjectDef, subjectInstance))) { 5236 return false; 5237 } 5238 } 5239 } 5240 // allow (a function) 5241 var calendarEventStore = currentState.eventStore; // need global-to-calendar, not local to component (splittable)state 5242 for (var _i = 0, _a = subjectConfig.allows; _i < _a.length; _i++) { 5243 var subjectAllow = _a[_i]; 5244 var subjectDateSpan = __assign(__assign({}, dateSpanMeta), { range: subjectInstance.range, allDay: subjectDef.allDay }); 5245 var origDef = calendarEventStore.defs[subjectDef.defId]; 5246 var origInstance = calendarEventStore.instances[subjectInstanceId]; 5247 var eventApi = void 0; 5248 if (origDef) { // was previously in the calendar 5249 eventApi = new EventApi(context, origDef, origInstance); 5250 } 5251 else { // was an external event 5252 eventApi = new EventApi(context, subjectDef); // no instance, because had no dates 5253 } 5254 if (!subjectAllow(buildDateSpanApiWithContext(subjectDateSpan, context), eventApi)) { 5255 return false;
5256 } 5257 } 5258 } 5259 return true; 5260 } 5261 // Date Selection Validation 5262 // ------------------------------------------------------------------------------------------------------------------------ 5263 function isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig) { 5264 var relevantEventStore = state.eventStore; 5265 var relevantDefs = relevantEventStore.defs; 5266 var relevantInstances = relevantEventStore.instances; 5267 var selection = state.dateSelection; 5268 var selectionRange = selection.range; 5269 var selectionConfig = context.getCurrentData().selectionConfig; 5270 if (filterConfig) { 5271 selectionConfig = filterConfig(selectionConfig); 5272 } 5273 // constraint 5274 if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, context)) { 5275 return false; 5276 } 5277 // overlap 5278 var selectOverlap = context.options.selectOverlap; 5279 var selectOverlapFunc = typeof selectOverlap === 'function' ? selectOverlap : null; 5280 for (var relevantInstanceId in relevantInstances) { 5281 var relevantInstance = relevantInstances[relevantInstanceId]; 5282 // intersect! evaluate 5283 if (rangesIntersect(selectionRange, relevantInstance.range)) { 5284 if (selectionConfig.overlap === false) { 5285 return false; 5286 } 5287 if (selectOverlapFunc && !selectOverlapFunc(new EventApi(context, relevantDefs[relevantInstance.defId], relevantInstance), null)) { 5288 return false; 5289 } 5290 } 5291 } 5292 // allow (a function) 5293 for (var _i = 0, _a = selectionConfig.allows; _i < _a.length; _i++) { 5294 var selectionAllow = _a[_i]; 5295 var fullDateSpan = __assign(__assign({}, dateSpanMeta), selection); 5296 if (!selectionAllow(buildDateSpanApiWithContext(fullDateSpan, context), null)) { 5297 return false; 5298 } 5299 } 5300 return true; 5301 } 5302 // Constraint Utils 5303 // ------------------------------------------------------------------------------------------------------------------------ 5304 function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, context) { 5305 for (var _i = 0, constraints_1 = constraints; _i < constraints_1.length; _i++) { 5306 var constraint = constraints_1[_i]; 5307 if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, context), subjectRange)) { 5308 return false; 5309 } 5310 } 5311 return true; 5312 } 5313 function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours 5314 otherEventStore, // for if constraint is an even group ID 5315 businessHoursUnexpanded, // for if constraint is 'businessHours' 5316 context) { 5317 if (constraint === 'businessHours') { 5318 return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, context)); 5319 } 5320 if (typeof constraint === 'string') { // an group ID 5321 return eventStoreToRanges(filterEventStoreDefs(otherEventStore, function (eventDef) { return eventDef.groupId === constraint; })); 5322 } 5323 if (typeof constraint === 'object' && constraint) { // non-null object 5324 return eventStoreToRanges(expandRecurring(constraint, subjectRange, context)); 5325 } 5326 return []; // if it's false 5327 } 5328 // TODO: move to event-store file? 5329 function eventStoreToRanges(eventStore) { 5330 var instances = eventStore.instances; 5331 var ranges = []; 5332 for (var instanceId in instances) { 5333 ranges.push(instances[instanceId].range); 5334 } 5335 return ranges; 5336 } 5337 // TODO: move to geom file? 5338 function anyRangesContainRange(outerRanges, innerRange) { 5339 for (var _i = 0, outerRanges_1 = outerRanges; _i < outerRanges_1.length; _i++) { 5340 var outerRange = outerRanges_1[_i]; 5341 if (rangeContainsRange(outerRange, innerRange)) { 5342 return true; 5343 } 5344 } 5345 return false;
5346 } 5347 5348 /* 5349 an INTERACTABLE date component 5350 5351 PURPOSES: 5352 - hook up to fg, fill, and mirror renderers 5353 - interface for dragging and hits 5354 */ 5355 var DateComponent = /** @class */ (function (_super) { 5356 __extends(DateComponent, _super); 5357 function DateComponent() { 5358 var _this = _super !== null && _super.apply(this, arguments) || this; 5359 _this.uid = guid(); 5360 return _this; 5361 } 5362 // Hit System 5363 // ----------------------------------------------------------------------------------------------------------------- 5364 DateComponent.prototype.prepareHits = function () { 5365 }; 5366 DateComponent.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) { 5367 return null; // this should be abstract 5368 }; 5369 // Validation 5370 // ----------------------------------------------------------------------------------------------------------------- 5371 DateComponent.prototype.isInteractionValid = function (interaction) { 5372 var dateProfile = this.props.dateProfile; // HACK 5373 var instances = interaction.mutatedEvents.instances; 5374 if (dateProfile) { // HACK for MorePopover 5375 for (var instanceId in instances) { 5376 if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) { 5377 return false; 5378 } 5379 } 5380 } 5381 return isInteractionValid(interaction, this.context); 5382 }; 5383 DateComponent.prototype.isDateSelectionValid = function (selection) { 5384 var dateProfile = this.props.dateProfile; // HACK 5385 if (dateProfile && // HACK for MorePopover 5386 !rangeContainsRange(dateProfile.validRange, selection.range)) { 5387 return false; 5388 } 5389 return isDateSelectionValid(selection, this.context); 5390 }; 5391 // Pointer Interaction Utils 5392 // ----------------------------------------------------------------------------------------------------------------- 5393 DateComponent.prototype.isValidSegDownEl = function (el) { 5394 return !this.props.eventDrag && // HACK 5395 !this.props.eventResize && // HACK 5396 !elementClosest(el, '.fc-event-mirror'); 5397 }; 5398 DateComponent.prototype.isValidDateDownEl = function (el) { 5399 return !elementClosest(el, '.fc-event:not(.fc-bg-event)') && 5400 !elementClosest(el, '.fc-daygrid-more-link') && // a "more.." link 5401 !elementClosest(el, 'a[data-navlink]') && // a clickable nav link 5402 !elementClosest(el, '.fc-popover'); // hack 5403 }; 5404 return DateComponent; 5405 }(BaseComponent)); 5406 5407 // TODO: easier way to add new hooks? need to update a million things 5408 function createPlugin(input) { 5409 return { 5410 id: guid(), 5411 deps: input.deps || [], 5412 reducers: input.reducers || [], 5413 isLoadingFuncs: input.isLoadingFuncs || [], 5414 contextInit: [].concat(input.contextInit || []), 5415 eventRefiners: input.eventRefiners || {}, 5416 eventDefMemberAdders: input.eventDefMemberAdders || [], 5417 eventSourceRefiners: input.eventSourceRefiners || {}, 5418 isDraggableTransformers: input.isDraggableTransformers || [], 5419 eventDragMutationMassagers: input.eventDragMutationMassagers || [], 5420 eventDefMutationAppliers: input.eventDefMutationAppliers || [], 5421 dateSelectionTransformers: input.dateSelectionTransformers || [], 5422 datePointTransforms: input.datePointTransforms || [], 5423 dateSpanTransforms: input.dateSpanTransforms || [], 5424 views: input.views || {}, 5425 viewPropsTransformers: input.viewPropsTransformers || [], 5426 isPropsValid: input.isPropsValid || null, 5427 externalDefTransforms: input.externalDefTransforms || [], 5428 eventResizeJoinTransforms: input.eventResizeJoinTransforms || [], 5429 viewContainerAppends: input.viewContainerAppends || [], 5430 eventDropTransformers: input.eventDropTransformers || [], 5431 componentInteractions: input.componentInteractions || [], 5432 calendarInteractions: input.calendarInteractions || [],
5433 themeClasses: input.themeClasses || {}, 5434 eventSourceDefs: input.eventSourceDefs || [], 5435 cmdFormatter: input.cmdFormatter, 5436 recurringTypes: input.recurringTypes || [], 5437 namedTimeZonedImpl: input.namedTimeZonedImpl, 5438 initialView: input.initialView || '', 5439 elementDraggingImpl: input.elementDraggingImpl, 5440 optionChangeHandlers: input.optionChangeHandlers || {}, 5441 scrollGridImpl: input.scrollGridImpl || null, 5442 contentTypeHandlers: input.contentTypeHandlers || {}, 5443 listenerRefiners: input.listenerRefiners || {}, 5444 optionRefiners: input.optionRefiners || {}, 5445 propSetHandlers: input.propSetHandlers || {}, 5446 }; 5447 } 5448 function buildPluginHooks(pluginDefs, globalDefs) { 5449 var isAdded = {}; 5450 var hooks = { 5451 reducers: [], 5452 isLoadingFuncs: [], 5453 contextInit: [], 5454 eventRefiners: {}, 5455 eventDefMemberAdders: [], 5456 eventSourceRefiners: {}, 5457 isDraggableTransformers: [], 5458 eventDragMutationMassagers: [], 5459 eventDefMutationAppliers: [], 5460 dateSelectionTransformers: [], 5461 datePointTransforms: [], 5462 dateSpanTransforms: [], 5463 views: {}, 5464 viewPropsTransformers: [], 5465 isPropsValid: null, 5466 externalDefTransforms: [], 5467 eventResizeJoinTransforms: [], 5468 viewContainerAppends: [], 5469 eventDropTransformers: [], 5470 componentInteractions: [], 5471 calendarInteractions: [], 5472 themeClasses: {}, 5473 eventSourceDefs: [], 5474 cmdFormatter: null, 5475 recurringTypes: [], 5476 namedTimeZonedImpl: null, 5477 initialView: '', 5478 elementDraggingImpl: null, 5479 optionChangeHandlers: {}, 5480 scrollGridImpl: null, 5481 contentTypeHandlers: {}, 5482 listenerRefiners: {}, 5483 optionRefiners: {}, 5484 propSetHandlers: {}, 5485 }; 5486 function addDefs(defs) { 5487 for (var _i = 0, defs_1 = defs; _i < defs_1.length; _i++) { 5488 var def = defs_1[_i]; 5489 if (!isAdded[def.id]) { 5490 isAdded[def.id] = true; 5491 addDefs(def.deps); 5492 hooks = combineHooks(hooks, def); 5493 } 5494 } 5495 } 5496 if (pluginDefs) { 5497 addDefs(pluginDefs); 5498 } 5499 addDefs(globalDefs); 5500 return hooks; 5501 } 5502 function buildBuildPluginHooks() { 5503 var currentOverrideDefs = []; 5504 var currentGlobalDefs = []; 5505 var currentHooks; 5506 return function (overrideDefs, globalDefs) { 5507 if (!currentHooks || !isArraysEqual(overrideDefs, currentOverrideDefs) || !isArraysEqual(globalDefs, currentGlobalDefs)) { 5508 currentHooks = buildPluginHooks(overrideDefs, globalDefs); 5509 } 5510 currentOverrideDefs = overrideDefs; 5511 currentGlobalDefs = globalDefs; 5512 return currentHooks; 5513 }; 5514 } 5515 function combineHooks(hooks0, hooks1) { 5516 return { 5517 reducers: hooks0.reducers.concat(hooks1.reducers), 5518 isLoadingFuncs: hooks0.isLoadingFuncs.concat(hooks1.isLoadingFuncs), 5519 contextInit: hooks0.contextInit.concat(hooks1.contextInit), 5520 eventRefiners: __assign(__assign({}, hooks0.eventRefiners), hooks1.eventRefiners), 5521 eventDefMemberAdders: hooks0.eventDefMemberAdders.concat(hooks1.eventDefMemberAdders), 5522 eventSourceRefiners: __assign(__assign({}, hooks0.eventSourceRefiners), hooks1.eventSourceRefiners), 5523 isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers), 5524 eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers), 5525 eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers), 5526 dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers), 5527 datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms), 5528 dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms), 5529 views: __assign(__assign({}, hooks0.views), hooks1.views), 5530 viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers), 5531 isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid, 5532 externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms), 5533 eventResizeJoinTransforms: hooks0.eventResizeJoinTransforms.concat(hooks1.eventResizeJoinTransforms), 5534 viewContainerAppends: hooks0.viewContainerAppends.concat(hooks1.viewContainerAppends), 5535 eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers), 5536 calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions), 5537 componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions),
5538 themeClasses: __assign(__assign({}, hooks0.themeClasses), hooks1.themeClasses), 5539 eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs), 5540 cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter, 5541 recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes), 5542 namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl, 5543 initialView: hooks0.initialView || hooks1.initialView, 5544 elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl, 5545 optionChangeHandlers: __assign(__assign({}, hooks0.optionChangeHandlers), hooks1.optionChangeHandlers), 5546 scrollGridImpl: hooks1.scrollGridImpl || hooks0.scrollGridImpl, 5547 contentTypeHandlers: __assign(__assign({}, hooks0.contentTypeHandlers), hooks1.contentTypeHandlers), 5548 listenerRefiners: __assign(__assign({}, hooks0.listenerRefiners), hooks1.listenerRefiners), 5549 optionRefiners: __assign(__assign({}, hooks0.optionRefiners), hooks1.optionRefiners), 5550 propSetHandlers: __assign(__assign({}, hooks0.propSetHandlers), hooks1.propSetHandlers), 5551 }; 5552 } 5553 5554 var StandardTheme = /** @class */ (function (_super) { 5555 __extends(StandardTheme, _super); 5556 function StandardTheme() { 5557 return _super !== null && _super.apply(this, arguments) || this; 5558 } 5559 return StandardTheme; 5560 }(Theme)); 5561 StandardTheme.prototype.classes = { 5562 root: 'fc-theme-standard', 5563 tableCellShaded: 'fc-cell-shaded', 5564 buttonGroup: 'fc-button-group', 5565 button: 'fc-button fc-button-primary', 5566 buttonActive: 'fc-button-active', 5567 }; 5568 StandardTheme.prototype.baseIconClass = 'fc-icon'; 5569 StandardTheme.prototype.iconClasses = { 5570 close: 'fc-icon-x', 5571 prev: 'fc-icon-chevron-left', 5572 next: 'fc-icon-chevron-right', 5573 prevYear: 'fc-icon-chevrons-left', 5574 nextYear: 'fc-icon-chevrons-right', 5575 }; 5576 StandardTheme.prototype.rtlIconClasses = { 5577 prev: 'fc-icon-chevron-right', 5578 next: 'fc-icon-chevron-left', 5579 prevYear: 'fc-icon-chevrons-right', 5580 nextYear: 'fc-icon-chevrons-left', 5581 }; 5582 StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; // TODO: make TS-friendly 5583 StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon'; 5584 StandardTheme.prototype.iconOverridePrefix = 'fc-icon-'; 5585 5586 function compileViewDefs(defaultConfigs, overrideConfigs) { 5587 var hash = {}; 5588 var viewType; 5589 for (viewType in defaultConfigs) { 5590 ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs); 5591 } 5592 for (viewType in overrideConfigs) { 5593 ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs); 5594 } 5595 return hash; 5596 } 5597 function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) { 5598 if (hash[viewType]) { 5599 return hash[viewType]; 5600 } 5601 var viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs); 5602 if (viewDef) { 5603 hash[viewType] = viewDef; 5604 } 5605 return viewDef; 5606 } 5607 function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) { 5608 var defaultConfig = defaultConfigs[viewType]; 5609 var overrideConfig = overrideConfigs[viewType]; 5610 var queryProp = function (name) { return ((defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] : 5611 ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null)); }; 5612 var theComponent = queryProp('component'); 5613 var superType = queryProp('superType'); 5614 var superDef = null; 5615 if (superType) { 5616 if (superType === viewType) { 5617 throw new Error('Can\'t have a custom view type that references itself'); 5618 } 5619 superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs); 5620 } 5621 if (!theComponent && superDef) { 5622 theComponent = superDef.component; 5623 } 5624 if (!theComponent) { 5625 return null; // don't throw a warning, might be settings for a single-unit view 5626 } 5627 return { 5628 type: viewType, 5629 component: theComponent, 5630 defaults: __assign(__assign({}, (superDef ? superDef.defaults : {})), (defaultConfig ? defaultConfig.rawOptions : {})), 5631 overrides: __assign(__assign({}, (superDef ? superDef.overrides : {})), (overrideConfig ? overrideConfig.rawOptions : {})), 5632 }; 5633 } 5634
5635 /* eslint max-classes-per-file: off */ 5636 // NOTE: in JSX, you should always use this class with <HookProps> arg. otherwise, will default to any??? 5637 var RenderHook = /** @class */ (function (_super) { 5638 __extends(RenderHook, _super); 5639 function RenderHook() { 5640 var _this = _super !== null && _super.apply(this, arguments) || this; 5641 _this.rootElRef = createRef(); 5642 _this.handleRootEl = function (el) { 5643 setRef(_this.rootElRef, el); 5644 if (_this.props.elRef) { 5645 setRef(_this.props.elRef, el); 5646 } 5647 }; 5648 return _this; 5649 } 5650 RenderHook.prototype.render = function () { 5651 var _this = this; 5652 var props = this.props; 5653 var hookProps = props.hookProps; 5654 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); })); })); 5655 }; 5656 return RenderHook; 5657 }(BaseComponent)); 5658 // TODO: rename to be about function, not default. use in above type 5659 // for forcing rerender of components that use the ContentHook 5660 var CustomContentRenderContext = createContext$1(0); 5661 function ContentHook(props) { 5662 return (createElement(CustomContentRenderContext.Consumer, null, function (renderId) { return (createElement(ContentHookInner, __assign({ renderId: renderId }, props))); })); 5663 } 5664 var ContentHookInner = /** @class */ (function (_super) { 5665 __extends(ContentHookInner, _super); 5666 function ContentHookInner() { 5667 var _this = _super !== null && _super.apply(this, arguments) || this; 5668 _this.innerElRef = createRef(); 5669 return _this; 5670 } 5671 ContentHookInner.prototype.render = function () { 5672 return this.props.children(this.innerElRef, this.renderInnerContent()); 5673 }; 5674 ContentHookInner.prototype.componentDidMount = function () { 5675 this.updateCustomContent(); 5676 }; 5677 ContentHookInner.prototype.componentDidUpdate = function () { 5678 this.updateCustomContent(); 5679 }; 5680 ContentHookInner.prototype.componentWillUnmount = function () { 5681 if (this.customContentInfo && this.customContentInfo.destroy) { 5682 this.customContentInfo.destroy(); 5683 } 5684 }; 5685 ContentHookInner.prototype.renderInnerContent = function () { 5686 var contentTypeHandlers = this.context.pluginHooks.contentTypeHandlers; 5687 var _a = this, props = _a.props, customContentInfo = _a.customContentInfo; 5688 var rawVal = props.content; 5689 var innerContent = normalizeContent(rawVal, props.hookProps); 5690 var innerContentVDom = null; 5691 if (innerContent === undefined) { // use the default 5692 innerContent = normalizeContent(props.defaultContent, props.hookProps); 5693 } 5694 if (innerContent !== undefined) { // we allow custom content handlers to return nothing 5695 if (customContentInfo) { 5696 customContentInfo.contentVal = innerContent[customContentInfo.contentKey]; 5697 } 5698 else if (typeof innerContent === 'object') { 5699 // look for a prop that would indicate a custom content handler is needed 5700 for (var contentKey in contentTypeHandlers) { 5701 if (innerContent[contentKey] !== undefined) { 5702 var stuff = contentTypeHandlers[contentKey](); 5703 customContentInfo = this.customContentInfo = __assign({ contentKey: contentKey, contentVal: innerContent[contentKey] }, stuff); 5704 break; 5705 } 5706 } 5707 } 5708 if (customContentInfo) { 5709 innerContentVDom = []; // signal that something was specified 5710 } 5711 else { 5712 innerContentVDom = innerContent; // assume a [p]react vdom node. use it 5713 } 5714 } 5715 return innerContentVDom; 5716 }; 5717 ContentHookInner.prototype.updateCustomContent = function () { 5718 if (this.customContentInfo) { 5719 this.customContentInfo.render(this.innerElRef.current || this.props.backupElRef.current, // the element to render into 5720 this.customContentInfo.contentVal); 5721 } 5722 }; 5723 return ContentHookInner; 5724 }(BaseComponent)); 5725 var MountHook = /** @class */ (function (_super) { 5726 __extends(MountHook, _super); 5727 function MountHook() { 5728 var _this = _super !== null && _super.apply(this, arguments) || this; 5729 _this.handleRootEl = function (rootEl) { 5730 _this.rootEl = rootEl; 5731 if (_this.props.elRef) { 5732 setRef(_this.props.elRef, rootEl); 5733 } 5734 }; 5735 return _this; 5736 } 5737 MountHook.prototype.render = function () { 5738 return this.props.children(this.handleRootEl); 5739 }; 5740 MountHook.prototype.componentDidMount = function () { 5741 var callback = this.props.didMount; 5742 if (callback) { 5743 callback(__assign(__assign({}, this.props.hookProps), { el: this.rootEl })); 5744 } 5745 }; 5746 MountHook.prototype.componentWillUnmount = function () { 5747 var callback = this.props.willUnmount; 5748 if (callback) { 5749 callback(__assign(__assign({}, this.props.hookProps), { el: this.rootEl })); 5750 } 5751 }; 5752 return MountHook; 5753 }(BaseComponent)); 5754 function buildClassNameNormalizer() { 5755 var currentGenerator; 5756 var currentHookProps; 5757 var currentClassNames = []; 5758 return function (generator, hookProps) { 5759 if (!currentHookProps || !isPropsEqual(currentHookProps, hookProps) || generator !== currentGenerator) { 5760 currentGenerator = generator; 5761 currentHookProps = hookProps; 5762 currentClassNames = normalizeClassNames(generator, hookProps); 5763 } 5764 return currentClassNames; 5765 }; 5766 } 5767 function normalizeClassNames(classNames, hookProps) { 5768 if (typeof classNames === 'function') { 5769 classNames = classNames(hookProps); 5770 } 5771 return parseClassNames(classNames); 5772 } 5773 function normalizeContent(input, hookProps) { 5774 if (typeof input === 'function') { 5775 return input(hookProps, createElement); // give the function the vdom-creation func 5776 } 5777 return input; 5778 } 5779 5780 var ViewRoot = /** @class */ (function (_super) { 5781 __extends(ViewRoot, _super); 5782 function ViewRoot() { 5783 var _this = _super !== null && _super.apply(this, arguments) || this; 5784 _this.normalizeClassNames = buildClassNameNormalizer(); 5785 return _this; 5786 } 5787 ViewRoot.prototype.render = function () { 5788 var _a = this, props = _a.props, context = _a.context; 5789 var options = context.options; 5790 var hookProps = { view: context.viewApi }; 5791 var customClassNames = this.normalizeClassNames(options.viewClassNames, hookProps); 5792 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)); })); 5793 }; 5794 return ViewRoot; 5795 }(BaseComponent)); 5796 5797 function parseViewConfigs(inputs) { 5798 return mapHash(inputs, parseViewConfig); 5799 } 5800 function parseViewConfig(input) { 5801 var rawOptions = typeof input === 'function' ? 5802 { component: input } : 5803 input; 5804 var component = rawOptions.component; 5805 if (rawOptions.content) { 5806 component = createViewHookComponent(rawOptions); 5807 // TODO: remove content/classNames/didMount/etc from options? 5808 } 5809 return { 5810 superType: rawOptions.type, 5811 component: component, 5812 rawOptions: rawOptions, 5813 }; 5814 } 5815 function createViewHookComponent(options) { 5816 return function (viewProps) { return (createElement(ViewContextType.Consumer, null, function (context) { return (createElement(ViewRoot, { viewSpec: context.viewSpec }, function (viewElRef, viewClassNames) { 5817 var hookProps = __assign(__assign({}, viewProps), { nextDayThreshold: context.options.nextDayThreshold }); 5818 return (createElement(RenderHook, { hookProps: hookProps, classNames: options.classNames, content: options.content, didMount: options.didMount, willUnmount: options.willUnmount, elRef: viewElRef }, function (rootElRef, customClassNames, innerElRef, innerContent) { return (createElement("div", { className: viewClassNames.c
5818oncat(customClassNames).join(' '), ref: rootElRef }, innerContent)); })); 5819 })); })); }; 5820 } 5821 5822 function buildViewSpecs(defaultInputs, optionOverrides, dynamicOptionOverrides, localeDefaults) { 5823 var defaultConfigs = parseViewConfigs(defaultInputs); 5824 var overrideConfigs = parseViewConfigs(optionOverrides.views); 5825 var viewDefs = compileViewDefs(defaultConfigs, overrideConfigs); 5826 return mapHash(viewDefs, function (viewDef) { return buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults); }); 5827 } 5828 function buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults) { 5829 var durationInput = viewDef.overrides.duration || 5830 viewDef.defaults.duration || 5831 dynamicOptionOverrides.duration || 5832 optionOverrides.duration; 5833 var duration = null; 5834 var durationUnit = ''; 5835 var singleUnit = ''; 5836 var singleUnitOverrides = {}; 5837 if (durationInput) { 5838 duration = createDurationCached(durationInput); 5839 if (duration) { // valid? 5840 var denom = greatestDurationDenominator(duration); 5841 durationUnit = denom.unit; 5842 if (denom.value === 1) { 5843 singleUnit = durationUnit; 5844 singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].rawOptions : {}; 5845 } 5846 } 5847 } 5848 var queryButtonText = function (optionsSubset) { 5849 var buttonTextMap = optionsSubset.buttonText || {}; 5850 var buttonTextKey = viewDef.defaults.buttonTextKey; 5851 if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) { 5852 return buttonTextMap[buttonTextKey]; 5853 } 5854 if (buttonTextMap[viewDef.type] != null) { 5855 return buttonTextMap[viewDef.type]; 5856 } 5857 if (buttonTextMap[singleUnit] != null) { 5858 return buttonTextMap[singleUnit]; 5859 } 5860 return null; 5861 }; 5862 return { 5863 type: viewDef.type, 5864 component: viewDef.component, 5865 duration: duration, 5866 durationUnit: durationUnit, 5867 singleUnit: singleUnit, 5868 optionDefaults: viewDef.defaults, 5869 optionOverrides: __assign(__assign({}, singleUnitOverrides), viewDef.overrides), 5870 buttonTextOverride: queryButtonText(dynamicOptionOverrides) || 5871 queryButtonText(optionOverrides) || // constructor-specified buttonText lookup hash takes precedence 5872 viewDef.overrides.buttonText, 5873 buttonTextDefault: queryButtonText(localeDefaults) || 5874 viewDef.defaults.buttonText || 5875 queryButtonText(BASE_OPTION_DEFAULTS) || 5876 viewDef.type, 5877 }; 5878 } 5879 // hack to get memoization working 5880 var durationInputMap = {}; 5881 function createDurationCached(durationInput) { 5882 var json = JSON.stringify(durationInput); 5883 var res = durationInputMap[json]; 5884 if (res === undefined) { 5885 res = createDuration(durationInput); 5886 durationInputMap[json] = res; 5887 } 5888 return res; 5889 } 5890 5891 var DateProfileGenerator = /** @class */ (function () { 5892 function DateProfileGenerator(props) { 5893 this.props = props; 5894 this.nowDate = getNow(props.nowInput, props.dateEnv); 5895 this.initHiddenDays(); 5896 } 5897 /* Date Range Computation 5898 ------------------------------------------------------------------------------------------------------------------*/ 5899 // Builds a structure with info about what the dates/ranges will be for the "prev" view. 5900 DateProfileGenerator.prototype.buildPrev = function (currentDateProfile, currentDate, forceToValid) { 5901 var dateEnv = this.props.dateEnv; 5902 var prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month 5903 currentDateProfile.dateIncrement); 5904 return this.build(prevDate, -1, forceToValid); 5905 }; 5906 // Builds a structure with info about what the dates/ranges will be for the "next" view. 5907 DateProfileGenerator.prototype.buildNext = function (currentDateProfile, currentDate, forceToValid) { 5908 var dateEnv = this.props.dateEnv; 5909 var nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month 5910 currentDateProfile.dateIncrement); 5911 return this.build(nextDate, 1, forceToValid); 5912 }; 5913 // Builds a structure holding dates/ranges for rendering around the given date. 5914 // Optional direction param indicates whether the date is being incremented/decremented 5915 // from its previous value. decremented = -1, incremented = 1 (default). 5916 DateProfileGenerator.prototype.build = function (currentDate, direction, forceToValid) { 5917 if (forceToValid === void 0) { forceToValid = true; } 5918 var props = this.props;
5919 var validRange; 5920 var currentInfo; 5921 var isRangeAllDay; 5922 var renderRange; 5923 var activeRange; 5924 var isValid; 5925 validRange = this.buildValidRange(); 5926 validRange = this.trimHiddenDays(validRange); 5927 if (forceToValid) { 5928 currentDate = constrainMarkerToRange(currentDate, validRange); 5929 } 5930 currentInfo = this.buildCurrentRangeInfo(currentDate, direction); 5931 isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit); 5932 renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay); 5933 renderRange = this.trimHiddenDays(renderRange); 5934 activeRange = renderRange; 5935 if (!props.showNonCurrentDates) { 5936 activeRange = intersectRanges(activeRange, currentInfo.range); 5937 } 5938 activeRange = this.adjustActiveRange(activeRange); 5939 activeRange = intersectRanges(activeRange, validRange); // might return null 5940 // it's invalid if the originally requested date is not contained, 5941 // or if the range is completely outside of the valid range. 5942 isValid = rangesIntersect(currentInfo.range, validRange); 5943 return { 5944 // constraint for where prev/next operations can go and where events can be dragged/resized to. 5945 // an object with optional start and end properties. 5946 validRange: validRange, 5947 // range the view is formally responsible for. 5948 // for example, a month view might have 1st-31st, excluding padded dates 5949 currentRange: currentInfo.range, 5950 // name of largest unit being displayed, like "month" or "week" 5951 currentRangeUnit: currentInfo.unit, 5952 isRangeAllDay: isRangeAllDay, 5953 // dates that display events and accept drag-n-drop 5954 // will be `null` if no dates accept events 5955 activeRange: activeRange, 5956 // date range with a rendered skeleton 5957 // includes not-active days that need some sort of DOM 5958 renderRange: renderRange, 5959 // Duration object that denotes the first visible time of any given day 5960 slotMinTime: props.slotMinTime, 5961 // Duration object that denotes the exclusive visible end time of any given day 5962 slotMaxTime: props.slotMaxTime, 5963 isValid: isValid, 5964 // how far the current date will move for a prev/next operation 5965 dateIncrement: this.buildDateIncrement(currentInfo.duration), 5966 }; 5967 }; 5968 // Builds an object with optional start/end properties. 5969 // Indicates the minimum/maximum dates to display. 5970 // not responsible for trimming hidden days. 5971 DateProfileGenerator.prototype.buildValidRange = function () { 5972 var input = this.props.validRangeInput; 5973 var simpleInput = typeof input === 'function' 5974 ? input.call(this.props.calendarApi, this.nowDate) 5975 : input; 5976 return this.refineRange(simpleInput) || 5977 { start: null, end: null }; // completely open-ended 5978 }; 5979 // Builds a structure with info about the "current" range, the range that is 5980 // highlighted as being the current month for example. 5981 // See build() for a description of `direction`. 5982 // Guaranteed to have `range` and `unit` properties. `duration` is optional. 5983 DateProfileGenerator.prototype.buildCurrentRangeInfo = function (date, direction) { 5984 var props = this.props; 5985 var duration = null; 5986 var unit = null; 5987 var range = null; 5988 var dayCount; 5989 if (props.duration) { 5990 duration = props.duration; 5991 unit = props.durationUnit; 5992 range = this.buildRangeFromDuration(date, direction, duration, unit); 5993 } 5994 else if ((dayCount = this.props.dayCount)) { 5995 unit = 'day'; 5996 range = this.buildRangeFromDayCount(date, direction, dayCount); 5997 } 5998 else if ((range = this.buildCustomVisibleRange(date))) { 5999 unit = props.dateEnv.greatestWholeUnit(range.start, range.end).unit; 6000 } 6001 else { 6002 duration = this.getFallbackDuration(); 6003 unit = greatestDurationDenominator(duration).unit; 6004 range = this.buildRangeFromDuration(date, direction, duration, unit); 6005 } 6006 return { duration: duration, unit: unit, range: range }; 6007 }; 6008 DateProfileGenerator.prototype.getFallbackDuration = function () { 6009 return createDuration({ day: 1 }); 6010 }; 6011 // Returns a new activeRange to have time values (un-ambiguate) 6012 // slotMinTime or slotMaxTime causes the range to expand. 6013 DateProfileGenerator.prototype.adjustActiveRange = function (range) { 6014 var _a = this.props, dateEnv = _a.dateEnv, usesMinMaxTime = _a.usesMinMaxTime, slotMinTime = _a.slotMinTime, slotMaxTime = _a.slotMaxTime; 6015 var start = range.start, end = range.end; 6016 if (usesMinMaxTime) { 6017 // expand active range if slotMinTime is negative (why not when positive?) 6018 if (asRoughDays(slotMinTime) < 0) { 6019 start = startOfDay(start); // necessary? 6020 start = dateEnv.add(start, slotMinTime); 6021 } 6022 // expand active range if slotMaxTime is beyond one day (why not when negative?) 6023 if (asRoughDays(slotMaxTime) > 1) { 6024 end = startOfDay(end); // necessary? 6025 end = addDays(end, -1); 6026 end = dateEnv.add(end, slotMaxTime); 6027 } 6028 } 6029 return { start: start, end: end }; 6030 }; 6031 // Builds the "current" range when it is specified as an explicit duration. 6032 // `unit` is the already-computed greatestDurationDenominator unit of duration. 6033 DateProfileGenerator.prototype.buildRangeFromDuration = function (date, direction, duration, unit) { 6034 var _a = this.props, dateEnv = _a.dateEnv, dateAlignment = _a.dateAlignment; 6035 var start; 6036 var end; 6037 var res; 6038 // compute what the alignment should be 6039 if (!dateAlignment) { 6040 var dateIncrement = this.props.dateIncrement; 6041 if (dateIncrement) { 6042 // use the smaller of the two units 6043 if (asRoughMs(dateIncrement) < asRoughMs(duration)) { 6044 dateAlignment = greatestDurationDenominator(dateIncrement).unit; 6045 } 6046 else { 6047 dateAlignment = unit; 6048 } 6049 } 6050 else { 6051 dateAlignment = unit; 6052 } 6053 }
6054 // if the view displays a single day or smaller 6055 if (asRoughDays(duration) <= 1) { 6056 if (this.isHiddenDay(start)) { 6057 start = this.skipHiddenDays(start, direction); 6058 start = startOfDay(start); 6059 } 6060 } 6061 function computeRes() { 6062 start = dateEnv.startOf(date, dateAlignment); 6063 end = dateEnv.add(start, duration); 6064 res = { start: start, end: end }; 6065 } 6066 computeRes(); 6067 // if range is completely enveloped by hidden days, go past the hidden days 6068 if (!this.trimHiddenDays(res)) { 6069 date = this.skipHiddenDays(date, direction); 6070 computeRes(); 6071 } 6072 return res; 6073 }; 6074 // Builds the "current" range when a dayCount is specified. 6075 DateProfileGenerator.prototype.buildRangeFromDayCount = function (date, direction, dayCount) { 6076 var _a = this.props, dateEnv = _a.dateEnv, dateAlignment = _a.dateAlignment; 6077 var runningCount = 0; 6078 var start = date; 6079 var end; 6080 if (dateAlignment) { 6081 start = dateEnv.startOf(start, dateAlignment); 6082 } 6083 start = startOfDay(start); 6084 start = this.skipHiddenDays(start, direction); 6085 end = start; 6086 do { 6087 end = addDays(end, 1); 6088 if (!this.isHiddenDay(end)) { 6089 runningCount += 1; 6090 } 6091 } while (runningCount < dayCount); 6092 return { start: start, end: end }; 6093 }; 6094 // Builds a normalized range object for the "visible" range, 6095 // which is a way to define the currentRange and activeRange at the same time. 6096 DateProfileGenerator.prototype.buildCustomVisibleRange = function (date) { 6097 var props = this.props; 6098 var input = props.visibleRangeInput; 6099 var simpleInput = typeof input === 'function' 6100 ? input.call(props.calendarApi, props.dateEnv.toDate(date)) 6101 : input; 6102 var range = this.refineRange(simpleInput); 6103 if (range && (range.start == null || range.end == null)) { 6104 return null; 6105 } 6106 return range; 6107 }; 6108 // Computes the range that will represent the element/cells for *rendering*, 6109 // but which may have voided days/times. 6110 // not responsible for trimming hidden days. 6111 DateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) { 6112 return currentRange; 6113 }; 6114 // Compute the duration value that should be added/substracted to the current date 6115 // when a prev/next operation happens. 6116 DateProfileGenerator.prototype.buildDateIncrement = function (fallback) { 6117 var dateIncrement = this.props.dateIncrement; 6118 var customAlignment; 6119 if (dateIncrement) { 6120 return dateIncrement; 6121 } 6122 if ((customAlignment = this.props.dateAlignment)) { 6123 return createDuration(1, customAlignment); 6124 } 6125 if (fallback) { 6126 return fallback; 6127 } 6128 return createDuration({ days: 1 }); 6129 }; 6130 DateProfileGenerator.prototype.refineRange = function (rangeInput) { 6131 if (rangeInput) { 6132 var range = parseRange(rangeInput, this.props.dateEnv); 6133 if (range) { 6134 range = computeVisibleDayRange(range); 6135 } 6136 return range; 6137 } 6138 return null; 6139 }; 6140 /* Hidden Days 6141 ------------------------------------------------------------------------------------------------------------------*/ 6142 // Initializes internal variables related to calculating hidden days-of-week 6143 DateProfileGenerator.prototype.initHiddenDays = function () { 6144 var hiddenDays = this.props.hiddenDays || []; // array of day-of-week indices that are hidden
6145 var isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool) 6146 var dayCnt = 0; 6147 var i; 6148 if (this.props.weekends === false) { 6149 hiddenDays.push(0, 6); // 0=sunday, 6=saturday 6150 } 6151 for (i = 0; i < 7; i += 1) { 6152 if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) { 6153 dayCnt += 1; 6154 } 6155 } 6156 if (!dayCnt) { 6157 throw new Error('invalid hiddenDays'); // all days were hidden? bad. 6158 } 6159 this.isHiddenDayHash = isHiddenDayHash; 6160 }; 6161 // Remove days from the beginning and end of the range that are computed as hidden. 6162 // If the whole range is trimmed off, returns null 6163 DateProfileGenerator.prototype.trimHiddenDays = function (range) { 6164 var start = range.start, end = range.end; 6165 if (start) { 6166 start = this.skipHiddenDays(start); 6167 } 6168 if (end) { 6169 end = this.skipHiddenDays(end, -1, true); 6170 } 6171 if (start == null || end == null || start < end) { 6172 return { start: start, end: end }; 6173 } 6174 return null; 6175 }; 6176 // Is the current day hidden? 6177 // `day` is a day-of-week index (0-6), or a Date (used for UTC) 6178 DateProfileGenerator.prototype.isHiddenDay = function (day) { 6179 if (day instanceof Date) { 6180 day = day.getUTCDay(); 6181 } 6182 return this.isHiddenDayHash[day]; 6183 }; 6184 // Incrementing the current day until it is no longer a hidden day, returning a copy. 6185 // DOES NOT CONSIDER validRange! 6186 // If the initial value of `date` is not a hidden day, don't do anything. 6187 // Pass `isExclusive` as `true` if you are dealing with an end date. 6188 // `inc` defaults to `1` (increment one day forward each time) 6189 DateProfileGenerator.prototype.skipHiddenDays = function (date, inc, isExclusive) { 6190 if (inc === void 0) { inc = 1; } 6191 if (isExclusive === void 0) { isExclusive = false; } 6192 while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) { 6193 date = addDays(date, inc); 6194 } 6195 return date; 6196 }; 6197 return DateProfileGenerator; 6198 }()); 6199 6200 function reduceViewType(viewType, action) { 6201 switch (action.type) { 6202 case 'CHANGE_VIEW_TYPE': 6203 viewType = action.viewType; 6204 } 6205 return viewType; 6206 } 6207 6208 function reduceDynamicOptionOverrides(dynamicOptionOverrides, action) { 6209 var _a; 6210 switch (action.type) { 6211 case 'SET_OPTION': 6212 return __assign(__assign({}, dynamicOptionOverrides), (_a = {}, _a[action.optionName] = action.rawOptionValue, _a)); 6213 default: 6214 return dynamicOptionOverrides; 6215 } 6216 } 6217 6218 function reduceDateProfile(currentDateProfile, action, currentDate, dateProfileGenerator) { 6219 var dp; 6220 switch (action.type) { 6221 case 'CHANGE_VIEW_TYPE': 6222 return dateProfileGenerator.build(action.dateMarker || currentDate); 6223 case 'CHANGE_DATE': 6224 if (!currentDateProfile.activeRange || 6225 !rangeContainsMarker(currentDateProfile.currentRange, action.dateMarker) // don't move if date already in view 6226 ) { 6227 return dateProfileGenerator.build(action.dateMarker); 6228 } 6229 break; 6230 case 'PREV': 6231 dp = dateProfileGenerator.buildPrev(currentDateProfile, currentDate); 6232 if (dp.isValid) { 6233 return dp; 6234 } 6235 break; 6236 case 'NEXT': 6237 dp = dateProfileGenerator.buildNext(currentDateProfile, currentDate); 6238 if (dp.isValid) { 6239 return dp; 6240 } 6241 break; 6242 } 6243 return currentDateProfile; 6244 } 6245 6246 function initEventSources(calendarOptions, dateProfile, context) { 6247 var activeRange = dateProfile ? dateProfile.activeRange : null; 6248 return addSources({}, parseInitialSources(calendarOptions, context), activeRange, context); 6249 } 6250 function reduceEventSources(eventSources, action, dateProfile, context) { 6251 var activeRange = dateProfile ? dateProfile.activeRange : null; // need this check? 6252 switch (action.type) { 6253 case 'ADD_EVENT_SOURCES': // already parsed 6254 return addSources(eventSources, action.sources, activeRange, context);
6255 case 'REMOVE_EVENT_SOURCE': 6256 return removeSource(eventSources, action.sourceId); 6257 case 'PREV': // TODO: how do we track all actions that affect dateProfile :( 6258 case 'NEXT': 6259 case 'CHANGE_DATE': 6260 case 'CHANGE_VIEW_TYPE': 6261 if (dateProfile) { 6262 return fetchDirtySources(eventSources, activeRange, context); 6263 } 6264 return eventSources; 6265 case 'FETCH_EVENT_SOURCES': 6266 return fetchSourcesByIds(eventSources, action.sourceIds ? // why no type? 6267 arrayToHash(action.sourceIds) : 6268 excludeStaticSources(eventSources, context), activeRange, context); 6269 case 'RECEIVE_EVENTS': 6270 case 'RECEIVE_EVENT_ERROR': 6271 return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange); 6272 case 'REMOVE_ALL_EVENT_SOURCES': 6273 return {}; 6274 default: 6275 return eventSources; 6276 } 6277 } 6278 function reduceEventSourcesNewTimeZone(eventSources, dateProfile, context) { 6279 var activeRange = dateProfile ? dateProfile.activeRange : null; // need this check? 6280 return fetchSourcesByIds(eventSources, excludeStaticSources(eventSources, context), activeRange, context); 6281 } 6282 function computeEventSourcesLoading(eventSources) { 6283 for (var sourceId in eventSources) { 6284 if (eventSources[sourceId].isFetching) { 6285 return true; 6286 } 6287 } 6288 return false; 6289 } 6290 function addSources(eventSourceHash, sources, fetchRange, context) { 6291 var hash = {}; 6292 for (var _i = 0, sources_1 = sources; _i < sources_1.length; _i++) { 6293 var source = sources_1[_i]; 6294 hash[source.sourceId] = source; 6295 } 6296 if (fetchRange) { 6297 hash = fetchDirtySources(hash, fetchRange, context); 6298 } 6299 return __assign(__assign({}, eventSourceHash), hash); 6300 } 6301 function removeSource(eventSourceHash, sourceId) { 6302 return filterHash(eventSourceHash, function (eventSource) { return eventSource.sourceId !== sourceId; }); 6303 } 6304 function fetchDirtySources(sourceHash, fetchRange, context) { 6305 return fetchSourcesByIds(sourceHash, filterHash(sourceHash, function (eventSource) { return isSourceDirty(eventSource, fetchRange, context); }), fetchRange, context); 6306 } 6307 function isSourceDirty(eventSource, fetchRange, context) { 6308 if (!doesSourceNeedRange(eventSource, context)) { 6309 return !eventSource.latestFetchId; 6310 } 6311 return !context.options.lazyFetching || 6312 !eventSource.fetchRange || 6313 eventSource.isFetching || // always cancel outdated in-progress fetches 6314 fetchRange.start < eventSource.fetchRange.start || 6315 fetchRange.end > eventSource.fetchRange.end; 6316 } 6317 function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, context) { 6318 var nextSources = {}; 6319 for (var sourceId in prevSources) { 6320 var source = prevSources[sourceId]; 6321 if (sourceIdHash[sourceId]) { 6322 nextSources[sourceId] = fetchSource(source, fetchRange, context); 6323 } 6324 else { 6325 nextSources[sourceId] = source; 6326 } 6327 } 6328 return nextSources; 6329 } 6330 function fetchSource(eventSource, fetchRange, context) { 6331 var options = context.options, calendarApi = context.calendarApi; 6332 var sourceDef = context.pluginHooks.eventSourceDefs[eventSource.sourceDefId]; 6333 var fetchId = guid(); 6334 sourceDef.fetch({ 6335 eventSource: eventSource, 6336 range: fetchRange, 6337 context: context, 6338 }, function (res) { 6339 var rawEvents = res.rawEvents; 6340 if (options.eventSourceSuccess) { 6341 rawEvents = options.eventSourceSuccess.call(calendarApi, rawEvents, res.xhr) || rawEvents; 6342 } 6343 if (eventSource.success) { 6344 rawEvents = eventSource.success.call(calendarApi, rawEvents, res.xhr) || rawEvents; 6345 } 6346 context.dispatch({ 6347 type: 'RECEIVE_EVENTS', 6348 sourceId: eventSource.sourceId, 6349 fetchId: fetchId, 6350 fetchRange: fetchRange, 6351 rawEvents: rawEvents, 6352 }); 6353 }, function (error) { 6354 console.warn(error.message, error); 6355 if (options.eventSourceFailure) { 6356 options.eventSourceFailure.call(calendarApi, error); 6357 } 6358 if (eventSource.failure) { 6359 eventSource.failure(error); 6360 } 6361 context.dispatch({ 6362 type: 'RECEIVE_EVENT_ERROR', 6363 sourceId: eventSource.sourceId, 6364 fetchId: fetchId, 6365 fetchRange: fetchRange, 6366 error: error, 6367 }); 6368 }); 6369 return __assign(__assign({}, eventSource), { isFetching: true, latestFetchId: fetchId }); 6370 } 6371 function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) { 6372 var _a; 6373 var eventSource = sourceHash[sourceId]; 6374 if (eventSource && // not already removed 6375 fetchId === eventSource.latestFetchId) { 6376 return __assign(__assign({}, sourceHash), (_a = {}, _a[sourceId] = __assign(__assign({}, eventSource), { isFetching: false, fetchRange: fetchRange }), _a)); 6377 } 6378 return sourceHash; 6379 } 6380 function excludeStaticSources(eventSources, context) { 6381 return filterHash(eventSources, function (eventSource) { return doesSourceNeedRange(eventSource, context); }); 6382 } 6383 function parseInitialSources(rawOptions, context) { 6384 var refiners = buildEventSourceRefiners(context); 6385 var rawSources = [].concat(rawOptions.eventSources || []); 6386 var sources = []; // parsed 6387 if (rawOptions.initialEvents) { 6388 rawSources.unshift(rawOptions.initialEvents); 6389 } 6390 if (rawOptions.events) { 6391 rawSources.unshift(rawOptions.events); 6392 } 6393 for (var _i = 0, rawSources_1 = rawSources; _i < rawSources_1.length; _i++) { 6394 var rawSource = rawSources_1[_i]; 6395 var source = parseEventSource(rawSource, context, refiners); 6396 if (source) { 6397 sources.push(source); 6398 } 6399 } 6400 return sources; 6401 } 6402 function doesSourceNeedRange(eventSource, context) { 6403 var defs = context.pluginHooks.eventSourceDefs; 6404 return !defs[eventSource.sourceDefId].ignoreRange; 6405 } 6406 6407 function reduceDateSelection(currentSelection, action) { 6408 switch (action.type) { 6409 case 'UNSELECT_DATES': 6410 return null; 6411 case 'SELECT_DATES': 6412 return action.selection; 6413 default: 6414 return currentSelection; 6415 } 6416 } 6417 6418 function reduceSelectedEvent(currentInstanceId, action) { 6419 switch (action.type) { 6420 case 'UNSELECT_EVENT': 6421 return ''; 6422 case 'SELECT_EVENT': 6423 return action.eventInstanceId; 6424 default: 6425 return currentInstanceId; 6426 } 6427 } 6428 6429 function reduceEventDrag(currentDrag, action) { 6430 var newDrag; 6431 switch (action.type) { 6432 case 'UNSET_EVENT_DRAG': 6433 return null; 6434 case 'SET_EVENT_DRAG': 6435 newDrag = action.state; 6436 return { 6437 affectedEvents: newDrag.affectedEvents, 6438 mutatedEvents: newDrag.mutatedEvents, 6439 isEvent: newDrag.isEvent, 6440 }; 6441 default: 6442 return currentDrag; 6443 } 6444 } 6445 6446 function reduceEventResize(currentResize, action) { 6447 var newResize; 6448 switch (action.type) { 6449 case 'UNSET_EVENT_RESIZE': 6450 return null; 6451 case 'SET_EVENT_RESIZE': 6452 newResize = action.state; 6453 return { 6454 affectedEvents: newResize.affectedEvents, 6455 mutatedEvents: newResize.mutatedEvents, 6456 isEvent: newResize.isEvent, 6457 }; 6458 default: 6459 return currentResize; 6460 } 6461 } 6462 6463 function parseToolbars(calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) { 6464 var viewsWithButtons = []; 6465 var headerToolbar = calendarOptions.headerToolbar ? parseToolbar(calendarOptions.headerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons) : null; 6466 var footerToolbar = calendarOptions.footerToolbar ? parseToolbar(calendarOptions.footerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons) : null; 6467 return { headerToolbar: headerToolbar, footerToolbar: footerToolbar, viewsWithButtons: viewsWithButtons }; 6468 } 6469 function parseToolbar(sectionStrHash, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons) { 6470 return mapHash(sectionStrHash, function (sectionStr) { return parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons); }); 6471 } 6472 /* 6473 BAD: querying icons and text here. should be done at render time 6474 */ 6475 function parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons) { 6476 var isRtl = calendarOptions.direction === 'rtl'; 6477 var calendarCustomButtons = calendarOptions.customButtons || {}; 6478 var calendarButtonTextOverrides = calendarOptionOverrides.buttonText || {}; 6479 var calendarButtonText = calendarOptions.buttonText || {}; 6480 var sectionSubstrs = sectionStr ? sectionStr.split(' ') : []; 6481 return sectionSubstrs.map(function (buttonGroupStr) { return (buttonGroupStr.split(',').map(function (buttonName) { 6482 if (buttonName === 'title') { 6483 return { buttonName: buttonName }; 6484 } 6485 var customButtonProps; 6486 var viewSpec; 6487 var buttonClick; 6488 var buttonIcon; // only one of these will be set 6489 var buttonText; // " 6490 if ((customButtonProps = calendarCustomButtons[buttonName])) { 6491 buttonClick = function (ev) { 6492 if (customButtonProps.click) { 6493 customButtonProps.click.call(ev.target, ev, ev.target); 6494 } 6495 }; 6496 (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) || 6497 (buttonIcon = theme.getIconClass(buttonName, isRtl)) || 6498 (buttonText = customButtonProps.text); 6499 } 6500 else if ((viewSpec = viewSpecs[buttonName])) { 6501 viewsWithButtons.push(buttonName); 6502 buttonClick = function () { 6503 calendarApi.changeView(buttonName); 6504 }; 6505 (buttonText = viewSpec.buttonTextOverride) || 6506 (buttonIcon = theme.getIconClass(buttonName, isRtl)) || 6507 (buttonText = viewSpec.buttonTextDefault); 6508 } 6509 else if (calendarApi[buttonName]) { // a calendarApi method 6510 buttonClick = function () { 6511 calendarApi[buttonName](); 6512 }; 6513 (buttonText = calendarButtonTextOverrides[buttonName]) || 6514 (buttonIcon = theme.getIconClass(buttonName, isRtl)) || 6515 (buttonText = calendarButtonText[buttonName]); 6516 // ^ everything else is considered default 6517 } 6518 return { buttonName: buttonName, buttonClick: buttonClick, buttonIcon: buttonIcon, buttonText: buttonText }; 6519 })); }); 6520 } 6521 6522 var eventSourceDef = { 6523 ignoreRange: true, 6524 parseMeta: function (refined) { 6525 if (Array.isArray(refined.events)) { 6526 return refined.events; 6527 } 6528 return null; 6529 }, 6530 fetch: function (arg, success) { 6531 success({ 6532 rawEvents: arg.eventSource.meta, 6533 }); 6534 }, 6535 }; 6536 var arrayEventSourcePlugin = createPlugin({ 6537 eventSourceDefs: [eventSourceDef], 6538 }); 6539 6540 var eventSourceDef$1 = { 6541 parseMeta: function (refined) { 6542 if (typeof refined.events === 'function') { 6543 return refined.events; 6544 } 6545 return null; 6546 }, 6547 fetch: function (arg, success, failure) { 6548 var dateEnv = arg.context.dateEnv; 6549 var func = arg.eventSource.meta; 6550 unpromisify(func.bind(null, buildRangeApiWithTimeZone(arg.range, dateEnv)), function (rawEvents) { 6551 success({ rawEvents: rawEvents }); // needs an object response 6552 }, failure); 6553 }, 6554 }; 6555 var funcEventSourcePlugin = createPlugin({ 6556 eventSourceDefs: [eventSourceDef$1], 6557 }); 6558 6559 function requestJson(method, url, params, successCallback, failureCallback) { 6560 method = method.toUpperCase(); 6561 var body = null; 6562 if (method === 'GET') { 6563 url = injectQueryStringParams(url, params); 6564 } 6565 else { 6566 body = encodeParams(params); 6567 } 6568 var xhr = new XMLHttpRequest(); 6569 xhr.open(method, url, true); 6570 if (method !== 'GET') { 6571 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 6572 } 6573 xhr.onload = function () { 6574 if (xhr.status >= 200 && xhr.status < 400) { 6575 var parsed = false;
6576 var res = void 0; 6577 try { 6578 res = JSON.parse(xhr.responseText); 6579 parsed = true; 6580 } 6581 catch (err) { 6582 // will handle parsed=false 6583 } 6584 if (parsed) { 6585 successCallback(res, xhr); 6586 } 6587 else { 6588 failureCallback('Failure parsing JSON', xhr); 6589 } 6590 } 6591 else { 6592 failureCallback('Request failed', xhr); 6593 } 6594 }; 6595 xhr.onerror = function () { 6596 failureCallback('Request failed', xhr); 6597 }; 6598 xhr.send(body); 6599 } 6600 function injectQueryStringParams(url, params) { 6601 return url + 6602 (url.indexOf('?') === -1 ? '?' : '&') + 6603 encodeParams(params); 6604 } 6605 function encodeParams(params) { 6606 var parts = []; 6607 for (var key in params) { 6608 parts.push(encodeURIComponent(key) + "=" + encodeURIComponent(params[key])); 6609 } 6610 return parts.join('&'); 6611 } 6612 6613 var JSON_FEED_EVENT_SOURCE_REFINERS = { 6614 method: String, 6615 extraParams: identity, 6616 startParam: String, 6617 endParam: String, 6618 timeZoneParam: String, 6619 }; 6620 6621 var eventSourceDef$2 = { 6622 parseMeta: function (refined) { 6623 if (refined.url && (refined.format === 'json' || !refined.format)) { 6624 return { 6625 url: refined.url, 6626 format: 'json', 6627 method: (refined.method || 'GET').toUpperCase(), 6628 extraParams: refined.extraParams, 6629 startParam: refined.startParam, 6630 endParam: refined.endParam, 6631 timeZoneParam: refined.timeZoneParam, 6632 }; 6633 } 6634 return null; 6635 }, 6636 fetch: function (arg, success, failure) { 6637 var meta = arg.eventSource.meta; 6638 var requestParams = buildRequestParams(meta, arg.range, arg.context); 6639 requestJson(meta.method, meta.url, requestParams, function (rawEvents, xhr) { 6640 success({ rawEvents: rawEvents, xhr: xhr }); 6641 }, function (errorMessage, xhr) { 6642 failure({ message: errorMessage, xhr: xhr }); 6643 }); 6644 }, 6645 }; 6646 var jsonFeedEventSourcePlugin = createPlugin({ 6647 eventSourceRefiners: JSON_FEED_EVENT_SOURCE_REFINERS, 6648 eventSourceDefs: [eventSourceDef$2], 6649 }); 6650 function buildRequestParams(meta, range, context) { 6651 var dateEnv = context.dateEnv, options = context.options; 6652 var startParam; 6653 var endParam; 6654 var timeZoneParam;
6655 var customRequestParams; 6656 var params = {}; 6657 startParam = meta.startParam; 6658 if (startParam == null) { 6659 startParam = options.startParam; 6660 } 6661 endParam = meta.endParam; 6662 if (endParam == null) { 6663 endParam = options.endParam; 6664 } 6665 timeZoneParam = meta.timeZoneParam; 6666 if (timeZoneParam == null) { 6667 timeZoneParam = options.timeZoneParam; 6668 } 6669 // retrieve any outbound GET/POST data from the options 6670 if (typeof meta.extraParams === 'function') { 6671 // supplied as a function that returns a key/value object 6672 customRequestParams = meta.extraParams(); 6673 } 6674 else { 6675 // probably supplied as a straight key/value object 6676 customRequestParams = meta.extraParams || {}; 6677 } 6678 __assign(params, customRequestParams); 6679 params[startParam] = dateEnv.formatIso(range.start); 6680 params[endParam] = dateEnv.formatIso(range.end); 6681 if (dateEnv.timeZone !== 'local') { 6682 params[timeZoneParam] = dateEnv.timeZone; 6683 } 6684 return params; 6685 } 6686 6687 var SIMPLE_RECURRING_REFINERS = { 6688 daysOfWeek: identity, 6689 startTime: createDuration, 6690 endTime: createDuration, 6691 duration: createDuration, 6692 startRecur: identity, 6693 endRecur: identity, 6694 }; 6695 6696 var recurring = { 6697 parse: function (refined, dateEnv) { 6698 if (refined.daysOfWeek || refined.startTime || refined.endTime || refined.startRecur || refined.endRecur) { 6699 var recurringData = { 6700 daysOfWeek: refined.daysOfWeek || null, 6701 startTime: refined.startTime || null, 6702 endTime: refined.endTime || null, 6703 startRecur: refined.startRecur ? dateEnv.createMarker(refined.startRecur) : null, 6704 endRecur: refined.endRecur ? dateEnv.createMarker(refined.endRecur) : null, 6705 }; 6706 var duration = void 0; 6707 if (refined.duration) { 6708 duration = refined.duration; 6709 } 6710 if (!duration && refined.startTime && refined.endTime) { 6711 duration = subtractDurations(refined.endTime, refined.startTime); 6712 } 6713 return { 6714 allDayGuess: Boolean(!refined.startTime && !refined.endTime), 6715 duration: duration, 6716 typeData: recurringData, 6717 }; 6718 } 6719 return null; 6720 }, 6721 expand: function (typeData, framingRange, dateEnv) { 6722 var clippedFramingRange = intersectRanges(framingRange, { start: typeData.startRecur, end: typeData.endRecur }); 6723 if (clippedFramingRange) { 6724 return expandRanges(typeData.daysOfWeek, typeData.startTime, clippedFramingRange, dateEnv); 6725 } 6726 return []; 6727 }, 6728 }; 6729 var simpleRecurringEventsPlugin = createPlugin({ 6730 recurringTypes: [recurring], 6731 eventRefiners: SIMPLE_RECURRING_REFINERS, 6732 }); 6733 function expandRanges(daysOfWeek, startTime, framingRange, dateEnv) { 6734 var dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null; 6735 var dayMarker = startOfDay(framingRange.start); 6736 var endMarker = framingRange.end; 6737 var instanceStarts = []; 6738 while (dayMarker < endMarker) { 6739 var instanceStart 6740 // if everyday, or this particular day-of-week 6741 = void 0; 6742 // if everyday, or this particular day-of-week 6743 if (!dowHash || dowHash[dayMarker.getUTCDay()]) { 6744 if (startTime) { 6745 instanceStart = dateEnv.add(dayMarker, startTime); 6746 } 6747 else { 6748 instanceStart = dayMarker; 6749 } 6750 instanceStarts.push(instanceStart); 6751 } 6752 dayMarker = addDays(dayMarker, 1); 6753 } 6754 return instanceStarts; 6755 } 6756 6757 var changeHandlerPlugin = createPlugin({ 6758 optionChangeHandlers: { 6759 events: function (events, context) { 6760 handleEventSources([events], context); 6761 }, 6762 eventSources: handleEventSources, 6763 }, 6764 }); 6765 /* 6766 BUG: if `event` was supplied, all previously-given `eventSources` will be wiped out 6767 */ 6768 function handleEventSources(inputs, context) { 6769 var unfoundSources = hashValuesToArray(context.getCurrentData().eventSources);
6770 var newInputs = []; 6771 for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) { 6772 var input = inputs_1[_i]; 6773 var inputFound = false; 6774 for (var i = 0; i < unfoundSources.length; i += 1) { 6775 if (unfoundSources[i]._raw === input) { 6776 unfoundSources.splice(i, 1); // delete 6777 inputFound = true; 6778 break; 6779 } 6780 } 6781 if (!inputFound) { 6782 newInputs.push(input); 6783 } 6784 } 6785 for (var _a = 0, unfoundSources_1 = unfoundSources; _a < unfoundSources_1.length; _a++) { 6786 var unfoundSource = unfoundSources_1[_a]; 6787 context.dispatch({ 6788 type: 'REMOVE_EVENT_SOURCE', 6789 sourceId: unfoundSource.sourceId, 6790 }); 6791 } 6792 for (var _b = 0, newInputs_1 = newInputs; _b < newInputs_1.length; _b++) { 6793 var newInput = newInputs_1[_b]; 6794 context.calendarApi.addEventSource(newInput); 6795 } 6796 } 6797 6798 function handleDateProfile(dateProfile, context) { 6799 context.emitter.trigger('datesSet', __assign(__assign({}, buildRangeApiWithTimeZone(dateProfile.activeRange, context.dateEnv)), { view: context.viewApi })); 6800 } 6801 6802 function handleEventStore(eventStore, context) { 6803 var emitter = context.emitter; 6804 if (emitter.hasHandlers('eventsSet')) { 6805 emitter.trigger('eventsSet', buildEventApis(eventStore, context)); 6806 } 6807 } 6808 6809 /* 6810 this array is exposed on the root namespace so that UMD plugins can add to it. 6811 see the rollup-bundles script. 6812 */ 6813 var globalPlugins = [ 6814 arrayEventSourcePlugin, 6815 funcEventSourcePlugin, 6816 jsonFeedEventSourcePlugin, 6817 simpleRecurringEventsPlugin, 6818 changeHandlerPlugin, 6819 createPlugin({ 6820 isLoadingFuncs: [ 6821 function (state) { return computeEventSourcesLoading(state.eventSources); }, 6822 ], 6823 contentTypeHandlers: { 6824 html: function () { return ({ render: injectHtml }); }, 6825 domNodes: function () { return ({ render: injectDomNodes }); }, 6826 }, 6827 propSetHandlers: { 6828 dateProfile: handleDateProfile, 6829 eventStore: handleEventStore, 6830 }, 6831 }), 6832 ]; 6833 function injectHtml(el, html) { 6834 el.innerHTML = html; 6835 } 6836 function injectDomNodes(el, domNodes) { 6837 var oldNodes = Array.prototype.slice.call(el.childNodes); // TODO: use array util 6838 var newNodes = Array.prototype.slice.call(domNodes); // TODO: use array util 6839 if (!isArraysEqual(oldNodes, newNodes)) { 6840 for (var _i = 0, newNodes_1 = newNodes; _i < newNodes_1.length; _i++) { 6841 var newNode = newNodes_1[_i]; 6842 el.appendChild(newNode); 6843 } 6844 oldNodes.forEach(removeElement); 6845 } 6846 } 6847 6848 var DelayedRunner = /** @class */ (function () { 6849 function DelayedRunner(drainedOption) { 6850 this.drainedOption = drainedOption; 6851 this.isRunning = false; 6852 this.isDirty = false; 6853 this.pauseDepths = {}; 6854 this.timeoutId = 0; 6855 } 6856 DelayedRunner.prototype.request = function (delay) { 6857 this.isDirty = true; 6858 if (!this.isPaused()) { 6859 this.clearTimeout(); 6860 if (delay == null) { 6861 this.tryDrain(); 6862 } 6863 else { 6864 this.timeoutId = setTimeout(// NOT OPTIMAL! TODO: look at debounce 6865 this.tryDrain.bind(this), delay); 6866 } 6867 } 6868 }; 6869 DelayedRunner.prototype.pause = function (scope) { 6870 if (scope === void 0) { scope = ''; } 6871 var pauseDepths = this.pauseDepths; 6872 pauseDepths[scope] = (pauseDepths[scope] || 0) + 1; 6873 this.clearTimeout(); 6874 }; 6875 DelayedRunner.prototype.resume = function (scope, force) { 6876 if (scope === void 0) { scope = ''; } 6877 var pauseDepths = this.pauseDepths; 6878 if (scope in pauseDepths) { 6879 if (force) { 6880 delete pauseDepths[scope]; 6881 } 6882 else { 6883 pauseDepths[scope] -= 1; 6884 var depth = pauseDepths[scope]; 6885 if (depth <= 0) { 6886 delete pauseDepths[scope]; 6887 } 6888 } 6889 this.tryDrain(); 6890 } 6891 }; 6892 DelayedRunner.prototype.isPaused = function () { 6893 return Object.keys(this.pauseDepths).length; 6894 }; 6895 DelayedRunner.prototype.tryDrain = function () { 6896 if (!this.isRunning && !this.isPaused()) { 6897 this.isRunning = true; 6898 while (this.isDirty) { 6899 this.isDirty = false;
6900 this.drained(); // might set isDirty to true again 6901 } 6902 this.isRunning = false; 6903 } 6904 }; 6905 DelayedRunner.prototype.clear = function () { 6906 this.clearTimeout(); 6907 this.isDirty = false; 6908 this.pauseDepths = {}; 6909 }; 6910 DelayedRunner.prototype.clearTimeout = function () { 6911 if (this.timeoutId) { 6912 clearTimeout(this.timeoutId); 6913 this.timeoutId = 0; 6914 } 6915 }; 6916 DelayedRunner.prototype.drained = function () { 6917 if (this.drainedOption) { 6918 this.drainedOption(); 6919 } 6920 }; 6921 return DelayedRunner; 6922 }()); 6923 6924 var TaskRunner = /** @class */ (function () { 6925 function TaskRunner(runTaskOption, drainedOption) { 6926 this.runTaskOption = runTaskOption; 6927 this.drainedOption = drainedOption; 6928 this.queue = []; 6929 this.delayedRunner = new DelayedRunner(this.drain.bind(this)); 6930 } 6931 TaskRunner.prototype.request = function (task, delay) { 6932 this.queue.push(task); 6933 this.delayedRunner.request(delay); 6934 }; 6935 TaskRunner.prototype.pause = function (scope) { 6936 this.delayedRunner.pause(scope); 6937 }; 6938 TaskRunner.prototype.resume = function (scope, force) { 6939 this.delayedRunner.resume(scope, force); 6940 }; 6941 TaskRunner.prototype.drain = function () { 6942 var queue = this.queue; 6943 while (queue.length) { 6944 var completedTasks = []; 6945 var task = void 0; 6946 while ((task = queue.shift())) { 6947 this.runTask(task); 6948 completedTasks.push(task); 6949 } 6950 this.drained(completedTasks); 6951 } // keep going, in case new tasks were added in the drained handler 6952 }; 6953 TaskRunner.prototype.runTask = function (task) { 6954 if (this.runTaskOption) { 6955 this.runTaskOption(task); 6956 } 6957 }; 6958 TaskRunner.prototype.drained = function (completedTasks) { 6959 if (this.drainedOption) { 6960 this.drainedOption(completedTasks); 6961 } 6962 }; 6963 return TaskRunner; 6964 }()); 6965 6966 // Computes what the title at the top of the calendarApi should be for this view 6967 function buildTitle(dateProfile, viewOptions, dateEnv) { 6968 var range; 6969 // for views that span a large unit of time, show the proper interval, ignoring stray days before and after 6970 if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) { 6971 range = dateProfile.currentRange; 6972 } 6973 else { // for day units or smaller, use the actual day range 6974 range = dateProfile.activeRange; 6975 } 6976 return dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || buildTitleFormat(dateProfile)), { 6977 isEndExclusive: dateProfile.isRangeAllDay, 6978 defaultSeparator: viewOptions.titleRangeSeparator, 6979 }); 6980 } 6981 // Generates the format string that should be used to generate the title for the current date range. 6982 // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`. 6983 function buildTitleFormat(dateProfile) { 6984 var currentRangeUnit = dateProfile.currentRangeUnit; 6985 if (currentRangeUnit === 'year') { 6986 return { year: 'numeric' }; 6987 } 6988 if (currentRangeUnit === 'month') { 6989 return { year: 'numeric', month: 'long' }; // like "September 2014" 6990 } 6991 var days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end); 6992 if (days !== null && days > 1) { 6993 // multi-day range. shorter, like "Sep 9 - 10 2014" 6994 return { year: 'numeric', month: 'short', day: 'numeric' }; 6995 } 6996 // one day. longer, like "September 9 2014" 6997 return { year: 'numeric', month: 'long', day: 'numeric' }; 6998 } 6999 7000 // in future refactor, do the redux-style function(state=initial) for initial-state 7001 // also, whatever is happening in constructor, have it happen in action queue too 7002 var CalendarDataManager = /** @class */ (function () { 7003 function CalendarDataManager(props) { 7004 var _this = this; 7005 this.computeOptionsData = memoize(this._computeOptionsData); 7006 this.computeCurrentViewData = memoize(this._computeCurrentViewData);
7007 this.organizeRawLocales = memoize(organizeRawLocales); 7008 this.buildLocale = memoize(buildLocale); 7009 this.buildPluginHooks = buildBuildPluginHooks(); 7010 this.buildDateEnv = memoize(buildDateEnv$1); 7011 this.buildTheme = memoize(buildTheme); 7012 this.parseToolbars = memoize(parseToolbars); 7013 this.buildViewSpecs = memoize(buildViewSpecs); 7014 this.buildDateProfileGenerator = memoizeObjArg(buildDateProfileGenerator); 7015 this.buildViewApi = memoize(buildViewApi); 7016 this.buildViewUiProps = memoizeObjArg(buildViewUiProps); 7017 this.buildEventUiBySource = memoize(buildEventUiBySource, isPropsEqual); 7018 this.buildEventUiBases = memoize(buildEventUiBases); 7019 this.parseContextBusinessHours = memoizeObjArg(parseContextBusinessHours); 7020 this.buildTitle = memoize(buildTitle); 7021 this.emitter = new Emitter(); 7022 this.actionRunner = new TaskRunner(this._handleAction.bind(this), this.updateData.bind(this)); 7023 this.currentCalendarOptionsInput = {}; 7024 this.currentCalendarOptionsRefined = {}; 7025 this.currentViewOptionsInput = {}; 7026 this.currentViewOptionsRefined = {}; 7027 this.currentCalendarOptionsRefiners = {}; 7028 this.getCurrentData = function () { return _this.data; }; 7029 this.dispatch = function (action) { 7030 _this.actionRunner.request(action); // protects against recursive calls to _handleAction 7031 }; 7032 this.props = props; 7033 this.actionRunner.pause(); 7034 var dynamicOptionOverrides = {}; 7035 var optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi); 7036 var currentViewType = optionsData.calendarOptions.initialView || optionsData.pluginHooks.initialView; 7037 var currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides); 7038 // wire things up 7039 // TODO: not DRY 7040 props.calendarApi.currentDataManager = this; 7041 this.emitter.setThisContext(props.calendarApi); 7042 this.emitter.setOptions(currentViewData.options); 7043 var currentDate = getInitialDate(optionsData.calendarOptions, optionsData.dateEnv); 7044 var dateProfile = currentViewData.dateProfileGenerator.build(currentDate); 7045 if (!rangeContainsMarker(dateProfile.activeRange, currentDate)) { 7046 currentDate = dateProfile.currentRange.start; 7047 } 7048 var calendarContext = { 7049 dateEnv: optionsData.dateEnv, 7050 options: optionsData.calendarOptions, 7051 pluginHooks: optionsData.pluginHooks, 7052 calendarApi: props.calendarApi, 7053 dispatch: this.dispatch, 7054 emitter: this.emitter, 7055 getCurrentData: this.getCurrentData, 7056 }; 7057 // needs to be after setThisContext 7058 for (var _i = 0, _a = optionsData.pluginHooks.contextInit; _i < _a.length; _i++) { 7059 var callback = _a[_i]; 7060 callback(calendarContext); 7061 } 7062 // NOT DRY 7063 var eventSources = initEventSources(optionsData.calendarOptions, dateProfile, calendarContext); 7064 var initialState = { 7065 dynamicOptionOverrides: dynamicOptionOverrides, 7066 currentViewType: currentViewType, 7067 currentDate: currentDate, 7068 dateProfile: dateProfile, 7069 businessHours: this.parseContextBusinessHours(calendarContext), 7070 eventSources: eventSources, 7071 eventUiBases: {}, 7072 eventStore: createEmptyEventStore(), 7073 renderableEventStore: createEmptyEventStore(), 7074 dateSelection: null, 7075 eventSelection: '', 7076 eventDrag: null, 7077 eventResize: null, 7078 selectionConfig: this.buildViewUiProps(calendarContext).selectionConfig, 7079 }; 7080 var contextAndState = __assign(__assign({}, calendarContext), initialState); 7081 for (var _b = 0, _c = optionsData.pluginHooks.reducers; _b < _c.length; _b++) { 7082 var reducer = _c[_b]; 7083 __assign(initialState, reducer(null, null, contextAndState)); 7084 } 7085 if (computeIsLoading(initialState, calendarContext)) { 7086 this.emitter.trigger('loading', true); // NOT DRY 7087 } 7088 this.state = initialState; 7089 this.updateData(); 7090 this.actionRunner.resume(); 7091 } 7092 CalendarDataManager.prototype.resetOptions = function (optionOverrides, append) { 7093 var props = this.props; 7094 props.optionOverrides = append 7095 ? __assign(__assign({}, props.optionOverrides), optionOverrides) : optionOverrides; 7096 this.actionRunner.request({ 7097 type: 'NOTHING', 7098 }); 7099 }; 7100 CalendarDataManager.prototype._handleAction = function (action) { 7101 var _a = this, props = _a.props, state = _a.state, emitter = _a.emitter; 7102 var dynamicOptionOverrides = reduceDynamicOptionOverrides(state.dynamicOptionOverrides, action); 7103 var optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi); 7104 var currentViewType = reduceViewType(state.currentViewType, action); 7105 var currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides); 7106 // wire things up 7107 // TODO: not DRY 7108 props.calendarApi.currentDataManager = this; 7109 emitter.setThisContext(props.calendarApi); 7110 emitter.setOptions(currentViewData.options); 7111 var calendarContext = { 7112 dateEnv: optionsData.dateEnv, 7113 options: optionsData.calendarOptions, 7114 pluginHooks: optionsData.pluginHooks, 7115 calendarApi: props.calendarApi, 7116 dispatch: this.dispatch, 7117 emitter: emitter, 7118 getCurrentData: this.getCurrentData, 7119 }; 7120 var currentDate = state.currentDate, dateProfile = state.dateProfile; 7121 if (this.data && this.data.dateProfileGenerator !== currentViewData.dateProfileGenerator) { // hack 7122 dateProfile = currentViewData.dateProfileGenerator.build(currentDate); 7123 } 7124 currentDate = reduceCurrentDate(currentDate, action); 7125 dateProfile = reduceDateProfile(dateProfile, action, currentDate, currentViewData.dateProfileGenerator); 7126 if (!rangeContainsMarker(dateProfile.currentRange, currentDate)) { 7127 currentDate = dateProfile.currentRange.start; 7128 } 7129 var eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendarContext); 7130 var eventStore = reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendarContext); 7131 var isEventsLoading = computeEventSourcesLoading(eventSources);
7131 // BAD. also called in this func in computeIsLoading 7132 var renderableEventStore = (isEventsLoading && !currentViewData.options.progressiveEventRendering) ? 7133 (state.renderableEventStore || eventStore) : // try from previous state 7134 eventStore; 7135 var _b = this.buildViewUiProps(calendarContext), eventUiSingleBase = _b.eventUiSingleBase, selectionConfig = _b.selectionConfig; // will memoize obj 7136 var eventUiBySource = this.buildEventUiBySource(eventSources); 7137 var eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource); 7138 var newState = { 7139 dynamicOptionOverrides: dynamicOptionOverrides, 7140 currentViewType: currentViewType, 7141 currentDate: currentDate, 7142 dateProfile: dateProfile, 7143 eventSources: eventSources, 7144 eventStore: eventStore, 7145 renderableEventStore: renderableEventStore, 7146 selectionConfig: selectionConfig, 7147 eventUiBases: eventUiBases, 7148 businessHours: this.parseContextBusinessHours(calendarContext), 7149 dateSelection: reduceDateSelection(state.dateSelection, action), 7150 eventSelection: reduceSelectedEvent(state.eventSelection, action), 7151 eventDrag: reduceEventDrag(state.eventDrag, action), 7152 eventResize: reduceEventResize(state.eventResize, action), 7153 }; 7154 var contextAndState = __assign(__assign({}, calendarContext), newState); 7155 for (var _i = 0, _c = optionsData.pluginHooks.reducers; _i < _c.length; _i++) { 7156 var reducer = _c[_i]; 7157 __assign(newState, reducer(state, action, contextAndState)); // give the OLD state, for old value 7158 } 7159 var wasLoading = computeIsLoading(state, calendarContext); 7160 var isLoading = computeIsLoading(newState, calendarContext); 7161 // TODO: use propSetHandlers in plugin system 7162 if (!wasLoading && isLoading) { 7163 emitter.trigger('loading', true); 7164 } 7165 else if (wasLoading && !isLoading) { 7166 emitter.trigger('loading', false); 7167 } 7168 this.state = newState; 7169 if (props.onAction) { 7170 props.onAction(action); 7171 } 7172 }; 7173 CalendarDataManager.prototype.updateData = function () { 7174 var _a = this, props = _a.props, state = _a.state; 7175 var oldData = this.data; 7176 var optionsData = this.computeOptionsData(props.optionOverrides, state.dynamicOptionOverrides, props.calendarApi); 7177 var currentViewData = this.computeCurrentViewData(state.currentViewType, optionsData, props.optionOverrides, state.dynamicOptionOverrides); 7178 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); 7179 var changeHandlers = optionsData.pluginHooks.optionChangeHandlers; 7180 var oldCalendarOptions = oldData && oldData.calendarOptions; 7181 var newCalendarOptions = optionsData.calendarOptions; 7182 if (oldCalendarOptions && oldCalendarOptions !== newCalendarOptions) { 7183 if (oldCalendarOptions.timeZone !== newCalendarOptions.timeZone) { 7184 // hack 7185 state.eventSources = data.eventSources = reduceEventSourcesNewTimeZone(data.eventSources, state.dateProfile, data); 7186 state.eventStore = data.eventStore = rezoneEventStoreDates(data.eventStore, oldData.dateEnv, data.dateEnv); 7187 } 7188 for (var optionName in changeHandlers) { 7189 if (oldCalendarOptions[optionName] !== newCalendarOptions[optionName]) { 7190 changeHandlers[optionName](newCalendarOptions[optionName], data); 7191 } 7192 } 7193 } 7194 if (props.onData) { 7195 props.onData(data); 7196 } 7197 }; 7198 CalendarDataManager.prototype._computeOptionsData = function (optionOverrides, dynamicOptionOverrides, calendarApi) { 7199 // TODO: blacklist options that are handled by optionChangeHandlers 7200 var _a = this.processRawCalendarOptions(optionOverrides, dynamicOptionOverrides), refinedOptions = _a.refinedOptions, pluginHooks = _a.pluginHooks, localeDefaults = _a.localeDefaults, availableLocaleData = _a.availableLocaleData, extra = _a.extra; 7201 warnUnknownOptions(extra); 7202 var dateEnv = this.buildDateEnv(refinedOptions.timeZone, refinedOptions.locale, refinedOptions.weekNumberCalculation, refinedOptions.firstDay, refinedOptions.weekText, pluginHooks, availableLocaleData, refinedOptions.defaultRangeSeparator); 7203 var viewSpecs = this.buildViewSpecs(pluginHooks.views, optionOverrides, dynamicOptionOverrides, localeDefaults); 7204 var theme = this.buildTheme(refinedOptions, pluginHooks); 7205 var toolbarConfig = this.parseToolbars(refinedOptions, optionOverrides, theme, viewSpecs, calendarApi); 7206 return { 7207 calendarOptions: refinedOptions, 7208 pluginHooks: pluginHooks, 7209 dateEnv: dateEnv, 7210 viewSpecs: viewSpecs, 7211 theme: theme, 7212 toolbarConfig: toolbarConfig, 7213 localeDefaults: localeDefaults, 7214 availableRawLocales: availableLocaleData.map, 7215 }; 7216 }; 7217 // always called from behind a memoizer 7218 CalendarDataManager.prototype.processRawCalendarOptions = function (optionOverrides, dynamicOptionOverrides) { 7219 var _a = mergeRawOptions([ 7220 BASE_OPTION_DEFAULTS, 7221 optionOverrides, 7222 dynamicOptionOverrides, 7223 ]), locales = _a.locales, locale = _a.locale; 7224 var availableLocaleData = this.organizeRawLocales(locales); 7225 var availableRawLocales = availableLocaleData.map; 7226 var localeDefaults = this.buildLocale(locale || availableLocaleData.defaultCode, availableRawLocales).options; 7227 var pluginHooks = this.buildPluginHooks(optionOverrides.plugins || [], globalPlugins); 7228 var refiners = this.currentCalendarOptionsRefiners = __assign(__assign(__assign(__assign(__assign({}, BASE_OPTION_REFINERS), CALENDAR_LISTENER_REFINERS), CALENDAR_OPTION_REFINERS), pluginHooks.listenerRefiners), pluginHooks.optionRefiners); 7229 var extra = {}; 7230 var raw = mergeRawOptions([ 7231 BASE_OPTION_DEFAULTS, 7232 localeDefaults, 7233 optionOverrides, 7234 dynamicOptionOverrides, 7235 ]);
7236 var refined = {}; 7237 var currentRaw = this.currentCalendarOptionsInput; 7238 var currentRefined = this.currentCalendarOptionsRefined; 7239 var anyChanges = false; 7240 for (var optionName in raw) { 7241 if (optionName !== 'plugins') { // because plugins is special-cased 7242 if (raw[optionName] === currentRaw[optionName] || 7243 (COMPLEX_OPTION_COMPARATORS[optionName] && 7244 (optionName in currentRaw) && 7245 COMPLEX_OPTION_COMPARATORS[optionName](currentRaw[optionName], raw[optionName]))) { 7246 refined[optionName] = currentRefined[optionName]; 7247 } 7248 else if (refiners[optionName]) { 7249 refined[optionName] = refiners[optionName](raw[optionName]); 7250 anyChanges = true; 7251 } 7252 else { 7253 extra[optionName] = currentRaw[optionName]; 7254 } 7255 } 7256 } 7257 if (anyChanges) { 7258 this.currentCalendarOptionsInput = raw; 7259 this.currentCalendarOptionsRefined = refined; 7260 } 7261 return { 7262 rawOptions: this.currentCalendarOptionsInput, 7263 refinedOptions: this.currentCalendarOptionsRefined, 7264 pluginHooks: pluginHooks, 7265 availableLocaleData: availableLocaleData, 7266 localeDefaults: localeDefaults, 7267 extra: extra, 7268 }; 7269 }; 7270 CalendarDataManager.prototype._computeCurrentViewData = function (viewType, optionsData, optionOverrides, dynamicOptionOverrides) { 7271 var viewSpec = optionsData.viewSpecs[viewType]; 7272 if (!viewSpec) { 7273 throw new Error("viewType \"" + viewType + "\" is not available. Please make sure you've loaded all neccessary plugins"); 7274 } 7275 var _a = this.processRawViewOptions(viewSpec, optionsData.pluginHooks, optionsData.localeDefaults, optionOverrides, dynamicOptionOverrides), refinedOptions = _a.refinedOptions, extra = _a.extra; 7276 warnUnknownOptions(extra); 7277 var dateProfileGenerator = this.buildDateProfileGenerator({ 7278 dateProfileGeneratorClass: viewSpec.optionDefaults.dateProfileGeneratorClass, 7279 duration: viewSpec.duration, 7280 durationUnit: viewSpec.durationUnit, 7281 usesMinMaxTime: viewSpec.optionDefaults.usesMinMaxTime, 7282 dateEnv: optionsData.dateEnv, 7283 calendarApi: this.props.calendarApi, 7284 slotMinTime: refinedOptions.slotMinTime, 7285 slotMaxTime: refinedOptions.slotMaxTime, 7286 showNonCurrentDates: refinedOptions.showNonCurrentDates, 7287 dayCount: refinedOptions.dayCount, 7288 dateAlignment: refinedOptions.dateAlignment, 7289 dateIncrement: refinedOptions.dateIncrement, 7290 hiddenDays: refinedOptions.hiddenDays, 7291 weekends: refinedOptions.weekends, 7292 nowInput: refinedOptions.now, 7293 validRangeInput: refinedOptions.validRange, 7294 visibleRangeInput: refinedOptions.visibleRange, 7295 monthMode: refinedOptions.monthMode, 7296 fixedWeekCount: refinedOptions.fixedWeekCount, 7297 }); 7298 var viewApi = this.buildViewApi(viewType, this.getCurrentData, optionsData.dateEnv); 7299 return { viewSpec: viewSpec, options: refinedOptions, dateProfileGenerator: dateProfileGenerator, viewApi: viewApi }; 7300 }; 7301 CalendarDataManager.prototype.processRawViewOptions = function (viewSpec, pluginHooks, localeDefaults, optionOverrides, dynamicOptionOverrides) { 7302 var raw = mergeRawOptions([ 7303 BASE_OPTION_DEFAULTS, 7304 viewSpec.optionDefaults, 7305 localeDefaults, 7306 optionOverrides, 7307 viewSpec.optionOverrides, 7308 dynamicOptionOverrides, 7309 ]); 7310 var refiners = __assign(__assign(__assign(__assign(__assign(__assign({}, BASE_OPTION_REFINERS), CALENDAR_LISTENER_REFINERS), CALENDAR_OPTION_REFINERS), VIEW_OPTION_REFINERS), pluginHooks.listenerRefiners), pluginHooks.optionRefiners);
7311 var refined = {}; 7312 var currentRaw = this.currentViewOptionsInput; 7313 var currentRefined = this.currentViewOptionsRefined; 7314 var anyChanges = false; 7315 var extra = {}; 7316 for (var optionName in raw) { 7317 if (raw[optionName] === currentRaw[optionName]) { 7318 refined[optionName] = currentRefined[optionName]; 7319 } 7320 else { 7321 if (raw[optionName] === this.currentCalendarOptionsInput[optionName]) { 7322 if (optionName in this.currentCalendarOptionsRefined) { // might be an "extra" prop 7323 refined[optionName] = this.currentCalendarOptionsRefined[optionName]; 7324 } 7325 } 7326 else if (refiners[optionName]) { 7327 refined[optionName] = refiners[optionName](raw[optionName]); 7328 } 7329 else { 7330 extra[optionName] = raw[optionName]; 7331 } 7332 anyChanges = true; 7333 } 7334 } 7335 if (anyChanges) { 7336 this.currentViewOptionsInput = raw; 7337 this.currentViewOptionsRefined = refined; 7338 } 7339 return { 7340 rawOptions: this.currentViewOptionsInput, 7341 refinedOptions: this.currentViewOptionsRefined, 7342 extra: extra, 7343 }; 7344 }; 7345 return CalendarDataManager; 7346 }()); 7347 function buildDateEnv$1(timeZone, explicitLocale, weekNumberCalculation, firstDay, weekText, pluginHooks, availableLocaleData, defaultSeparator) { 7348 var locale = buildLocale(explicitLocale || availableLocaleData.defaultCode, availableLocaleData.map); 7349 return new DateEnv({ 7350 calendarSystem: 'gregory', 7351 timeZone: timeZone, 7352 namedTimeZoneImpl: pluginHooks.namedTimeZonedImpl, 7353 locale: locale, 7354 weekNumberCalculation: weekNumberCalculation, 7355 firstDay: firstDay, 7356 weekText: weekText, 7357 cmdFormatter: pluginHooks.cmdFormatter, 7358 defaultSeparator: defaultSeparator, 7359 }); 7360 } 7361 function buildTheme(options, pluginHooks) { 7362 var ThemeClass = pluginHooks.themeClasses[options.themeSystem] || StandardTheme; 7363 return new ThemeClass(options); 7364 } 7365 function buildDateProfileGenerator(props) { 7366 var DateProfileGeneratorClass = props.dateProfileGeneratorClass || DateProfileGenerator; 7367 return new DateProfileGeneratorClass(props); 7368 } 7369 function buildViewApi(type, getCurrentData, dateEnv) { 7370 return new ViewApi(type, getCurrentData, dateEnv); 7371 } 7372 function buildEventUiBySource(eventSources) { 7373 return mapHash(eventSources, function (eventSource) { return eventSource.ui; }); 7374 } 7375 function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) { 7376 var eventUiBases = { '': eventUiSingleBase }; 7377 for (var defId in eventDefs) { 7378 var def = eventDefs[defId]; 7379 if (def.sourceId && eventUiBySource[def.sourceId]) { 7380 eventUiBases[defId] = eventUiBySource[def.sourceId]; 7381 } 7382 } 7383 return eventUiBases; 7384 } 7385 function buildViewUiProps(calendarContext) { 7386 var options = calendarContext.options; 7387 return { 7388 eventUiSingleBase: createEventUi({ 7389 display: options.eventDisplay, 7390 editable: options.editable, 7391 startEditable: options.eventStartEditable, 7392 durationEditable: options.eventDurationEditable, 7393 constraint: options.eventConstraint, 7394 overlap: typeof options.eventOverlap === 'boolean' ? options.eventOverlap : undefined, 7395 allow: options.eventAllow, 7396 backgroundColor: options.eventBackgroundColor, 7397 borderColor: options.eventBorderColor, 7398 textColor: options.eventTextColor, 7399 color: options.eventColor, 7400 }, calendarContext), 7401 selectionConfig: createEventUi({ 7402 constraint: options.selectConstraint, 7403 overlap: typeof options.selectOverlap === 'boolean' ? options.selectOverlap : undefined, 7404 allow: options.selectAllow, 7405 }, calendarContext), 7406 }; 7407 } 7408 function computeIsLoading(state, context) { 7409 for (var _i = 0, _a = context.pluginHooks.isLoadingFuncs; _i < _a.length; _i++) { 7410 var isLoadingFunc = _a[_i]; 7411 if (isLoadingFunc(state)) { 7412 return true; 7413 } 7414 } 7415 return false;
7416 } 7417 function parseContextBusinessHours(calendarContext) { 7418 return parseBusinessHours(calendarContext.options.businessHours, calendarContext); 7419 } 7420 function warnUnknownOptions(options, viewName) { 7421 for (var optionName in options) { 7422 console.warn("Unknown option '" + optionName + "'" + 7423 (viewName ? " for view '" + viewName + "'" : '')); 7424 } 7425 } 7426 7427 // TODO: move this to react plugin? 7428 var CalendarDataProvider = /** @class */ (function (_super) { 7429 __extends(CalendarDataProvider, _super); 7430 function CalendarDataProvider(props) { 7431 var _this = _super.call(this, props) || this; 7432 _this.handleData = function (data) { 7433 if (!_this.dataManager) { // still within initial run, before assignment in constructor 7434 // eslint-disable-next-line react/no-direct-mutation-state 7435 _this.state = data; // can't use setState yet 7436 } 7437 else { 7438 _this.setState(data); 7439 } 7440 }; 7441 _this.dataManager = new CalendarDataManager({ 7442 optionOverrides: props.optionOverrides, 7443 calendarApi: props.calendarApi, 7444 onData: _this.handleData, 7445 }); 7446 return _this; 7447 } 7448 CalendarDataProvider.prototype.render = function () { 7449 return this.props.children(this.state); 7450 }; 7451 CalendarDataProvider.prototype.componentDidUpdate = function (prevProps) { 7452 var newOptionOverrides = this.props.optionOverrides; 7453 if (newOptionOverrides !== prevProps.optionOverrides) { // prevent recursive handleData 7454 this.dataManager.resetOptions(newOptionOverrides); 7455 } 7456 }; 7457 return CalendarDataProvider; 7458 }(Component)); 7459 7460 // HELPERS 7461 /* 7462 if nextDayThreshold is specified, slicing is done in an all-day fashion. 7463 you can get nextDayThreshold from context.nextDayThreshold 7464 */ 7465 function sliceEvents(props, allDay) { 7466 return sliceEventStore(props.eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? props.nextDayThreshold : null).fg; 7467 } 7468 7469 var NamedTimeZoneImpl = /** @class */ (function () { 7470 function NamedTimeZoneImpl(timeZoneName) { 7471 this.timeZoneName = timeZoneName; 7472 } 7473 return NamedTimeZoneImpl; 7474 }()); 7475 7476 var Interaction = /** @class */ (function () { 7477 function Interaction(settings) { 7478 this.component = settings.component; 7479 } 7480 Interaction.prototype.destroy = function () { 7481 }; 7482 return Interaction; 7483 }()); 7484 function parseInteractionSettings(component, input) { 7485 return { 7486 component: component, 7487 el: input.el, 7488 useEventCenter: input.useEventCenter != null ? input.useEventCenter : true, 7489 }; 7490 } 7491 function interactionSettingsToStore(settings) { 7492 var _a; 7493 return _a = {}, 7494 _a[settings.component.uid] = settings, 7495 _a; 7496 } 7497 // global state 7498 var interactionSettingsStore = {}; 7499 7500 /* 7501 An abstraction for a dragging interaction originating on an event. 7502 Does higher-level things than PointerDragger, such as possibly: 7503 - a "mirror" that moves with the pointer 7504 - a minimum number of pixels or other criteria for a true drag to begin 7505 7506 subclasses must emit: 7507 - pointerdown 7508 - dragstart 7509 - dragmove 7510 - pointerup 7511 - dragend 7512 */ 7513 var ElementDragging = /** @class */ (function () { 7514 function ElementDragging(el, selector) { 7515 this.emitter = new Emitter(); 7516 } 7517 ElementDragging.prototype.destroy = function () { 7518 }; 7519 ElementDragging.prototype.setMirrorIsVisible = function (bool) { 7520 // optional if subclass doesn't want to support a mirror 7521 }; 7522 ElementDragging.prototype.setMirrorNeedsRevert = function (bool) { 7523 // optional if subclass doesn't want to support a mirror 7524 }; 7525 ElementDragging.prototype.setAutoScrollEnabled = function (bool) { 7526 // optional 7527 }; 7528 return ElementDragging; 7529 }()); 7530 7531 // TODO: get rid of this in favor of options system, 7532 // tho it's really easy to access this globally rather than pass thru options. 7533 var config = {}; 7534 7535 /* 7536 Information about what will happen when an external element is dragged-and-dropped 7537 onto a calendar. Contains information for creating an event. 7538 */ 7539 var DRAG_META_REFINERS = { 7540 startTime: createDuration, 7541 duration: createDuration, 7542 create: Boolean, 7543 sourceId: String, 7544 }; 7545 function parseDragMeta(raw) {
7546 var _a = refineProps(raw, DRAG_META_REFINERS), refined = _a.refined, extra = _a.extra; 7547 return { 7548 startTime: refined.startTime || null, 7549 duration: refined.duration || null, 7550 create: refined.create != null ? refined.create : true, 7551 sourceId: refined.sourceId, 7552 leftoverProps: extra, 7553 }; 7554 } 7555 7556 var ToolbarSection = /** @class */ (function (_super) { 7557 __extends(ToolbarSection, _super); 7558 function ToolbarSection() { 7559 return _super !== null && _super.apply(this, arguments) || this; 7560 } 7561 ToolbarSection.prototype.render = function () { 7562 var _this = this; 7563 var children = this.props.widgetGroups.map(function (widgetGroup) { return _this.renderWidgetGroup(widgetGroup); }); 7564 return createElement.apply(void 0, __spreadArrays(['div', { className: 'fc-toolbar-chunk' }], children)); 7565 }; 7566 ToolbarSection.prototype.renderWidgetGroup = function (widgetGroup) { 7567 var props = this.props; 7568 var theme = this.context.theme; 7569 var children = []; 7570 var isOnlyButtons = true; 7571 for (var _i = 0, widgetGroup_1 = widgetGroup; _i < widgetGroup_1.length; _i++) { 7572 var widget = widgetGroup_1[_i]; 7573 var buttonName = widget.buttonName, buttonClick = widget.buttonClick, buttonText = widget.buttonText, buttonIcon = widget.buttonIcon; 7574 if (buttonName === 'title') { 7575 isOnlyButtons = false; 7576 children.push(createElement("h2", { className: "fc-toolbar-title" }, props.title)); 7577 } 7578 else { 7579 var ariaAttrs = buttonIcon ? { 'aria-label': buttonName } : {}; 7580 var buttonClasses = ["fc-" + buttonName + "-button", theme.getClass('button')]; 7581 if (buttonName === props.activeButton) { 7582 buttonClasses.push(theme.getClass('buttonActive')); 7583 } 7584 var isDisabled = (!props.isTodayEnabled && buttonName === 'today') || 7585 (!props.isPrevEnabled && buttonName === 'prev') || 7586 (!props.isNextEnabled && buttonName === 'next'); 7587 children.push(createElement("button", __assign({ disabled: isDisabled, className: buttonClasses.join(' '), onClick: buttonClick, type: "button" }, ariaAttrs), buttonText || (buttonIcon ? createElement("span", { className: buttonIcon }) : ''))); 7588 } 7589 } 7590 if (children.length > 1) { 7591 var groupClassName = (isOnlyButtons && theme.getClass('buttonGroup')) || ''; 7592 return createElement.apply(void 0, __spreadArrays(['div', { className: groupClassName }], children)); 7593 } 7594 return children[0]; 7595 }; 7596 return ToolbarSection; 7597 }(BaseComponent)); 7598 7599 var Toolbar = /** @class */ (function (_super) { 7600 __extends(Toolbar, _super); 7601 function Toolbar() { 7602 return _super !== null && _super.apply(this, arguments) || this; 7603 } 7604 Toolbar.prototype.render = function () { 7605 var _a = this.props, model = _a.model, extraClassName = _a.extraClassName; 7606 var forceLtr = false; 7607 var startContent; 7608 var endContent; 7609 var centerContent = model.center; 7610 if (model.left) { 7611 forceLtr = true; 7612 startContent = model.left; 7613 } 7614 else { 7615 startContent = model.start; 7616 } 7617 if (model.right) { 7618 forceLtr = true; 7619 endContent = model.right; 7620 } 7621 else { 7622 endContent = model.end; 7623 } 7624 var classNames = [ 7625 extraClassName || '', 7626 'fc-toolbar', 7627 forceLtr ? 'fc-toolbar-ltr' : '', 7628 ]; 7629 return (createElement("div", { className: classNames.join(' ') }, 7630 this.renderSection('start', startContent || []), 7631 this.renderSection('center', centerContent || []), 7632 this.renderSection('end', endContent || []))); 7633 }; 7634 Toolbar.prototype.renderSection = function (key, widgetGroups) { 7635 var props = this.props; 7636 return (createElement(ToolbarSection, { key: key, widgetGroups: widgetGroups, title: props.title, activeButton: props.activeButton, isTodayEnabled: props.isTodayEnabled, isPrevEnabled: props.isPrevEnabled, isNextEnabled: props.isNextEnabled })); 7637 }; 7638 return Toolbar; 7639 }(BaseComponent)); 7640 7641 // TODO: do function component? 7642 var ViewContainer = /** @class */ (function (_super) { 7643 __extends(ViewContainer, _super); 7644 function ViewContainer() { 7645 var _this = _super !== null && _super.apply(this, arguments) || this; 7646 _this.state = { 7647 availableWidth: null, 7648 }; 7649 _this.handleEl = function (el) { 7650 _this.el = el; 7651 setRef(_this.props.elRef, el); 7652 _this.updateAvailableWidth(); 7653 }; 7654 _this.handleResize = function () { 7655 _this.updateAvailableWidth(); 7656 }; 7657 return _this; 7658 } 7659 ViewContainer.prototype.render = function () { 7660 var _a = this, props = _a.props, state = _a.state; 7661 var aspectRatio = props.aspectRatio; 7662 var classNames = [ 7663 'fc-view-harness', 7664 (aspectRatio || props.liquid || props.height) 7665 ? 'fc-view-harness-active' // harness controls the height
7666 : 'fc-view-harness-passive', 7667 ]; 7668 var height = ''; 7669 var paddingBottom = ''; 7670 if (aspectRatio) { 7671 if (state.availableWidth !== null) { 7672 height = state.availableWidth / aspectRatio; 7673 } 7674 else { 7675 // while waiting to know availableWidth, we can't set height to *zero* 7676 // because will cause lots of unnecessary scrollbars within scrollgrid. 7677 // BETTER: don't start rendering ANYTHING yet until we know container width 7678 // NOTE: why not always use paddingBottom? Causes height oscillation (issue 5606) 7679 paddingBottom = (1 / aspectRatio) * 100 + "%"; 7680 } 7681 } 7682 else { 7683 height = props.height || ''; 7684 } 7685 return (createElement("div", { ref: this.handleEl, onClick: props.onClick, className: classNames.join(' '), style: { height: height, paddingBottom: paddingBottom } }, props.children)); 7686 }; 7687 ViewContainer.prototype.componentDidMount = function () { 7688 this.context.addResizeHandler(this.handleResize); 7689 }; 7690 ViewContainer.prototype.componentWillUnmount = function () { 7691 this.context.removeResizeHandler(this.handleResize); 7692 }; 7693 ViewContainer.prototype.updateAvailableWidth = function () { 7694 if (this.el && // needed. but why? 7695 this.props.aspectRatio // aspectRatio is the only height setting that needs availableWidth 7696 ) { 7697 this.setState({ availableWidth: this.el.offsetWidth }); 7698 } 7699 }; 7700 return ViewContainer; 7701 }(BaseComponent)); 7702 7703 /* 7704 Detects when the user clicks on an event within a DateComponent 7705 */ 7706 var EventClicking = /** @class */ (function (_super) { 7707 __extends(EventClicking, _super); 7708 function EventClicking(settings) { 7709 var _this = _super.call(this, settings) || this; 7710 _this.handleSegClick = function (ev, segEl) { 7711 var component = _this.component; 7712 var context = component.context; 7713 var seg = getElSeg(segEl); 7714 if (seg && // might be the <div> surrounding the more link 7715 component.isValidSegDownEl(ev.target)) { 7716 // our way to simulate a link click for elements that can't be <a> tags 7717 // grab before trigger fired in case trigger trashes DOM thru rerendering 7718 var hasUrlContainer = elementClosest(ev.target, '.fc-event-forced-url'); 7719 var url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : ''; 7720 context.emitter.trigger('eventClick', { 7721 el: segEl, 7722 event: new EventApi(component.context, seg.eventRange.def, seg.eventRange.instance), 7723 jsEvent: ev, 7724 view: context.viewApi, 7725 }); 7726 if (url && !ev.defaultPrevented) { 7727 window.location.href = url; 7728 } 7729 } 7730 }; 7731 _this.destroy = listenBySelector(settings.el, 'click', '.fc-event', // on both fg and bg events 7732 _this.handleSegClick); 7733 return _this; 7734 } 7735 return EventClicking; 7736 }(Interaction)); 7737 7738 /* 7739 Triggers events and adds/removes core classNames when the user's pointer 7740 enters/leaves event-elements of a component. 7741 */ 7742 var EventHovering = /** @class */ (function (_super) { 7743 __extends(EventHovering, _super); 7744 function EventHovering(settings) { 7745 var _this = _super.call(this, settings) || this; 7746 // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it 7747 _this.handleEventElRemove = function (el) { 7748 if (el === _this.currentSegEl) { 7749 _this.handleSegLeave(null, _this.currentSegEl); 7750 } 7751 }; 7752 _this.handleSegEnter = function (ev, segEl) { 7753 if (getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper 7754 _this.currentSegEl = segEl; 7755 _this.triggerEvent('eventMouseEnter', ev, segEl); 7756 } 7757 }; 7758 _this.handleSegLeave = function (ev, segEl) { 7759 if (_this.currentSegEl) { 7760 _this.currentSegEl = null; 7761 _this.triggerEvent('eventMouseLeave', ev, segEl); 7762 } 7763 }; 7764 _this.removeHoverListeners = listenToHoverBySelector(settings.el, '.fc-event', // on both fg and bg events 7765 _this.handleSegEnter, _this.handleSegLeave); 7766 return _this; 7767 } 7768 EventHovering.prototype.destroy = function () { 7769 this.removeHoverListeners(); 7770 }; 7771 EventHovering.prototype.triggerEvent = function (publicEvName, ev, segEl) { 7772 var component = this.component; 7773 var context = component.context; 7774 var seg = getElSeg(segEl); 7775 if (!ev || component.isValidSegDownEl(ev.target)) { 7776 context.emitter.trigger(publicEvName, { 7777 el: segEl, 7778 event: new EventApi(context, seg.eventRange.def, seg.eventRange.instance), 7779 jsEvent: ev, 7780 view: context.viewApi, 7781 }); 7782 } 7783 }; 7784 return EventHovering; 7785 }(Interaction)); 7786 7787 var CalendarContent = /** @class */ (function (_super) { 7788 __extends(CalendarContent, _super); 7789 function CalendarContent() { 7790 var _this = _super !== null && _super.apply(this, arguments) || this; 7791 _this.buildViewContext = memoize(buildViewContext); 7792 _this.buildViewPropTransformers = memoize(buildViewPropTransformers); 7793 _this.buildToolbarProps = memoize(buildToolbarProps); 7794 _this.handleNavLinkClick = buildDelegationHandler('a[data-navlink]', _this._handleNavLinkClick.bind(_this)); 7795 _this.headerRef = createRef(); 7796 _this.footerRef = createRef(); 7797 _this.interactionsStore = {}; 7798 // Component Registration 7799 // ----------------------------------------------------------------------------------------------------------------- 7800 _this.registerInteractiveComponent = function (component, settingsInput) { 7801 var settings = parseInteractionSettings(component, settingsInput); 7802 var DEFAULT_INTERACTIONS = [ 7803 EventClicking, 7804 EventHovering, 7805 ]; 7806 var interactionClasses = DEFAULT_INTERACTIONS.concat(_this.props.pluginHooks.componentInteractions); 7807 var interactions = interactionClasses.map(function (TheInteractionClass) { return new TheInteractionClass(settings); }); 7808 _this.interactionsStore[component.uid] = interactions; 7809 interactionSettingsStore[component.uid] = settings; 7810 }; 7811 _this.unregisterInteractiveComponent = function (component) { 7812 for (var _i = 0, _a = _this.interactionsStore[component.uid]; _i < _a.length; _i++) { 7813 var listener = _a[_i]; 7814 listener.destroy(); 7815 } 7816 delete _this.interactionsStore[component.uid]; 7817 delete interactionSettingsStore[component.uid]; 7818 }; 7819 // Resizing 7820 // ----------------------------------------------------------------------------------------------------------------- 7821 _this.resizeRunner = new DelayedRunner(function () { 7822 _this.props.emitter.trigger('_resize', true); // should window resizes be considered "forced" ? 7823 _this.props.emitter.trigger('windowResize', { view: _this.props.viewApi }); 7824 }); 7825 _this.handleWindowResize = function (ev) { 7826 var options = _this.props.options; 7827 if (options.handleWindowResize && 7828 ev.target === window // avoid jqui events 7829 ) { 7830 _this.resizeRunner.request(options.windowResizeDelay); 7831 } 7832 }; 7833 return _this; 7834 } 7835 /* 7836 renders INSIDE of an outer div 7837 */ 7838 CalendarContent.prototype.render = function () { 7839 var props = this.props; 7840 var toolbarConfig = props.toolbarConfig, options = props.options; 7841 var toolbarProps = this.buildToolbarProps(props.viewSpec, props.dateProfile, props.dateProfileGenerator, props.currentDate, getNow(props.options.now, props.dateEnv), // TODO: use NowTimer???? 7842 props.viewTitle); 7843 var viewVGrow = false;
7844 var viewHeight = ''; 7845 var viewAspectRatio; 7846 if (props.isHeightAuto || props.forPrint) { 7847 viewHeight = ''; 7848 } 7849 else if (options.height != null) { 7850 viewVGrow = true; 7851 } 7852 else if (options.contentHeight != null) { 7853 viewHeight = options.contentHeight; 7854 } 7855 else { 7856 viewAspectRatio = Math.max(options.aspectRatio, 0.5); // prevent from getting too tall 7857 } 7858 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); 7859 return (createElement(ViewContextType.Provider, { value: viewContext }, 7860 toolbarConfig.headerToolbar && (createElement(Toolbar, __assign({ ref: this.headerRef, extraClassName: "fc-header-toolbar", model: toolbarConfig.headerToolbar }, toolbarProps))), 7861 createElement(ViewContainer, { liquid: viewVGrow, height: viewHeight, aspectRatio: viewAspectRatio, onClick: this.handleNavLinkClick }, 7862 this.renderView(props), 7863 this.buildAppendContent()), 7864 toolbarConfig.footerToolbar && (createElement(Toolbar, __assign({ ref: this.footerRef, extraClassName: "fc-footer-toolbar", model: toolbarConfig.footerToolbar }, toolbarProps))))); 7865 }; 7866 CalendarContent.prototype.componentDidMount = function () { 7867 var props = this.props; 7868 this.calendarInteractions = props.pluginHooks.calendarInteractions 7869 .map(function (CalendarInteractionClass) { return new CalendarInteractionClass(props); }); 7870 window.addEventListener('resize', this.handleWindowResize); 7871 var propSetHandlers = props.pluginHooks.propSetHandlers; 7872 for (var propName in propSetHandlers) { 7873 propSetHandlers[propName](props[propName], props); 7874 } 7875 }; 7876 CalendarContent.prototype.componentDidUpdate = function (prevProps) { 7877 var props = this.props; 7878 var propSetHandlers = props.pluginHooks.propSetHandlers; 7879 for (var propName in propSetHandlers) { 7880 if (props[propName] !== prevProps[propName]) { 7881 propSetHandlers[propName](props[propName], props); 7882 } 7883 } 7884 }; 7885 CalendarContent.prototype.componentWillUnmount = function () { 7886 window.removeEventListener('resize', this.handleWindowResize); 7887 this.resizeRunner.clear(); 7888 for (var _i = 0, _a = this.calendarInteractions; _i < _a.length; _i++) { 7889 var interaction = _a[_i]; 7890 interaction.destroy(); 7891 } 7892 this.props.emitter.trigger('_unmount'); 7893 }; 7894 CalendarContent.prototype._handleNavLinkClick = function (ev, anchorEl) { 7895 var _a = this.props, dateEnv = _a.dateEnv, options = _a.options, calendarApi = _a.calendarApi; 7896 var navLinkOptions = anchorEl.getAttribute('data-navlink'); 7897 navLinkOptions = navLinkOptions ? JSON.parse(navLinkOptions) : {}; 7898 var dateMarker = dateEnv.createMarker(navLinkOptions.date); 7899 var viewType = navLinkOptions.type; 7900 var customAction = viewType === 'day' ? options.navLinkDayClick : 7901 viewType === 'week' ? options.navLinkWeekClick : null; 7902 if (typeof customAction === 'function') { 7903 customAction.call(calendarApi, dateEnv.toDate(dateMarker), ev); 7904 } 7905 else { 7906 if (typeof customAction === 'string') { 7907 viewType = customAction; 7908 } 7909 calendarApi.zoomTo(dateMarker, viewType); 7910 } 7911 }; 7912 CalendarContent.prototype.buildAppendContent = function () { 7913 var props = this.props; 7914 var children = props.pluginHooks.viewContainerAppends.map(function (buildAppendContent) { return buildAppendContent(props); }); 7915 return createElement.apply(void 0, __spreadArrays([Fragment, {}], children)); 7916 }; 7917 CalendarContent.prototype.renderView = function (props) { 7918 var pluginHooks = props.pluginHooks; 7919 var viewSpec = props.viewSpec; 7920 var viewProps = { 7921 dateProfile: props.dateProfile, 7922 businessHours: props.businessHours, 7923 eventStore: props.renderableEventStore, 7924 eventUiBases: props.eventUiBases, 7925 dateSelection: props.dateSelection, 7926 eventSelection: props.eventSelection, 7927 eventDrag: props.eventDrag, 7928 eventResize: props.eventResize, 7929 isHeightAuto: props.isHeightAuto, 7930 forPrint: props.forPrint, 7931 }; 7932 var transformers = this.buildViewPropTransformers(pluginHooks.viewPropsTransformers); 7933 for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) { 7934 var transformer = transformers_1[_i]; 7935 __assign(viewProps, transformer.transform(viewProps, props)); 7936 } 7937 var ViewComponent = viewSpec.component; 7938 return (createElement(ViewComponent, __assign({}, viewProps))); 7939 }; 7940 return CalendarContent; 7941 }(PureComponent)); 7942 function buildToolbarProps(viewSpec, dateProfile, dateProfileGenerator, currentDate, now, title) { 7943 // don't force any date-profiles to valid date profiles (the `false`) so that we can tell if it's invalid 7944 var todayInfo = dateProfileGenerator.build(now, undefined, false); // TODO: need `undefined` or else INFINITE LOOP for some reason 7945 var prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate, false); 7946 var nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate, false); 7947 return { 7948 title: title, 7949 activeButton: viewSpec.type, 7950 isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now), 7951 isPrevEnabled: prevInfo.isValid, 7952 isNextEnabled: nextInfo.isValid, 7953 }; 7954 } 7955 // Plugin 7956 // ----------------------------------------------------------------------------------------------------------------- 7957 function buildViewPropTransformers(theClasses) { 7958 return theClasses.map(function (TheClass) { return new TheClass(); }); 7959 } 7960 7961 var CalendarRoot = /** @class */ (function (_super) { 7962 __extends(CalendarRoot, _super); 7963 function CalendarRoot() { 7964 var _this = _super !== null && _super.apply(this, arguments) || this; 7965 _this.state = { 7966 forPrint: false, 7967 }; 7968 _this.handleBeforePrint = function () { 7969 _this.setState({ forPrint: true }); 7970 }; 7971 _this.handleAfterPrint = function () { 7972 _this.setState({ forPrint: false }); 7973 }; 7974 return _this; 7975 } 7976 CalendarRoot.prototype.render = function () { 7977 var props = this.props; 7978 var options = props.options; 7979 var forPrint = this.state.forPrint; 7980 var isHeightAuto = forPrint || options.height === 'auto' || options.contentHeight === 'auto'; 7981 var height = (!isHeightAuto && options.height != null) ? options.height : ''; 7982 var classNames = [ 7983 'fc', 7984 forPrint ? 'fc-media-print' : 'fc-media-screen', 7985 "fc-direction-" + options.direction, 7986 props.theme.getClass('root'), 7987 ]; 7988 if (!getCanVGrowWithinCell()) { 7989 classNames.push('fc-liquid-hack'); 7990 } 7991 return props.children(classNames, height, isHeightAuto, forPrint); 7992 }; 7993 CalendarRoot.prototype.componentDidMount = function () { 7994 var emitter = this.props.emitter; 7995 emitter.on('_beforeprint', this.handleBeforePrint); 7996 emitter.on('_afterprint', this.handleAfterPrint); 7997 }; 7998 CalendarRoot.prototype.componentWillUnmount = function () { 7999 var emitter = this.props.emitter; 8000 emitter.off('_beforeprint', this.handleBeforePrint); 8001 emitter.off('_afterprint', this.handleAfterPrint); 8002 }; 8003 return CalendarRoot; 8004 }(BaseComponent)); 8005 8006 // Computes a default column header formatting string if `colFormat` is not explicitly defined 8007 function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) { 8008 // if more than one week row, or if there are a lot of columns with not much space, 8009 // put just the day numbers will be in each cell 8010 if (!datesRepDistinctDays || dayCnt > 10) { 8011 return createFormatter({ weekday: 'short' }); // "Sat" 8012 } 8013 if (dayCnt > 1) { 8014 return createFormatter({ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }); // "Sat 11/12" 8015 } 8016 return createFormatter({ weekday: 'long' }); // "Saturday" 8017 } 8018 8019 var CLASS_NAME = 'fc-col-header-cell'; // do the cushion too? no 8020 function renderInner(hookProps) { 8021 return hookProps.text; 8022 } 8023 8024 var TableDateCell = /** @class */ (function (_super) { 8025 __extends(TableDateCell, _super); 8026 function TableDateCell() { 8027 return _super !== null && _super.apply(this, arguments) || this; 8028 } 8029 TableDateCell.prototype.render = function () { 8030 var _a = this.context, dateEnv = _a.dateEnv, options = _a.options, theme = _a.theme, viewApi = _a.viewApi; 8031 var props = this.props; 8032 var date = props.date, dateProfile = props.dateProfile;
8033 var dayMeta = getDateMeta(date, props.todayRange, null, dateProfile); 8034 var classNames = [CLASS_NAME].concat(getDayClassNames(dayMeta, theme)); 8035 var text = dateEnv.format(date, props.dayHeaderFormat); 8036 // if colCnt is 1, we are already in a day-view and don't need a navlink 8037 var navLinkAttrs = (options.navLinks && !dayMeta.isDisabled && props.colCnt > 1) 8038 ? { 'data-navlink': buildNavLinkData(date), tabIndex: 0 } 8039 : {}; 8040 var hookProps = __assign(__assign(__assign({ date: dateEnv.toDate(date), view: viewApi }, props.extraHookProps), { text: text }), dayMeta); 8041 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), 8042 createElement("div", { className: "fc-scrollgrid-sync-inner" }, !dayMeta.isDisabled && (createElement("a", __assign({ ref: innerElRef, className: [ 8043 'fc-col-header-cell-cushion', 8044 props.isSticky ? 'fc-sticky' : '', 8045 ].join(' ') }, navLinkAttrs), innerContent))))); })); 8046 }; 8047 return TableDateCell; 8048 }(BaseComponent)); 8049 8050 var TableDowCell = /** @class */ (function (_super) { 8051 __extends(TableDowCell, _super); 8052 function TableDowCell() { 8053 return _super !== null && _super.apply(this, arguments) || this; 8054 } 8055 TableDowCell.prototype.render = function () { 8056 var props = this.props; 8057 var _a = this.context, dateEnv = _a.dateEnv, theme = _a.theme, viewApi = _a.viewApi, options = _a.options; 8058 var date = addDays(new Date(259200000), props.dow); // start with Sun, 04 Jan 1970 00:00:00 GMT 8059 var dateMeta = { 8060 dow: props.dow, 8061 isDisabled: false, 8062 isFuture: false, 8063 isPast: false, 8064 isToday: false, 8065 isOther: false, 8066 }; 8067 var classNames = [CLASS_NAME].concat(getDayClassNames(dateMeta, theme), props.extraClassNames || []); 8068 var text = dateEnv.format(date, props.dayHeaderFormat); 8069 var hookProps = __assign(__assign(__assign(__assign({ // TODO: make this public? 8070 date: date }, dateMeta), { view: viewApi }), props.extraHookProps), { text: text }); 8071 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), 8072 createElement("div", { className: "fc-scrollgrid-sync-inner" }, 8073 createElement("a", { className: [ 8074 'fc-col-header-cell-cushion', 8075 props.isSticky ? 'fc-sticky' : '', 8076 ].join(' '), ref: innerElRef }, innerContent)))); })); 8077 }; 8078 return TableDowCell; 8079 }(BaseComponent)); 8080 8081 var NowTimer = /** @class */ (function (_super) { 8082 __extends(NowTimer, _super); 8083 function NowTimer(props, context) { 8084 var _this = _super.call(this, props, context) || this; 8085 _this.initialNowDate = getNow(context.options.now, context.dateEnv); 8086 _this.initialNowQueriedMs = new Date().valueOf(); 8087 _this.state = _this.computeTiming().currentState; 8088 return _this; 8089 } 8090 NowTimer.prototype.render = function () { 8091 var _a = this, props = _a.props, state = _a.state; 8092 return props.children(state.nowDate, state.todayRange); 8093 }; 8094 NowTimer.prototype.componentDidMount = function () { 8095 this.setTimeout(); 8096 }; 8097 NowTimer.prototype.componentDidUpdate = function (prevProps) { 8098 if (prevProps.unit !== this.props.unit) { 8099 this.clearTimeout(); 8100 this.setTimeout(); 8101 } 8102 }; 8103 NowTimer.prototype.componentWillUnmount = function () { 8104 this.clearTimeout(); 8105 }; 8106 NowTimer.prototype.computeTiming = function () { 8107 var _a = this, props = _a.props, context = _a.context; 8108 var unroundedNow = addMs(this.initialNowDate, new Date().valueOf() - this.initialNowQueriedMs); 8109 var currentUnitStart = context.dateEnv.startOf(unroundedNow, props.unit); 8110 var nextUnitStart = context.dateEnv.add(currentUnitStart, createDuration(1, props.unit)); 8111 var waitMs = nextUnitStart.valueOf() - unroundedNow.valueOf(); 8112 // there is a max setTimeout ms value (https://stackoverflow.com/a/3468650/96342) 8113 // ensure no longer than a day 8114 waitMs = Math.min(1000 * 60 * 60 * 24, waitMs); 8115 return { 8116 currentState: { nowDate: currentUnitStart, todayRange: buildDayRange(currentUnitStart) }, 8117 nextState: { nowDate: nextUnitStart, todayRange: buildDayRange(nextUnitStart) }, 8118 waitMs: waitMs, 8119 }; 8120 }; 8121 NowTimer.prototype.setTimeout = function () { 8122 var _this = this; 8123 var _a = this.computeTiming(), nextState = _a.nextState, waitMs = _a.waitMs; 8124 this.timeoutId = setTimeout(function () { 8125 _this.setState(nextState, function () { 8126 _this.setTimeout(); 8127 }); 8128 }, waitMs); 8129 }; 8130 NowTimer.prototype.clearTimeout = function () { 8131 if (this.timeoutId) { 8132 clearTimeout(this.timeoutId); 8133 } 8134 }; 8135 NowTimer.contextType = ViewContextType; 8136 return NowTimer; 8137 }(Component)); 8138 function buildDayRange(date) { 8139 var start = startOfDay(date); 8140 var end = addDays(start, 1); 8141 return { start: start, end: end }; 8142 } 8143 8144 var DayHeader = /** @class */ (function (_super) { 8145 __extends(DayHeader, _super); 8146 function DayHeader() { 8147 var _this = _super !== null && _super.apply(this, arguments) || this; 8148 _this.createDayHeaderFormatter = memoize(createDayHeaderFormatter); 8149 return _this; 8150 } 8151 DayHeader.prototype.render = function () { 8152 var context = this.context; 8153 var _a = this.props, dates = _a.dates, dateProfile = _a.dateProfile, datesRepDistinctDays = _a.datesRepDistinctDays, renderIntro = _a.renderIntro; 8154 var dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dates.length); 8155 return (createElement(NowTimer, { unit: "day" }, function (nowDate, todayRange) { return (createElement("tr", null, 8156 renderIntro && renderIntro('day'), 8157 dates.map(function (date) { return (datesRepDistinctDays ? (createElement(TableDateCell, { key: date.toISOString(), date: date, dateProfile: dateProfile, todayRange: todayRange, colCnt: dates.length, dayHeaderFormat: dayHeaderFormat })) : (createElement(TableDowCell, { key: date.getUTCDay(), dow: date.getUTCDay(), dayHeaderFormat: dayHeaderFormat }))); }))); })); 8158 }; 8159 return DayHeader; 8160 }(BaseComponent)); 8161 function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) { 8162 return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt); 8163 } 8164
8165 var DaySeriesModel = /** @class */ (function () { 8166 function DaySeriesModel(range, dateProfileGenerator) { 8167 var date = range.start; 8168 var end = range.end; 8169 var indices = []; 8170 var dates = []; 8171 var dayIndex = -1; 8172 while (date < end) { // loop each day from start to end 8173 if (dateProfileGenerator.isHiddenDay(date)) { 8174 indices.push(dayIndex + 0.5); // mark that it's between indices 8175 } 8176 else { 8177 dayIndex += 1; 8178 indices.push(dayIndex); 8179 dates.push(date); 8180 } 8181 date = addDays(date, 1); 8182 } 8183 this.dates = dates; 8184 this.indices = indices; 8185 this.cnt = dates.length; 8186 } 8187 DaySeriesModel.prototype.sliceRange = function (range) { 8188 var firstIndex = this.getDateDayIndex(range.start); // inclusive first index 8189 var lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index 8190 var clippedFirstIndex = Math.max(0, firstIndex); 8191 var clippedLastIndex = Math.min(this.cnt - 1, lastIndex); 8192 // deal with in-between indices 8193 clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell 8194 clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell 8195 if (clippedFirstIndex <= clippedLastIndex) { 8196 return { 8197 firstIndex: clippedFirstIndex, 8198 lastIndex: clippedLastIndex, 8199 isStart: firstIndex === clippedFirstIndex, 8200 isEnd: lastIndex === clippedLastIndex, 8201 }; 8202 } 8203 return null; 8204 }; 8205 // Given a date, returns its chronolocial cell-index from the first cell of the grid. 8206 // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets. 8207 // If before the first offset, returns a negative number. 8208 // If after the last offset, returns an offset past the last cell offset. 8209 // Only works for *start* dates of cells. Will not work for exclusive end dates for cells. 8210 DaySeriesModel.prototype.getDateDayIndex = function (date) { 8211 var indices = this.indices; 8212 var dayOffset = Math.floor(diffDays(this.dates[0], date)); 8213 if (dayOffset < 0) { 8214 return indices[0] - 1; 8215 } 8216 if (dayOffset >= indices.length) { 8217 return indices[indices.length - 1] + 1; 8218 } 8219 return indices[dayOffset]; 8220 };
8221 return DaySeriesModel; 8222 }()); 8223 8224 var DayTableModel = /** @class */ (function () { 8225 function DayTableModel(daySeries, breakOnWeeks) { 8226 var dates = daySeries.dates; 8227 var daysPerRow; 8228 var firstDay; 8229 var rowCnt; 8230 if (breakOnWeeks) { 8231 // count columns until the day-of-week repeats 8232 firstDay = dates[0].getUTCDay(); 8233 for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow += 1) { 8234 if (dates[daysPerRow].getUTCDay() === firstDay) { 8235 break; 8236 } 8237 } 8238 rowCnt = Math.ceil(dates.length / daysPerRow); 8239 } 8240 else { 8241 rowCnt = 1; 8242 daysPerRow = dates.length; 8243 } 8244 this.rowCnt = rowCnt; 8245 this.colCnt = daysPerRow; 8246 this.daySeries = daySeries; 8247 this.cells = this.buildCells(); 8248 this.headerDates = this.buildHeaderDates(); 8249 } 8250 DayTableModel.prototype.buildCells = function () { 8251 var rows = []; 8252 for (var row = 0; row < this.rowCnt; row += 1) { 8253 var cells = []; 8254 for (var col = 0; col < this.colCnt; col += 1) { 8255 cells.push(this.buildCell(row, col)); 8256 } 8257 rows.push(cells); 8258 } 8259 return rows; 8260 }; 8261 DayTableModel.prototype.buildCell = function (row, col) { 8262 var date = this.daySeries.dates[row * this.colCnt + col]; 8263 return { 8264 key: date.toISOString(), 8265 date: date, 8266 }; 8267 }; 8268 DayTableModel.prototype.buildHeaderDates = function () { 8269 var dates = []; 8270 for (var col = 0; col < this.colCnt; col += 1) { 8271 dates.push(this.cells[0][col].date); 8272 } 8273 return dates; 8274 }; 8275 DayTableModel.prototype.sliceRange = function (range) { 8276 var colCnt = this.colCnt; 8277 var seriesSeg = this.daySeries.sliceRange(range); 8278 var segs = []; 8279 if (seriesSeg) { 8280 var firstIndex = seriesSeg.firstIndex, lastIndex = seriesSeg.lastIndex; 8281 var index = firstIndex; 8282 while (index <= lastIndex) { 8283 var row = Math.floor(index / colCnt); 8284 var nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1); 8285 segs.push({ 8286 row: row, 8287 firstCol: index % colCnt, 8288 lastCol: (nextIndex - 1) % colCnt, 8289 isStart: seriesSeg.isStart && index === firstIndex, 8290 isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex, 8291 }); 8292 index = nextIndex; 8293 } 8294 } 8295 return segs; 8296 }; 8297 return DayTableModel; 8298 }()); 8299 8300 var Slicer = /** @class */ (function () { 8301 function Slicer() { 8302 this.sliceBusinessHours = memoize(this._sliceBusinessHours); 8303 this.sliceDateSelection = memoize(this._sliceDateSpan); 8304 this.sliceEventStore = memoize(this._sliceEventStore); 8305 this.sliceEventDrag = memoize(this._sliceInteraction); 8306 this.sliceEventResize = memoize(this._sliceInteraction); 8307 this.forceDayIfListItem = false; // hack 8308 } 8309 Slicer.prototype.sliceProps = function (props, dateProfile, nextDayThreshold, context) { 8310 var extraArgs = []; 8311 for (var _i = 4; _i < arguments.length; _i++) { 8312 extraArgs[_i - 4] = arguments[_i]; 8313 } 8314 var eventUiBases = props.eventUiBases; 8315 var eventSegs = this.sliceEventStore.apply(this, __spreadArrays([props.eventStore, eventUiBases, dateProfile, nextDayThreshold], extraArgs)); 8316 return { 8317 dateSelectionSegs: this.sliceDateSelection.apply(this, __spreadArrays([props.dateSelection, eventUiBases, context], extraArgs)), 8318 businessHourSegs: this.sliceBusinessHours.apply(this, __spreadArrays([props.businessHours, dateProfile, nextDayThreshold, context], extraArgs)), 8319 fgEventSegs: eventSegs.fg, 8320 bgEventSegs: eventSegs.bg, 8321 eventDrag: this.sliceEventDrag.apply(this, __spreadArrays([props.eventDrag, eventUiBases, dateProfile, nextDayThreshold], extraArgs)), 8322 eventResize: this.sliceEventResize.apply(this, __spreadArrays([props.eventResize, eventUiBases, dateProfile, nextDayThreshold], extraArgs)), 8323 eventSelection: props.eventSelection, 8324 }; // TODO: give interactionSegs? 8325 }; 8326 Slicer.prototype.sliceNowDate = function (// does not memoize 8327 date, context) { 8328 var extraArgs = []; 8329 for (var _i = 2; _i < arguments.length; _i++) { 8330 extraArgs[_i - 2] = arguments[_i]; 8331 } 8332 return this._sliceDateSpan.apply(this, __spreadArrays([{ range: { start: date, end: addMs(date, 1) }, allDay: false }, 8333 {}, 8334 context], extraArgs)); 8335 }; 8336 Slicer.prototype._sliceBusinessHours = function (businessHours, dateProfile, nextDayThreshold, context) { 8337 var extraArgs = []; 8338 for (var _i = 4; _i < arguments.length; _i++) { 8339 extraArgs[_i - 4] = arguments[_i]; 8340 } 8341 if (!businessHours) { 8342 return []; 8343 } 8344 return this._sliceEventStore.apply(this, __spreadArrays([expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), context), 8345 {}, 8346 dateProfile, 8347 nextDayThreshold], extraArgs)).bg; 8348 }; 8349 Slicer.prototype._sliceEventStore = function (eventStore, eventUiBases, dateProfile, nextDayThreshold) { 8350 var extraArgs = []; 8351 for (var _i = 4; _i < arguments.length; _i++) { 8352 extraArgs[_i - 4] = arguments[_i]; 8353 } 8354 if (eventStore) { 8355 var rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold); 8356 return { 8357 bg: this.sliceEventRanges(rangeRes.bg, extraArgs), 8358 fg: this.sliceEventRanges(rangeRes.fg, extraArgs), 8359 }; 8360 } 8361 return { bg: [], fg: [] }; 8362 }; 8363 Slicer.prototype._sliceInteraction = function (interaction, eventUiBases, dateProfile, nextDayThreshold) { 8364 var extraArgs = []; 8365 for (var _i = 4; _i < arguments.length; _i++) { 8366 extraArgs[_i - 4] = arguments[_i]; 8367 } 8368 if (!interaction) { 8369 return null; 8370 } 8371 var rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold); 8372 return { 8373 segs: this.sliceEventRanges(rangeRes.fg, extraArgs), 8374 affectedInstances: interaction.affectedEvents.instances, 8375 isEvent: interaction.isEvent, 8376 }; 8377 }; 8378 Slicer.prototype._sliceDateSpan = function (dateSpan, eventUiBases, context) { 8379 var extraArgs = []; 8380 for (var _i = 3; _i < arguments.length; _i++) { 8381 extraArgs[_i - 3] = arguments[_i]; 8382 } 8383 if (!dateSpan) { 8384 return []; 8385 } 8386 var eventRange = fabricateEventRange(dateSpan, eventUiBases, context); 8387 var segs = this.sliceRange.apply(this, __spreadArrays([dateSpan.range], extraArgs)); 8388 for (var _a = 0, segs_1 = segs; _a < segs_1.length; _a++) { 8389 var seg = segs_1[_a]; 8390 seg.eventRange = eventRange; 8391 } 8392 return segs; 8393 }; 8394 /* 8395 "complete" seg means it has component and eventRange 8396 */ 8397 Slicer.prototype.sliceEventRanges = function (eventRanges, extraArgs) { 8398 var segs = []; 8399 for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) { 8400 var eventRange = eventRanges_1[_i]; 8401 segs.push.apply(segs, this.sliceEventRange(eventRange, extraArgs)); 8402 } 8403 return segs; 8404 }; 8405 /* 8406 "complete" seg means it has component and eventRange 8407 */ 8408 Slicer.prototype.sliceEventRange = function (eventRange, extraArgs) { 8409 var dateRange = eventRange.range; 8410 // hack to make multi-day events that are being force-displayed as list-items to take up only one day 8411 if (this.forceDayIfListItem && eventRange.ui.display === 'list-item') { 8412 dateRange = { 8413 start: dateRange.start, 8414 end: addDays(dateRange.start, 1), 8415 }; 8416 } 8417 var segs = this.sliceRange.apply(this, __spreadArrays([dateRange], extraArgs)); 8418 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 8419 var seg = segs_2[_i]; 8420 seg.eventRange = eventRange; 8421 seg.isStart = eventRange.isStart && seg.isStart; 8422 seg.isEnd = eventRange.isEnd && seg.isEnd; 8423 } 8424 return segs; 8425 }; 8426 return Slicer; 8427 }()); 8428 /* 8429 for incorporating slotMinTime/slotMaxTime if appropriate 8430 TODO: should be part of DateProfile! 8431 TimelineDateProfile already does this btw 8432 */ 8433 function computeActiveRange(dateProfile, isComponentAllDay) { 8434 var range = dateProfile.activeRange; 8435 if (isComponentAllDay) { 8436 return range; 8437 } 8438 return { 8439 start: addMs(range.start, dateProfile.slotMinTime.milliseconds), 8440 end: addMs(range.end, dateProfile.slotMaxTime.milliseconds - 864e5), 8441 }; 8442 } 8443 8444 var VISIBLE_HIDDEN_RE = /^(visible|hidden)$/; 8445 var Scroller = /** @class */ (function (_super) { 8446 __extends(Scroller, _super); 8447 function Scroller() { 8448 var _this = _super !== null && _super.apply(this, arguments) || this; 8449 _this.handleEl = function (el) { 8450 _this.el = el; 8451 setRef(_this.props.elRef, el); 8452 }; 8453 return _this; 8454 } 8455 Scroller.prototype.render = function () { 8456 var props = this.props; 8457 var liquid = props.liquid, liquidIsAbsolute = props.liquidIsAbsolute; 8458 var isAbsolute = liquid && liquidIsAbsolute; 8459 var className = ['fc-scroller']; 8460 if (liquid) { 8461 if (liquidIsAbsolute) { 8462 className.push('fc-scroller-liquid-absolute'); 8463 } 8464 else { 8465 className.push('fc-scroller-liquid'); 8466 } 8467 } 8468 return (createElement("div", { ref: this.handleEl, className: className.join(' '), style: { 8469 overflowX: props.overflowX, 8470 overflowY: props.overflowY, 8471 left: (isAbsolute && -(props.overcomeLeft || 0)) || '', 8472 right: (isAbsolute && -(props.overcomeRight || 0
8472)) || '', 8473 bottom: (isAbsolute && -(props.overcomeBottom || 0)) || '', 8474 marginLeft: (!isAbsolute && -(props.overcomeLeft || 0)) || '', 8475 marginRight: (!isAbsolute && -(props.overcomeRight || 0)) || '', 8476 marginBottom: (!isAbsolute && -(props.overcomeBottom || 0)) || '', 8477 maxHeight: props.maxHeight || '', 8478 } }, props.children)); 8479 }; 8480 Scroller.prototype.needsXScrolling = function () { 8481 if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) { 8482 return false; 8483 } 8484 // testing scrollWidth>clientWidth is unreliable cross-browser when pixel heights aren't integers. 8485 // much more reliable to see if children are taller than the scroller, even tho doesn't account for 8486 // inner-child margins and absolute positioning 8487 var el = this.el; 8488 var realClientWidth = this.el.getBoundingClientRect().width - this.getYScrollbarWidth(); 8489 var children = el.children; 8490 for (var i = 0; i < children.length; i += 1) { 8491 var childEl = children[i]; 8492 if (childEl.getBoundingClientRect().width > realClientWidth) { 8493 return true; 8494 } 8495 } 8496 return false; 8497 }; 8498 Scroller.prototype.needsYScrolling = function () { 8499 if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) { 8500 return false; 8501 } 8502 // testing scrollHeight>clientHeight is unreliable cross-browser when pixel heights aren't integers. 8503 // much more reliable to see if children are taller than the scroller, even tho doesn't account for 8504 // inner-child margins and absolute positioning 8505 var el = this.el; 8506 var realClientHeight = this.el.getBoundingClientRect().height - this.getXScrollbarWidth(); 8507 var children = el.children; 8508 for (var i = 0; i < children.length; i += 1) { 8509 var childEl = children[i]; 8510 if (childEl.getBoundingClientRect().height > realClientHeight) { 8511 return true; 8512 } 8513 } 8514 return false; 8515 }; 8516 Scroller.prototype.getXScrollbarWidth = function () { 8517 if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) { 8518 return 0; 8519 } 8520 return this.el.offsetHeight - this.el.clientHeight; // only works because we guarantee no borders. TODO: add to CSS with important? 8521 }; 8522 Scroller.prototype.getYScrollbarWidth = function () { 8523 if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) { 8524 return 0; 8525 } 8526 return this.el.offsetWidth - this.el.clientWidth; // only works because we guarantee no borders. TODO: add to CSS with important? 8527 }; 8528 return Scroller; 8529 }(BaseComponent)); 8530 8531 /* 8532 TODO: somehow infer OtherArgs from masterCallback? 8533 TODO: infer RefType from masterCallback if provided 8534 */ 8535 var RefMap = /** @class */ (function () { 8536 function RefMap(masterCallback) { 8537 var _this = this; 8538 this.masterCallback = masterCallback; 8539 this.currentMap = {}; 8540 this.depths = {}; 8541 this.callbackMap = {}; 8542 this.handleValue = function (val, key) { 8543 var _a = _this, depths = _a.depths, currentMap = _a.currentMap; 8544 var removed = false; 8545 var added = false; 8546 if (val !== null) { 8547 // for bug... ACTUALLY: can probably do away with this now that callers don't share numeric indices anymore 8548 removed = (key in currentMap); 8549 currentMap[key] = val; 8550 depths[key] = (depths[key] || 0) + 1; 8551 added = true; 8552 } 8553 else { 8554 depths[key] -= 1; 8555 if (!depths[key]) { 8556 delete currentMap[key]; 8557 delete _this.callbackMap[key]; 8558 removed = true; 8559 } 8560 } 8561 if (_this.masterCallback) { 8562 if (removed) { 8563 _this.masterCallback(null, String(key)); 8564 } 8565 if (added) { 8566 _this.masterCallback(val, String(key)); 8567 } 8568 } 8569 }; 8570 } 8571 RefMap.prototype.createRef = function (key) { 8572 var _this = this; 8573 var refCallback = this.callbackMap[key]; 8574 if (!refCallback) { 8575 refCallback = this.callbackMap[key] = function (val) { 8576 _this.handleValue(val, String(key)); 8577 }; 8578 } 8579 return refCallback; 8580 }; 8581 // TODO: check callers that don't care about order. should use getAll instead 8582 // NOTE: this method has become less valuable now that we are encouraged to map order by some other index 8583 // TODO: provide ONE array-export function, buildArray, which fails on non-numeric indexes. caller can manipulate and "collect" 8584 RefMap.prototype.collect = function (startIndex, endIndex, step) { 8585 return collectFromHash(this.currentMap, startIndex, endIndex, step); 8586 }; 8587 RefMap.prototype.getAll = function () { 8588 return hashValuesToArray(this.currentMap); 8589 }; 8590 return RefMap; 8591 }()); 8592 8593 function computeShrinkWidth(chunkEls) { 8594 var shrinkCells = findElements(chunkEls, '.fc-scrollgrid-shrink'); 8595 var largestWidth = 0; 8596 for (var _i = 0, shrinkCells_1 = shrinkCells; _i < shrinkCells_1.length; _i++) { 8597 var shrinkCell = shrinkCells_1[_i]; 8598 largestWidth = Math.max(largestWidth, computeSmallestCellWidth(shrinkCell)); 8599 } 8600 return Math.ceil(largestWidth); // <table> elements work best with integers. round up to ensure contents fits 8601 } 8602 function getSectionHasLiquidHeight(props, sectionConfig) { 8603 return props.liquid && sectionConfig.liquid; // does the section do liquid-height? (need to have whole scrollgrid liquid-height as well) 8604 } 8605 function getAllowYScrolling(props, sectionConfig) { 8606 return sectionConfig.maxHeight != null || // if its possible for the height to max out, we might need scrollbars 8607 getSectionHasLiquidHeight(props, sectionConfig); // if the section is liquid height, it might condense enough to require scrollbars 8608 } 8609 // TODO: ONLY use `arg`. force out internal function to use same API 8610 function renderChunkContent(sectionConfig, chunkConfig, arg) { 8611 var expandRows = arg.expandRows; 8612 var content = typeof chunkConfig.content === 'function' ? 8613 chunkConfig.content(arg) : 8614 createElement('table', { 8615 className: [ 8616 chunkConfig.tableClassName, 8617 sectionConfig.syncRowHeights ? 'fc-scrollgrid-sync-table' : '', 8618 ].join(' '), 8619 style: { 8620 minWidth: arg.tableMinWidth, 8621 width: arg.clientWidth, 8622 height: expandRows ? arg.clientHeight : '', 8623 }, 8624 }, arg.tableColGroupNode, createElement('tbody', {}, typeof chunkConfig.rowContent === 'function' ? chunkConfig.rowContent(arg) : chunkConfig.rowContent)); 8625 return content; 8626 } 8627 function isColPropsEqual(cols0, cols1) { 8628 return isArraysEqual(cols0, cols1, isPropsEqual); 8629 } 8630 function renderMicroColGroup(cols, shrinkWidth) { 8631 var colNodes = []; 8632 /* 8633 for ColProps with spans, it would have been great to make a single <col span=""> 8634 HOWEVER, Chrome was getting messing up distributing the width to <td>/<th> elements with colspans. 8635 SOLUTION: making individual <col> elements makes Chrome behave. 8636 */ 8637 for (var _i = 0, cols_1 = cols; _i < cols_1.length; _i++) { 8638 var colProps = cols_1[_i]; 8639 var span = colProps.span || 1; 8640 for (var i = 0; i < span; i += 1) {
8641 colNodes.push(createElement("col", { style: { 8642 width: colProps.width === 'shrink' ? sanitizeShrinkWidth(shrinkWidth) : (colProps.width || ''), 8643 minWidth: colProps.minWidth || '', 8644 } })); 8645 } 8646 } 8647 return createElement.apply(void 0, __spreadArrays(['colgroup', {}], colNodes)); 8648 } 8649 function sanitizeShrinkWidth(shrinkWidth) { 8650 /* why 4? if we do 0, it will kill any border, which are needed for computeSmallestCellWidth 8651 4 accounts for 2 2-pixel borders. TODO: better solution? */ 8652 return shrinkWidth == null ? 4 : shrinkWidth; 8653 } 8654 function hasShrinkWidth(cols) { 8655 for (var _i = 0, cols_2 = cols; _i < cols_2.length; _i++) { 8656 var col = cols_2[_i]; 8657 if (col.width === 'shrink') { 8658 return true; 8659 } 8660 } 8661 return false; 8662 } 8663 function getScrollGridClassNames(liquid, context) { 8664 var classNames = [ 8665 'fc-scrollgrid', 8666 context.theme.getClass('table'), 8667 ]; 8668 if (liquid) { 8669 classNames.push('fc-scrollgrid-liquid'); 8670 } 8671 return classNames; 8672 } 8673 function getSectionClassNames(sectionConfig, wholeTableVGrow) { 8674 var classNames = [ 8675 'fc-scrollgrid-section', 8676 "fc-scrollgrid-section-" + sectionConfig.type, 8677 sectionConfig.className, 8678 ]; 8679 if (wholeTableVGrow && sectionConfig.liquid && sectionConfig.maxHeight == null) { 8680 classNames.push('fc-scrollgrid-section-liquid'); 8681 } 8682 if (sectionConfig.isSticky) { 8683 classNames.push('fc-scrollgrid-section-sticky'); 8684 } 8685 return classNames; 8686 }
8687 function renderScrollShim(arg) { 8688 return (createElement("div", { className: "fc-scrollgrid-sticky-shim", style: { 8689 width: arg.clientWidth, 8690 minWidth: arg.tableMinWidth, 8691 } })); 8692 } 8693 function getStickyHeaderDates(options) { 8694 var stickyHeaderDates = options.stickyHeaderDates; 8695 if (stickyHeaderDates == null || stickyHeaderDates === 'auto') { 8696 stickyHeaderDates = options.height === 'auto' || options.viewHeight === 'auto'; 8697 } 8698 return stickyHeaderDates; 8699 } 8700 function getStickyFooterScrollbar(options) { 8701 var stickyFooterScrollbar = options.stickyFooterScrollbar; 8702 if (stickyFooterScrollbar == null || stickyFooterScrollbar === 'auto') { 8703 stickyFooterScrollbar = options.height === 'auto' || options.viewHeight === 'auto'; 8704 } 8705 return stickyFooterScrollbar; 8706 } 8707 8708 var SimpleScrollGrid = /** @class */ (function (_super) { 8709 __extends(SimpleScrollGrid, _super); 8710 function SimpleScrollGrid() { 8711 var _this = _super !== null && _super.apply(this, arguments) || this; 8712 _this.processCols = memoize(function (a) { return a; }, isColPropsEqual); // so we get same `cols` props every time 8713 // yucky to memoize VNodes, but much more efficient for consumers 8714 _this.renderMicroColGroup = memoize(renderMicroColGroup); 8715 _this.scrollerRefs = new RefMap(); 8716 _this.scrollerElRefs = new RefMap(_this._handleScrollerEl.bind(_this)); 8717 _this.state = { 8718 shrinkWidth: null, 8719 forceYScrollbars: false, 8720 scrollerClientWidths: {}, 8721 scrollerClientHeights: {}, 8722 }; 8723 // TODO: can do a really simple print-view. dont need to join rows 8724 _this.handleSizing = function () { 8725 _this.setState(__assign({ shrinkWidth: _this.computeShrinkWidth() }, _this.computeScrollerDims())); 8726 }; 8727 return _this; 8728 } 8729 SimpleScrollGrid.prototype.render = function () { 8730 var _a = this, props = _a.props, state = _a.state, context = _a.context; 8731 var sectionConfigs = props.sections || []; 8732 var cols = this.processCols(props.cols); 8733 var microColGroupNode = this.renderMicroColGroup(cols, state.shrinkWidth); 8734 var classNames = getScrollGridClassNames(props.liquid, context); 8735 // TODO: make DRY 8736 var configCnt = sectionConfigs.length; 8737 var configI = 0; 8738 var currentConfig; 8739 var headSectionNodes = []; 8740 var bodySectionNodes = []; 8741 var footSectionNodes = []; 8742 while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'header') { 8743 headSectionNodes.push(this.renderSection(currentConfig, microColGroupNode)); 8744 configI += 1; 8745 } 8746 while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'body') { 8747 bodySectionNodes.push(this.renderSection(currentConfig, microColGroupNode)); 8748 configI += 1; 8749 } 8750 while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'footer') { 8751 footSectionNodes.push(this.renderSection(currentConfig, microColGroupNode)); 8752 configI += 1; 8753 } 8754 // firefox bug: when setting height on table and there is a thead or tfoot, 8755 // the necessary height:100% on the liquid-height body section forces the *whole* table to be taller. (bug #5524) 8756 // use getCanVGrowWithinCell as a way to detect table-stupid firefox. 8757 // if so, use a simpler dom structure, jam everything into a lone tbody. 8758 var isBuggy = !getCanVGrowWithinCell(); 8759 return createElement('table', { 8760 className: classNames.join(' '), 8761 style: { height: props.height }, 8762 }, Boolean(!isBuggy && headSectionNodes.length) && createElement.apply(void 0, __spreadArrays(['thead', {}
8762], 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))); 8763 }; 8764 SimpleScrollGrid.prototype.renderSection = function (sectionConfig, microColGroupNode) { 8765 if ('outerContent' in sectionConfig) { 8766 return (createElement(Fragment, { key: sectionConfig.key }, sectionConfig.outerContent)); 8767 } 8768 return (createElement("tr", { key: sectionConfig.key, className: getSectionClassNames(sectionConfig, this.props.liquid).join(' ') }, this.renderChunkTd(sectionConfig, microColGroupNode, sectionConfig.chunk))); 8769 }; 8770 SimpleScrollGrid.prototype.renderChunkTd = function (sectionConfig, microColGroupNode, chunkConfig) { 8771 if ('outerContent' in chunkConfig) { 8772 return chunkConfig.outerContent; 8773 } 8774 var props = this.props; 8775 var _a = this.state, forceYScrollbars = _a.forceYScrollbars, scrollerClientWidths = _a.scrollerClientWidths, scrollerClientHeights = _a.scrollerClientHeights; 8776 var needsYScrolling = getAllowYScrolling(props, sectionConfig); // TODO: do lazily. do in section config? 8777 var isLiquid = getSectionHasLiquidHeight(props, sectionConfig); 8778 // for `!props.liquid` - is WHOLE scrollgrid natural height? 8779 // TODO: do same thing in advanced scrollgrid? prolly not b/c always has horizontal scrollbars 8780 var overflowY = !props.liquid ? 'visible' : 8781 forceYScrollbars ? 'scroll' : 8782 !needsYScrolling ? 'hidden' : 8783 'auto'; 8784 var sectionKey = sectionConfig.key; 8785 var content = renderChunkContent(sectionConfig, chunkConfig, { 8786 tableColGroupNode: microColGroupNode, 8787 tableMinWidth: '', 8788 clientWidth: scrollerClientWidths[sectionKey] !== undefined ? scrollerClientWidths[sectionKey] : null, 8789 clientHeight: scrollerClientHeights[sectionKey] !== undefined ? scrollerClientHeights[sectionKey] : null, 8790 expandRows: sectionConfig.expandRows, 8791 syncRowHeights: false, 8792 rowSyncHeights: [], 8793 reportRowHeightChange: function () { }, 8794 }); 8795 return (createElement("td", { ref: chunkConfig.elRef }, 8796 createElement("div", { className: "fc-scroller-harness" + (isLiquid ? ' fc-scroller-harness-liquid' : '') }, 8797 createElement(Scroller, { ref: this.scrollerRefs.createRef(sectionKey), elRef: this.scrollerElRefs.createRef(sectionKey), overflowY: overflowY, overflowX: !props.liquid ? 'visible' : 'hidden' /* natural height? */, maxHeight: sectionConfig.maxHeight, liquid: isLiquid, liquidIsAbsolute // because its within a harness 8798 : true }, content)))); 8799 }; 8800 SimpleScrollGrid.prototype._handleScrollerEl = function (scrollerEl, key) { 8801 var section = getSectionByKey(this.props.sections, key); 8802 if (section) { 8803 setRef(section.chunk.scrollerElRef, scrollerEl); 8804 } 8805 }; 8806 SimpleScrollGrid.prototype.componentDidMount = function () { 8807 this.handleSizing(); 8808 this.context.addResizeHandler(this.handleSizing); 8809 }; 8810 SimpleScrollGrid.prototype.componentDidUpdate = function () { 8811 // TODO: need better solution when state contains non-sizing things 8812 this.handleSizing(); 8813 }; 8814 SimpleScrollGrid.prototype.componentWillUnmount = function () { 8815 this.context.removeResizeHandler(this.handleSizing); 8816 }; 8817 SimpleScrollGrid.prototype.computeShrinkWidth = function () { 8818 return hasShrinkWidth(this.props.cols) 8819 ? computeShrinkWidth(this.scrollerElRefs.getAll()) 8820 : 0; 8821 }; 8822 SimpleScrollGrid.prototype.computeScrollerDims = function () { 8823 var scrollbarWidth = getScrollbarWidths(); 8824 var _a = this, scrollerRefs = _a.scrollerRefs, scrollerElRefs = _a.scrollerElRefs; 8825 var forceYScrollbars = false;
8826 var scrollerClientWidths = {}; 8827 var scrollerClientHeights = {}; 8828 for (var sectionKey in scrollerRefs.currentMap) { 8829 var scroller = scrollerRefs.currentMap[sectionKey]; 8830 if (scroller && scroller.needsYScrolling()) { 8831 forceYScrollbars = true; 8832 break; 8833 } 8834 } 8835 for (var _i = 0, _b = this.props.sections; _i < _b.length; _i++) { 8836 var section = _b[_i]; 8837 var sectionKey = section.key; 8838 var scrollerEl = scrollerElRefs.currentMap[sectionKey]; 8839 if (scrollerEl) { 8840 var harnessEl = scrollerEl.parentNode; // TODO: weird way to get this. need harness b/c doesn't include table borders 8841 scrollerClientWidths[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().width - (forceYScrollbars 8842 ? scrollbarWidth.y // use global because scroller might not have scrollbars yet but will need them in future 8843 : 0)); 8844 scrollerClientHeights[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().height); 8845 } 8846 } 8847 return { forceYScrollbars: forceYScrollbars, scrollerClientWidths: scrollerClientWidths, scrollerClientHeights: scrollerClientHeights }; 8848 }; 8849 return SimpleScrollGrid; 8850 }(BaseComponent)); 8851 SimpleScrollGrid.addStateEquality({ 8852 scrollerClientWidths: isPropsEqual, 8853 scrollerClientHeights: isPropsEqual, 8854 }); 8855 function getSectionByKey(sections, key) { 8856 for (var _i = 0, sections_1 = sections; _i < sections_1.length; _i++) { 8857 var section = sections_1[_i]; 8858 if (section.key === key) { 8859 return section; 8860 } 8861 } 8862 return null; 8863 } 8864 8865 var EventRoot = /** @class */ (function (_super) { 8866 __extends(EventRoot, _super); 8867 function EventRoot() { 8868 var _this = _super !== null && _super.apply(this, arguments) || this; 8869 _this.elRef = createRef(); 8870 return _this; 8871 } 8872 EventRoot.prototype.render = function () { 8873 var _a = this, props = _a.props, context = _a.context; 8874 var options = context.options; 8875 var seg = props.seg; 8876 var eventRange = seg.eventRange; 8877 var ui = eventRange.ui; 8878 var hookProps = { 8879 event: new EventApi(context, eventRange.def, eventRange.instance), 8880 view: context.viewApi, 8881 timeText: props.timeText, 8882 textColor: ui.textColor, 8883 backgroundColor: ui.backgroundColor, 8884 borderColor: ui.borderColor, 8885 isDraggable: !props.disableDragging && computeSegDraggable(seg, context), 8886 isStartResizable: !props.disableResizing && computeSegStartResizable(seg, context), 8887 isEndResizable: !props.disableResizing && computeSegEndResizable(seg), 8888 isMirror: Boolean(props.isDragging || props.isResizing || props.isDateSelecting), 8889 isStart: Boolean(seg.isStart), 8890 isEnd: Boolean(seg.isEnd), 8891 isPast: Boolean(props.isPast), 8892 isFuture: Boolean(props.isFuture), 8893 isToday: Boolean(props.isToday), 8894 isSelected: Boolean(props.isSelected), 8895 isDragging: Boolean(props.isDragging), 8896 isResizing: Boolean(props.isResizing), 8897 }; 8898 var standardClassNames = getEventClassNames(hookProps).concat(ui.classNames); 8899 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); })); 8900 }; 8901 EventRoot.prototype.componentDidMount = function () { 8902 setElSeg(this.elRef.current, this.props.seg); 8903 }; 8904 /* 8905 need to re-assign seg to the element if seg changes, even if the element is the same 8906 */ 8907 EventRoot.prototype.componentDidUpdate = function (prevProps) { 8908 var seg = this.props.seg; 8909 if (seg !== prevProps.seg) { 8910 setElSeg(this.elRef.current, seg); 8911 } 8912 }; 8913 return EventRoot; 8914 }(BaseComponent)); 8915 8916 // should not be a purecomponent 8917 var StandardEvent = /** @class */ (function (_super) { 8918 __extends(StandardEvent, _super); 8919 function StandardEvent() { 8920 return _super !== null && _super.apply(this, arguments) || this; 8921 } 8922 StandardEvent.prototype.render = function () { 8923 var _a = this, props = _a.props, context = _a.context; 8924 var seg = props.seg; 8925 var timeFormat = context.options.eventTimeFormat || props.defaultTimeFormat; 8926 var timeText = buildSegTimeText(seg, timeFormat, context, props.defaultDisplayEventTime, props.defaultDisplayEventEnd); 8927 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
8927oncat(classNames).join(' '), style: { 8928 borderColor: hookProps.borderColor, 8929 backgroundColor: hookProps.backgroundColor, 8930 }, ref: rootElRef }, getSegAnchorAttrs(seg)), 8931 createElement("div", { className: "fc-event-main", ref: innerElRef, style: { color: hookProps.textColor } }, innerContent), 8932 hookProps.isStartResizable && 8933 createElement("div", { className: "fc-event-resizer fc-event-resizer-start" }), 8934 hookProps.isEndResizable && 8935 createElement("div", { className: "fc-event-resizer fc-event-resizer-end" }))); })); 8936 }; 8937 return StandardEvent; 8938 }(BaseComponent)); 8939 function renderInnerContent(innerProps) { 8940 return (createElement("div", { className: "fc-event-main-frame" }, 8941 innerProps.timeText && (createElement("div", { className: "fc-event-time" }, innerProps.timeText)), 8942 createElement("div", { className: "fc-event-title-container" }, 8943 createElement("div", { className: "fc-event-title fc-sticky" }, innerProps.event.title || createElement(Fragment, null, "\u00A0"))))); 8944 } 8945 function getSegAnchorAttrs(seg) { 8946 var url = seg.eventRange.def.url; 8947 return url ? { href: url } : {}; 8948 } 8949 8950 var NowIndicatorRoot = function (props) { return (createElement(ViewContextType.Consumer, null, function (context) { 8951 var options = context.options; 8952 var hookProps = { 8953 isAxis: props.isAxis, 8954 date: context.dateEnv.toDate(props.date), 8955 view: context.viewApi, 8956 }; 8957 return (createElement(RenderHook, { hookProps: hookProps, classNames: options.nowIndicatorClassNames, content: options.nowIndicatorContent, didMount: options.nowIndicatorDidMount, willUnmount: options.nowIndicatorWillUnmount }, props.children)); 8958 })); }; 8959 8960 var DAY_NUM_FORMAT = createFormatter({ day: 'numeric' }); 8961 var DayCellContent = /** @class */ (function (_super) { 8962 __extends(DayCellContent, _super); 8963 function DayCellContent() { 8964 return _super !== null && _super.apply(this, arguments) || this; 8965 } 8966 DayCellContent.prototype.render = function () { 8967 var _a = this, props = _a.props, context = _a.context; 8968 var options = context.options; 8969 var hookProps = refineDayCellHookProps({ 8970 date: props.date, 8971 dateProfile: props.dateProfile, 8972 todayRange: props.todayRange, 8973 showDayNumber: props.showDayNumber, 8974 extraProps: props.extraHookProps, 8975 viewApi: context.viewApi, 8976 dateEnv: context.dateEnv, 8977 }); 8978 return (createElement(ContentHook, { hookProps: hookProps, content: options.dayCellContent, defaultContent: props.defaultContent }, props.children)); 8979 }; 8980 return DayCellContent; 8981 }(BaseComponent)); 8982 function refineDayCellHookProps(raw) { 8983 var date = raw.date, dateEnv = raw.dateEnv; 8984 var dayMeta = getDateMeta(date, raw.todayRange, null, raw.dateProfile); 8985 return __assign(__assign(__assign({ date: dateEnv.toDate(date), view: raw.viewApi }, dayMeta), { dayNumberText: raw.showDayNumber ? dateEnv.format(date, DAY_NUM_FORMAT) : '' }), raw.extraProps); 8986 } 8987 8988 var DayCellRoot = /** @class */ (function (_super) { 8989 __extends(DayCellRoot, _super); 8990 function DayCellRoot() { 8991 var _this = _super !== null && _super.apply(this, arguments) || this; 8992 _this.refineHookProps = memoizeObjArg(refineDayCellHookProps); 8993 _this.normalizeClassNames = buildClassNameNormalizer(); 8994 return _this; 8995 } 8996 DayCellRoot.prototype.render = function () { 8997 var _a = this, props = _a.props, context = _a.context; 8998 var options = context.options; 8999 var hookProps = this.refineHookProps({ 9000 date: props.date, 9001 dateProfile: props.dateProfile, 9002 todayRange: props.todayRange, 9003 showDayNumber: props.showDayNumber, 9004 extraProps: props.extraHookProps, 9005 viewApi: context.viewApi, 9006 dateEnv: context.dateEnv, 9007 }); 9008 var classNames = getDayClassNames(hookProps, context.theme).concat(hookProps.isDisabled 9009 ? [] // don't use custom classNames if disabled 9010 : this.normalizeClassNames(options.dayCellClassNames, hookProps)); 9011 var dataAttrs = hookProps.isDisabled ? {} : { 9012 'data-date': formatDayString(props.date), 9013 }; 9014 return (createElement(MountHook, { hookProps: hookProps, didMount: options.dayCellDidMount, willUnmount: options.dayCellWillUnmount, elRef: props.elRef }, function (rootElRef) { return props.children(rootElRef, classNames, dataAttrs, hookProps.isDisabled); })); 9015 }; 9016 return DayCellRoot; 9017 }(BaseComponent)); 9018 9019 function renderFill(fillType) { 9020 return (createElement("div", { className: "fc-" + fillType })); 9021 } 9022 var BgEvent = function (props) { return (createElement(EventRoot, { defaultContent: renderInnerContent$1, seg: props.seg /* uselesss i think */, timeText: "", 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: { 9023 backgroundColor: hookProps.backgroundColor, 9024 } }, innerContent)); })); }; 9025 function renderInnerContent$1(props) { 9026 var title = props.event.title; 9027 return title && (createElement("div", { className: "fc-event-title" }, props.event.title)); 9028 } 9029 9030 var WeekNumberRoot = function (props) { return (createElement(ViewContextType.Consumer, null, function (context) { 9031 var dateEnv = context.dateEnv, options = context.options; 9032 var date = props.date; 9033 var format = options.weekNumberFormat || props.defaultFormat; 9034 var num = dateEnv.computeWeekNumber(date); // TODO: somehow use for formatting as well? 9035 var text = dateEnv.format(date, format); 9036 var hookProps = { num: num, text: text, date: date }; 9037 return (createElement(RenderHook, { hookProps: hookProps, classNames: options.weekNumberClassNames, content: options.weekNumberContent, defaultContent: renderInner$1, didMount: options.weekNumberDidMount, willUnmount: options.weekNumberWillUnmount }, props.children)); 9038 })); }; 9039 function renderInner$1(innerProps) { 9040 return innerProps.text; 9041 } 9042 9043 // exports 9044 // -------------------------------------------------------------------------------------------------- 9045 var version = '5.5.1'; // important to type it, so .d.ts has generic string 9046 9047 var Calendar = /** @class */ (function (_super) { 9048 __extends(Calendar, _super); 9049 function Calendar(el, optionOverrides) { 9050 if (optionOverrides === void 0) { optionOverrides = {}; } 9051 var _this = _super.call(this) || this; 9052 _this.isRendering = false;
9053 _this.isRendered = false; 9054 _this.currentClassNames = []; 9055 _this.customContentRenderId = 0; // will affect custom generated classNames? 9056 _this.handleAction = function (action) { 9057 // actions we know we want to render immediately 9058 switch (action.type) { 9059 case 'SET_EVENT_DRAG': 9060 case 'SET_EVENT_RESIZE': 9061 _this.renderRunner.tryDrain(); 9062 } 9063 }; 9064 _this.handleData = function (data) { 9065 _this.currentData = data; 9066 _this.renderRunner.request(data.calendarOptions.rerenderDelay); 9067 }; 9068 _this.handleRenderRequest = function () { 9069 if (_this.isRendering) { 9070 _this.isRendered = true; 9071 var currentData_1 = _this.currentData; 9072 render(createElement(CalendarRoot, { options: currentData_1.calendarOptions, theme: currentData_1.theme, emitter: currentData_1.emitter }, function (classNames, height, isHeightAuto, forPrint) { 9073 _this.setClassNames(classNames); 9074 _this.setHeight(height); 9075 return (createElement(CustomContentRenderContext.Provider, { value: _this.customContentRenderId }, 9076 createElement(CalendarContent, __assign({ isHeightAuto: isHeightAuto, forPrint: forPrint }, currentData_1)))); 9077 }), _this.el); 9078 } 9079 else if (_this.isRendered) { 9080 _this.isRendered = false; 9081 unmountComponentAtNode$1(_this.el); 9082 _this.setClassNames([]); 9083 _this.setHeight(''); 9084 } 9085 flushToDom$1(); 9086 }; 9087 _this.el = el; 9088 _this.renderRunner = new DelayedRunner(_this.handleRenderRequest); 9089 new CalendarDataManager({ 9090 optionOverrides: optionOverrides, 9091 calendarApi: _this, 9092 onAction: _this.handleAction, 9093 onData: _this.handleData, 9094 }); 9095 return _this; 9096 } 9097 Object.defineProperty(Calendar.prototype, "view", { 9098 get: function () { return this.currentData.viewApi; } // for public API 9099 , 9100 enumerable: false, 9101 configurable: true 9102 }); 9103 Calendar.prototype.render = function () { 9104 var wasRendering = this.isRendering; 9105 if (!wasRendering) { 9106 this.isRendering = true; 9107 } 9108 else { 9109 this.customContentRenderId += 1; 9110 } 9111 this.renderRunner.request(); 9112 if (wasRendering) { 9113 this.updateSize(); 9114 } 9115 }; 9116 Calendar.prototype.destroy = function () { 9117 if (this.isRendering) { 9118 this.isRendering = false; 9119 this.renderRunner.request(); 9120 } 9121 }; 9122 Calendar.prototype.updateSize = function () { 9123 _super.prototype.updateSize.call(this); 9124 flushToDom$1(); 9125 }; 9126 Calendar.prototype.batchRendering = function (func) { 9127 this.renderRunner.pause('batchRendering'); 9128 func(); 9129 this.renderRunner.resume('batchRendering'); 9130 }; 9131 Calendar.prototype.pauseRendering = function () { 9132 this.renderRunner.pause('pauseRendering'); 9133 }; 9134 Calendar.prototype.resumeRendering = function () { 9135 this.renderRunner.resume('pauseRendering', true); 9136 }; 9137 Calendar.prototype.resetOptions = function (optionOverrides, append) { 9138 this.currentDataManager.resetOptions(optionOverrides, append); 9139 }; 9140 Calendar.prototype.setClassNames = function (classNames) { 9141 if (!isArraysEqual(classNames, this.currentClassNames)) { 9142 var classList = this.el.classList; 9143 for (var _i = 0, _a = this.currentClassNames; _i < _a.length; _i++) { 9144 var className = _a[_i]; 9145 classList.remove(className); 9146 } 9147 for (var _b = 0, classNames_1 = classNames; _b < classNames_1.length; _b++) { 9148 var className = classNames_1[_b]; 9149 classList.add(className); 9150 } 9151 this.currentClassNames = classNames; 9152 } 9153 }; 9154 Calendar.prototype.setHeight = function (height) { 9155 applyStyleProp(this.el, 'height', height); 9156 }; 9157 return Calendar; 9158 }(CalendarApi)); 9159 9160 config.touchMouseIgnoreWait = 500; 9161 var ignoreMouseDepth = 0; 9162 var listenerCnt = 0; 9163 var isWindowTouchMoveCancelled = false;
9164 /* 9165 Uses a "pointer" abstraction, which monitors UI events for both mouse and touch. 9166 Tracks when the pointer "drags" on a certain element, meaning down+move+up. 9167 9168 Also, tracks if there was touch-scrolling. 9169 Also, can prevent touch-scrolling from happening. 9170 Also, can fire pointermove events when scrolling happens underneath, even when no real pointer movement. 9171 9172 emits: 9173 - pointerdown 9174 - pointermove 9175 - pointerup 9176 */ 9177 var PointerDragging = /** @class */ (function () { 9178 function PointerDragging(containerEl) { 9179 var _this = this; 9180 this.subjectEl = null; 9181 // options that can be directly assigned by caller 9182 this.selector = ''; // will cause subjectEl in all emitted events to be this element 9183 this.handleSelector = ''; 9184 this.shouldIgnoreMove = false; 9185 this.shouldWatchScroll = true; // for simulating pointermove on scroll 9186 // internal states 9187 this.isDragging = false; 9188 this.isTouchDragging = false; 9189 this.wasTouchScroll = false; 9190 // Mouse 9191 // ---------------------------------------------------------------------------------------------------- 9192 this.handleMouseDown = function (ev) { 9193 if (!_this.shouldIgnoreMouse() && 9194 isPrimaryMouseButton(ev) && 9195 _this.tryStart(ev)) { 9196 var pev = _this.createEventFromMouse(ev, true); 9197 _this.emitter.trigger('pointerdown', pev); 9198 _this.initScrollWatch(pev); 9199 if (!_this.shouldIgnoreMove) { 9200 document.addEventListener('mousemove', _this.handleMouseMove); 9201 } 9202 document.addEventListener('mouseup', _this.handleMouseUp); 9203 } 9204 }; 9205 this.handleMouseMove = function (ev) { 9206 var pev = _this.createEventFromMouse(ev); 9207 _this.recordCoords(pev); 9208 _this.emitter.trigger('pointermove', pev); 9209 }; 9210 this.handleMouseUp = function (ev) { 9211 document.removeEventListener('mousemove', _this.handleMouseMove); 9212 document.removeEventListener('mouseup', _this.handleMouseUp); 9213 _this.emitter.trigger('pointerup', _this.createEventFromMouse(ev)); 9214 _this.cleanup(); // call last so that pointerup has access to props 9215 }; 9216 // Touch 9217 // ---------------------------------------------------------------------------------------------------- 9218 this.handleTouchStart = function (ev) { 9219 if (_this.tryStart(ev)) { 9220 _this.isTouchDragging = true; 9221 var pev = _this.createEventFromTouch(ev, true); 9222 _this.emitter.trigger('pointerdown', pev); 9223 _this.initScrollWatch(pev); 9224 // unlike mouse, need to attach to target, not document 9225 // https://stackoverflow.com/a/45760014 9226 var targetEl = ev.target; 9227 if (!_this.shouldIgnoreMove) { 9228 targetEl.addEventListener('touchmove', _this.handleTouchMove); 9229 } 9230 targetEl.addEventListener('touchend', _this.handleTouchEnd); 9231 targetEl.addEventListener('touchcancel', _this.handleTouchEnd); // treat it as a touch end 9232 // attach a handler to get called when ANY scroll action happens on the page. 9233 // this was impossible to do with normal on/off because 'scroll' doesn't bubble. 9234 // http://stackoverflow.com/a/32954565/96342 9235 window.addEventListener('scroll', _this.handleTouchScroll, true); 9236 } 9237 }; 9238 this.handleTouchMove = function (ev) { 9239 var pev = _this.createEventFromTouch(ev); 9240 _this.recordCoords(pev); 9241 _this.emitter.trigger('pointermove', pev); 9242 }; 9243 this.handleTouchEnd = function (ev) { 9244 if (_this.isDragging) { // done to guard against touchend followed by touchcancel 9245 var targetEl = ev.target; 9246 targetEl.removeEventListener('touchmove', _this.handleTouchMove); 9247 targetEl.removeEventListener('touchend', _this.handleTouchEnd); 9248 targetEl.removeEventListener('touchcancel', _this.handleTouchEnd); 9249 window.removeEventListener('scroll', _this.handleTouchScroll, true); // useCaptured=true 9250 _this.emitter.trigger('pointerup', _this.createEventFromTouch(ev)); 9251 _this.cleanup(); // call last so that pointerup has access to props 9252 _this.isTouchDragging = false;
9253 startIgnoringMouse(); 9254 } 9255 }; 9256 this.handleTouchScroll = function () { 9257 _this.wasTouchScroll = true; 9258 }; 9259 this.handleScroll = function (ev) { 9260 if (!_this.shouldIgnoreMove) { 9261 var pageX = (window.pageXOffset - _this.prevScrollX) + _this.prevPageX; 9262 var pageY = (window.pageYOffset - _this.prevScrollY) + _this.prevPageY; 9263 _this.emitter.trigger('pointermove', { 9264 origEvent: ev, 9265 isTouch: _this.isTouchDragging, 9266 subjectEl: _this.subjectEl, 9267 pageX: pageX, 9268 pageY: pageY, 9269 deltaX: pageX - _this.origPageX, 9270 deltaY: pageY - _this.origPageY, 9271 }); 9272 } 9273 }; 9274 this.containerEl = containerEl; 9275 this.emitter = new Emitter(); 9276 containerEl.addEventListener('mousedown', this.handleMouseDown); 9277 containerEl.addEventListener('touchstart', this.handleTouchStart, { passive: true }); 9278 listenerCreated(); 9279 } 9280 PointerDragging.prototype.destroy = function () { 9281 this.containerEl.removeEventListener('mousedown', this.handleMouseDown); 9282 this.containerEl.removeEventListener('touchstart', this.handleTouchStart, { passive: true }); 9283 listenerDestroyed(); 9284 }; 9285 PointerDragging.prototype.tryStart = function (ev) { 9286 var subjectEl = this.querySubjectEl(ev); 9287 var downEl = ev.target; 9288 if (subjectEl && 9289 (!this.handleSelector || elementClosest(downEl, this.handleSelector))) { 9290 this.subjectEl = subjectEl; 9291 this.isDragging = true; // do this first so cancelTouchScroll will work 9292 this.wasTouchScroll = false; 9293 return true; 9294 } 9295 return false; 9296 }; 9297 PointerDragging.prototype.cleanup = function () { 9298 isWindowTouchMoveCancelled = false; 9299 this.isDragging = false; 9300 this.subjectEl = null; 9301 // keep wasTouchScroll around for later access 9302 this.destroyScrollWatch(); 9303 }; 9304 PointerDragging.prototype.querySubjectEl = function (ev) { 9305 if (this.selector) { 9306 return elementClosest(ev.target, this.selector); 9307 } 9308 return this.containerEl; 9309 }; 9310 PointerDragging.prototype.shouldIgnoreMouse = function () { 9311 return ignoreMouseDepth || this.isTouchDragging; 9312 }; 9313 // can be called by user of this class, to cancel touch-based scrolling for the current drag 9314 PointerDragging.prototype.cancelTouchScroll = function () { 9315 if (this.isDragging) { 9316 isWindowTouchMoveCancelled = true; 9317 } 9318 }; 9319 // Scrolling that simulates pointermoves 9320 // ---------------------------------------------------------------------------------------------------- 9321 PointerDragging.prototype.initScrollWatch = function (ev) { 9322 if (this.shouldWatchScroll) { 9323 this.recordCoords(ev); 9324 window.addEventListener('scroll', this.handleScroll, true); // useCapture=true 9325 } 9326 }; 9327 PointerDragging.prototype.recordCoords = function (ev) { 9328 if (this.shouldWatchScroll) { 9329 this.prevPageX = ev.pageX; 9330 this.prevPageY = ev.pageY; 9331 this.prevScrollX = window.pageXOffset; 9332 this.prevScrollY = window.pageYOffset; 9333 } 9334 }; 9335 PointerDragging.prototype.destroyScrollWatch = function () { 9336 if (this.shouldWatchScroll) { 9337 window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true 9338 } 9339 }; 9340 // Event Normalization 9341 // ---------------------------------------------------------------------------------------------------- 9342 PointerDragging.prototype.createEventFromMouse = function (ev, isFirst) { 9343 var deltaX = 0; 9344 var deltaY = 0; 9345 // TODO: repeat code 9346 if (isFirst) { 9347 this.origPageX = ev.pageX; 9348 this.origPageY = ev.pageY; 9349 } 9350 else { 9351 deltaX = ev.pageX - this.origPageX; 9352 deltaY = ev.pageY - this.origPageY; 9353 } 9354 return { 9355 origEvent: ev, 9356 isTouch: false, 9357 subjectEl: this.subjectEl, 9358 pageX: ev.pageX, 9359 pageY: ev.pageY, 9360 deltaX: deltaX, 9361 deltaY: deltaY, 9362 }; 9363 }; 9364 PointerDragging.prototype.createEventFromTouch = function (ev, isFirst) { 9365 var touches = ev.touches; 9366 var pageX; 9367 var pageY; 9368 var deltaX = 0; 9369 var deltaY = 0; 9370 // if touch coords available, prefer, 9371 // because FF would give bad ev.pageX ev.pageY 9372 if (touches && touches.length) { 9373 pageX = touches[0].pageX; 9374 pageY = touches[0].pageY; 9375 } 9376 else { 9377 pageX = ev.pageX; 9378 pageY = ev.pageY; 9379 } 9380 // TODO: repeat code 9381 if (isFirst) { 9382 this.origPageX = pageX; 9383 this.origPageY = pageY; 9384 } 9385 else { 9386 deltaX = pageX - this.origPageX; 9387 deltaY = pageY - this.origPageY; 9388 } 9389 return { 9390 origEvent: ev, 9391 isTouch: true, 9392 subjectEl: this.subjectEl, 9393 pageX: pageX, 9394 pageY: pageY, 9395 deltaX: deltaX, 9396 deltaY: deltaY, 9397 }; 9398 }; 9399 return PointerDragging; 9400 }());
9401 // Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac) 9402 function isPrimaryMouseButton(ev) { 9403 return ev.button === 0 && !ev.ctrlKey; 9404 } 9405 // Ignoring fake mouse events generated by touch 9406 // ---------------------------------------------------------------------------------------------------- 9407 function startIgnoringMouse() { 9408 ignoreMouseDepth += 1; 9409 setTimeout(function () { 9410 ignoreMouseDepth -= 1; 9411 }, config.touchMouseIgnoreWait); 9412 } 9413 // We want to attach touchmove as early as possible for Safari 9414 // ---------------------------------------------------------------------------------------------------- 9415 function listenerCreated() { 9416 listenerCnt += 1; 9417 if (listenerCnt === 1) { 9418 window.addEventListener('touchmove', onWindowTouchMove, { passive: false }); 9419 } 9420 } 9421 function listenerDestroyed() { 9422 listenerCnt -= 1; 9423 if (!listenerCnt) { 9424 window.removeEventListener('touchmove', onWindowTouchMove, { passive: false }); 9425 } 9426 } 9427 function onWindowTouchMove(ev) { 9428 if (isWindowTouchMoveCancelled) { 9429 ev.preventDefault(); 9430 } 9431 } 9432 9433 /* 9434 An effect in which an element follows the movement of a pointer across the screen. 9435 The moving element is a clone of some other element. 9436 Must call start + handleMove + stop. 9437 */ 9438 var ElementMirror = /** @class */ (function () { 9439 function ElementMirror() { 9440 this.isVisible = false; // must be explicitly enabled 9441 this.sourceEl = null; 9442 this.mirrorEl = null; 9443 this.sourceElRect = null; // screen coords relative to viewport 9444 // options that can be set directly by caller 9445 this.parentNode = document.body; 9446 this.zIndex = 9999; 9447 this.revertDuration = 0; 9448 } 9449 ElementMirror.prototype.start = function (sourceEl, pageX, pageY) { 9450 this.sourceEl = sourceEl; 9451 this.sourceElRect = this.sourceEl.getBoundingClientRect(); 9452 this.origScreenX = pageX - window.pageXOffset; 9453 this.origScreenY = pageY - window.pageYOffset; 9454 this.deltaX = 0; 9455 this.deltaY = 0; 9456 this.updateElPosition(); 9457 }; 9458 ElementMirror.prototype.handleMove = function (pageX, pageY) { 9459 this.deltaX = (pageX - window.pageXOffset) - this.origScreenX; 9460 this.deltaY = (pageY - window.pageYOffset) - this.origScreenY; 9461 this.updateElPosition(); 9462 }; 9463 // can be called before start 9464 ElementMirror.prototype.setIsVisible = function (bool) { 9465 if (bool) { 9466 if (!this.isVisible) { 9467 if (this.mirrorEl) { 9468 this.mirrorEl.style.display = ''; 9469 } 9470 this.isVisible = bool; // needs to happen before updateElPosition 9471 this.updateElPosition(); // because was not updating the position while invisible 9472 } 9473 } 9474 else if (this.isVisible) { 9475 if (this.mirrorEl) { 9476 this.mirrorEl.style.display = 'none'; 9477 } 9478 this.isVisible = bool; 9479 } 9480 }; 9481 // always async 9482 ElementMirror.prototype.stop = function (needsRevertAnimation, callback) { 9483 var _this = this; 9484 var done = function () { 9485 _this.cleanup(); 9486 callback(); 9487 }; 9488 if (needsRevertAnimation && 9489 this.mirrorEl && 9490 this.isVisible && 9491 this.revertDuration && // if 0, transition won't work 9492 (this.deltaX || this.deltaY) // if same coords, transition won't work 9493 ) { 9494 this.doRevertAnimation(done, this.revertDuration); 9495 } 9496 else { 9497 setTimeout(done, 0); 9498 } 9499 }; 9500 ElementMirror.prototype.doRevertAnimation = function (callback, revertDuration) { 9501 var mirrorEl = this.mirrorEl; 9502 var finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened 9503 mirrorEl.style.transition = 9504 'top ' + revertDuration + 'ms,' + 9505 'left ' + revertDuration + 'ms'; 9506 applyStyle(mirrorEl, { 9507 left: finalSourceElRect.left, 9508 top: finalSourceElRect.top, 9509 }); 9510 whenTransitionDone(mirrorEl, function () { 9511 mirrorEl.style.transition = ''; 9512 callback(); 9513 }); 9514 }; 9515 ElementMirror.prototype.cleanup = function () { 9516 if (this.mirrorEl) { 9517 removeElement(this.mirrorEl); 9518 this.mirrorEl = null; 9519 } 9520 this.sourceEl = null; 9521 }; 9522 ElementMirror.prototype.updateElPosition = function () { 9523 if (this.sourceEl && this.isVisible) { 9524 applyStyle(this.getMirrorEl(), { 9525 left: this.sourceElRect.left + this.deltaX,
9526 top: this.sourceElRect.top + this.deltaY, 9527 }); 9528 } 9529 }; 9530 ElementMirror.prototype.getMirrorEl = function () { 9531 var sourceElRect = this.sourceElRect; 9532 var mirrorEl = this.mirrorEl; 9533 if (!mirrorEl) { 9534 mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true 9535 // we don't want long taps or any mouse interaction causing selection/menus. 9536 // would use preventSelection(), but that prevents selectstart, causing problems. 9537 mirrorEl.classList.add('fc-unselectable'); 9538 mirrorEl.classList.add('fc-event-dragging'); 9539 applyStyle(mirrorEl, { 9540 position: 'fixed', 9541 zIndex: this.zIndex, 9542 visibility: '', 9543 boxSizing: 'border-box', 9544 width: sourceElRect.right - sourceElRect.left, 9545 height: sourceElRect.bottom - sourceElRect.top, 9546 right: 'auto', 9547 bottom: 'auto', 9548 margin: 0, 9549 }); 9550 this.parentNode.appendChild(mirrorEl); 9551 } 9552 return mirrorEl; 9553 }; 9554 return ElementMirror; 9555 }()); 9556 9557 /* 9558 Is a cache for a given element's scroll information (all the info that ScrollController stores) 9559 in addition the "client rectangle" of the element.. the area within the scrollbars. 9560 9561 The cache can be in one of two modes: 9562 - doesListening:false - ignores when the container is scrolled by someone else 9563 - doesListening:true - watch for scrolling and update the cache 9564 */ 9565 var ScrollGeomCache = /** @class */ (function (_super) { 9566 __extends(ScrollGeomCache, _super); 9567 function ScrollGeomCache(scrollController, doesListening) { 9568 var _this = _super.call(this) || this; 9569 _this.handleScroll = function () { 9570 _this.scrollTop = _this.scrollController.getScrollTop(); 9571 _this.scrollLeft = _this.scrollController.getScrollLeft(); 9572 _this.handleScrollChange(); 9573 }; 9574 _this.scrollController = scrollController; 9575 _this.doesListening = doesListening; 9576 _this.scrollTop = _this.origScrollTop = scrollController.getScrollTop(); 9577 _this.scrollLeft = _this.origScrollLeft = scrollController.getScrollLeft();
9578 _this.scrollWidth = scrollController.getScrollWidth(); 9579 _this.scrollHeight = scrollController.getScrollHeight(); 9580 _this.clientWidth = scrollController.getClientWidth(); 9581 _this.clientHeight = scrollController.getClientHeight(); 9582 _this.clientRect = _this.computeClientRect(); // do last in case it needs cached values 9583 if (_this.doesListening) { 9584 _this.getEventTarget().addEventListener('scroll', _this.handleScroll); 9585 } 9586 return _this; 9587 } 9588 ScrollGeomCache.prototype.destroy = function () { 9589 if (this.doesListening) { 9590 this.getEventTarget().removeEventListener('scroll', this.handleScroll); 9591 } 9592 }; 9593 ScrollGeomCache.prototype.getScrollTop = function () { 9594 return this.scrollTop; 9595 }; 9596 ScrollGeomCache.prototype.getScrollLeft = function () { 9597 return this.scrollLeft; 9598 }; 9599 ScrollGeomCache.prototype.setScrollTop = function (top) { 9600 this.scrollController.setScrollTop(top); 9601 if (!this.doesListening) { 9602 // we are not relying on the element to normalize out-of-bounds scroll values 9603 // so we need to sanitize ourselves 9604 this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0); 9605 this.handleScrollChange(); 9606 } 9607 }; 9608 ScrollGeomCache.prototype.setScrollLeft = function (top) { 9609 this.scrollController.setScrollLeft(top); 9610 if (!this.doesListening) { 9611 // we are not relying on the element to normalize out-of-bounds scroll values 9612 // so we need to sanitize ourselves 9613 this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0); 9614 this.handleScrollChange(); 9615 } 9616 }; 9617 ScrollGeomCache.prototype.getClientWidth = function () { 9618 return this.clientWidth; 9619 }; 9620 ScrollGeomCache.prototype.getClientHeight = function () { 9621 return this.clientHeight; 9622 }; 9623 ScrollGeomCache.prototype.getScrollWidth = function () { 9624 return this.scrollWidth; 9625 }; 9626 ScrollGeomCache.prototype.getScrollHeight = function () { 9627 return this.scrollHeight; 9628 }; 9629 ScrollGeomCache.prototype.handleScrollChange = function () { 9630 }; 9631 return ScrollGeomCache; 9632 }(ScrollController)); 9633 9634 var ElementScrollGeomCache = /** @class */ (function (_super) { 9635 __extends(ElementScrollGeomCache, _super); 9636 function ElementScrollGeomCache(el, doesListening) { 9637 return _super.call(this, new ElementScrollController(el), doesListening) || this; 9638 } 9639 ElementScrollGeomCache.prototype.getEventTarget = function () { 9640 return this.scrollController.el; 9641 }; 9642 ElementScrollGeomCache.prototype.computeClientRect = function () { 9643 return computeInnerRect(this.scrollController.el); 9644 }; 9645 return ElementScrollGeomCache; 9646 }(ScrollGeomCache)); 9647 9648 var WindowScrollGeomCache = /** @class */ (function (_super) { 9649 __extends(WindowScrollGeomCache, _super); 9650 function WindowScrollGeomCache(doesListening) { 9651 return _super.call(this, new WindowScrollController(), doesListening) || this; 9652 } 9653 WindowScrollGeomCache.prototype.getEventTarget = function () { 9654 return window; 9655 }; 9656 WindowScrollGeomCache.prototype.computeClientRect = function () { 9657 return { 9658 left: this.scrollLeft, 9659 right: this.scrollLeft + this.clientWidth, 9660 top: this.scrollTop, 9661 bottom: this.scrollTop + this.clientHeight, 9662 }; 9663 }; 9664 // the window is the only scroll object that changes it's rectangle relative 9665 // to the document's topleft as it scrolls 9666 WindowScrollGeomCache.prototype.handleScrollChange = function () { 9667 this.clientRect = this.computeClientRect(); 9668 }; 9669 return WindowScrollGeomCache; 9670 }(ScrollGeomCache)); 9671 9672 // If available we are using native "performance" API instead of "Date" 9673 // Read more about it on MDN: 9674 // https://developer.mozilla.org/en-US/docs/Web/API/Performance 9675 var getTime = typeof performance === 'function' ? performance.now : Date.now; 9676 /* 9677 For a pointer interaction, automatically scrolls certain scroll containers when the pointer 9678 approaches the edge. 9679 9680 The caller must call start + handleMove + stop. 9681 */ 9682 var AutoScroller = /** @class */ (function () { 9683 function AutoScroller() { 9684 var _this = this; 9685 // options that can be set by caller 9686 this.isEnabled = true; 9687 this.scrollQuery = [window, '.fc-scroller']; 9688 this.edgeThreshold = 50; // pixels 9689 this.maxVelocity = 300; // pixels per second 9690 // internal state 9691 this.pointerScreenX = null; 9692 this.pointerScreenY = null; 9693 this.isAnimating = false;
9694 this.scrollCaches = null; 9695 // protect against the initial pointerdown being too close to an edge and starting the scroll 9696 this.everMovedUp = false; 9697 this.everMovedDown = false; 9698 this.everMovedLeft = false; 9699 this.everMovedRight = false; 9700 this.animate = function () { 9701 if (_this.isAnimating) { // wasn't cancelled between animation calls 9702 var edge = _this.computeBestEdge(_this.pointerScreenX + window.pageXOffset, _this.pointerScreenY + window.pageYOffset); 9703 if (edge) { 9704 var now = getTime(); 9705 _this.handleSide(edge, (now - _this.msSinceRequest) / 1000); 9706 _this.requestAnimation(now); 9707 } 9708 else { 9709 _this.isAnimating = false; // will stop animation 9710 } 9711 } 9712 }; 9713 } 9714 AutoScroller.prototype.start = function (pageX, pageY) { 9715 if (this.isEnabled) { 9716 this.scrollCaches = this.buildCaches(); 9717 this.pointerScreenX = null; 9718 this.pointerScreenY = null; 9719 this.everMovedUp = false; 9720 this.everMovedDown = false; 9721 this.everMovedLeft = false; 9722 this.everMovedRight = false; 9723 this.handleMove(pageX, pageY); 9724 } 9725 }; 9726 AutoScroller.prototype.handleMove = function (pageX, pageY) { 9727 if (this.isEnabled) { 9728 var pointerScreenX = pageX - window.pageXOffset; 9729 var pointerScreenY = pageY - window.pageYOffset; 9730 var yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY; 9731 var xDelta = this.pointerScreenX === null ? 0 : pointerScreenX - this.pointerScreenX; 9732 if (yDelta < 0) { 9733 this.everMovedUp = true; 9734 } 9735 else if (yDelta > 0) { 9736 this.everMovedDown = true; 9737 } 9738 if (xDelta < 0) { 9739 this.everMovedLeft = true; 9740 } 9741 else if (xDelta > 0) { 9742 this.everMovedRight = true; 9743 } 9744 this.pointerScreenX = pointerScreenX; 9745 this.pointerScreenY = pointerScreenY; 9746 if (!this.isAnimating) { 9747 this.isAnimating = true; 9748 this.requestAnimation(getTime()); 9749 } 9750 } 9751 }; 9752 AutoScroller.prototype.stop = function () { 9753 if (this.isEnabled) { 9754 this.isAnimating = false; // will stop animation 9755 for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { 9756 var scrollCache = _a[_i]; 9757 scrollCache.destroy(); 9758 } 9759 this.scrollCaches = null; 9760 } 9761 }; 9762 AutoScroller.prototype.requestAnimation = function (now) { 9763 this.msSinceRequest = now; 9764 requestAnimationFrame(this.animate); 9765 }; 9766 AutoScroller.prototype.handleSide = function (edge, seconds) { 9767 var scrollCache = edge.scrollCache; 9768 var edgeThreshold = this.edgeThreshold; 9769 var invDistance = edgeThreshold - edge.distance; 9770 var velocity = // the closer to the edge, the faster we scroll 9771 ((invDistance * invDistance) / (edgeThreshold * edgeThreshold)) * // quadratic 9772 this.maxVelocity * seconds; 9773 var sign = 1; 9774 switch (edge.name) { 9775 case 'left': 9776 sign = -1; 9777 // falls through 9778 case 'right': 9779 scrollCache.setScrollLeft(scrollCache.getScrollLeft() + velocity * sign); 9780 break; 9781 case 'top': 9782 sign = -1; 9783 // falls through 9784 case 'bottom': 9785 scrollCache.setScrollTop(scrollCache.getScrollTop() + velocity * sign); 9786 break; 9787 } 9788 }; 9789 // left/top are relative to document topleft 9790 AutoScroller.prototype.computeBestEdge = function (left, top) { 9791 var edgeThreshold = this.edgeThreshold; 9792 var bestSide = null; 9793 for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { 9794 var scrollCache = _a[_i]; 9795 var rect = scrollCache.clientRect; 9796 var leftDist = left - rect.left; 9797 var rightDist = rect.right - left; 9798 var topDist = top - rect.top; 9799 var bottomDist = rect.bottom - top; 9800 // completely within the rect? 9801 if (leftDist >= 0 && rightDist >= 0 && topDist >= 0 && bottomDist >= 0) { 9802 if (topDist <= edgeThreshold && this.everMovedUp && scrollCache.canScrollUp() && 9803 (!bestSide || bestSide.distance > topDist)) { 9804 bestSide = { scrollCache: scrollCache, name: 'top', distance: topDist }; 9805 } 9806 if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() && 9807 (!bestSide || bestSide.distance > bottomDist)) { 9808 bestSide = { scrollCache: scrollCache, name: 'bottom', distance: bottomDist }; 9809 } 9810 if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() && 9811 (!bestSide || bestSide.distance > leftDist)) { 9812 bestSide = { scrollCache: scrollCache, name: 'left', distance: leftDist }; 9813 } 9814 if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() && 9815 (!bestSide || bestSide.distance > rightDist)) { 9816 bestSide = { scrollCache: scrollCache, name: 'right', distance: rightDist }; 9817 } 9818 } 9819 } 9820 return bestSide; 9821 }; 9822 AutoScroller.prototype.buildCaches = function () { 9823 return this.queryScrollEls().map(function (el) { 9824 if (el === window) { 9825 return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls 9826 } 9827 return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls 9828 }); 9829 }; 9830 AutoScroller.prototype.queryScrollEls = function () { 9831 var els = []; 9832 for (var _i = 0, _a = this.scrollQuery; _i < _a.length; _i++) { 9833 var query = _a[_i]; 9834 if (typeof query === 'object') { 9835 els.push(query); 9836 } 9837 else { 9838 els.push.apply(els, Array.prototype.slice.call(document.querySelectorAll(query))); 9839 } 9840 } 9841 return els; 9842 }; 9843 return AutoScroller; 9844 }()); 9845 9846 /* 9847 Monitors dragging on an element. Has a number of high-level features: 9848 - minimum distance required before dragging 9849 - minimum wait time ("delay") before dragging 9850 - a mirror element that follows the pointer 9851 */ 9852 var FeaturefulElementDragging = /** @class */ (function (_super) { 9853 __extends(FeaturefulElementDragging, _super); 9854 function FeaturefulElementDragging(containerEl, selector) { 9855 var _this = _super.call(this, containerEl) || this; 9856 // options that can be directly set by caller 9857 // the caller can also set the PointerDragging's options as well 9858 _this.delay = null; 9859 _this.minDistance = 0; 9860 _this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag 9861 _this.mirrorNeedsRevert = false;
9862 _this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup 9863 _this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation 9864 _this.isDelayEnded = false; 9865 _this.isDistanceSurpassed = false; 9866 _this.delayTimeoutId = null; 9867 _this.onPointerDown = function (ev) { 9868 if (!_this.isDragging) { // so new drag doesn't happen while revert animation is going 9869 _this.isInteracting = true; 9870 _this.isDelayEnded = false; 9871 _this.isDistanceSurpassed = false; 9872 preventSelection(document.body); 9873 preventContextMenu(document.body); 9874 // prevent links from being visited if there's an eventual drag. 9875 // also prevents selection in older browsers (maybe?). 9876 // not necessary for touch, besides, browser would complain about passiveness. 9877 if (!ev.isTouch) { 9878 ev.origEvent.preventDefault(); 9879 } 9880 _this.emitter.trigger('pointerdown', ev); 9881 if (_this.isInteracting && // not destroyed via pointerdown handler 9882 !_this.pointer.shouldIgnoreMove) { 9883 // actions related to initiating dragstart+dragmove+dragend... 9884 _this.mirror.setIsVisible(false); // reset. caller must set-visible 9885 _this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down 9886 _this.startDelay(ev); 9887 if (!_this.minDistance) { 9888 _this.handleDistanceSurpassed(ev); 9889 } 9890 } 9891 } 9892 }; 9893 _this.onPointerMove = function (ev) { 9894 if (_this.isInteracting) { 9895 _this.emitter.trigger('pointermove', ev); 9896 if (!_this.isDistanceSurpassed) { 9897 var minDistance = _this.minDistance; 9898 var distanceSq = void 0; // current distance from the origin, squared 9899 var deltaX = ev.deltaX, deltaY = ev.deltaY; 9900 distanceSq = deltaX * deltaX + deltaY * deltaY; 9901 if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem 9902 _this.handleDistanceSurpassed(ev); 9903 } 9904 } 9905 if (_this.isDragging) { 9906 // a real pointer move? (not one simulated by scrolling) 9907 if (ev.origEvent.type !== 'scroll') { 9908 _this.mirror.handleMove(ev.pageX, ev.pageY); 9909 _this.autoScroller.handleMove(ev.pageX, ev.pageY); 9910 } 9911 _this.emitter.trigger('dragmove', ev); 9912 } 9913 } 9914 }; 9915 _this.onPointerUp = function (ev) { 9916 if (_this.isInteracting) { 9917 _this.isInteracting = false; 9918 allowSelection(document.body); 9919 allowContextMenu(document.body); 9920 _this.emitter.trigger('pointerup', ev); // can potentially set mirrorNeedsRevert 9921 if (_this.isDragging) { 9922 _this.autoScroller.stop(); 9923 _this.tryStopDrag(ev); // which will stop the mirror 9924 } 9925 if (_this.delayTimeoutId) { 9926 clearTimeout(_this.delayTimeoutId); 9927 _this.delayTimeoutId = null; 9928 } 9929 } 9930 }; 9931 var pointer = _this.pointer = new PointerDragging(containerEl); 9932 pointer.emitter.on('pointerdown', _this.onPointerDown); 9933 pointer.emitter.on('pointermove', _this.onPointerMove); 9934 pointer.emitter.on('pointerup', _this.onPointerUp); 9935 if (selector) { 9936 pointer.selector = selector; 9937 } 9938 _this.mirror = new ElementMirror(); 9939 _this.autoScroller = new AutoScroller(); 9940 return _this; 9941 } 9942 FeaturefulElementDragging.prototype.destroy = function () { 9943 this.pointer.destroy(); 9944 // HACK: simulate a pointer-up to end the current drag
9945 // TODO: fire 'dragend' directly and stop interaction. discourage use of pointerup event (b/c might not fire) 9946 this.onPointerUp({}); 9947 }; 9948 FeaturefulElementDragging.prototype.startDelay = function (ev) { 9949 var _this = this; 9950 if (typeof this.delay === 'number') { 9951 this.delayTimeoutId = setTimeout(function () { 9952 _this.delayTimeoutId = null; 9953 _this.handleDelayEnd(ev); 9954 }, this.delay); // not assignable to number! 9955 } 9956 else { 9957 this.handleDelayEnd(ev); 9958 } 9959 }; 9960 FeaturefulElementDragging.prototype.handleDelayEnd = function (ev) { 9961 this.isDelayEnded = true; 9962 this.tryStartDrag(ev); 9963 }; 9964 FeaturefulElementDragging.prototype.handleDistanceSurpassed = function (ev) { 9965 this.isDistanceSurpassed = true; 9966 this.tryStartDrag(ev); 9967 }; 9968 FeaturefulElementDragging.prototype.tryStartDrag = function (ev) { 9969 if (this.isDelayEnded && this.isDistanceSurpassed) { 9970 if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) { 9971 this.isDragging = true; 9972 this.mirrorNeedsRevert = false; 9973 this.autoScroller.start(ev.pageX, ev.pageY); 9974 this.emitter.trigger('dragstart', ev); 9975 if (this.touchScrollAllowed === false) { 9976 this.pointer.cancelTouchScroll(); 9977 } 9978 } 9979 } 9980 }; 9981 FeaturefulElementDragging.prototype.tryStopDrag = function (ev) { 9982 // .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events 9983 // that come from the document to fire beforehand. much more convenient this way. 9984 this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev)); 9985 }; 9986 FeaturefulElementDragging.prototype.stopDrag = function (ev) { 9987 this.isDragging = false; 9988 this.emitter.trigger('dragend', ev); 9989 }; 9990 // fill in the implementations... 9991 FeaturefulElementDragging.prototype.setIgnoreMove = function (bool) { 9992 this.pointer.shouldIgnoreMove = bool; 9993 }; 9994 FeaturefulElementDragging.prototype.setMirrorIsVisible = function (bool) { 9995 this.mirror.setIsVisible(bool); 9996 }; 9997 FeaturefulElementDragging.prototype.setMirrorNeedsRevert = function (bool) { 9998 this.mirrorNeedsRevert = bool; 9999 }; 10000 FeaturefulElementDragging.prototype.setAutoScrollEnabled = function (bool) { 10001 this.autoScroller.isEnabled = bool; 10002 }; 10003 return FeaturefulElementDragging; 10004 }(ElementDragging)); 10005 10006 /* 10007 When this class is instantiated, it records the offset of an element (relative to the document topleft), 10008 and continues to monitor scrolling, updating the cached coordinates if it needs to. 10009 Does not access the DOM after instantiation, so highly performant. 10010 10011 Also keeps track of all scrolling/overflow:hidden containers that are parents of the given element 10012 and an determine if a given point is inside the combined clipping rectangle. 10013 */ 10014 var OffsetTracker = /** @class */ (function () { 10015 function OffsetTracker(el) { 10016 this.origRect = computeRect(el); 10017 // will work fine for divs that have overflow:hidden 10018 this.scrollCaches = getClippingParents(el).map(function (scrollEl) { return new ElementScrollGeomCache(scrollEl, true); }); 10019 } 10020 OffsetTracker.prototype.destroy = function () { 10021 for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { 10022 var scrollCache = _a[_i]; 10023 scrollCache.destroy(); 10024 } 10025 }; 10026 OffsetTracker.prototype.computeLeft = function () { 10027 var left = this.origRect.left; 10028 for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { 10029 var scrollCache = _a[_i]; 10030 left += scrollCache.origScrollLeft - scrollCache.getScrollLeft(); 10031 } 10032 return left; 10033 }; 10034 OffsetTracker.prototype.computeTop = function () { 10035 var top = this.origRect.top; 10036 for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { 10037 var scrollCache = _a[_i]; 10038 top += scrollCache.origScrollTop - scrollCache.getScrollTop(); 10039 } 10040 return top; 10041 }; 10042 OffsetTracker.prototype.isWithinClipping = function (pageX, pageY) { 10043 var point = { left: pageX, top: pageY }; 10044 for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { 10045 var scrollCache = _a[_i];
10046 if (!isIgnoredClipping(scrollCache.getEventTarget()) && 10047 !pointInsideRect(point, scrollCache.clientRect)) { 10048 return false; 10049 } 10050 } 10051 return true; 10052 }; 10053 return OffsetTracker; 10054 }()); 10055 // certain clipping containers should never constrain interactions, like <html> and <body> 10056 // https://github.com/fullcalendar/fullcalendar/issues/3615 10057 function isIgnoredClipping(node) { 10058 var tagName = node.tagName; 10059 return tagName === 'HTML' || tagName === 'BODY'; 10060 } 10061 10062 /* 10063 Tracks movement over multiple droppable areas (aka "hits") 10064 that exist in one or more DateComponents. 10065 Relies on an existing draggable. 10066 10067 emits: 10068 - pointerdown 10069 - dragstart 10070 - hitchange - fires initially, even if not over a hit 10071 - pointerup 10072 - (hitchange - again, to null, if ended over a hit) 10073 - dragend 10074 */ 10075 var HitDragging = /** @class */ (function () { 10076 function HitDragging(dragging, droppableStore) { 10077 var _this = this; 10078 // options that can be set by caller 10079 this.useSubjectCenter = false; 10080 this.requireInitial = true; // if doesn't start out on a hit, won't emit any events 10081 this.initialHit = null; 10082 this.movingHit = null; 10083 this.finalHit = null; // won't ever be populated if shouldIgnoreMove 10084 this.handlePointerDown = function (ev) { 10085 var dragging = _this.dragging; 10086 _this.initialHit = null; 10087 _this.movingHit = null; 10088 _this.finalHit = null; 10089 _this.prepareHits(); 10090 _this.processFirstCoord(ev); 10091 if (_this.initialHit || !_this.requireInitial) { 10092 dragging.setIgnoreMove(false);
10093 // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :( 10094 _this.emitter.trigger('pointerdown', ev); 10095 } 10096 else { 10097 dragging.setIgnoreMove(true); 10098 } 10099 }; 10100 this.handleDragStart = function (ev) { 10101 _this.emitter.trigger('dragstart', ev); 10102 _this.handleMove(ev, true); // force = fire even if initially null 10103 }; 10104 this.handleDragMove = function (ev) { 10105 _this.emitter.trigger('dragmove', ev); 10106 _this.handleMove(ev); 10107 }; 10108 this.handlePointerUp = function (ev) { 10109 _this.releaseHits(); 10110 _this.emitter.trigger('pointerup', ev); 10111 }; 10112 this.handleDragEnd = function (ev) { 10113 if (_this.movingHit) { 10114 _this.emitter.trigger('hitupdate', null, true, ev); 10115 } 10116 _this.finalHit = _this.movingHit; 10117 _this.movingHit = null; 10118 _this.emitter.trigger('dragend', ev); 10119 }; 10120 this.droppableStore = droppableStore; 10121 dragging.emitter.on('pointerdown', this.handlePointerDown); 10122 dragging.emitter.on('dragstart', this.handleDragStart); 10123 dragging.emitter.on('dragmove', this.handleDragMove); 10124 dragging.emitter.on('pointerup', this.handlePointerUp); 10125 dragging.emitter.on('dragend', this.handleDragEnd); 10126 this.dragging = dragging; 10127 this.emitter = new Emitter(); 10128 } 10129 // sets initialHit 10130 // sets coordAdjust 10131 HitDragging.prototype.processFirstCoord = function (ev) { 10132 var origPoint = { left: ev.pageX, top: ev.pageY }; 10133 var adjustedPoint = origPoint; 10134 var subjectEl = ev.subjectEl; 10135 var subjectRect; 10136 if (subjectEl !== document) { 10137 subjectRect = computeRect(subjectEl); 10138 adjustedPoint = constrainPoint(adjustedPoint, subjectRect); 10139 } 10140 var initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top); 10141 if (initialHit) { 10142 if (this.useSubjectCenter && subjectRect) { 10143 var slicedSubjectRect = intersectRects(subjectRect, initialHit.rect); 10144 if (slicedSubjectRect) { 10145 adjustedPoint = getRectCenter(slicedSubjectRect); 10146 } 10147 } 10148 this.coordAdjust = diffPoints(adjustedPoint, origPoint); 10149 } 10150 else { 10151 this.coordAdjust = { left: 0, top: 0 }; 10152 } 10153 }; 10154 HitDragging.prototype.handleMove = function (ev, forceHandle) { 10155 var hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top); 10156 if (forceHandle || !isHitsEqual(this.movingHit, hit)) { 10157 this.movingHit = hit; 10158 this.emitter.trigger('hitupdate', hit, false, ev); 10159 } 10160 }; 10161 HitDragging.prototype.prepareHits = function () { 10162 this.offsetTrackers = mapHash(this.droppableStore, function (interactionSettings) { 10163 interactionSettings.component.prepareHits(); 10164 return new OffsetTracker(interactionSettings.el); 10165 }); 10166 }; 10167 HitDragging.prototype.releaseHits = function () { 10168 var offsetTrackers = this.offsetTrackers; 10169 for (var id in offsetTrackers) { 10170 offsetTrackers[id].destroy(); 10171 } 10172 this.offsetTrackers = {}; 10173 }; 10174 HitDragging.prototype.queryHitForOffset = function (offsetLeft, offsetTop) { 10175 var _a = this, droppableStore = _a.droppableStore, offsetTrackers = _a.offsetTrackers; 10176 var bestHit = null; 10177 for (var id in droppableStore) { 10178 var component = droppableStore[id].component; 10179 var offsetTracker = offsetTrackers[id]; 10180 if (offsetTracker && // wasn't destroyed mid-drag 10181 offsetTracker.isWithinClipping(offsetLeft, offsetTop)) { 10182 var originLeft = offsetTracker.computeLeft(); 10183 var originTop = offsetTracker.computeTop(); 10184 var positionLeft = offsetLeft - originLeft; 10185 var positionTop = offsetTop - originTop; 10186 var origRect = offsetTracker.origRect; 10187 var width = origRect.right - origRect.left; 10188 var height = origRect.bottom - origRect.top; 10189 if ( 10190 // must be within the element's bounds 10191 positionLeft >= 0 && positionLeft < width && 10192 positionTop >= 0 && positionTop < height) { 10193 var hit = component.queryHit(positionLeft, positionTop, width, height); 10194 var dateProfile = component.context.getCurrentData().dateProfile; 10195 if (hit && 10196 ( 10197 // make sure the hit is within activeRange, meaning it's not a deal cell 10198 rangeContainsRange(dateProfile.activeRange, hit.dateSpan.range)) && 10199 (!bestHit || hit.layer > bestHit.layer)) { 10200 // TODO: better way to re-orient rectangle 10201 hit.rect.left += originLeft; 10202 hit.rect.right += originLeft; 10203 hit.rect.top += originTop; 10204 hit.rect.bottom += originTop; 10205 bestHit = hit; 10206 } 10207 } 10208 } 10209 } 10210 return bestHit; 10211 }; 10212 return HitDragging; 10213 }()); 10214 function isHitsEqual(hit0, hit1) { 10215 if (!hit0 && !hit1) { 10216 return true; 10217 } 10218 if (Boolean(hit0) !== Boolean(hit1)) { 10219 return false;
10220 } 10221 return isDateSpansEqual(hit0.dateSpan, hit1.dateSpan); 10222 } 10223 10224 function buildDatePointApiWithContext(dateSpan, context) { 10225 var props = {}; 10226 for (var _i = 0, _a = context.pluginHooks.datePointTransforms; _i < _a.length; _i++) { 10227 var transform = _a[_i]; 10228 __assign(props, transform(dateSpan, context)); 10229 } 10230 __assign(props, buildDatePointApi(dateSpan, context.dateEnv)); 10231 return props; 10232 } 10233 function buildDatePointApi(span, dateEnv) { 10234 return { 10235 date: dateEnv.toDate(span.range.start), 10236 dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }), 10237 allDay: span.allDay, 10238 }; 10239 } 10240 10241 /* 10242 Monitors when the user clicks on a specific date/time of a component. 10243 A pointerdown+pointerup on the same "hit" constitutes a click. 10244 */ 10245 var DateClicking = /** @class */ (function (_super) { 10246 __extends(DateClicking, _super); 10247 function DateClicking(settings) { 10248 var _this = _super.call(this, settings) || this; 10249 _this.handlePointerDown = function (pev) { 10250 var dragging = _this.dragging; 10251 var downEl = pev.origEvent.target; 10252 // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired 10253 dragging.setIgnoreMove(!_this.component.isValidDateDownEl(downEl)); 10254 }; 10255 // won't even fire if moving was ignored 10256 _this.handleDragEnd = function (ev) { 10257 var component = _this.component; 10258 var pointer = _this.dragging.pointer; 10259 if (!pointer.wasTouchScroll) { 10260 var _a = _this.hitDragging, initialHit = _a.initialHit, finalHit = _a.finalHit; 10261 if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) { 10262 var context = component.context; 10263 var arg = __assign(__assign({}, buildDatePointApiWithContext(initialHit.dateSpan, context)), { dayEl: initialHit.dayEl, jsEvent: ev.origEvent, view: context.viewApi || context.calendarApi.view }); 10264 context.emitter.trigger('dateClick', arg); 10265 } 10266 } 10267 }; 10268 // we DO want to watch pointer moves because otherwise finalHit won't get populated 10269 _this.dragging = new FeaturefulElementDragging(settings.el); 10270 _this.dragging.autoScroller.isEnabled = false; 10271 var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, interactionSettingsToStore(settings)); 10272 hitDragging.emitter.on('pointerdown', _this.handlePointerDown); 10273 hitDragging.emitter.on('dragend', _this.handleDragEnd); 10274 return _this; 10275 } 10276 DateClicking.prototype.destroy = function () { 10277 this.dragging.destroy(); 10278 }; 10279 return DateClicking; 10280 }(Interaction)); 10281 10282 /* 10283 Tracks when the user selects a portion of time of a component, 10284 constituted by a drag over date cells, with a possible delay at the beginning of the drag. 10285 */ 10286 var DateSelecting = /** @class */ (function (_super) { 10287 __extends(DateSelecting, _super); 10288 function DateSelecting(settings) { 10289 var _this = _super.call(this, settings) || this; 10290 _this.dragSelection = null; 10291 _this.handlePointerDown = function (ev) { 10292 var _a = _this, component = _a.component, dragging = _a.dragging; 10293 var options = component.context.options; 10294 var canSelect = options.selectable && 10295 component.isValidDateDownEl(ev.origEvent.target); 10296 // don't bother to watch expensive moves if component won't do selection 10297 dragging.setIgnoreMove(!canSelect); 10298 // if touch, require user to hold down 10299 dragging.delay = ev.isTouch ? getComponentTouchDelay(component) : null; 10300 }; 10301 _this.handleDragStart = function (ev) { 10302 _this.component.context.calendarApi.unselect(ev); // unselect previous selections 10303 }; 10304 _this.handleHitUpdate = function (hit, isFinal) { 10305 var context = _this.component.context; 10306 var dragSelection = null; 10307 var isInvalid = false;
10308 if (hit) { 10309 dragSelection = joinHitsIntoSelection(_this.hitDragging.initialHit, hit, context.pluginHooks.dateSelectionTransformers); 10310 if (!dragSelection || !_this.component.isDateSelectionValid(dragSelection)) { 10311 isInvalid = true; 10312 dragSelection = null; 10313 } 10314 } 10315 if (dragSelection) { 10316 context.dispatch({ type: 'SELECT_DATES', selection: dragSelection }); 10317 } 10318 else if (!isFinal) { // only unselect if moved away while dragging 10319 context.dispatch({ type: 'UNSELECT_DATES' }); 10320 } 10321 if (!isInvalid) { 10322 enableCursor(); 10323 } 10324 else { 10325 disableCursor(); 10326 } 10327 if (!isFinal) { 10328 _this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging 10329 } 10330 }; 10331 _this.handlePointerUp = function (pev) { 10332 if (_this.dragSelection) { 10333 // selection is already rendered, so just need to report selection 10334 triggerDateSelect(_this.dragSelection, pev, _this.component.context); 10335 _this.dragSelection = null; 10336 } 10337 }; 10338 var component = settings.component; 10339 var options = component.context.options; 10340 var dragging = _this.dragging = new FeaturefulElementDragging(settings.el); 10341 dragging.touchScrollAllowed = false; 10342 dragging.minDistance = options.selectMinDistance || 0; 10343 dragging.autoScroller.isEnabled = options.dragScroll; 10344 var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, interactionSettingsToStore(settings)); 10345 hitDragging.emitter.on('pointerdown', _this.handlePointerDown); 10346 hitDragging.emitter.on('dragstart', _this.handleDragStart); 10347 hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); 10348 hitDragging.emitter.on('pointerup', _this.handlePointerUp); 10349 return _this; 10350 } 10351 DateSelecting.prototype.destroy = function () { 10352 this.dragging.destroy(); 10353 }; 10354 return DateSelecting; 10355 }(Interaction)); 10356 function getComponentTouchDelay(component) { 10357 var options = component.context.options; 10358 var delay = options.selectLongPressDelay; 10359 if (delay == null) { 10360 delay = options.longPressDelay; 10361 } 10362 return delay; 10363 } 10364 function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) { 10365 var dateSpan0 = hit0.dateSpan; 10366 var dateSpan1 = hit1.dateSpan; 10367 var ms = [ 10368 dateSpan0.range.start, 10369 dateSpan0.range.end, 10370 dateSpan1.range.start, 10371 dateSpan1.range.end, 10372 ]; 10373 ms.sort(compareNumbers); 10374 var props = {}; 10375 for (var _i = 0, dateSelectionTransformers_1 = dateSelectionTransformers; _i < dateSelectionTransformers_1.length; _i++) { 10376 var transformer = dateSelectionTransformers_1[_i]; 10377 var res = transformer(hit0, hit1); 10378 if (res === false) { 10379 return null; 10380 } 10381 if (res) { 10382 __assign(props, res); 10383 } 10384 } 10385 props.range = { start: ms[0], end: ms[3] }; 10386 props.allDay = dateSpan0.allDay; 10387 return props; 10388 } 10389 10390 var EventDragging = /** @class */ (function (_super) { 10391 __extends(EventDragging, _super); 10392 function EventDragging(settings) { 10393 var _this = _super.call(this, settings) || this; 10394 // internal state 10395 _this.subjectEl = null; 10396 _this.subjectSeg = null; // the seg being selected/dragged 10397 _this.isDragging = false; 10398 _this.eventRange = null; 10399 _this.relevantEvents = null; // the events being dragged 10400 _this.receivingContext = null; 10401 _this.validMutation = null; 10402 _this.mutatedRelevantEvents = null; 10403 _this.handlePointerDown = function (ev) { 10404 var origTarget = ev.origEvent.target; 10405 var _a = _this, component = _a.component, dragging = _a.dragging; 10406 var mirror = dragging.mirror; 10407 var options = component.context.options; 10408 var initialContext = component.context; 10409 _this.subjectEl = ev.subjectEl; 10410 var subjectSeg = _this.subjectSeg = getElSeg(ev.subjectEl); 10411 var eventRange = _this.eventRange = subjectSeg.eventRange; 10412 var eventInstanceId = eventRange.instance.instanceId; 10413 _this.relevantEvents = getRelevantEvents(initialContext.getCurrentData().eventStore, eventInstanceId); 10414 dragging.minDistance = ev.isTouch ? 0 : options.eventDragMinDistance; 10415 dragging.delay = 10416 // only do a touch delay if touch and this event hasn't been selected yet 10417 (ev.isTouch && eventInstanceId !== component.props.eventSelection) ? 10418 getComponentTouchDelay$1(component) : 10419 null; 10420 if (options.fixedMirrorParent) { 10421 mirror.parentNode = options.fixedMirrorParent; 10422 } 10423 else { 10424 mirror.parentNode = elementClosest(origTarget, '.fc'); 10425 } 10426 mirror.revertDuration = options.dragRevertDuration; 10427 var isValid = component.isValidSegDownEl(origTarget) && 10428 !elementClosest(origTarget, '.fc-event-resizer'); // NOT on a resizer 10429 dragging.setIgnoreMove(!isValid); 10430 // disable dragging for elements that are resizable (ie, selectable) 10431 // but are not draggable 10432 _this.isDragging = isValid && 10433 ev.subjectEl.classList.contains('fc-event-draggable'); 10434 }; 10435 _this.handleDragStart = function (ev) { 10436 var initialContext = _this.component.context; 10437 var eventRange = _this.eventRange; 10438 var eventInstanceId = eventRange.instance.instanceId; 10439 if (ev.isTouch) { 10440 // need to select a different event? 10441 if (eventInstanceId !== _this.component.props.eventSelection) { 10442 initialContext.dispatch({ type: 'SELECT_EVENT', eventInstanceId: eventInstanceId }); 10443 } 10444 } 10445 else { 10446 // if now using mouse, but was previous touch interaction, clear selected event 10447 initialContext.dispatch({ type: 'UNSELECT_EVENT' }); 10448 } 10449 if (_this.isDragging) { 10450 initialContext.calendarApi.unselect(ev); // unselect *date* selection 10451 initialContext.emitter.trigger('eventDragStart', { 10452 el: _this.subjectEl, 10453 event: new EventApi(initialContext, eventRange.def, eventRange.instance), 10454 jsEvent: ev.origEvent, 10455 view: initialContext.viewApi, 10456 }); 10457 } 10458 }; 10459 _this.handleHitUpdate = function (hit, isFinal) { 10460 if (!_this.isDragging) { 10461 return; 10462 } 10463 var relevantEvents = _this.relevantEvents; 10464 var initialHit = _this.hitDragging.initialHit; 10465 var initialContext = _this.component.context; 10466 // states based on new hit 10467 var receivingContext = null; 10468 var mutation = null; 10469 var mutatedRelevantEvents = null; 10470 var isInvalid = false;
10471 var interaction = { 10472 affectedEvents: relevantEvents, 10473 mutatedEvents: createEmptyEventStore(), 10474 isEvent: true, 10475 }; 10476 if (hit) { 10477 var receivingComponent = hit.component; 10478 receivingContext = receivingComponent.context; 10479 var receivingOptions = receivingContext.options; 10480 if (initialContext === receivingContext || 10481 (receivingOptions.editable && receivingOptions.droppable)) { 10482 mutation = computeEventMutation(initialHit, hit, receivingContext.getCurrentData().pluginHooks.eventDragMutationMassagers); 10483 if (mutation) { 10484 mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, receivingContext.getCurrentData().eventUiBases, mutation, receivingContext); 10485 interaction.mutatedEvents = mutatedRelevantEvents; 10486 if (!receivingComponent.isInteractionValid(interaction)) { 10487 isInvalid = true; 10488 mutation = null; 10489 mutatedRelevantEvents = null; 10490 interaction.mutatedEvents = createEmptyEventStore(); 10491 } 10492 } 10493 } 10494 else { 10495 receivingContext = null; 10496 } 10497 } 10498 _this.displayDrag(receivingContext, interaction); 10499 if (!isInvalid) { 10500 enableCursor(); 10501 } 10502 else { 10503 disableCursor(); 10504 } 10505 if (!isFinal) { 10506 if (initialContext === receivingContext && // TODO: write test for this 10507 isHitsEqual(initialHit, hit)) { 10508 mutation = null; 10509 } 10510 _this.dragging.setMirrorNeedsRevert(!mutation); 10511 // render the mirror if no already-rendered mirror 10512 // TODO: wish we could somehow wait for dispatch to guarantee render 10513 _this.dragging.setMirrorIsVisible(!hit || !document.querySelector('.fc-event-mirror')); 10514 // assign states based on new hit 10515 _this.receivingContext = receivingContext; 10516 _this.validMutation = mutation; 10517 _this.mutatedRelevantEvents = mutatedRelevantEvents; 10518 } 10519 }; 10520 _this.handlePointerUp = function () { 10521 if (!_this.isDragging) { 10522 _this.cleanup(); // because handleDragEnd won't fire 10523 } 10524 }; 10525 _this.handleDragEnd = function (ev) { 10526 if (_this.isDragging) { 10527 var initialContext_1 = _this.component.context; 10528 var initialView = initialContext_1.viewApi; 10529 var _a = _this, receivingContext_1 = _a.receivingContext, validMutation = _a.validMutation; 10530 var eventDef = _this.eventRange.def; 10531 var eventInstance = _this.eventRange.instance; 10532 var eventApi = new EventApi(initialContext_1, eventDef, eventInstance); 10533 var relevantEvents_1 = _this.relevantEvents; 10534 var mutatedRelevantEvents_1 = _this.mutatedRelevantEvents; 10535 var finalHit = _this.hitDragging.finalHit; 10536 _this.clearDrag(); // must happen after revert animation 10537 initialContext_1.emitter.trigger('eventDragStop', { 10538 el: _this.subjectEl, 10539 event: eventApi, 10540 jsEvent: ev.origEvent, 10541 view: initialView, 10542 }); 10543 if (validMutation) { 10544 // dropped within same calendar 10545 if (receivingContext_1 === initialContext_1) { 10546 var updatedEventApi = new EventApi(initialContext_1, mutatedRelevantEvents_1.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents_1.instances[eventInstance.instanceId] : null); 10547 initialContext_1.dispatch({ 10548 type: 'MERGE_EVENTS', 10549 eventStore: mutatedRelevantEvents_1, 10550 }); 10551 var eventChangeArg = { 10552 oldEvent: eventApi, 10553 event: updatedEventApi, 10554 relatedEvents: buildEventApis(mutatedRelevantEvents_1, initialContext_1, eventInstance), 10555 revert: function () { 10556 initialContext_1.dispatch({ 10557 type: 'MERGE_EVENTS', 10558 eventStore: relevantEvents_1, 10559 }); 10560 }, 10561 }; 10562 var transformed = {}; 10563 for (var _i = 0, _b = initialContext_1.getCurrentData().pluginHooks.eventDropTransformers; _i < _b.length; _i++) { 10564 var transformer = _b[_i]; 10565 __assign(transformed, transformer(validMutation, initialContext_1)); 10566 } 10567 initialContext_1.emitter.trigger('eventDrop', __assign(__assign(__assign({}, eventChangeArg), transformed), { el: ev.subjectEl, delta: validMutation.datesDelta, jsEvent: ev.origEvent, view: initialView })); 10568 initialContext_1.emitter.trigger('eventChange', eventChangeArg); 10569 // dropped in different calendar 10570 } 10571 else if (receivingContext_1) { 10572 var eventRemoveArg = { 10573 event: eventApi, 10574 relatedEvents: buildEventApis(relevantEvents_1, initialContext_1, eventInstance), 10575 revert: function () { 10576 initialContext_1.dispatch({ 10577 type: 'MERGE_EVENTS', 10578 eventStore: relevantEvents_1, 10579 }); 10580 }, 10581 }; 10582 initialContext_1.emitter.trigger('eventLeave', __assign(__assign({}, eventRemoveArg), { draggedEl: ev.subjectEl, view: initialView })); 10583 initialContext_1.dispatch({
10584 type: 'REMOVE_EVENTS', 10585 eventStore: relevantEvents_1, 10586 }); 10587 initialContext_1.emitter.trigger('eventRemove', eventRemoveArg); 10588 var addedEventDef = mutatedRelevantEvents_1.defs[eventDef.defId]; 10589 var addedEventInstance = mutatedRelevantEvents_1.instances[eventInstance.instanceId]; 10590 var addedEventApi = new EventApi(receivingContext_1, addedEventDef, addedEventInstance); 10591 receivingContext_1.dispatch({ 10592 type: 'MERGE_EVENTS', 10593 eventStore: mutatedRelevantEvents_1, 10594 }); 10595 var eventAddArg = { 10596 event: addedEventApi, 10597 relatedEvents: buildEventApis(mutatedRelevantEvents_1, receivingContext_1, addedEventInstance), 10598 revert: function () { 10599 receivingContext_1.dispatch({ 10600 type: 'REMOVE_EVENTS', 10601 eventStore: mutatedRelevantEvents_1, 10602 }); 10603 }, 10604 }; 10605 receivingContext_1.emitter.trigger('eventAdd', eventAddArg); 10606 if (ev.isTouch) { 10607 receivingContext_1.dispatch({ 10608 type: 'SELECT_EVENT', 10609 eventInstanceId: eventInstance.instanceId, 10610 }); 10611 } 10612 receivingContext_1.emitter.trigger('drop', __assign(__assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext_1)), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.component.context.viewApi })); 10613 receivingContext_1.emitter.trigger('eventReceive', __assign(__assign({}, eventAddArg), { draggedEl: ev.subjectEl, view: finalHit.component.context.viewApi })); 10614 } 10615 } 10616 else { 10617 initialContext_1.emitter.trigger('_noEventDrop'); 10618 } 10619 } 10620 _this.cleanup(); 10621 }; 10622 var component = _this.component; 10623 var options = component.context.options; 10624 var dragging = _this.dragging = new FeaturefulElementDragging(settings.el); 10625 dragging.pointer.selector = EventDragging.SELECTOR; 10626 dragging.touchScrollAllowed = false; 10627 dragging.autoScroller.isEnabled = options.dragScroll; 10628 var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, interactionSettingsStore); 10629 hitDragging.useSubjectCenter = settings.useEventCenter; 10630 hitDragging.emitter.on('pointerdown', _this.handlePointerDown); 10631 hitDragging.emitter.on('dragstart', _this.handleDragStart); 10632 hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); 10633 hitDragging.emitter.on('pointerup', _this.handlePointerUp); 10634 hitDragging.emitter.on('dragend', _this.handleDragEnd); 10635 return _this; 10636 } 10637 EventDragging.prototype.destroy = function () { 10638 this.dragging.destroy(); 10639 }; 10640 // render a drag state on the next receivingCalendar 10641 EventDragging.prototype.displayDrag = function (nextContext, state) { 10642 var initialContext = this.component.context; 10643 var prevContext = this.receivingContext; 10644 // does the previous calendar need to be cleared? 10645 if (prevContext && prevContext !== nextContext) { 10646 // does the initial calendar need to be cleared? 10647 // if so, don't clear all the way. we still need to to hide the affectedEvents 10648 if (prevContext === initialContext) { 10649 prevContext.dispatch({ 10650 type: 'SET_EVENT_DRAG', 10651 state: { 10652 affectedEvents: state.affectedEvents, 10653 mutatedEvents: createEmptyEventStore(), 10654 isEvent: true, 10655 }, 10656 }); 10657 // completely clear the old calendar if it wasn't the initial 10658 } 10659 else { 10660 prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' }); 10661 } 10662 } 10663 if (nextContext) { 10664 nextContext.dispatch({ type: 'SET_EVENT_DRAG', state: state }); 10665 } 10666 }; 10667 EventDragging.prototype.clearDrag = function () { 10668 var initialCalendar = this.component.context; 10669 var receivingContext = this.receivingContext; 10670 if (receivingContext) { 10671 receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' }); 10672 } 10673 // the initial calendar might have an dummy drag state from displayDrag 10674 if (initialCalendar !== receivingContext) { 10675 initialCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); 10676 } 10677 }; 10678 EventDragging.prototype.cleanup = function () { 10679 this.subjectSeg = null; 10680 this.isDragging = false;
10681 this.eventRange = null; 10682 this.relevantEvents = null; 10683 this.receivingContext = null; 10684 this.validMutation = null; 10685 this.mutatedRelevantEvents = null; 10686 }; 10687 // TODO: test this in IE11 10688 // QUESTION: why do we need it on the resizable??? 10689 EventDragging.SELECTOR = '.fc-event-draggable, .fc-event-resizable'; 10690 return EventDragging; 10691 }(Interaction)); 10692 function computeEventMutation(hit0, hit1, massagers) { 10693 var dateSpan0 = hit0.dateSpan; 10694 var dateSpan1 = hit1.dateSpan; 10695 var date0 = dateSpan0.range.start; 10696 var date1 = dateSpan1.range.start; 10697 var standardProps = {}; 10698 if (dateSpan0.allDay !== dateSpan1.allDay) { 10699 standardProps.allDay = dateSpan1.allDay; 10700 standardProps.hasEnd = hit1.component.context.options.allDayMaintainDuration; 10701 if (dateSpan1.allDay) { 10702 // means date1 is already start-of-day, 10703 // but date0 needs to be converted 10704 date0 = startOfDay(date0); 10705 } 10706 } 10707 var delta = diffDates(date0, date1, hit0.component.context.dateEnv, hit0.component === hit1.component ? 10708 hit0.component.largeUnit : 10709 null); 10710 if (delta.milliseconds) { // has hours/minutes/seconds 10711 standardProps.allDay = false; 10712 } 10713 var mutation = { 10714 datesDelta: delta, 10715 standardProps: standardProps, 10716 }; 10717 for (var _i = 0, massagers_1 = massagers; _i < massagers_1.length; _i++) { 10718 var massager = massagers_1[_i]; 10719 massager(mutation, hit0, hit1); 10720 } 10721 return mutation; 10722 } 10723 function getComponentTouchDelay$1(component) { 10724 var options = component.context.options; 10725 var delay = options.eventLongPressDelay; 10726 if (delay == null) { 10727 delay = options.longPressDelay; 10728 } 10729 return delay; 10730 } 10731 10732 var EventResizing = /** @class */ (function (_super) { 10733 __extends(EventResizing, _super); 10734 function EventResizing(settings) { 10735 var _this = _super.call(this, settings) || this; 10736 // internal state 10737 _this.draggingSegEl = null; 10738 _this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg? 10739 _this.eventRange = null; 10740 _this.relevantEvents = null; 10741 _this.validMutation = null; 10742 _this.mutatedRelevantEvents = null; 10743 _this.handlePointerDown = function (ev) { 10744 var component = _this.component; 10745 var segEl = _this.querySegEl(ev); 10746 var seg = getElSeg(segEl); 10747 var eventRange = _this.eventRange = seg.eventRange; 10748 _this.dragging.minDistance = component.context.options.eventDragMinDistance; 10749 // if touch, need to be working with a selected event 10750 _this.dragging.setIgnoreMove(!_this.component.isValidSegDownEl(ev.origEvent.target) || 10751 (ev.isTouch && _this.component.props.eventSelection !== eventRange.instance.instanceId)); 10752 }; 10753 _this.handleDragStart = function (ev) { 10754 var context = _this.component.context; 10755 var eventRange = _this.eventRange; 10756 _this.relevantEvents = getRelevantEvents(context.getCurrentData().eventStore, _this.eventRange.instance.instanceId); 10757 var segEl = _this.querySegEl(ev); 10758 _this.draggingSegEl = segEl; 10759 _this.draggingSeg = getElSeg(segEl); 10760 context.calendarApi.unselect(); 10761 context.emitter.trigger('eventResizeStart', { 10762 el: segEl, 10763 event: new EventApi(context, eventRange.def, eventRange.instance), 10764 jsEvent: ev.origEvent, 10765 view: context.viewApi, 10766 }); 10767 }; 10768 _this.handleHitUpdate = function (hit, isFinal, ev) { 10769 var context = _this.component.context; 10770 var relevantEvents = _this.relevantEvents; 10771 var initialHit = _this.hitDragging.initialHit; 10772 var eventInstance = _this.eventRange.instance; 10773 var mutation = null; 10774 var mutatedRelevantEvents = null; 10775 var isInvalid = false;
10776 var interaction = { 10777 affectedEvents: relevantEvents, 10778 mutatedEvents: createEmptyEventStore(), 10779 isEvent: true, 10780 }; 10781 if (hit) { 10782 mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-event-resizer-start'), eventInstance.range, context.pluginHooks.eventResizeJoinTransforms); 10783 } 10784 if (mutation) { 10785 mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, context.getCurrentData().eventUiBases, mutation, context); 10786 interaction.mutatedEvents = mutatedRelevantEvents; 10787 if (!_this.component.isInteractionValid(interaction)) { 10788 isInvalid = true; 10789 mutation = null; 10790 mutatedRelevantEvents = null; 10791 interaction.mutatedEvents = null; 10792 } 10793 } 10794 if (mutatedRelevantEvents) { 10795 context.dispatch({ 10796 type: 'SET_EVENT_RESIZE', 10797 state: interaction, 10798 }); 10799 } 10800 else { 10801 context.dispatch({ type: 'UNSET_EVENT_RESIZE' }); 10802 } 10803 if (!isInvalid) { 10804 enableCursor(); 10805 } 10806 else { 10807 disableCursor(); 10808 } 10809 if (!isFinal) { 10810 if (mutation && isHitsEqual(initialHit, hit)) { 10811 mutation = null; 10812 } 10813 _this.validMutation = mutation; 10814 _this.mutatedRelevantEvents = mutatedRelevantEvents; 10815 } 10816 }; 10817 _this.handleDragEnd = function (ev) { 10818 var context = _this.component.context; 10819 var eventDef = _this.eventRange.def; 10820 var eventInstance = _this.eventRange.instance; 10821 var eventApi = new EventApi(context, eventDef, eventInstance); 10822 var relevantEvents = _this.relevantEvents; 10823 var mutatedRelevantEvents = _this.mutatedRelevantEvents; 10824 context.emitter.trigger('eventResizeStop', { 10825 el: _this.draggingSegEl, 10826 event: eventApi, 10827 jsEvent: ev.origEvent, 10828 view: context.viewApi, 10829 }); 10830 if (_this.validMutation) { 10831 var updatedEventApi = new EventApi(context, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null); 10832 context.dispatch({ 10833 type: 'MERGE_EVENTS', 10834 eventStore: mutatedRelevantEvents, 10835 }); 10836 var eventChangeArg = { 10837 oldEvent: eventApi, 10838 event: updatedEventApi, 10839 relatedEvents: buildEventApis(mutatedRelevantEvents, context, eventInstance), 10840 revert: function () { 10841 context.dispatch({ 10842 type: 'MERGE_EVENTS', 10843 eventStore: relevantEvents, 10844 }); 10845 }, 10846 }; 10847 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 })); 10848 context.emitter.trigger('eventChange', eventChangeArg); 10849 } 10850 else { 10851 context.emitter.trigger('_noEventResize'); 10852 } 10853 // reset all internal state 10854 _this.draggingSeg = null; 10855 _this.relevantEvents = null; 10856 _this.validMutation = null; 10857 // okay to keep eventInstance around. useful to set it in handlePointerDown 10858 }; 10859 var component = settings.component; 10860 var dragging = _this.dragging = new FeaturefulElementDragging(settings.el); 10861 dragging.pointer.selector = '.fc-event-resizer'; 10862 dragging.touchScrollAllowed = false;
10863 dragging.autoScroller.isEnabled = component.context.options.dragScroll; 10864 var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, interactionSettingsToStore(settings)); 10865 hitDragging.emitter.on('pointerdown', _this.handlePointerDown); 10866 hitDragging.emitter.on('dragstart', _this.handleDragStart); 10867 hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); 10868 hitDragging.emitter.on('dragend', _this.handleDragEnd); 10869 return _this; 10870 } 10871 EventResizing.prototype.destroy = function () { 10872 this.dragging.destroy(); 10873 }; 10874 EventResizing.prototype.querySegEl = function (ev) { 10875 return elementClosest(ev.subjectEl, '.fc-event'); 10876 }; 10877 return EventResizing; 10878 }(Interaction)); 10879 function computeMutation(hit0, hit1, isFromStart, instanceRange, transforms) { 10880 var dateEnv = hit0.component.context.dateEnv; 10881 var date0 = hit0.dateSpan.range.start; 10882 var date1 = hit1.dateSpan.range.start; 10883 var delta = diffDates(date0, date1, dateEnv, hit0.component.largeUnit); 10884 var props = {}; 10885 for (var _i = 0, transforms_1 = transforms; _i < transforms_1.length; _i++) { 10886 var transform = transforms_1[_i]; 10887 var res = transform(hit0, hit1); 10888 if (res === false) { 10889 return null; 10890 } 10891 if (res) { 10892 __assign(props, res); 10893 } 10894 } 10895 if (isFromStart) { 10896 if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) { 10897 props.startDelta = delta; 10898 return props; 10899 } 10900 } 10901 else if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) { 10902 props.endDelta = delta; 10903 return props; 10904 } 10905 return null; 10906 } 10907 10908 var UnselectAuto = /** @class */ (function () { 10909 function UnselectAuto(context) { 10910 var _this = this; 10911 this.context = context; 10912 this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system 10913 this.matchesCancel = false; 10914 this.matchesEvent = false; 10915 this.onSelect = function (selectInfo) { 10916 if (selectInfo.jsEvent) { 10917 _this.isRecentPointerDateSelect = true; 10918 } 10919 }; 10920 this.onDocumentPointerDown = function (pev) { 10921 var unselectCancel = _this.context.options.unselectCancel; 10922 var downEl = pev.origEvent.target; 10923 _this.matchesCancel = !!elementClosest(downEl, unselectCancel); 10924 _this.matchesEvent = !!elementClosest(downEl, EventDragging.SELECTOR); // interaction started on an event? 10925 }; 10926 this.onDocumentPointerUp = function (pev) { 10927 var context = _this.context; 10928 var documentPointer = _this.documentPointer; 10929 var calendarState = context.getCurrentData(); 10930 // touch-scrolling should never unfocus any type of selection 10931 if (!documentPointer.wasTouchScroll) { 10932 if (calendarState.dateSelection && // an existing date selection? 10933 !_this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp? 10934 ) { 10935 var unselectAuto = context.options.unselectAuto; 10936 if (unselectAuto && (!unselectAuto || !_this.matchesCancel)) { 10937 context.calendarApi.unselect(pev); 10938 } 10939 } 10940 if (calendarState.eventSelection && // an existing event selected? 10941 !_this.matchesEvent // interaction DIDN'T start on an event 10942 ) { 10943 context.dispatch({ type: 'UNSELECT_EVENT' }); 10944 } 10945 } 10946 _this.isRecentPointerDateSelect = false; 10947 }; 10948 var documentPointer = this.documentPointer = new PointerDragging(document); 10949 documentPointer.shouldIgnoreMove = true; 10950 documentPointer.shouldWatchScroll = false;
10951 documentPointer.emitter.on('pointerdown', this.onDocumentPointerDown); 10952 documentPointer.emitter.on('pointerup', this.onDocumentPointerUp); 10953 /* 10954 TODO: better way to know about whether there was a selection with the pointer 10955 */ 10956 context.emitter.on('select', this.onSelect); 10957 } 10958 UnselectAuto.prototype.destroy = function () { 10959 this.context.emitter.off('select', this.onSelect); 10960 this.documentPointer.destroy(); 10961 }; 10962 return UnselectAuto; 10963 }()); 10964 10965 var OPTION_REFINERS = { 10966 fixedMirrorParent: identity, 10967 }; 10968 var LISTENER_REFINERS = { 10969 dateClick: identity, 10970 eventDragStart: identity, 10971 eventDragStop: identity, 10972 eventDrop: identity, 10973 eventResizeStart: identity, 10974 eventResizeStop: identity, 10975 eventResize: identity, 10976 drop: identity, 10977 eventReceive: identity, 10978 eventLeave: identity, 10979 }; 10980 10981 /* 10982 Given an already instantiated draggable object for one-or-more elements, 10983 Interprets any dragging as an attempt to drag an events that lives outside 10984 of a calendar onto a calendar. 10985 */ 10986 var ExternalElementDragging = /** @class */ (function () { 10987 function ExternalElementDragging(dragging, suppliedDragMeta) { 10988 var _this = this; 10989 this.receivingContext = null; 10990 this.droppableEvent = null; // will exist for all drags, even if create:false 10991 this.suppliedDragMeta = null; 10992 this.dragMeta = null; 10993 this.handleDragStart = function (ev) { 10994 _this.dragMeta = _this.buildDragMeta(ev.subjectEl); 10995 }; 10996 this.handleHitUpdate = function (hit, isFinal, ev) { 10997 var dragging = _this.hitDragging.dragging; 10998 var receivingContext = null; 10999 var droppableEvent = null; 11000 var isInvalid = false; 11001 var interaction = { 11002 affectedEvents: createEmptyEventStore(), 11003 mutatedEvents: createEmptyEventStore(), 11004 isEvent: _this.dragMeta.create, 11005 }; 11006 if (hit) { 11007 receivingContext = hit.component.context; 11008 if (_this.canDropElOnCalendar(ev.subjectEl, receivingContext)) { 11009 droppableEvent = computeEventForDateSpan(hit.dateSpan, _this.dragMeta, receivingContext); 11010 interaction.mutatedEvents = eventTupleToStore(droppableEvent); 11011 isInvalid = !isInteractionValid(interaction, receivingContext); 11012 if (isInvalid) { 11013 interaction.mutatedEvents = createEmptyEventStore(); 11014 droppableEvent = null; 11015 } 11016 } 11017 } 11018 _this.displayDrag(receivingContext, interaction); 11019 // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?) 11020 // TODO: wish we could somehow wait for dispatch to guarantee render 11021 dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-event-mirror')); 11022 if (!isInvalid) { 11023 enableCursor(); 11024 } 11025 else { 11026 disableCursor(); 11027 } 11028 if (!isFinal) { 11029 dragging.setMirrorNeedsRevert(!droppableEvent); 11030 _this.receivingContext = receivingContext; 11031 _this.droppableEvent = droppableEvent; 11032 } 11033 }; 11034 this.handleDragEnd = function (pev) { 11035 var _a = _this, receivingContext = _a.receivingContext, droppableEvent = _a.droppableEvent; 11036 _this.clearDrag(); 11037 if (receivingContext && droppableEvent) { 11038 var finalHit = _this.hitDragging.finalHit; 11039 var finalView = finalHit.component.context.viewApi; 11040 var dragMeta = _this.dragMeta; 11041 receivingContext.emitter.trigger('drop', __assign(__assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView })); 11042 if (dragMeta.create) { 11043 var addingEvents_1 = eventTupleToStore(droppableEvent); 11044 receivingContext.dispatch({ 11045 type: 'MERGE_EVENTS', 11046 eventStore: addingEvents_1, 11047 }); 11048 if (pev.isTouch) { 11049 receivingContext.dispatch({ 11050 type: 'SELECT_EVENT', 11051 eventInstanceId: droppableEvent.instance.instanceId, 11052 }); 11053 } 11054 // signal that an external event landed 11055 receivingContext.emitter.trigger('eventReceive', { 11056 event: new EventApi(receivingContext, droppableEvent.def, droppableEvent.instance), 11057 relatedEvents: [], 11058 revert: function () { 11059 receivingContext.dispatch({
11060 type: 'REMOVE_EVENTS', 11061 eventStore: addingEvents_1, 11062 }); 11063 }, 11064 draggedEl: pev.subjectEl, 11065 view: finalView, 11066 }); 11067 } 11068 } 11069 _this.receivingContext = null; 11070 _this.droppableEvent = null; 11071 }; 11072 var hitDragging = this.hitDragging = new HitDragging(dragging, interactionSettingsStore); 11073 hitDragging.requireInitial = false; // will start outside of a component 11074 hitDragging.emitter.on('dragstart', this.handleDragStart); 11075 hitDragging.emitter.on('hitupdate', this.handleHitUpdate); 11076 hitDragging.emitter.on('dragend', this.handleDragEnd); 11077 this.suppliedDragMeta = suppliedDragMeta; 11078 } 11079 ExternalElementDragging.prototype.buildDragMeta = function (subjectEl) { 11080 if (typeof this.suppliedDragMeta === 'object') { 11081 return parseDragMeta(this.suppliedDragMeta); 11082 } 11083 if (typeof this.suppliedDragMeta === 'function') { 11084 return parseDragMeta(this.suppliedDragMeta(subjectEl)); 11085 } 11086 return getDragMetaFromEl(subjectEl); 11087 }; 11088 ExternalElementDragging.prototype.displayDrag = function (nextContext, state) { 11089 var prevContext = this.receivingContext; 11090 if (prevContext && prevContext !== nextContext) { 11091 prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' }); 11092 } 11093 if (nextContext) { 11094 nextContext.dispatch({ type: 'SET_EVENT_DRAG', state: state }); 11095 } 11096 }; 11097 ExternalElementDragging.prototype.clearDrag = function () { 11098 if (this.receivingContext) { 11099 this.receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' }); 11100 } 11101 }; 11102 ExternalElementDragging.prototype.canDropElOnCalendar = function (el, receivingContext) { 11103 var dropAccept = receivingContext.options.dropAccept; 11104 if (typeof dropAccept === 'function') { 11105 return dropAccept.call(receivingContext.calendarApi, el); 11106 } 11107 if (typeof dropAccept === 'string' && dropAccept) { 11108 return Boolean(elementMatches(el, dropAccept)); 11109 } 11110 return true; 11111 }; 11112 return ExternalElementDragging; 11113 }()); 11114 // Utils for computing event store from the DragMeta 11115 // ---------------------------------------------------------------------------------------------------- 11116 function computeEventForDateSpan(dateSpan, dragMeta, context) { 11117 var defProps = __assign({}, dragMeta.leftoverProps); 11118 for (var _i = 0, _a = context.pluginHooks.externalDefTransforms; _i < _a.length; _i++) { 11119 var transform = _a[_i]; 11120 __assign(defProps, transform(dateSpan, dragMeta)); 11121 } 11122 var _b = refineEventDef(defProps, context), refined = _b.refined, extra = _b.extra; 11123 var def = parseEventDef(refined, extra, dragMeta.sourceId, dateSpan.allDay, context.options.forceEventDuration || Boolean(dragMeta.duration), // hasEnd 11124 context); 11125 var start = dateSpan.range.start; 11126 // only rely on time info if drop zone is all-day, 11127 // otherwise, we already know the time 11128 if (dateSpan.allDay && dragMeta.startTime) { 11129 start = context.dateEnv.add(start, dragMeta.startTime); 11130 } 11131 var end = dragMeta.duration ? 11132 context.dateEnv.add(start, dragMeta.duration) : 11133 getDefaultEventEnd(dateSpan.allDay, start, context); 11134 var instance = createEventInstance(def.defId, { start: start, end: end }); 11135 return { def: def, instance: instance }; 11136 } 11137 // Utils for extracting data from element 11138 // ---------------------------------------------------------------------------------------------------- 11139 function getDragMetaFromEl(el) { 11140 var str = getEmbeddedElData(el, 'event'); 11141 var obj = str ? 11142 JSON.parse(str) : 11143 { create: false }; // if no embedded data, assume no event creation 11144 return parseDragMeta(obj); 11145 } 11146 config.dataAttrPrefix = ''; 11147 function getEmbeddedElData(el, name) { 11148 var prefix = config.dataAttrPrefix; 11149 var prefixedName = (prefix ? prefix + '-' : '') + name; 11150 return el.getAttribute('data-' + prefixedName) || ''; 11151 } 11152 11153 /* 11154 Makes an element (that is *external* to any calendar) draggable. 11155 Can pass in data that determines how an event will be created when dropped onto a calendar. 11156 Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system. 11157 */
11158 var ExternalDraggable = /** @class */ (function () { 11159 function ExternalDraggable(el, settings) { 11160 var _this = this; 11161 if (settings === void 0) { settings = {}; } 11162 this.handlePointerDown = function (ev) { 11163 var dragging = _this.dragging; 11164 var _a = _this.settings, minDistance = _a.minDistance, longPressDelay = _a.longPressDelay; 11165 dragging.minDistance = 11166 minDistance != null ? 11167 minDistance : 11168 (ev.isTouch ? 0 : BASE_OPTION_DEFAULTS.eventDragMinDistance); 11169 dragging.delay = 11170 ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv 11171 (longPressDelay != null ? longPressDelay : BASE_OPTION_DEFAULTS.longPressDelay) : 11172 0; 11173 }; 11174 this.handleDragStart = function (ev) { 11175 if (ev.isTouch && 11176 _this.dragging.delay && 11177 ev.subjectEl.classList.contains('fc-event')) { 11178 _this.dragging.mirror.getMirrorEl().classList.add('fc-event-selected'); 11179 } 11180 }; 11181 this.settings = settings; 11182 var dragging = this.dragging = new FeaturefulElementDragging(el); 11183 dragging.touchScrollAllowed = false; 11184 if (settings.itemSelector != null) { 11185 dragging.pointer.selector = settings.itemSelector; 11186 } 11187 if (settings.appendTo != null) { 11188 dragging.mirror.parentNode = settings.appendTo; // TODO: write tests 11189 } 11190 dragging.emitter.on('pointerdown', this.handlePointerDown); 11191 dragging.emitter.on('dragstart', this.handleDragStart); 11192 new ExternalElementDragging(dragging, settings.eventData); // eslint-disable-line no-new 11193 } 11194 ExternalDraggable.prototype.destroy = function () { 11195 this.dragging.destroy(); 11196 }; 11197 return ExternalDraggable; 11198 }()); 11199 11200 /* 11201 Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements. 11202 The third-party system is responsible for drawing the visuals effects of the drag. 11203 This class simply monitors for pointer movements and fires events. 11204 It also has the ability to hide the moving element (the "mirror") during the drag. 11205 */ 11206 var InferredElementDragging = /** @class */ (function (_super) { 11207 __extends(InferredElementDragging, _super); 11208 function InferredElementDragging(containerEl) { 11209 var _this = _super.call(this, containerEl) || this; 11210 _this.shouldIgnoreMove = false; 11211 _this.mirrorSelector = ''; 11212 _this.currentMirrorEl = null; 11213 _this.handlePointerDown = function (ev) { 11214 _this.emitter.trigger('pointerdown', ev); 11215 if (!_this.shouldIgnoreMove) { 11216 // fire dragstart right away. does not support delay or min-distance 11217 _this.emitter.trigger('dragstart', ev); 11218 } 11219 }; 11220 _this.handlePointerMove = function (ev) { 11221 if (!_this.shouldIgnoreMove) { 11222 _this.emitter.trigger('dragmove', ev); 11223 } 11224 }; 11225 _this.handlePointerUp = function (ev) { 11226 _this.emitter.trigger('pointerup', ev); 11227 if (!_this.shouldIgnoreMove) { 11228 // fire dragend right away. does not support a revert animation 11229 _this.emitter.trigger('dragend', ev); 11230 } 11231 }; 11232 var pointer = _this.pointer = new PointerDragging(containerEl); 11233 pointer.emitter.on('pointerdown', _this.handlePointerDown); 11234 pointer.emitter.on('pointermove', _this.handlePointerMove); 11235 pointer.emitter.on('pointerup', _this.handlePointerUp); 11236 return _this; 11237 } 11238 InferredElementDragging.prototype.destroy = function () { 11239 this.pointer.destroy(); 11240 }; 11241 InferredElementDragging.prototype.setIgnoreMove = function (bool) { 11242 this.shouldIgnoreMove = bool; 11243 }; 11244 InferredElementDragging.prototype.setMirrorIsVisible = function (bool) { 11245 if (bool) { 11246 // restore a previously hidden element. 11247 // use the reference in case the selector class has already been removed. 11248 if (this.currentMirrorEl) { 11249 this.currentMirrorEl.style.visibility = ''; 11250 this.currentMirrorEl = null; 11251 } 11252 } 11253 else { 11254 var mirrorEl = this.mirrorSelector ? 11255 document.querySelector(this.mirrorSelector) : 11256 null; 11257 if (mirrorEl) { 11258 this.currentMirrorEl = mirrorEl; 11259 mirrorEl.style.visibility = 'hidden'; 11260 } 11261 } 11262 }; 11263 return InferredElementDragging; 11264 }(ElementDragging)); 11265 11266 /* 11267 Bridges third-party drag-n-drop systems with FullCalendar. 11268 Must be instantiated and destroyed by caller. 11269 */ 11270 var ThirdPartyDraggable = /** @class */ (function () { 11271 function ThirdPartyDraggable(containerOrSettings, settings) { 11272 var containerEl = document; 11273 if ( 11274 // wish we could just test instanceof EventTarget, but doesn't work in IE11 11275 containerOrSettings === document || 11276 containerOrSettings instanceof Element) { 11277 containerEl = containerOrSettings; 11278 settings = settings || {}; 11279 } 11280 else { 11281 settings = (containerOrSettings || {}); 11282 } 11283 var dragging = this.dragging = new InferredElementDragging(containerEl); 11284 if (typeof settings.itemSelector === 'string') { 11285 dragging.pointer.selector = settings.itemSelector; 11286 } 11287 else if (containerEl === document) { 11288 dragging.pointer.selector = '[data-event]'; 11289 } 11290 if (typeof settings.mirrorSelector === 'string') { 11291 dragging.mirrorSelector = settings.mirrorSelector; 11292 } 11293 new ExternalElementDragging(dragging, settings.eventData); // eslint-disable-line no-new 11294 } 11295 ThirdPartyDraggable.prototype.destroy = function () { 11296 this.dragging.destroy(); 11297 }; 11298 return ThirdPartyDraggable; 11299 }()); 11300 11301 var interactionPlugin = createPlugin({ 11302 componentInteractions: [DateClicking, DateSelecting, EventDragging, EventResizing], 11303 calendarInteractions: [UnselectAuto], 11304 elementDraggingImpl: FeaturefulElementDragging, 11305 optionRefiners: OPTION_REFINERS, 11306 listenerRefiners: LISTENER_REFINERS, 11307 }); 11308 11309 /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells. 11310 ----------------------------------------------------------------------------------------------------------------------*/ 11311 // It is a manager for a Table subcomponent, which does most of the heavy lifting. 11312 // It is responsible for managing width/height. 11313 var TableView = /** @class */ (function (_super) { 11314 __extends(TableView, _super); 11315 function TableView() { 11316 var _this = _super !== null && _super.apply(this, arguments) || this; 11317 _this.headerElRef = createRef(); 11318 return _this; 11319 } 11320 TableView.prototype.renderSimpleLayout = function (headerRowContent, bodyContent) { 11321 var _a = this, props = _a.props, context = _a.context; 11322 var sections = []; 11323 var stickyHeaderDates = getStickyHeaderDates(context.options); 11324 if (headerRowContent) { 11325 sections.push({ 11326 type: 'header', 11327 key: 'header', 11328 isSticky: stickyHeaderDates, 11329 chunk: { 11330 elRef: this.headerElRef, 11331 tableClassName: 'fc-col-header', 11332 rowContent: headerRowContent, 11333 }, 11334 }); 11335 } 11336 sections.push({ 11337 type: 'body', 11338 key: 'body', 11339 liquid: true, 11340 chunk: { content: bodyContent }, 11341 }); 11342 return (createElement(ViewRoot, { viewSpec: context.viewSpec }, function (rootElRef, classNames) { return (createElement("div", { ref: rootElRef, className: ['fc-daygri
11342d'].concat(classNames).join(' ') }, 11343 createElement(SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, cols: [] /* TODO: make optional? */, sections: sections }))); })); 11344 }; 11345 TableView.prototype.renderHScrollLayout = function (headerRowContent, bodyContent, colCnt, dayMinWidth) { 11346 var ScrollGrid = this.context.pluginHooks.scrollGridImpl; 11347 if (!ScrollGrid) { 11348 throw new Error('No ScrollGrid implementation'); 11349 } 11350 var _a = this, props = _a.props, context = _a.context; 11351 var stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options); 11352 var stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options); 11353 var sections = []; 11354 if (headerRowContent) { 11355 sections.push({ 11356 type: 'header', 11357 key: 'header', 11358 isSticky: stickyHeaderDates, 11359 chunks: [{ 11360 key: 'main', 11361 elRef: this.headerElRef, 11362 tableClassName: 'fc-col-header', 11363 rowContent: headerRowContent, 11364 }], 11365 }); 11366 } 11367 sections.push({ 11368 type: 'body', 11369 key: 'body', 11370 liquid: true, 11371 chunks: [{ 11372 key: 'main', 11373 content: bodyContent, 11374 }], 11375 }); 11376 if (stickyFooterScrollbar) { 11377 sections.push({ 11378 type: 'footer', 11379 key: 'footer', 11380 isSticky: true, 11381 chunks: [{ 11382 key: 'main', 11383 content: renderScrollShim, 11384 }], 11385 }); 11386 } 11387 return (createElement(ViewRoot, { viewSpec: context.viewSpec }, function (rootElRef, classNames) { return (createElement("div", { ref: rootElRef, className: ['fc-daygrid'].concat(classNames).join(' ') }, 11388 createElement(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }], sections: sections }))); })); 11389 }; 11390 return TableView; 11391 }(DateComponent)); 11392 11393 function splitSegsByRow(segs, rowCnt) { 11394 var byRow = []; 11395 for (var i = 0; i < rowCnt; i += 1) { 11396 byRow[i] = []; 11397 } 11398 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 11399 var seg = segs_1[_i]; 11400 byRow[seg.row].push(seg); 11401 } 11402 return byRow; 11403 } 11404 function splitSegsByFirstCol(segs, colCnt) { 11405 var byCol = []; 11406 for (var i = 0; i < colCnt; i += 1) { 11407 byCol[i] = []; 11408 } 11409 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 11410 var seg = segs_2[_i]; 11411 byCol[seg.firstCol].push(seg); 11412 } 11413 return byCol; 11414 } 11415 function splitInteractionByRow(ui, rowCnt) { 11416 var byRow = []; 11417 if (!ui) { 11418 for (var i = 0; i < rowCnt; i += 1) { 11419 byRow[i] = null; 11420 } 11421 } 11422 else { 11423 for (var i = 0; i < rowCnt; i += 1) { 11424 byRow[i] = { 11425 affectedInstances: ui.affectedInstances, 11426 isEvent: ui.isEvent, 11427 segs: [], 11428 }; 11429 } 11430 for (var _i = 0, _a = ui.segs; _i < _a.length; _i++) { 11431 var seg = _a[_i]; 11432 byRow[seg.row].segs.push(seg); 11433 } 11434 } 11435 return byRow; 11436 } 11437 11438 var TableCellTop = /** @class */ (function (_super) { 11439 __extends(TableCellTop, _super); 11440 function TableCellTop() { 11441 return _super !== null && _super.apply(this, arguments) || this; 11442 } 11443 TableCellTop.prototype.render = function () { 11444 var props = this.props; 11445 var navLinkAttrs = this.context.options.navLinks 11446 ? { 'data-navlink': buildNavLinkData(props.date), tabIndex: 0 } 11447 : {}; 11448 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) && (createElement("div", { className: "fc-daygri
11448d-day-top", ref: innerElRef }, 11449 createElement("a", __assign({ className: "fc-daygrid-day-number" }, navLinkAttrs), innerContent || createElement(Fragment, null, "\u00A0"))))); })); 11450 }; 11451 return TableCellTop; 11452 }(BaseComponent)); 11453 function renderTopInner(props) { 11454 return props.dayNumberText; 11455 } 11456 11457 var DEFAULT_WEEK_NUM_FORMAT = createFormatter({ week: 'narrow' }); 11458 var TableCell = /** @class */ (function (_super) { 11459 __extends(TableCell, _super); 11460 function TableCell() { 11461 var _this = _super !== null && _super.apply(this, arguments) || this; 11462 _this.handleRootEl = function (el) { 11463 _this.rootEl = el; 11464 setRef(_this.props.elRef, el); 11465 }; 11466 _this.handleMoreLinkClick = function (ev) { 11467 var props = _this.props; 11468 if (props.onMoreClick) { 11469 var allSegs = props.segsByEachCol; 11470 var hiddenSegs = allSegs.filter(function (seg) { return props.segIsHidden[seg.eventRange.instance.instanceId]; }); 11471 props.onMoreClick({ 11472 date: props.date, 11473 allSegs: allSegs, 11474 hiddenSegs: hiddenSegs, 11475 moreCnt: props.moreCnt, 11476 dayEl: _this.rootEl, 11477 ev: ev, 11478 }); 11479 } 11480 }; 11481 return _this; 11482 } 11483 TableCell.prototype.render = function () { 11484 var _this = this; 11485 var _a = this.context, options = _a.options, viewApi = _a.viewApi; 11486 var props = this.props; 11487 var date = props.date, dateProfile = props.dateProfile; 11488 var hookProps = { 11489 num: props.moreCnt, 11490 text: props.buildMoreLinkText(props.moreCnt), 11491 view: viewApi, 11492 }; 11493 var navLinkAttrs = options.navLinks 11494 ? { 'data-navlink': buildNavLinkData(date, 'week'), tabIndex: 0 } 11495 : {}; 11496 return (createElement(DayCellRoot, { date: date, dateProfile: dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, extraHookProps: props.extraHookProps, elRef: this.handleRootEl }, function (dayElRef, dayClassNames, rootDataAttrs, isDisabled) { return (createElement("td", __assign({ ref: dayElRef, className: ['fc-daygrid-day'].concat(dayClassNames, props.extraClassNames || []).join(' ') }, rootDataAttrs, props.extraDataAttrs), 11497 createElement("div", { className: "fc-daygrid-day-frame fc-scrollgrid-sync-inner", ref: props.innerElRef /* different from hook system! RENAME */ }, 11498 props.showWeekNumber && (createElement(WeekNumberRoot, { date: date, defaultFormat: DEFAULT_WEEK_NUM_FORMAT }, function (weekElRef, weekClassNames, innerElRef, innerContent) { return (createElement("a", __assign({ ref: weekElRef, className: ['fc-daygrid-week-number'].concat(weekClassNames).join(' ') }, navLinkAttrs), innerContent)); })), 11499 !isDisabled && (createElement(TableCellTop, { date: date, dateProfile: dateProfile, showDayNumber: props.showDayNumber, forceDayTop: props.forceDayTop, todayRange: props.todayRange, extraHookProps: props.extraHookProps })), 11500 createElement("div", { className: "fc-daygrid-day-events", ref: props.fgContentElRef, style: { paddingBottom: props.fgPaddingBottom } }, 11501 props.fgContent, 11502 Boolean(props.moreCnt) && (createElement("div", { className: "fc-daygrid-day-bottom", style: { marginTop: props.moreMarginTop } }, 11503 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", { ref: rootElRef, className: ['fc-daygrid-more-link'].concat(classNames).join(' '), onClick: _this.handleMoreLinkClick }, innerContent)); })))), 11504 createElement("div", { className: "fc-daygri
11504d-day-bg" }, props.bgContent)))); })); 11505 }; 11506 return TableCell; 11507 }(DateComponent)); 11508 TableCell.addPropsEquality({ 11509 onMoreClick: true, 11510 }); 11511 function renderMoreLinkInner(props) { 11512 return props.text; 11513 } 11514 11515 var DEFAULT_TABLE_EVENT_TIME_FORMAT = createFormatter({ 11516 hour: 'numeric', 11517 minute: '2-digit', 11518 omitZeroMinute: true, 11519 meridiem: 'narrow', 11520 }); 11521 function hasListItemDisplay(seg) { 11522 var display = seg.eventRange.ui.display; 11523 return display === 'list-item' || (display === 'auto' && 11524 !seg.eventRange.def.allDay && 11525 seg.firstCol === seg.lastCol && // can't be multi-day 11526 seg.isStart && // " 11527 seg.isEnd // " 11528 ); 11529 } 11530 11531 var TableListItemEvent = /** @class */ (function (_super) { 11532 __extends(TableListItemEvent, _super); 11533 function TableListItemEvent() { 11534 return _super !== null && _super.apply(this, arguments) || this; 11535 } 11536 TableListItemEvent.prototype.render = function () { 11537 var _a = this, props = _a.props, context = _a.context; 11538 var timeFormat = context.options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT; 11539 var timeText = buildSegTimeText(props.seg, timeFormat, context, true, props.defaultDisplayEventEnd); 11540 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! 11541 createElement("a", __assign({ className: ['fc-daygrid-event', 'fc-daygri
11541d-dot-event'].concat(classNames).join(' '), ref: rootElRef }, getSegAnchorAttrs$1(props.seg)), innerContent)); })); 11542 }; 11543 return TableListItemEvent; 11544 }(BaseComponent)); 11545 function renderInnerContent$2(innerProps) { 11546 return (createElement(Fragment, null, 11547 createElement("div", { className: "fc-daygrid-event-dot", style: { borderColor: innerProps.borderColor || innerProps.backgroundColor } }), 11548 innerProps.timeText && (createElement("div", { className: "fc-event-time" }, innerProps.timeText)), 11549 createElement("div", { className: "fc-event-title" }, innerProps.event.title || createElement(Fragment, null, "\u00A0")))); 11550 } 11551 function getSegAnchorAttrs$1(seg) { 11552 var url = seg.eventRange.def.url; 11553 return url ? { href: url } : {}; 11554 } 11555 11556 var TableBlockEvent = /** @class */ (function (_super) { 11557 __extends(TableBlockEvent, _super); 11558 function TableBlockEvent() { 11559 return _super !== null && _super.apply(this, arguments) || this; 11560 } 11561 TableBlockEvent.prototype.render = function () { 11562 var props = this.props; 11563 return (createElement(StandardEvent, __assign({}
11563, 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 }))); 11564 }; 11565 return TableBlockEvent; 11566 }(BaseComponent)); 11567 11568 function computeFgSegPlacement(// for one row. TODO: print mode? 11569 cellModels, segs, dayMaxEvents, dayMaxEventRows, eventHeights, maxContentHeight, colCnt, eventOrderSpecs) { 11570 var colPlacements = []; // if event spans multiple cols, its present in each col 11571 var moreCnts = []; // by-col 11572 var segIsHidden = {}; 11573 var segTops = {}; // always populated for each seg 11574 var segMarginTops = {}; // simetimes populated for each seg 11575 var moreTops = {}; 11576 var paddingBottoms = {}; // for each cell's inner-wrapper div 11577 for (var i = 0; i < colCnt; i += 1) { 11578 colPlacements.push([]); 11579 moreCnts.push(0); 11580 } 11581 segs = sortEventSegs(segs, eventOrderSpecs); 11582 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 11583 var seg = segs_1[_i]; 11584 var instanceId = seg.eventRange.instance.instanceId; 11585 var eventHeight = eventHeights[instanceId + ':' + seg.firstCol]; 11586 placeSeg(seg, eventHeight || 0); // will keep colPlacements sorted by top 11587 } 11588 if (dayMaxEvents === true || dayMaxEventRows === true) { 11589 limitByMaxHeight(moreCnts, segIsHidden, colPlacements, maxContentHeight); // populates moreCnts/segIsHidden 11590 } 11591 else if (typeof dayMaxEvents === 'number') { 11592 limitByMaxEvents(moreCnts, segIsHidden, colPlacements, dayMaxEvents); // populates moreCnts/segIsHidden 11593 } 11594 else if (typeof dayMaxEventRows === 'number') { 11595 limitByMaxRows(moreCnts, segIsHidden, colPlacements, dayMaxEventRows); // populates moreCnts/segIsHidden 11596 } 11597 // computes segTops/segMarginTops/moreTops/paddingBottoms 11598 for (var col = 0; col < colCnt; col += 1) { 11599 var placements = colPlacements[col]; 11600 var currentNonAbsBottom = 0; 11601 var currentAbsHeight = 0; 11602 for (var _a = 0, placements_1 = placements; _a < placements_1.length; _a++) { 11603 var placement = placements_1[_a]; 11604 var seg = placement.seg; 11605 if (!segIsHidden[seg.eventRange.instance.instanceId]) { 11606 segTops[seg.eventRange.instance.instanceId] = placement.top; // from top of container 11607 if (seg.firstCol === seg.lastCol && seg.isStart && seg.isEnd) { // TODO: simpler way? NOT DRY 11608 segMarginTops[seg.eventRange.instance.instanceId] = 11609 placement.top - currentNonAbsBottom; // from previous seg bottom 11610 currentAbsHeight = 0; 11611 currentNonAbsBottom = placement.bottom; 11612 } 11613 else { // multi-col event, abs positioned 11614 currentAbsHeight = placement.bottom - currentNonAbsBottom; 11615 } 11616 } 11617 } 11618 if (currentAbsHeight) { 11619 if (moreCnts[col]) { 11620 moreTops[col] = currentAbsHeight; 11621 } 11622 else { 11623 paddingBottoms[col] = currentAbsHeight; 11624 } 11625 } 11626 } 11627 function placeSeg(seg, segHeight) { 11628 if (!tryPlaceSegAt(seg, segHeight, 0)) { 11629 for (var col = seg.firstCol; col <= seg.lastCol; col += 1) { 11630 for (var _i = 0, _a = colPlacements[col]; _i < _a.length; _i++) { // will repeat multi-day segs!!!!!!! bad!!!!!! 11631 var placement = _a[_i]; 11632 if (tryPlaceSegAt(seg, segHeight, placement.bottom)) { 11633 return; 11634 } 11635 } 11636 } 11637 } 11638 } 11639 function tryPlaceSegAt(seg, segHeight, top) { 11640 if (canPlaceSegAt(seg, segHeight, top)) {
11641 for (var col = seg.firstCol; col <= seg.lastCol; col += 1) { 11642 var placements = colPlacements[col]; 11643 var insertionIndex = 0; 11644 while (insertionIndex < placements.length && 11645 top >= placements[insertionIndex].top) { 11646 insertionIndex += 1; 11647 } 11648 placements.splice(insertionIndex, 0, { 11649 seg: seg, 11650 top: top, 11651 bottom: top + segHeight, 11652 }); 11653 } 11654 return true; 11655 } 11656 return false; 11657 } 11658 function canPlaceSegAt(seg, segHeight, top) { 11659 for (var col = seg.firstCol; col <= seg.lastCol; col += 1) { 11660 for (var _i = 0, _a = colPlacements[col]; _i < _a.length; _i++) { 11661 var placement = _a[_i]; 11662 if (top < placement.bottom && top + segHeight > placement.top) { // collide? 11663 return false; 11664 } 11665 } 11666 } 11667 return true; 11668 } 11669 // what does this do!? 11670 for (var instanceIdAndFirstCol in eventHeights) { 11671 if (!eventHeights[instanceIdAndFirstCol]) { 11672 segIsHidden[instanceIdAndFirstCol.split(':')[0]] = true; 11673 } 11674 } 11675 var segsByFirstCol = colPlacements.map(extractFirstColSegs); // operates on the sorted cols 11676 var segsByEachCol = colPlacements.map(function (placements, col) { 11677 var segsForCols = extractAllColSegs(placements); 11678 segsForCols = resliceDaySegs(segsForCols, cellModels[col].date, col); 11679 return segsForCols; 11680 }); 11681 return { 11682 segsByFirstCol: segsByFirstCol, 11683 segsByEachCol: segsByEachCol, 11684 segIsHidden: segIsHidden, 11685 segTops: segTops, 11686 segMarginTops: segMarginTops, 11687 moreCnts: moreCnts, 11688 moreTops: moreTops, 11689 paddingBottoms: paddingBottoms, 11690 }; 11691 } 11692 function extractFirstColSegs(oneColPlacements, col) { 11693 var segs = []; 11694 for (var _i = 0, oneColPlacements_1 = oneColPlacements; _i < oneColPlacements_1.length; _i++) { 11695 var placement = oneColPlacements_1[_i]; 11696 if (placement.seg.firstCol === col) { 11697 segs.push(placement.seg); 11698 } 11699 } 11700 return segs; 11701 } 11702 function extractAllColSegs(oneColPlacements) { 11703 var segs = []; 11704 for (var _i = 0, oneColPlacements_2 = oneColPlacements; _i < oneColPlacements_2.length; _i++) { 11705 var placement = oneColPlacements_2[_i]; 11706 segs.push(placement.seg); 11707 } 11708 return segs; 11709 } 11710 function limitByMaxHeight(hiddenCnts, segIsHidden, colPlacements, maxContentHeight) { 11711 limitEvents(hiddenCnts, segIsHidden, colPlacements, true, function (placement) { return placement.bottom <= maxContentHeight; }); 11712 } 11713 function limitByMaxEvents(hiddenCnts, segIsHidden, colPlacements, dayMaxEvents) { 11714 limitEvents(hiddenCnts, segIsHidden, colPlacements, false, function (placement, levelIndex) { return levelIndex < dayMaxEvents; }); 11715 } 11716 function limitByMaxRows(hiddenCnts, segIsHidden, colPlacements, dayMaxEventRows) { 11717 limitEvents(hiddenCnts, segIsHidden, colPlacements, true, function (placement, levelIndex) { return levelIndex < dayMaxEventRows; }); 11718 } 11719 /* 11720 populates the given hiddenCnts/segIsHidden, which are supplied empty. 11721 TODO: return them instead 11722 */ 11723 function limitEvents(hiddenCnts, segIsHidden, colPlacements, _moreLinkConsumesLevel, isPlacementInBounds) { 11724 var colCnt = hiddenCnts.length; 11725 var segIsVisible = {}; // TODO: instead, use segIsHidden with true/false? 11726 var visibleColPlacements = []; // will mirror colPlacements 11727 for (var col = 0; col < colCnt; col += 1) { 11728 visibleColPlacements.push([]); 11729 } 11730 for (var col = 0; col < colCnt; col += 1) { 11731 var placements = colPlacements[col]; 11732 var level = 0; 11733 for (var _i = 0, placements_2 = placements; _i < placements_2.length; _i++) { 11734 var placement = placements_2[_i]; 11735 if (isPlacementInBounds(placement, level)) { 11736 recordVisible(placement); 11737 } 11738 else { 11739 recordHidden(placement, level, _moreLinkConsumesLevel); 11740 } 11741 // only considered a level if the seg had height 11742 if (placement.top !== placement.bottom) {
11743 level += 1; 11744 } 11745 } 11746 } 11747 function recordVisible(placement) { 11748 var seg = placement.seg; 11749 var instanceId = seg.eventRange.instance.instanceId; 11750 if (!segIsVisible[instanceId]) { 11751 segIsVisible[instanceId] = true; 11752 for (var col = seg.firstCol; col <= seg.lastCol; col += 1) { 11753 var destPlacements = visibleColPlacements[col]; 11754 var newPosition = 0; 11755 // insert while keeping top sorted in each column 11756 while (newPosition < destPlacements.length && 11757 placement.top >= destPlacements[newPosition].top) { 11758 newPosition += 1; 11759 } 11760 destPlacements.splice(newPosition, 0, placement); 11761 } 11762 } 11763 } 11764 function recordHidden(placement, currentLevel, moreLinkConsumesLevel) { 11765 var seg = placement.seg; 11766 var instanceId = seg.eventRange.instance.instanceId; 11767 if (!segIsHidden[instanceId]) { 11768 segIsHidden[instanceId] = true; 11769 for (var col = seg.firstCol; col <= seg.lastCol; col += 1) { 11770 hiddenCnts[col] += 1; 11771 var hiddenCnt = hiddenCnts[col]; 11772 if (moreLinkConsumesLevel && hiddenCnt === 1 && currentLevel > 0) { 11773 var doomedLevel = currentLevel - 1; 11774 while (visibleColPlacements[col].length > doomedLevel) { 11775 recordHidden(visibleColPlacements[col].pop(), // removes 11776 visibleColPlacements[col].length, // will execute after the pop. will be the index of the removed placement 11777 false); 11778 } 11779 } 11780 } 11781 } 11782 } 11783 } 11784 // Given the events within an array of segment objects, reslice them to be in a single day 11785 function resliceDaySegs(segs, dayDate, colIndex) { 11786 var dayStart = dayDate; 11787 var dayEnd = addDays(dayStart, 1); 11788 var dayRange = { start: dayStart, end: dayEnd }; 11789 var newSegs = []; 11790 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 11791 var seg = segs_2[_i]; 11792 var eventRange = seg.eventRange; 11793 var origRange = eventRange.range; 11794 var slicedRange = intersectRanges(origRange, dayRange); 11795 if (slicedRange) { 11796 newSegs.push(__assign(__assign({}, seg), { firstCol: colIndex, lastCol: colIndex, eventRange: { 11797 def: eventRange.def, 11798 ui: __assign(__assign({}, eventRange.ui), { durationEditable: false }), 11799 instance: eventRange.instance, 11800 range: slicedRange, 11801 }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() })); 11802 } 11803 } 11804 return newSegs; 11805 } 11806 11807 var TableRow = /** @class */ (function (_super) { 11808 __extends(TableRow, _super); 11809 function TableRow() { 11810 var _this = _super !== null && _super.apply(this, arguments) || this; 11811 _this.cellElRefs = new RefMap(); // the <td> 11812 _this.frameElRefs = new RefMap(); // the fc-daygrid-day-frame 11813 _this.fgElRefs = new RefMap(); // the fc-daygrid-day-events 11814 _this.segHarnessRefs = new RefMap(); // indexed by "instanceId:firstCol" 11815 _this.rootElRef = createRef(); 11816 _this.state = { 11817 framePositions: null, 11818 maxContentHeight: null, 11819 segHeights: {}, 11820 }; 11821 return _this; 11822 } 11823 TableRow.prototype.render = function () { 11824 var _this = this; 11825 var _a = this, props = _a.props, state = _a.state, context = _a.context; 11826 var colCnt = props.cells.length; 11827 var businessHoursByCol = splitSegsByFirstCol(props.businessHourSegs, colCnt); 11828 var bgEventSegsByCol = splitSegsByFirstCol(props.bgEventSegs, colCnt); 11829 var highlightSegsByCol = splitSegsByFirstCol(this.getHighlightSegs(), colCnt); 11830 var mirrorSegsByCol = splitSegsByFirstCol(this.getMirrorSegs(), colCnt); 11831 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; 11832 var selectedInstanceHash = // TODO: messy way to compute this 11833 (props.eventDrag && props.eventDrag.affectedInstances) || 11834 (props.eventResize && props.eventResize.affectedInstances) || 11835 {}; 11836 return (createElement("tr", { ref: this.rootElRef }, 11837 props.renderIntro && props.renderIntro(), 11838 props.cells.map(function (cell, col) { 11839 var normalFgNodes = _this.renderFgSegs(segsByFirstCol[col], segIsHidden, segTops, segMarginTops, selectedInstanceHash, props.todayRange); 11840 var mirrorFgNodes = _this.renderFgSegs(mirrorSegsByCol[col], {}, segTops, // use same tops as real rendering 11841 {}, {}, props.todayRange, Boolean(props.eventDrag), Boolean(props.eventResize), false); 11842 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: function (arg) { 11843 props.onMoreClick(__assign(__assign({}, arg), { fromCol: col })); 11844 }, segIsHidden: segIsHidden, moreMarginTop: moreTops[col] /* rename */, segsByEachCol: segsByEachCol[col], fgPaddingBottom: paddingBottoms[col], fgContentElRef: _this.fgElRefs.createRef(cell.key), fgContent: ( // Fragment scopes the keys 11845 createElement(Fragment, null, 11846 createElement(Fragment, null, normalFgNodes), 11847 createElement(Fragment, null, mirrorFgNodes))), bgContent: ( // Fragment scopes the keys 11848 createElement(Fragment, null, 11849 _this.renderFillSegs(highlightSegsByCol[col], 'highlight'), 11850 _this.renderFillSegs(businessHoursByCol[col], 'non-business'), 11851 _this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))) })); 11852 }))); 11853 }; 11854 TableRow.prototype.componentDidMount = function () { 11855 this.updateSizing(true); 11856 }; 11857 TableRow.prototype.componentDidUpdate = function (prevProps, prevState) { 11858 var currentProps = this.props; 11859 this.updateSizing(!isPropsEqual(prevProps, currentProps)); 11860 }; 11861 TableRow.prototype.getHighlightSegs = function () { 11862 var props = this.props; 11863 if (props.eventDrag && props.eventDrag.segs.length) { // messy check 11864 return props.eventDrag.segs; 11865 } 11866 if (props.eventResize && props.eventResize.segs.length) { // messy check 11867 return props.eventResize.segs; 11868 } 11869 return props.dateSelectionSegs; 11870 }; 11871 TableRow.prototype.getMirrorSegs = function () { 11872 var props = this.props; 11873 if (props.eventResize && props.eventResize.segs.length) { // messy check 11874 return props.eventResize.segs; 11875 } 11876 return []; 11877 }; 11878 TableRow.prototype.renderFgSegs = function (segs, segIsHidden, // does NOT mean display:hidden 11879 segTops, segMarginTops, selectedInstanceHash, todayRange, isDragging, isResizing, isDateSelecting) { 11880 var context = this.context; 11881 var eventSelection = this.props.eventSelection; 11882 var framePositions = this.state.framePositions; 11883 var defaultDisplayEventEnd = this.props.cells.length === 1; // colCnt === 1 11884 var nodes = []; 11885 if (framePositions) { 11886 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 11887 var seg = segs_1[_i]; 11888 var instanceId = seg.eventRange.instance.instanceId; 11889 var isMirror = isDragging || isResizing || isDateSelecting; 11890 var isSelected = selectedInstanceHash[instanceId]; 11891 var isInvisible = segIsHidden[instanceId] || isSelected; 11892 // TODO: simpler way? NOT DRY 11893 var isAbsolute = segIsHidden[instanceId] || isMirror || seg.firstCol !== seg.lastCol || !seg.isStart || !seg.isEnd; 11894 var marginTop = void 0; 11895 var top_1 = void 0; 11896 var left = void 0; 11897 var right = void 0; 11898 if (isAbsolute) { 11899 top_1 = segTops[instanceId]; 11900 if (context.isRtl) { 11901 right = 0; 11902 left = framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol]; 11903 } 11904 else { 11905 left = 0; 11906 right = framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol]; 11907 } 11908 } 11909 else { 11910 marginTop = segMarginTops[instanceId]; 11911 } 11912 /* 11913 known bug: events that are force to be list-item but span multiple days still take up space in later columns 11914 */ 11915 nodes.push(createElement("div", { className: 'fc-daygri
11915d-event-harness' + (isAbsolute ? ' fc-daygrid-event-harness-abs' : ''), key: instanceId, 11916 // in print mode when in mult cols, could collide 11917 ref: isMirror ? null : this.segHarnessRefs.createRef(instanceId + ':' + seg.firstCol), style: { 11918 visibility: isInvisible ? 'hidden' : '', 11919 marginTop: marginTop || '', 11920 top: top_1 || '', 11921 left: left || '', 11922 right: right || '', 11923 } }, hasListItemDisplay(seg) ? (createElement(TableListItemEvent, __assign({ seg: seg, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getSegMeta(seg, todayRange)))) : (createElement(TableBlockEvent, __assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getSegMeta(seg, todayRange)))))); 11924 } 11925 } 11926 return nodes; 11927 }; 11928 TableRow.prototype.renderFillSegs = function (segs, fillType) { 11929 var isRtl = this.context.isRtl; 11930 var todayRange = this.props.todayRange; 11931 var framePositions = this.state.framePositions; 11932 var nodes = []; 11933 if (framePositions) { 11934 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 11935 var seg = segs_2[_i]; 11936 var leftRightCss = isRtl ? { 11937 right: 0, 11938 left: framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol], 11939 } : { 11940 left: 0, 11941 right: framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol], 11942 }; 11943 nodes.push(createElement("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-daygrid-bg-harness", style: leftRightCss }, fillType === 'bg-event' ? 11944 createElement(BgEvent, __assign({ seg: seg }, getSegMeta(seg, todayRange))) : 11945 renderFill(fillType))); 11946 } 11947 } 11948 return createElement.apply(void 0, __spreadArrays([Fragment, {}], nodes)); 11949 }; 11950 TableRow.prototype.updateSizing = function (isExternalSizingChange) { 11951 var _a = this, props = _a.props, frameElRefs = _a.frameElRefs; 11952 if (props.clientWidth !== null) { // positioning ready? 11953 if (isExternalSizingChange) { 11954 var frameEls = props.cells.map(function (cell) { return frameElRefs.currentMap[cell.key]; }); 11955 if (frameEls.length) { 11956 var originEl = this.rootElRef.current; 11957 this.setState({ 11958 framePositions: new PositionCache(originEl, frameEls, true, // isHorizontal 11959 false), 11960 }); 11961 } 11962 } 11963 var limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true; 11964 this.setState({ 11965 segHeights: this.computeSegHeights(), 11966 maxContentHeight: limitByContentHeight ? this.computeMaxContentHeight() : null, 11967 }); 11968 } 11969 }; 11970 TableRow.prototype.computeSegHeights = function () { 11971 return mapHash(this.segHarnessRefs.currentMap, function (eventHarnessEl) { return (eventHarnessEl.getBoundingClientRect().height); }); 11972 }; 11973 TableRow.prototype.computeMaxContentHeight = function () { 11974 var firstKey = this.props.cells[0].key; 11975 var cellEl = this.cellElRefs.currentMap[firstKey]; 11976 var fcContainerEl = this.fgElRefs.currentMap[firstKey]; 11977 return cellEl.getBoundingClientRect().bottom - fcContainerEl.getBoundingClientRect().top; 11978 }; 11979 TableRow.prototype.getCellEls = function () { 11980 var elMap = this.cellElRefs.currentMap; 11981 return this.props.cells.map(function (cell) { return elMap[cell.key]; }); 11982 }; 11983 return TableRow; 11984 }(DateComponent)); 11985 TableRow.addPropsEquality({ 11986 onMoreClick: true, 11987 }); 11988 TableRow.addStateEquality({ 11989 segHeights: isPropsEqual, 11990 }); 11991 11992 var PADDING_FROM_VIEWPORT = 10; 11993 var SCROLL_DEBOUNCE = 10; 11994 var Popover = /** @class */ (function (_super) { 11995 __extends(Popover, _super); 11996 function Popover() { 11997 var _this = _super !== null && _super.apply(this, arguments) || this; 11998 _this.repositioner = new DelayedRunner(_this.updateSize.bind(_this)); 11999 _this.handleRootEl = function (el) { 12000 _this.rootEl = el; 12001 if (_this.props.elRef) { 12002 setRef(_this.props.elRef, el); 12003 } 12004 }; 12005 // Triggered when the user clicks *anywhere* in the document, for the autoHide feature 12006 _this.handleDocumentMousedown = function (ev) { 12007 var onClose = _this.props.onClose; 12008 // only hide the popover if the click happened outside the popover 12009 if (onClose && !_this.rootEl.contains(ev.target)) { 12010 onClose(); 12011 } 12012 }; 12013 _this.handleDocumentScroll = function () { 12014 _this.repositioner.request(SCROLL_DEBOUNCE); 12015 }; 12016 _this.handleCloseClick = function () { 12017 var onClose = _this.props.onClose; 12018 if (onClose) { 12019 onClose(); 12020 } 12021 }; 12022 return _this; 12023 } 12024 Popover.prototype.render = function () { 12025 var theme = this.context.theme; 12026 var props = this.props; 12027 var classNames = [ 12028 'fc-popover', 12029 theme.getClass('popover'), 12030 ].concat(props.extraClassNames || []); 12031 return (createElement("div", __assign({ className: classNames.join(' ') }, props.extraAttrs, { ref: this.handleRootEl }), 12032 createElement("div", { className: 'fc-popover-header ' + theme.getClass('popoverHeader') }, 12033 createElement("span", { className: "fc-popover-title" }, props.title), 12034 createElement("span", { className: 'fc-popover-close ' + theme.getIconClass('close'), onClick: this.handleCloseClick })), 12035 createElement("div", { className: 'fc-popover-body ' + theme.getClass('popoverContent') }, props.children))); 12036 }; 12037 Popover.prototype.componentDidMount = function () { 12038 document.addEventListener('mousedown', this.handleDocumentMousedown); 12039 document.addEventListener('scroll', this.handleDocumentScroll); 12040 this.updateSize(); 12041 }; 12042 Popover.prototype.componentWillUnmount = function () { 12043 document.removeEventListener('mousedown', this.handleDocumentMousedown); 12044 document.removeEventListener('scroll', this.handleDocumentScroll); 12045 }; 12046 // TODO: adjust on window resize 12047 /* 12048 NOTE: the popover is position:fixed, so coordinates are relative to the viewport 12049 NOTE: the PARENT calls this as well, on window resize. we would have wanted to use the repositioner, 12050 but need to ensure that all other components have updated size first (for alignmentEl) 12051 */ 12052 Popover.prototype.updateSize = function () { 12053 var _a = this.props, alignmentEl = _a.alignmentEl, topAlignmentEl = _a.topAlignmentEl; 12054 var rootEl = this.rootEl; 12055 if (!rootEl) { 12056 return;
12056 // not sure why this was null, but we shouldn't let external components call updateSize() anyway 12057 } 12058 var dims = rootEl.getBoundingClientRect(); // only used for width,height 12059 var alignment = alignmentEl.getBoundingClientRect(); 12060 var top = topAlignmentEl ? topAlignmentEl.getBoundingClientRect().top : alignment.top; 12061 top = Math.min(top, window.innerHeight - dims.height - PADDING_FROM_VIEWPORT); 12062 top = Math.max(top, PADDING_FROM_VIEWPORT); 12063 var left; 12064 if (this.context.isRtl) { 12065 left = alignment.right - dims.width; 12066 } 12067 else { 12068 left = alignment.left; 12069 } 12070 left = Math.min(left, window.innerWidth - dims.width - PADDING_FROM_VIEWPORT); 12071 left = Math.max(left, PADDING_FROM_VIEWPORT); 12072 applyStyle(rootEl, { top: top, left: left }); 12073 }; 12074 return Popover; 12075 }(BaseComponent)); 12076 12077 var MorePopover = /** @class */ (function (_super) { 12078 __extends(MorePopover, _super); 12079 function MorePopover() { 12080 var _this = _super !== null && _super.apply(this, arguments) || this; 12081 _this.rootElRef = createRef(); 12082 return _this; 12083 } 12084 MorePopover.prototype.render = function () { 12085 var _a = this.context, options = _a.options, dateEnv = _a.dateEnv; 12086 var props = this.props; 12087 var date = props.date, hiddenInstances = props.hiddenInstances, todayRange = props.todayRange, dateProfile = props.dateProfile, selectedInstanceId = props.selectedInstanceId; 12088 var title = dateEnv.format(date, options.dayPopoverFormat); 12089 return (createElement(DayCellRoot, { date: date, dateProfile: dateProfile, todayRange: todayRange, elRef: this.rootElRef }, 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 }, 12090 createElement(DayCellContent, { date: date, dateProfile: dateProfile, todayRange: todayRange }, function (innerElRef, innerContent) { return (innerContent && 12091 createElement("div", { className: "fc-more-popover-misc", ref: innerElRef }, innerContent)); }), 12092 props.segs.map(function (seg) { 12093 var instanceId = seg.eventRange.instance.instanceId; 12094 return (createElement("div", { className: "fc-daygrid-event-harness", key: instanceId, style: { 12095 visibility: hiddenInstances[instanceId] ? 'hidden' : '', 12096 } }, hasListItemDisplay(seg) ? (createElement(TableListItemEvent, __assign({ seg: seg, isDragging: false, isSelected: instanceId === selectedInstanceId, defaultDisplayEventEnd: false }, getSegMeta(seg, todayRange)))) : (createElement(TableBlockEvent, __assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === selectedInstanceId, defaultDisplayEventEnd: false }, getSegMeta(seg, todayRange)))))); 12097 }))); })); 12098 }; 12099 MorePopover.prototype.positionToHit = function (positionLeft, positionTop, originEl) { 12100 var rootEl = this.rootElRef.current; 12101 if (!originEl || !rootEl) { // why? 12102 return null; 12103 } 12104 var originRect = originEl.getBoundingClientRect(); 12105 var elRect = rootEl.getBoundingClientRect(); 12106 var newOriginLeft = elRect.left - originRect.left; 12107 var newOriginTop = elRect.top - originRect.top; 12108 var localLeft = positionLeft - newOriginLeft; 12109 var localTop = positionTop - newOriginTop; 12110 var date = this.props.date; 12111 if ( // ugly way to detect intersection 12112 localLeft >= 0 && localLeft < elRect.width && 12113 localTop >= 0 && localTop < elRect.height) { 12114 return { 12115 dateSpan: { 12116 allDay: true, 12117 range: { start: date, end: addDays(date, 1) }, 12118 }, 12119 dayEl: rootEl, 12120 relativeRect: { 12121 left: newOriginLeft, 12122 top: newOriginTop, 12123 right: elRect.width, 12124 bottom: elRect.height, 12125 }, 12126 layer: 1, 12127 }; 12128 } 12129 return null; 12130 }; 12131 return MorePopover; 12132 }(DateComponent)); 12133 12134 var Table = /** @class */ (function (_super) { 12135 __extends(Table, _super); 12136 function Table() { 12137 var _this = _super !== null && _super.apply(this, arguments) || this; 12138 _this.splitBusinessHourSegs = memoize(splitSegsByRow); 12139 _this.splitBgEventSegs = memoize(splitSegsByRow); 12140 _this.splitFgEventSegs = memoize(splitSegsByRow); 12141 _this.splitDateSelectionSegs = memoize(splitSegsByRow); 12142 _this.splitEventDrag = memoize(splitInteractionByRow); 12143 _this.splitEventResize = memoize(splitInteractionByRow); 12144 _this.buildBuildMoreLinkText = memoize(buildBuildMoreLinkText); 12145 _this.morePopoverRef = createRef(); 12146 _this.rowRefs = new RefMap(); 12147 _this.state = { 12148 morePopoverState: null, 12149 }; 12150 _this.handleRootEl = function (rootEl) { 12151 _this.rootEl = rootEl; 12152 setRef(_this.props.elRef, rootEl); 12153 }; 12154 // TODO: bad names "more link click" versus "more click" 12155 _this.handleMoreLinkClick = function (arg) { 12156 var context = _this.context; 12157 var dateEnv = context.dateEnv; 12158 var clickOption = context.options.moreLinkClick; 12159 function segForPublic(seg) { 12160 var _a = seg.eventRange, def = _a.def, instance = _a.instance, range = _a.range; 12161 return { 12162 event: new EventApi(context, def, instance), 12163 start: dateEnv.toDate(range.start), 12164 end: dateEnv.toDate(range.end), 12165 isStart: seg.isStart, 12166 isEnd: seg.isEnd, 12167 }; 12168 } 12169 if (typeof clickOption === 'function') { 12170 clickOption = clickOption({ 12171 date: dateEnv.toDate(arg.date), 12172 allDay: true, 12173 allSegs: arg.allSegs.map(segForPublic), 12174 hiddenSegs: arg.hiddenSegs.map(segForPublic), 12175 jsEvent: arg.ev, 12176 view: context.viewApi, 12177 }); // hack to handle void 12178 } 12179 if (!clickOption || clickOption === 'popover') { 12180 _this.setState({ 12181 morePopoverState: __assign(__assign({}, arg), { currentFgEventSegs: _this.props.fgEventSegs, fromRow: arg.fromRow, fromCol: arg.fromCol }), 12182 }); 12183 } 12184 else if (typeof clickOption === 'string') { // a view n
12184ame 12185 context.calendarApi.zoomTo(arg.date, clickOption); 12186 } 12187 }; 12188 _this.handleMorePopoverClose = function () { 12189 _this.setState({ 12190 morePopoverState: null, 12191 }); 12192 }; 12193 return _this; 12194 } 12195 Table.prototype.render = function () { 12196 var _this = this; 12197 var props = this.props; 12198 var dateProfile = props.dateProfile, dayMaxEventRows = props.dayMaxEventRows, dayMaxEvents = props.dayMaxEvents, expandRows = props.expandRows; 12199 var morePopoverState = this.state.morePopoverState; 12200 var rowCnt = props.cells.length; 12201 var businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt); 12202 var bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt); 12203 var fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt); 12204 var dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt); 12205 var eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt); 12206 var eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt); 12207 var buildMoreLinkText = this.buildBuildMoreLinkText(this.context.options.moreLinkText); 12208 var limitViaBalanced = dayMaxEvents === true || dayMaxEventRows === true; 12209 // if rows can't expand to fill fixed height, can't do balanced-height event limit 12210 // TODO: best place to normalize these options? 12211 if (limitViaBalanced && !expandRows) { 12212 limitViaBalanced = false; 12213 dayMaxEventRows = null; 12214 dayMaxEvents = null; 12215 } 12216 var classNames = [ 12217 'fc-daygrid-body', 12218 limitViaBalanced ? 'fc-daygrid-body-balanced' : 'fc-daygrid-body-unbalanced', 12219 expandRows ? '' : 'fc-daygrid-body-natural', 12220 ]; 12221 return (createElement("div", { className: classNames.join(' '), ref: this.handleRootEl, style: { 12222 // these props are important to give this wrapper correct dimensions for interactions 12223 // TODO: if we set it here, can we avoid giving to inner tables? 12224 width: props.clientWidth, 12225 minWidth: props.tableMinWidth, 12226 } }, 12227 createElement(NowTimer, { unit: "day" }, function (nowDate, todayRange) { return (createElement(Fragment, null, 12228 createElement("table", { className: "fc-scrollgrid-sync-table", style: { 12229 width: props.clientWidth, 12230 minWidth: props.tableMinWidth, 12231 height: expandRows ? props.clientHeight : '', 12232 } }, 12233 props.colGroupNode, 12234 createElement("tbody", null, props.cells.map(function (cells, row) { return (createElement(TableRow, { ref: _this.rowRefs.createRef(row), key: cells.length 12235 ? cells[0].date.toISOString() /* best? or put key on cell? or use diff formatter? */ 12236 : row // in case there are no cells (like when resource view is loading) 12237 , 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: function (arg) { 12238 _this.handleMoreLinkClick(__assign(__assign({}, arg), { fromRow: row })); 12239 } })); }))), 12240 (!props.forPrint && morePopoverState && morePopoverState.currentFgEventSegs === props.fgEventSegs) && (createElement(MorePopover, { ref: _this.morePopoverRef, 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 12241 (props.eventDrag ? props.eventDrag.affectedInstances : null) || 12242 (props.eventResize ? props.eventResize.affectedInstances : null) || 12243 {}, todayRange: todayRange })))); }))); 12244 }; 12245 // Hit System 12246 // ---------------------------------------------------------------------------------------------------- 12247 Table.prototype.prepareHits = function () { 12248 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 12249 false, true); 12250 this.colPositions = new PositionCache(this.rootEl, this.rowRefs.currentMap[0].getCellEls(), // cell els in first row 12251 true, // horizontal 12252 false); 12253 }; 12254 Table.prototype.positionToHit = function (leftPosition, topPosition) { 12255 var morePopover = this.morePopoverRef.current; 12256 var morePopoverHit = morePopover ? morePopover.positionToHit(leftPosition, topPosition, this.rootEl) : null; 12257 var morePopoverState = this.state.morePopoverState; 12258 if (morePopoverHit) { 12259 return __assign({ row: morePopoverState.fromRow, col: morePopoverState.fromCol }, morePopoverHit); 12260 }
12261 var _a = this, colPositions = _a.colPositions, rowPositions = _a.rowPositions; 12262 var col = colPositions.leftToIndex(leftPosition); 12263 var row = rowPositions.topToIndex(topPosition); 12264 if (row != null && col != null) { 12265 return { 12266 row: row, 12267 col: col, 12268 dateSpan: { 12269 range: this.getCellRange(row, col), 12270 allDay: true, 12271 }, 12272 dayEl: this.getCellEl(row, col), 12273 relativeRect: { 12274 left: colPositions.lefts[col], 12275 right: colPositions.rights[col], 12276 top: rowPositions.tops[row], 12277 bottom: rowPositions.bottoms[row], 12278 }, 12279 }; 12280 } 12281 return null; 12282 }; 12283 Table.prototype.getCellEl = function (row, col) { 12284 return this.rowRefs.currentMap[row].getCellEls()[col]; // TODO: not optimal 12285 }; 12286 Table.prototype.getCellRange = function (row, col) { 12287 var start = this.props.cells[row][col].date; 12288 var end = addDays(start, 1); 12289 return { start: start, end: end }; 12290 }; 12291 return Table; 12292 }(DateComponent)); 12293 function buildBuildMoreLinkText(moreLinkTextInput) { 12294 if (typeof moreLinkTextInput === 'function') { 12295 return moreLinkTextInput; 12296 } 12297 return function (num) { return "+" + num + " " + moreLinkTextInput; }; 12298 } 12299 function isSegAllDay(seg) { 12300 return seg.eventRange.def.allDay; 12301 } 12302 12303 var DayTableSlicer = /** @class */ (function (_super) { 12304 __extends(DayTableSlicer, _super); 12305 function DayTableSlicer() { 12306 var _this = _super !== null && _super.apply(this, arguments) || this; 12307 _this.forceDayIfListItem = true; 12308 return _this; 12309 } 12310 DayTableSlicer.prototype.sliceRange = function (dateRange, dayTableModel) { 12311 return dayTableModel.sliceRange(dateRange); 12312 }; 12313 return DayTableSlicer; 12314 }(Slicer)); 12315 12316 var DayTable = /** @class */ (function (_super) { 12317 __extends(DayTable, _super); 12318 function DayTable() { 12319 var _this = _super !== null && _super.apply(this, arguments) || this; 12320 _this.slicer = new DayTableSlicer(); 12321 _this.tableRef = createRef(); 12322 _this.handleRootEl = function (rootEl) { 12323 if (rootEl) { 12324 _this.context.registerInteractiveComponent(_this, { el: rootEl }); 12325 } 12326 else { 12327 _this.context.unregisterInteractiveComponent(_this); 12328 } 12329 }; 12330 return _this; 12331 } 12332 DayTable.prototype.render = function () { 12333 var _a = this, props = _a.props, context = _a.context; 12334 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 }))); 12335 }; 12336 DayTable.prototype.prepareHits = function () { 12337 this.tableRef.current.prepareHits(); 12338 }; 12339 DayTable.prototype.queryHit = function (positionLeft, positionTop) { 12340 var rawHit = this.tableRef.current.positionToHit(positionLeft, positionTop); 12341 if (rawHit) { 12342 return { 12343 component: this, 12344 dateSpan: rawHit.dateSpan, 12345 dayEl: rawHit.dayEl, 12346 rect: { 12347 left: rawHit.relativeRect.left, 12348 right: rawHit.relativeRect.right, 12349 top: rawHit.relativeRect.top, 12350 bottom: rawHit.relativeRect.bottom, 12351 }, 12352 layer: 0, 12353 }; 12354 } 12355 return null; 12356 }; 12357 return DayTable; 12358 }(DateComponent)); 12359 12360 var DayTableView = /** @class */ (function (_super) { 12361 __extends(DayTableView, _super); 12362 function DayTableView() { 12363 var _this = _super !== null && _super.apply(this, arguments) || this; 12364 _this.buildDayTableModel = memoize(buildDayTableModel); 12365 _this.headerRef = createRef(); 12366 _this.tableRef = createRef(); 12367 return _this; 12368 } 12369 DayTableView.prototype.render = function () { 12370 var _this = this; 12371 var _a = this.context, options = _a.options, dateProfileGenerator = _a.dateProfileGenerator; 12372 var props = this.props; 12373 var dayTableModel = this.buildDayTableModel(props.dateProfile, dateProfileGenerator); 12374 var headerContent = options.dayHeaders && (createElement(DayHeader, { ref: this.headerRef, dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: dayTableModel.rowCnt === 1 })); 12375 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 })); }; 12376 return options.dayMinWidth 12377 ? this.renderHScrollLayout(headerContent, bodyContent, dayTableModel.colCnt, options.dayMinWidth) 12378 : this.renderSimpleLayout(headerContent, bodyContent); 12379 }; 12380 return DayTableView; 12381 }(TableView)); 12382 function buildDayTableModel(dateProfile, dateProfileGenerator) {
12383 var daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator); 12384 return new DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit)); 12385 } 12386 12387 var TableDateProfileGenerator = /** @class */ (function (_super) { 12388 __extends(TableDateProfileGenerator, _super); 12389 function TableDateProfileGenerator() { 12390 return _super !== null && _super.apply(this, arguments) || this; 12391 } 12392 // Computes the date range that will be rendered. 12393 TableDateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) { 12394 var dateEnv = this.props.dateEnv; 12395 var renderRange = _super.prototype.buildRenderRange.call(this, currentRange, currentRangeUnit, isRangeAllDay); 12396 var start = renderRange.start; 12397 var end = renderRange.end; 12398 var endOfWeek; 12399 // year and month views should be aligned with weeks. this is already done for week 12400 if (/^(year|month)$/.test(currentRangeUnit)) { 12401 start = dateEnv.startOfWeek(start); 12402 // make end-of-week if not already 12403 endOfWeek = dateEnv.startOfWeek(end); 12404 if (endOfWeek.valueOf() !== end.valueOf()) { 12405 end = addWeeks(endOfWeek, 1); 12406 } 12407 } 12408 // ensure 6 weeks 12409 if (this.props.monthMode && 12410 this.props.fixedWeekCount) { 12411 var rowCnt = Math.ceil(// could be partial weeks due to hiddenDays 12412 diffWeeks(start, end)); 12413 end = addWeeks(end, 6 - rowCnt); 12414 } 12415 return { start: start, end: end }; 12416 }; 12417 return TableDateProfileGenerator; 12418 }(DateProfileGenerator)); 12419 12420 var OPTION_REFINERS$1 = { 12421 moreLinkClick: identity, 12422 moreLinkClassNames: identity, 12423 moreLinkContent: identity, 12424 moreLinkDidMount: identity, 12425 moreLinkWillUnmount: identity, 12426 }; 12427 12428 var dayGridPlugin = createPlugin({ 12429 initialView: 'dayGridMonth', 12430 optionRefiners: OPTION_REFINERS$1, 12431 views: { 12432 dayGrid: { 12433 component: DayTableView, 12434 dateProfileGeneratorClass: TableDateProfileGenerator, 12435 }, 12436 dayGridDay: { 12437 type: 'dayGrid', 12438 duration: { days: 1 }, 12439 }, 12440 dayGridWeek: { 12441 type: 'dayGrid', 12442 duration: { weeks: 1 }, 12443 }, 12444 dayGridMonth: { 12445 type: 'dayGrid', 12446 duration: { months: 1 }, 12447 monthMode: true, 12448 fixedWeekCount: true, 12449 }, 12450 }, 12451 }); 12452 12453 var AllDaySplitter = /** @class */ (function (_super) { 12454 __extends(AllDaySplitter, _super); 12455 function AllDaySplitter() { 12456 return _super !== null && _super.apply(this, arguments) || this; 12457 } 12458 AllDaySplitter.prototype.getKeyInfo = function () { 12459 return { 12460 allDay: {}, 12461 timed: {}, 12462 }; 12463 }; 12464 AllDaySplitter.prototype.getKeysForDateSpan = function (dateSpan) { 12465 if (dateSpan.allDay) { 12466 return ['allDay']; 12467 } 12468 return ['timed']; 12469 }; 12470 AllDaySplitter.prototype.getKeysForEventDef = function (eventDef) { 12471 if (!eventDef.allDay) { 12472 return ['timed']; 12473 } 12474 if (hasBgRendering(eventDef)) { 12475 return ['timed', 'allDay']; 12476 } 12477 return ['allDay']; 12478 }; 12479 return AllDaySplitter; 12480 }(Splitter)); 12481 12482 var DEFAULT_SLAT_LABEL_FORMAT = createFormatter({ 12483 hour: 'numeric', 12484 minute: '2-digit', 12485 omitZeroMinute: true, 12486 meridiem: 'short', 12487 }); 12488 function TimeColsAxisCell(props) { 12489 var classNames = [ 12490 'fc-timegrid-slot', 12491 'fc-timegrid-slot-label', 12492 props.isLabeled ? 'fc-scrollgrid-shrink' : 'fc-timegrid-slot-minor', 12493 ]; 12494 return (createElement(ViewContextType.Consumer, null, function (context) { 12495 if (!props.isLabeled) { 12496 return (createElement("td", { className: classNames.join(' '), "data-time": props.isoTimeStr })); 12497 } 12498 var dateEnv = context.dateEnv, options = context.options, viewApi = context.viewApi; 12499 var labelFormat = // TODO: fully pre-parse 12500 options.slotLabelFormat == null ? DEFAULT_SLAT_LABEL_FORMAT : 12501 Array.isArray(options.slotLabelFormat) ? createFormatter(options.slotLabelFormat[0]) : 12502 createFormatter(options.slotLabelFormat); 12503 var hookProps = { 12504 level: 0, 12505 time: props.time, 12506 date: dateEnv.toDate(props.date), 12507 view: viewApi, 12508 text: dateEnv.format(props.date, labelFormat), 12509 }; 12510 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
12510oncat(customClassNames).join(' '), "data-time": props.isoTimeStr }, 12511 createElement("div", { className: "fc-timegrid-slot-label-frame fc-scrollgrid-shrink-frame" }, 12512 createElement("div", { className: "fc-timegrid-slot-label-cushion fc-scrollgrid-shrink-cushion", ref: innerElRef }, innerContent)))); })); 12513 })); 12514 } 12515 function renderInnerContent$3(props) { 12516 return props.text; 12517 } 12518 12519 var TimeBodyAxis = /** @class */ (function (_super) { 12520 __extends(TimeBodyAxis, _super); 12521 function TimeBodyAxis() { 12522 return _super !== null && _super.apply(this, arguments) || this; 12523 } 12524 TimeBodyAxis.prototype.render = function () { 12525 return this.props.slatMetas.map(function (slatMeta) { return (createElement("tr", { key: slatMeta.key }, 12526 createElement(TimeColsAxisCell, __assign({}, slatMeta)))); }); 12527 }; 12528 return TimeBodyAxis; 12529 }(BaseComponent)); 12530 12531 var DEFAULT_WEEK_NUM_FORMAT$1 = createFormatter({ week: 'short' }); 12532 var AUTO_ALL_DAY_MAX_EVENT_ROWS = 5; 12533 var TimeColsView = /** @class */ (function (_super) { 12534 __extends(TimeColsView, _super); 12535 function TimeColsView() { 12536 var _this = _super !== null && _super.apply(this, arguments) || this; 12537 _this.allDaySplitter = new AllDaySplitter(); // for use by subclasses 12538 _this.headerElRef = createRef(); 12539 _this.rootElRef = createRef(); 12540 _this.scrollerElRef = createRef(); 12541 _this.state = { 12542 slatCoords: null, 12543 }; 12544 _this.handleScrollTopRequest = function (scrollTop) { 12545 var scrollerEl = _this.scrollerElRef.current; 12546 if (scrollerEl) { // TODO: not sure how this could ever be null. weirdness with the reducer 12547 scrollerEl.scrollTop = scrollTop; 12548 } 12549 }; 12550 /* Header Render Methods 12551 ------------------------------------------------------------------------------------------------------------------*/ 12552 _this.renderHeadAxis = function (rowKey, frameHeight) { 12553 if (frameHeight === void 0) { frameHeight = ''; } 12554 var options = _this.context.options; 12555 var dateProfile = _this.props.dateProfile; 12556 var range = dateProfile.renderRange; 12557 var dayCnt = diffDays(range.start, range.end); 12558 var navLinkAttrs = (options.navLinks && dayCnt === 1) // only do in day views (to avoid doing in week views that dont need it) 12559 ? { 'data-navlink': buildNavLinkData(range.start, 'week'), tabIndex: 0 } 12560 : {}; 12561 if (options.weekNumbers && rowKey === 'day') { 12562 return (createElement(WeekNumberRoot, { date: range.start, defaultFormat: DEFAULT_WEEK_NUM_FORMAT$1 }, function (rootElRef, classNames, innerElRef, innerContent) { return (createElement("th", { ref: rootElRef, className: [ 12563 'fc-timegrid-axis', 12564 'fc-scrollgrid-shrink', 12565 ].concat(classNames).join(' ') }, 12566 createElement("div", { className: "fc-timegrid-axis-frame fc-scrollgrid-shrink-frame fc-timegrid-axis-frame-liquid", style: { height: frameHeight } }, 12567 createElement("a", __assign({ ref: innerElRef, className: "fc-timegrid-axis-cushion fc-scrollgrid-shrink-cushion fc-scrollgrid-sync-inner" }, navLinkAttrs), innerContent)))); })); 12568 } 12569 return (createElement("th", { className: "fc-timegrid-axis" }, 12570 createElement("div", { className: "fc-timegrid-axis-frame", style: { height: frameHeight } }))); 12571 }; 12572 /* Table Component Render Methods 12573 ------------------------------------------------------------------------------------------------------------------*/ 12574 // only a one-way height sync. we don't send the axis inner-content height to the DayGrid, 12575 // but DayGrid still needs to have classNames on inner elements in order to measure. 12576 _this.renderTableRowAxis = function (rowHeight) { 12577 var _a = _this.context, options = _a.options, viewApi = _a.viewApi; 12578 var hookProps = { 12579 text: options.allDayText, 12580 view: viewApi, 12581 }; 12582 return ( 12583 // TODO: make reusable hook. used in list view too 12584 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: [ 12585 'fc-timegrid-axis', 12586 'fc-scrollgrid-shrink', 12587 ].concat(classNames).join(' ') }, 12588 createElement("div", { className: 'fc-timegrid-axis-frame fc-scrollgrid-shrink-frame' + (rowHeight == null ? ' fc-timegrid-axis-frame-liquid' : ''), style: { height: rowHeight } }, 12589 createElement("span", { className: "fc-timegrid-axis-cushion fc-scrollgrid-shrink-cushion fc-scrollgrid-sync-inner", ref: innerElRef }, innerContent)))); })); 12590 }; 12591 _this.handleSlatCoords = function (slatCoords) {
12592 _this.setState({ slatCoords: slatCoords }); 12593 }; 12594 return _this; 12595 } 12596 // rendering 12597 // ---------------------------------------------------------------------------------------------------- 12598 TimeColsView.prototype.renderSimpleLayout = function (headerRowContent, allDayContent, timeContent) { 12599 var _a = this, context = _a.context, props = _a.props; 12600 var sections = []; 12601 var stickyHeaderDates = getStickyHeaderDates(context.options); 12602 if (headerRowContent) { 12603 sections.push({ 12604 type: 'header', 12605 key: 'header', 12606 isSticky: stickyHeaderDates, 12607 chunk: { 12608 elRef: this.headerElRef, 12609 tableClassName: 'fc-col-header', 12610 rowContent: headerRowContent, 12611 }, 12612 }); 12613 } 12614 if (allDayContent) { 12615 sections.push({ 12616 type: 'body', 12617 key: 'all-day', 12618 chunk: { content: allDayContent }, 12619 }); 12620 sections.push({ 12621 type: 'body', 12622 key: 'all-day-divider', 12623 outerContent: ( // TODO: rename to cellContent so don't need to define <tr>? 12624 createElement("tr", { className: "fc-scrollgrid-section" }, 12625 createElement("td", { className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))), 12626 }); 12627 } 12628 sections.push({ 12629 type: 'body', 12630 key: 'body', 12631 liquid: true, 12632 expandRows: Boolean(context.options.expandRows), 12633 chunk: { 12634 scrollerElRef: this.scrollerElRef, 12635 content: timeContent, 12636 }, 12637 }); 12638 return (createElement(ViewRoot, { viewSpec: context.viewSpec, elRef: this.rootElRef }, function (rootElRef, classNames) { return (createElement("div", { className: ['fc-timegrid'].concat(classNames).join(' '), ref: rootElRef }, 12639 createElement(SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, cols: [{ width: 'shrink' }], sections: sections }))); })); 12640 }; 12641 TimeColsView.prototype.renderHScrollLayout = function (headerRowContent, allDayContent, timeContent, colCnt, dayMinWidth, slatMetas, slatCoords) { 12642 var _this = this; 12643 var ScrollGrid = this.context.pluginHooks.scrollGridImpl; 12644 if (!ScrollGrid) { 12645 throw new Error('No ScrollGrid implementation'); 12646 } 12647 var _a = this, context = _a.context, props = _a.props; 12648 var stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options); 12649 var stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options); 12650 var sections = []; 12651 if (headerRowContent) { 12652 sections.push({ 12653 type: 'header', 12654 key: 'header', 12655 isSticky: stickyHeaderDates, 12656 syncRowHeights: true, 12657 chunks: [ 12658 { 12659 key: 'axis', 12660 rowContent: function (arg) { return (createElement("tr", null, _this.renderHeadAxis('day', arg.rowSyncHeights[0]))); }, 12661 }, 12662 { 12663 key: 'cols', 12664 elRef: this.headerElRef, 12665 tableClassName: 'fc-col-header', 12666 rowContent: headerRowContent, 12667 }, 12668 ], 12669 }); 12670 } 12671 if (allDayContent) { 12672 sections.push({ 12673 type: 'body', 12674 key: 'all-day', 12675 syncRowHeights: true, 12676 chunks: [ 12677 { 12678 key: 'axis', 12679 rowContent: function (contentArg) { return (createElement("tr", null, _this.renderTableRowAxis(contentArg.rowSyncHeights[0]))); }, 12680 }, 12681 { 12682 key: 'cols', 12683 content: allDayContent, 12684 }, 12685 ], 12686 }); 12687 sections.push({ 12688 key: 'all-day-divider', 12689 type: 'body', 12690 outerContent: ( // TODO: rename to cellContent so don't need to define <tr>? 12691 createElement("tr", { className: "fc-scrollgrid-section" }, 12692 createElement("td", { colSpan: 2, className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))), 12693 }); 12694 } 12695 var isNowIndicator = context.options.nowIndicator; 12696 sections.push({ 12697 type: 'body', 12698 key: 'body', 12699 liquid: true, 12700 expandRows: Boolean(context.options.expandRows), 12701 chunks: [ 12702 { 12703 key: 'axis', 12704 content: function (arg) { return ( 12705 // TODO: make this now-indicator arrow more DRY with TimeColsContent 12706 createElement("div", { className: "fc-timegrid-axis-chunk" }, 12707 createElement("table", { style: { height: arg.expandRows ? arg.clientHeight : '' } }, 12708 arg.tableColGroupNode, 12709 createElement("tbody", null, 12710 createElement(TimeBodyAxis, { slatMetas: slatMetas }))), 12711 createElement("div", { className: "fc-timegrid-now-indicator-container" }, 12712 createElement(NowTimer, { unit: isNowIndicator ? 'minute' : 'day' /* hacky */ }, function (nowDate) { 12713 var nowIndicatorTop = isNowIndicator && 12714 slatCoords && 12715 slatCoords.safeComputeTop(nowDate); // might return void 12716 if (typeof nowIndicatorTop === 'number') { 12717 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)); })); 12718 } 12719 return null; 12720 })))); }, 12721 }, 12722 { 12723 key: 'cols', 12724 scrollerElRef: this.scrollerElRef, 12725 content: timeContent, 12726 }, 12727 ], 12728 }); 12729 if (stickyFooterScrollbar) { 12730 sections.push({ 12731 key: 'footer', 12732 type: 'footer', 12733 isSticky: true, 12734 chunks: [ 12735 { 12736 key: 'axis', 12737 content: renderScrollShim, 12738 }, 12739 { 12740 key: 'cols', 12741 content: renderScrollShim, 12742 }, 12743 ], 12744 }); 12745 } 12746 return (createElement(ViewRoot, { viewSpec: context.viewSpec, elRef: this.rootElRef }, function (rootElRef, classNames) { return (createElement("div", { className: ['fc-timegrid'].
12746concat(classNames).join(' '), ref: rootElRef }, 12747 createElement(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, colGroups: [ 12748 { width: 'shrink', cols: [{ width: 'shrink' }] }, 12749 { cols: [{ span: colCnt, minWidth: dayMinWidth }] }, 12750 ], sections: sections }))); })); 12751 }; 12752 /* Dimensions 12753 ------------------------------------------------------------------------------------------------------------------*/ 12754 TimeColsView.prototype.getAllDayMaxEventProps = function () { 12755 var _a = this.context.options, dayMaxEvents = _a.dayMaxEvents, dayMaxEventRows = _a.dayMaxEventRows; 12756 if (dayMaxEvents === true || dayMaxEventRows === true) { // is auto? 12757 dayMaxEvents = undefined; 12758 dayMaxEventRows = AUTO_ALL_DAY_MAX_EVENT_ROWS; // make sure "auto" goes to a real number 12759 } 12760 return { dayMaxEvents: dayMaxEvents, dayMaxEventRows: dayMaxEventRows }; 12761 }; 12762 return TimeColsView; 12763 }(DateComponent)); 12764 function renderAllDayInner(hookProps) { 12765 return hookProps.text; 12766 } 12767 12768 var TimeColsSlatsCoords = /** @class */ (function () { 12769 function TimeColsSlatsCoords(positions, dateProfile, slotDuration) { 12770 this.positions = positions; 12771 this.dateProfile = dateProfile; 12772 this.slotDuration = slotDuration; 12773 } 12774 TimeColsSlatsCoords.prototype.safeComputeTop = function (date) { 12775 var dateProfile = this.dateProfile; 12776 if (rangeContainsMarker(dateProfile.currentRange, date)) { 12777 var startOfDayDate = startOfDay(date); 12778 var timeMs = date.valueOf() - startOfDayDate.valueOf(); 12779 if (timeMs >= asRoughMs(dateProfile.slotMinTime) && 12780 timeMs < asRoughMs(dateProfile.slotMaxTime)) { 12781 return this.computeTimeTop(createDuration(timeMs)); 12782 } 12783 } 12784 return null; 12785 }; 12786 // Computes the top coordinate, relative to the bounds of the grid, of the given date. 12787 // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight. 12788 TimeColsSlatsCoords.prototype.computeDateTop = function (when, startOfDayDate) { 12789 if (!startOfDayDate) { 12790 startOfDayDate = startOfDay(when); 12791 } 12792 return this.computeTimeTop(createDuration(when.valueOf() - startOfDayDate.valueOf())); 12793 }; 12794 // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration). 12795 // This is a makeshify way to compute the time-top. Assumes all slatMetas dates are uniform. 12796 // Eventually allow computation with arbirary slat dates. 12797 TimeColsSlatsCoords.prototype.computeTimeTop = function (duration) { 12798 var _a = this, positions = _a.positions, dateProfile = _a.dateProfile; 12799 var len = positions.els.length; 12800 // floating-point value of # of slots covered 12801 var slatCoverage = (duration.milliseconds - asRoughMs(dateProfile.slotMinTime)) / asRoughMs(this.slotDuration); 12802 var slatIndex; 12803 var slatRemainder; 12804 // compute a floating-point number for how many slats should be progressed through. 12805 // from 0 to number of slats (inclusive) 12806 // constrained because slotMinTime/slotMaxTime might be customized. 12807 slatCoverage = Math.max(0, slatCoverage); 12808 slatCoverage = Math.min(len, slatCoverage); 12809 // an integer index of the furthest whole slat 12810 // from 0 to number slats (*exclusive*, so len-1) 12811 slatIndex = Math.floor(slatCoverage); 12812 slatIndex = Math.min(slatIndex, len - 1); 12813 // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition. 12814 // could be 1.0 if slatCoverage is covering *all* the slots 12815 slatRemainder = slatCoverage - slatIndex; 12816 return positions.tops[slatIndex] + 12817 positions.getHeight(slatIndex) * slatRemainder; 12818 }; 12819 return TimeColsSlatsCoords; 12820 }()); 12821 12822 var TimeColsSlatsBody = /** @class */ (function (_super) { 12823 __extends(TimeColsSlatsBody, _super); 12824 function TimeColsSlatsBody() { 12825 return _super !== null && _super.apply(this, arguments) || this; 12826 } 12827 TimeColsSlatsBody.prototype.render = function () { 12828 var _a = this, props = _a.props, context = _a.context; 12829 var options = context.options; 12830 var slatElRefs = props.slatElRefs; 12831 return (createElement("tbody", null, props.slatMetas.map(function (slatMeta, i) { 12832 var hookProps = { 12833 time: slatMeta.time, 12834 date: context.dateEnv.toDate(slatMeta.date), 12835 view: context.viewApi, 12836 }; 12837 var classNames = [ 12838 'fc-timegrid-slot', 12839 'fc-timegrid-slot-lane', 12840 slatMeta.isLabeled ? '' : 'fc-timegrid-slot-minor', 12841 ]; 12842 return (createElement("tr", { key: slatMeta.key, ref: slatElRefs.createRef(slatMeta.key) }, 12843 props.axis && (createElement(TimeColsAxisCell, __assign({}, slatMeta))), 12844 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.c
12844oncat(customClassNames).join(' '), "data-time": slatMeta.isoTimeStr }, innerContent)); }))); 12845 }))); 12846 }; 12847 return TimeColsSlatsBody; 12848 }(BaseComponent)); 12849 12850 /* 12851 for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL. 12852 */ 12853 var TimeColsSlats = /** @class */ (function (_super) { 12854 __extends(TimeColsSlats, _super); 12855 function TimeColsSlats() { 12856 var _this = _super !== null && _super.apply(this, arguments) || this; 12857 _this.rootElRef = createRef(); 12858 _this.slatElRefs = new RefMap(); 12859 return _this; 12860 } 12861 TimeColsSlats.prototype.render = function () { 12862 var _a = this, props = _a.props, context = _a.context; 12863 return (createElement("div", { className: "fc-timegrid-slots", ref: this.rootElRef }, 12864 createElement("table", { className: context.theme.getClass('table'), style: { 12865 minWidth: props.tableMinWidth, 12866 width: props.clientWidth, 12867 height: props.minHeight, 12868 } }, 12869 props.tableColGroupNode /* relies on there only being a single <col> for the axis */, 12870 createElement(TimeColsSlatsBody, { slatElRefs: this.slatElRefs, axis: props.axis, slatMetas: props.slatMetas })))); 12871 }; 12872 TimeColsSlats.prototype.componentDidMount = function () { 12873 this.updateSizing(); 12874 }; 12875 TimeColsSlats.prototype.componentDidUpdate = function () { 12876 this.updateSizing(); 12877 }; 12878 TimeColsSlats.prototype.componentWillUnmount = function () { 12879 if (this.props.onCoords) { 12880 this.props.onCoords(null); 12881 } 12882 }; 12883 TimeColsSlats.prototype.updateSizing = function () { 12884 var _a = this, context = _a.context, props = _a.props; 12885 if (props.onCoords && 12886 props.clientWidth !== null // means sizing has stabilized 12887 ) { 12888 var rootEl = this.rootElRef.current; 12889 if (rootEl.offsetHeight) { // not hidden by css 12890 props.onCoords(new TimeColsSlatsCoords(new PositionCache(this.rootElRef.current, collectSlatEls(this.slatElRefs.currentMap, props.slatMetas), false, true), this.props.dateProfile, context.options.slotDuration)); 12891 } 12892 } 12893 }; 12894 return TimeColsSlats; 12895 }(BaseComponent)); 12896 function collectSlatEls(elMap, slatMetas) { 12897 return slatMetas.map(function (slatMeta) { return elMap[slatMeta.key]; }); 12898 } 12899 12900 function splitSegsByCol(segs, colCnt) { 12901 var segsByCol = []; 12902 var i; 12903 for (i = 0; i < colCnt; i += 1) { 12904 segsByCol.push([]); 12905 } 12906 if (segs) { 12907 for (i = 0; i < segs.length; i += 1) { 12908 segsByCol[segs[i].col].push(segs[i]); 12909 } 12910 } 12911 return segsByCol; 12912 } 12913 function splitInteractionByCol(ui, colCnt) { 12914 var byRow = []; 12915 if (!ui) { 12916 for (var i = 0; i < colCnt; i += 1) { 12917 byRow[i] = null; 12918 } 12919 } 12920 else { 12921 for (var i = 0; i < colCnt; i += 1) { 12922 byRow[i] = { 12923 affectedInstances: ui.affectedInstances, 12924 isEvent: ui.isEvent, 12925 segs: [], 12926 }; 12927 } 12928 for (var _i = 0, _a = ui.segs; _i < _a.length; _i++) { 12929 var seg = _a[_i]; 12930 byRow[seg.col].segs.push(seg); 12931 } 12932 } 12933 return byRow; 12934 } 12935 12936 // UNFORTUNATELY, assigns results to the top/bottom/level/forwardCoord/backwardCoord props of the actual segs. 12937 // TODO: return hash (by instanceId) of results 12938 function computeSegCoords(segs, dayDate, slatCoords, eventMinHeight, eventOrderSpecs) { 12939 computeSegVerticals(segs, dayDate, slatCoords, eventMinHeight); 12940 return computeSegHorizontals(segs, eventOrderSpecs); // requires top/bottom from computeSegVerticals 12941 } 12942 // For each segment in an array, computes and assigns its top and bottom properties 12943 function computeSegVerticals(segs, dayDate, slatCoords, eventMinHeight) { 12944 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 12945 var seg = segs_1[_i]; 12946 seg.top = slatCoords.computeDateTop(seg.start, dayDate); 12947 seg.bottom = Math.max(seg.top + (eventMinHeight || 0
12947), // yuck 12948 slatCoords.computeDateTop(seg.end, dayDate)); 12949 } 12950 } 12951 // Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each. 12952 // Assumed the segs are already ordered. 12953 // NOTE: Also reorders the given array by date! 12954 function computeSegHorizontals(segs, eventOrderSpecs) { 12955 // IMPORTANT TO CLEAR OLD RESULTS :( 12956 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 12957 var seg = segs_2[_i]; 12958 seg.level = null; 12959 seg.forwardCoord = null; 12960 seg.backwardCoord = null; 12961 seg.forwardPressure = null; 12962 } 12963 segs = sortEventSegs(segs, eventOrderSpecs); 12964 var level0; 12965 var levels = buildSlotSegLevels(segs); 12966 computeForwardSlotSegs(levels); 12967 if ((level0 = levels[0])) { 12968 for (var _a = 0, level0_1 = level0; _a < level0_1.length; _a++) { 12969 var seg = level0_1[_a]; 12970 computeSlotSegPressures(seg); 12971 } 12972 for (var _b = 0, level0_2 = level0; _b < level0_2.length; _b++) { 12973 var seg = level0_2[_b]; 12974 computeSegForwardBack(seg, 0, 0, eventOrderSpecs); 12975 } 12976 } 12977 return segs; 12978 } 12979 // Builds an array of segments "levels". The first level will be the leftmost tier of segments if the calendar is 12980 // left-to-right, or the rightmost if the calendar is right-to-left. Assumes the segments are already ordered by date. 12981 function buildSlotSegLevels(segs) { 12982 var levels = []; 12983 var i; 12984 var seg; 12985 var j; 12986 for (i = 0; i < segs.length; i += 1) { 12987 seg = segs[i]; 12988 // go through all the levels and stop on the first level where there are no collisions 12989 for (j = 0; j < levels.length; j += 1) { 12990 if (!computeSlotSegCollisions(seg, levels[j]).length) { 12991 break; 12992 } 12993 } 12994 seg.level = j; 12995 (levels[j] || (levels[j] = [])).push(seg); 12996 } 12997 return levels; 12998 } 12999 // Find all the segments in `otherSegs` that vertically collide with `seg`. 13000 // Append into an optionally-supplied `results` array and return. 13001 function computeSlotSegCollisions(seg, otherSegs, results) { 13002 if (results === void 0) { results = []; } 13003 for (var i = 0; i < otherSegs.length; i += 1) { 13004 if (isSlotSegCollision(seg, otherSegs[i])) { 13005 results.push(otherSegs[i]); 13006 } 13007 } 13008 return results; 13009 } 13010 // Do these segments occupy the same vertical space? 13011 function isSlotSegCollision(seg1, seg2) { 13012 return seg1.bottom > seg2.top && seg1.top < seg2.bottom; 13013 } 13014 // For every segment, figure out the other segments that are in subsequent 13015 // levels that also occupy the same vertical space. Accumulate in seg.forwardSegs 13016 function computeForwardSlotSegs(levels) { 13017 var i; 13018 var level; 13019 var j; 13020 var seg; 13021 var k; 13022 for (i = 0; i < levels.length; i += 1) { 13023 level = levels[i]; 13024 for (j = 0; j < level.length; j += 1) { 13025 seg = level[j]; 13026 seg.forwardSegs = []; 13027 for (k = i + 1; k < levels.length; k += 1) { 13028 computeSlotSegCollisions(seg, levels[k], seg.forwardSegs); 13029 } 13030 } 13031 } 13032 } 13033 // Figure out which path forward (via seg.forwardSegs) results in the longest path until 13034 // the furthest edge is reached. The number of segments in this path will be seg.forwardPressure 13035 function computeSlotSegPressures(seg) { 13036 var forwardSegs = seg.forwardSegs; 13037 var forwardPressure = 0; 13038 var i; 13039 var forwardSeg; 13040 if (seg.forwardPressure == null) { // not already computed 13041 for (i = 0; i < forwardSegs.length; i += 1) { 13042 forwardSeg = forwardSegs[i]; 13043 // figure out the child's maximum forward path 13044 computeSlotSegPressures(forwardSeg); 13045 // either use the existing maximum, or use the child's forward pressure 13046 // plus one (for the forwardSeg itself) 13047 forwardPressure = Math.max(forwardPressure, 1 + forwardSeg.forwardPressure); 13048 } 13049 seg.forwardPressure = forwardPressure; 13050 } 13051 } 13052 // Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range 13053 // from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and 13054 // seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left. 13055 // 13056 // The segment might be part of a "series", which means consecutive segments with the same pressure 13057 // who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of 13058 // segments behind this one in the current series, and `seriesBackwardCoord` is the starting 13059 // coordinate of the first segment in the series. 13060 function computeSegForwardBack(seg, seriesBackwardPressure, seriesBackwardCoord, eventOrderSpecs) { 13061 var forwardSegs = seg.forwardSegs; 13062 var i; 13063 if (seg.forwardCoord == null) { // not already computed 13064 if (!forwardSegs.length) { 13065 // if there are no forward segments, this segment should butt up against the edge 13066 seg.forwardCoord = 1; 13067 } 13068 else { 13069 // sort highest pressure first 13070 sortForwardSegs(forwardSegs, eventOrderSpecs); 13071 // this segment's forwardCoord will be calculated from the backwardCoord of the 13072 // highest-pressure forward segment. 13073 computeSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord, eventOrderSpecs); 13074 seg.forwardCoord = forwardSegs[0].backwardCoord; 13075 } 13076 // calculate the backwardCoord from the forwardCoord. consider the series 13077 seg.backwardCoord = seg.forwardCoord - 13078 (seg.forwardCoord - seriesBackwardCoord) / // available width for series 13079 (seriesBackwardPressure + 1); // # of segments in the series
13080 // use this segment's coordinates to computed the coordinates of the less-pressurized 13081 // forward segments 13082 for (i = 0; i < forwardSegs.length; i += 1) { 13083 computeSegForwardBack(forwardSegs[i], 0, seg.forwardCoord, eventOrderSpecs); 13084 } 13085 } 13086 } 13087 function sortForwardSegs(forwardSegs, eventOrderSpecs) { 13088 var objs = forwardSegs.map(buildTimeGridSegCompareObj); 13089 var specs = [ 13090 // put higher-pressure first 13091 { field: 'forwardPressure', order: -1 }, 13092 // put segments that are closer to initial edge first (and favor ones with no coords yet) 13093 { field: 'backwardCoord', order: 1 }, 13094 ].concat(eventOrderSpecs); 13095 objs.sort(function (obj0, obj1) { return compareByFieldSpecs(obj0, obj1, specs); }); 13096 return objs.map(function (c) { return c._seg; }); 13097 } 13098 function buildTimeGridSegCompareObj(seg) { 13099 var obj = buildSegCompareObj(seg); 13100 obj.forwardPressure = seg.forwardPressure; 13101 obj.backwardCoord = seg.backwardCoord; 13102 return obj; 13103 } 13104 13105 var DEFAULT_TIME_FORMAT = createFormatter({ 13106 hour: 'numeric', 13107 minute: '2-digit', 13108 meridiem: false, 13109 }); 13110 var TimeColEvent = /** @class */ (function (_super) { 13111 __extends(TimeColEvent, _super); 13112 function TimeColEvent() { 13113 return _super !== null && _super.apply(this, arguments) || this; 13114 } 13115 TimeColEvent.prototype.render = function () { 13116 var classNames = [ 13117 'fc-timegrid-event', 13118 'fc-v-event', 13119 ]; 13120 if (this.props.isCondensed) { 13121 classNames.push('fc-timegrid-event-condensed'); 13122 } 13123 return (createElement(StandardEvent, __assign({}, this.props, { defaultTimeFormat: DEFAULT_TIME_FORMAT, extraClassNames: classNames }))); 13124 }; 13125 return TimeColEvent; 13126 }(BaseComponent)); 13127 13128 var TimeColMisc = /** @class */ (function (_super) { 13129 __extends(TimeColMisc, _super); 13130 function TimeColMisc() { 13131 return _super !== null && _super.apply(this, arguments) || this; 13132 } 13133 TimeColMisc.prototype.render = function () { 13134 var props = this.props; 13135 return (createElement(DayCellContent, { date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, extraHookProps: props.extraHookProps }, function (innerElRef, innerContent) { return (innerContent && 13136 createElement("div", { className: "fc-timegrid-col-misc", ref: innerElRef }, innerContent)); })); 13137 }; 13138 return TimeColMisc; 13139 }(BaseComponent)); 13140 13141 config.timeGridEventCondensedHeight = 30; 13142 var TimeCol = /** @class */ (function (_super) { 13143 __extends(TimeCol, _super); 13144 function TimeCol() { 13145 return _super !== null && _super.apply(this, arguments) || this; 13146 } 13147 TimeCol.prototype.render = function () { 13148 var _this = this; 13149 var _a = this, props = _a.props, context = _a.context; 13150 var isSelectMirror = context.options.selectMirror; 13151 var mirrorSegs = (props.eventDrag && props.eventDrag.segs) || 13152 (props.eventResize && props.eventResize.segs) || 13153 (isSelectMirror && props.dateSelectionSegs) || 13154 []; 13155 var interactionAffectedInstances = // TODO: messy way to compute this 13156 (props.eventDrag && props.eventDrag.affectedInstances) || 13157 (props.eventResize && props.eventResize.affectedInstances) || 13158 {}; 13159 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), 13160 createElement("div", { className: "fc-timegrid-col-frame" }, 13161 createElement("div", { className: "fc-timegrid-col-bg" }, 13162 _this.renderFillSegs(props.businessHourSegs, 'non-business'), 13163 _this.renderFillSegs(props.bgEventSegs, 'bg-event'), 13164 _this.renderFillSegs(props.dateSelectionSegs, 'highlight')), 13165 createElement("div", { className: "fc-timegrid-col-events" }, _this.renderFgSegs(props.fgEventSegs, interactionAffectedInstances)), 13166 createElement("div", { className: "fc-timegrid-col-events" }, _this.renderFgSegs(mirrorSegs, {}, Boolean(props.eventDrag), Boolean(props.eventResize), Boolean(isSelectMirror))), 13167 createElement("div", { className: "fc-timegrid-now-indicator-container" }, _this.renderNowIndicator(props.nowIndicatorSegs)), 13168 createElement(TimeColMisc, { date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, extraHookProps: props.extraHookProps })))); })); 13169 }; 13170 TimeCol.prototype.renderFgSegs = function (segs, segIsInvisible, isDragging, isResizing, isDateSelecting) { 13171 var props = this.props; 13172 if (props.forPrint) { 13173 return this.renderPrintFgSegs(segs); 13174 } 13175 if (props.slatCoords) { 13176 return this.renderPositionedFgSegs(segs, segIsInvisible, isDragging, isResizing, isDateSelecting); 13177 } 13178 return null; 13179 }; 13180 TimeCol.prototype.renderPrintFgSegs = function (segs) { 13181 var _a = this, props = _a.props, context = _a.context; 13182 // not DRY 13183 segs = sortEventSegs(segs, context.options.eventOrder); 13184 return segs.map(function (seg) { return (createElement("div", { className: "fc-timegrid-event-harness", key: seg.eventRange.instance.instanceId }, 13185 createElement(TimeColEvent, __assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false, isCondensed: fal
13185se }, getSegMeta(seg, props.todayRange, props.nowDate))))); }); 13186 }; 13187 TimeCol.prototype.renderPositionedFgSegs = function (segs, segIsInvisible, isDragging, isResizing, isDateSelecting) { 13188 var _this = this; 13189 var _a = this, context = _a.context, props = _a.props; 13190 // assigns TO THE SEGS THEMSELVES 13191 // also, receives resorted array 13192 segs = computeSegCoords(segs, props.date, props.slatCoords, context.options.eventMinHeight, context.options.eventOrder); 13193 return segs.map(function (seg) { 13194 var instanceId = seg.eventRange.instance.instanceId; 13195 var isMirror = isDragging || isResizing || isDateSelecting; 13196 var positionCss = isMirror 13197 // will span entire column width 13198 // also, won't assign z-index, which is good, fc-event-mirror will overpower other harnesses 13199 ? __assign({ left: 0, right: 0 }, _this.computeSegTopBottomCss(seg)) : _this.computeFgSegPositionCss(seg); 13200 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) }, 13201 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))))); 13202 }); 13203 }; 13204 TimeCol.prototype.renderFillSegs = function (segs, fillType) { 13205 var _this = this; 13206 var _a = this, context = _a.context, props = _a.props; 13207 if (!props.slatCoords) { 13208 return null; 13209 } 13210 // BAD: assigns TO THE SEGS THEMSELVES 13211 computeSegVerticals(segs, props.date, props.slatCoords, context.options.eventMinHeight); 13212 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' ? 13213 createElement(BgEvent, __assign({ seg: seg }, getSegMeta(seg, props.todayRange, props.nowDate))) : 13214 renderFill(fillType))); }); 13215 return createElement(Fragment, null, children); 13216 }; 13217 TimeCol.prototype.renderNowIndicator = function (segs) { 13218 var _a = this.props, slatCoords = _a.slatCoords, date = _a.date; 13219 if (!slatCoords) { 13220 return null; 13221 } 13222 return segs.map(function (seg, i) { return (createElement(NowIndicatorRoot, { isAxis: false, date: date, 13223 // key doesn't matter. will only ever be one 13224 key: i }, 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)); })); }); 13225 }; 13226 TimeCol.prototype.computeFgSegPositionCss = function (seg) { 13227 var _a = this.context, isRtl = _a.isRtl, options = _a.options; 13228 var shouldOverlap = options.slotEventOverlap; 13229 var backwardCoord = seg.backwardCoord; // the left side if LTR. the right side if RTL. floating-point 13230 var forwardCoord = seg.forwardCoord; // the right side if LTR. the left side if RTL. floating-point 13231 var left; // amount of space from left edge, a fraction of the total width 13232 var right; // amount of space from right edge, a fraction of the total width 13233 if (shouldOverlap) { 13234 // double the width, but don't go beyond the maximum forward coordinate (1.0) 13235 forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2); 13236 } 13237 if (isRtl) { 13238 left = 1 - forwardCoord; 13239 right = backwardCoord; 13240 } 13241 else { 13242 left = backwardCoord; 13243 right = 1 - forwardCoord; 13244 } 13245 var props = { 13246 zIndex: seg.level + 1, 13247 left: left * 100 + '%', 13248 right: right * 100 + '%', 13249 }; 13250 if (shouldOverlap && seg.forwardPressure) { 13251 // add padding to the edge so that forward stacked events don't cover the resizer's icon 13252 props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width 13253 } 13254 return __assign(__assign({}
13254, props), this.computeSegTopBottomCss(seg)); 13255 }; 13256 TimeCol.prototype.computeSegTopBottomCss = function (seg) { 13257 return { 13258 top: seg.top, 13259 bottom: -seg.bottom, 13260 }; 13261 }; 13262 return TimeCol; 13263 }(BaseComponent)); 13264 13265 var TimeColsContent = /** @class */ (function (_super) { 13266 __extends(TimeColsContent, _super); 13267 function TimeColsContent() { 13268 var _this = _super !== null && _super.apply(this, arguments) || this; 13269 _this.splitFgEventSegs = memoize(splitSegsByCol); 13270 _this.splitBgEventSegs = memoize(splitSegsByCol); 13271 _this.splitBusinessHourSegs = memoize(splitSegsByCol); 13272 _this.splitNowIndicatorSegs = memoize(splitSegsByCol); 13273 _this.splitDateSelectionSegs = memoize(splitSegsByCol); 13274 _this.splitEventDrag = memoize(splitInteractionByCol); 13275 _this.splitEventResize = memoize(splitInteractionByCol); 13276 _this.rootElRef = createRef(); 13277 _this.cellElRefs = new RefMap(); 13278 return _this; 13279 } 13280 TimeColsContent.prototype.render = function () { 13281 var _this = this; 13282 var _a = this, props = _a.props, context = _a.context; 13283 var nowIndicatorTop = context.options.nowIndicator && 13284 props.slatCoords && 13285 props.slatCoords.safeComputeTop(props.nowDate); // might return void 13286 var colCnt = props.cells.length; 13287 var fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, colCnt); 13288 var bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, colCnt); 13289 var businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, colCnt); 13290 var nowIndicatorSegsByRow = this.splitNowIndicatorSegs(props.nowIndicatorSegs, colCnt); 13291 var dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, colCnt); 13292 var eventDragByRow = this.splitEventDrag(props.eventDrag, colCnt); 13293 var eventResizeByRow = this.splitEventResize(props.eventResize, colCnt); 13294 return (createElement("div", { className: "fc-timegrid-cols", ref: this.rootElRef }, 13295 createElement("table", { style: { 13296 minWidth: props.tableMinWidth, 13297 width: props.clientWidth, 13298 } }, 13299 props.tableColGroupNode, 13300 createElement("tbody", null, 13301 createElement("tr", null, 13302 props.axis && (createElement("td", { className: "fc-timegrid-col fc-timegrid-axis" }, 13303 createElement("div", { className: "fc-timegrid-col-frame" }, 13304 createElement("div", { className: "fc-timegrid-now-indicator-container" }, typeof nowIndicatorTop === 'number' && (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)); })))))), 13305 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 })); })))))); 13306 }; 13307 TimeColsContent.prototype.componentDidMount = function () { 13308 this.updateCoords(); 13309 }; 13310 TimeColsContent.prototype.componentDidUpdate = function () { 13311 this.updateCoords(); 13312 }; 13313 TimeColsContent.prototype.updateCoords = function () { 13314 var props = this.props; 13315 if (props.onColCoords && 13316 props.clientWidth !== null // means sizing has stabilized 13317 ) { 13318 props.onColCoords(new PositionCache(this.rootElRef.current, collectCellEls(this.cellElRefs.currentMap, props.cells), true, // horizontal 13319 false)); 13320 } 13321 }; 13322 return TimeColsContent; 13323 }(BaseComponent)); 13324 function collectCellEls(elMap, cells) { 13325 return cells.map(function (cell) { return elMap[cell.key]; }); 13326 } 13327 13328 /* A component that renders one or more columns of vertical time slots 13329 ----------------------------------------------------------------------------------------------------------------------*/ 13330 var TimeCols = /** @class */ (function (_super) { 13331 __extends(TimeCols, _super); 13332 function TimeCols() { 13333 var _this = _super !== null && _super.apply(this, arguments) || this; 13334 _this.processSlotOptions = memoize(processSlotOptions); 13335 _this.state = { 13336 slatCoords: null, 13337 }; 13338 _this.handleScrollRequest = function (request) { 13339 var onScrollTopRequest = _this.props.onScrollTopRequest; 13340 var slatCoords = _this.state.slatCoords; 13341 if (onScrollTopRequest && slatCoords) { 13342 if (request.time) { 13343 var top_1 = slatCoords.computeTimeTop(request.time); 13344 top_1 = Math.ceil(top_1); // zoom can give weird floating-point values. rather scroll a little bit further 13345 if (top_1) { 13346 top_1 += 1; // to overcome top border that slots beyond the first have. looks better 13347 } 13348 onScrollTopRequest(top_1); 13349 } 13350 return true; 13351 } 13352 return false;
13353 }; 13354 _this.handleColCoords = function (colCoords) { 13355 _this.colCoords = colCoords; 13356 }; 13357 _this.handleSlatCoords = function (slatCoords) { 13358 _this.setState({ slatCoords: slatCoords }); 13359 if (_this.props.onSlatCoords) { 13360 _this.props.onSlatCoords(slatCoords); 13361 } 13362 }; 13363 return _this; 13364 } 13365 TimeCols.prototype.render = function () { 13366 var _a = this, props = _a.props, state = _a.state; 13367 return (createElement("div", { className: "fc-timegrid-body", ref: props.rootElRef, style: { 13368 // these props are important to give this wrapper correct dimensions for interactions 13369 // TODO: if we set it here, can we avoid giving to inner tables? 13370 width: props.clientWidth, 13371 minWidth: props.tableMinWidth, 13372 } }, 13373 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 }), 13374 createElement(TimeColsContent, { cells: props.cells, axis: props.axis, dateProfile: props.dateProfile, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bg
13374EventSegs, 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 }))); 13375 }; 13376 TimeCols.prototype.componentDidMount = function () { 13377 this.scrollResponder = this.context.createScrollResponder(this.handleScrollRequest); 13378 }; 13379 TimeCols.prototype.componentDidUpdate = function (prevProps) { 13380 this.scrollResponder.update(prevProps.dateProfile !== this.props.dateProfile); 13381 }; 13382 TimeCols.prototype.componentWillUnmount = function () { 13383 this.scrollResponder.detach(); 13384 }; 13385 TimeCols.prototype.positionToHit = function (positionLeft, positionTop) { 13386 var _a = this.context, dateEnv = _a.dateEnv, options = _a.options; 13387 var colCoords = this.colCoords; 13388 var dateProfile = this.props.dateProfile; 13389 var slatCoords = this.state.slatCoords; 13390 var _b = this.processSlotOptions(this.props.slotDuration, options.snapDuration), snapDuration = _b.snapDuration, snapsPerSlot = _b.snapsPerSlot; 13391 var colIndex = colCoords.leftToIndex(positionLeft); 13392 var slatIndex = slatCoords.positions.topToIndex(positionTop); 13393 if (colIndex != null && slatIndex != null) { 13394 var slatTop = slatCoords.positions.tops[slatIndex]; 13395 var slatHeight = slatCoords.positions.getHeight(slatIndex); 13396 var partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1 13397 var localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat 13398 var snapIndex = slatIndex * snapsPerSlot + localSnapIndex; 13399 var dayDate = this.props.cells[colIndex].date; 13400 var time = addDurations(dateProfile.slotMinTime, multiplyDuration(snapDuration, snapIndex)); 13401 var start = dateEnv.add(dayDate, time); 13402 var end = dateEnv.add(start, snapDuration); 13403 return { 13404 col: colIndex, 13405 dateSpan: { 13406 range: { start: start, end: end }, 13407 allDay: false, 13408 }, 13409 dayEl: colCoords.els[colIndex], 13410 relativeRect: { 13411 left: colCoords.lefts[colIndex], 13412 right: colCoords.rights[colIndex], 13413 top: slatTop, 13414 bottom: slatTop + slatHeight, 13415 }, 13416 }; 13417 } 13418 return null; 13419 }; 13420 return TimeCols; 13421 }(BaseComponent)); 13422 function processSlotOptions(slotDuration, snapDurationOverride) { 13423 var snapDuration = snapDurationOverride || slotDuration; 13424 var snapsPerSlot = wholeDivideDurations(slotDuration, snapDuration); 13425 if (snapsPerSlot === null) { 13426 snapDuration = slotDuration; 13427 snapsPerSlot = 1; 13428 // TODO: say warning? 13429 } 13430 return { snapDuration: snapDuration, snapsPerSlot: snapsPerSlot }; 13431 } 13432 13433 var DayTimeColsSlicer = /** @class */ (function (_super) { 13434 __extends(DayTimeColsSlicer, _super); 13435 function DayTimeColsSlicer() { 13436 return _super !== null && _super.apply(this, arguments) || this; 13437 } 13438 DayTimeColsSlicer.prototype.sliceRange = function (range, dayRanges) { 13439 var segs = []; 13440 for (var col = 0; col < dayRanges.length; col += 1) { 13441 var segRange = intersectRanges(range, dayRanges[col]); 13442 if (segRange) { 13443 segs.push({ 13444 start: segRange.start, 13445 end: segRange.end, 13446 isStart: segRange.start.valueOf() === range.start.valueOf(), 13447 isEnd: segRange.end.valueOf() === range.end.valueOf(), 13448 col: col, 13449 }); 13450 } 13451 } 13452 return segs; 13453 }; 13454 return DayTimeColsSlicer; 13455 }(Slicer)); 13456 13457 var DayTimeCols = /** @class */ (function (_super) { 13458 __extends(DayTimeCols, _super); 13459 function DayTimeCols() { 13460 var _this = _super !== null && _super.apply(this, arguments) || this; 13461 _this.buildDayRanges = memoize(buildDayRanges); 13462 _this.slicer = new DayTimeColsSlicer(); 13463 _this.timeColsRef = createRef(); 13464 _this.handleRootEl = function (rootEl) { 13465 if (rootEl) { 13466 _this.context.registerInteractiveComponent(_this, { el: rootEl }); 13467 } 13468 else { 13469 _this.context.unregisterInteractiveComponent(_this); 13470 } 13471 }; 13472 return _this; 13473 } 13474 DayTimeCols.prototype.render = function () { 13475 var _this = this; 13476 var _a = this, props = _a.props, context = _a.context; 13477 var dateProfile = props.dateProfile, dayTableModel = props.dayTableModel; 13478 var isNowIndicator = context.options.nowIndicator; 13479 var dayRanges = this.buildDayRanges(dayTableModel, dateProfile, context.dateEnv); 13480 // give it the first row of cells 13481 // TODO: would move this further down hierarchy, but sliceNowDate needs it 13482 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
13482owDate, nowIndicatorSegs: isNowIndicator && _this.slicer.sliceNowDate(nowDate, context, dayRanges), todayRange: todayRange, onScrollTopRequest: props.onScrollTopRequest, onSlatCoords: props.onSlatCoords }))); })); 13483 }; 13484 DayTimeCols.prototype.queryHit = function (positionLeft, positionTop) { 13485 var rawHit = this.timeColsRef.current.positionToHit(positionLeft, positionTop); 13486 if (rawHit) { 13487 return { 13488 component: this, 13489 dateSpan: rawHit.dateSpan, 13490 dayEl: rawHit.dayEl, 13491 rect: { 13492 left: rawHit.relativeRect.left, 13493 right: rawHit.relativeRect.right, 13494 top: rawHit.relativeRect.top, 13495 bottom: rawHit.relativeRect.bottom, 13496 }, 13497 layer: 0, 13498 }; 13499 } 13500 return null; 13501 }; 13502 return DayTimeCols; 13503 }(DateComponent)); 13504 function buildDayRanges(dayTableModel, dateProfile, dateEnv) { 13505 var ranges = []; 13506 for (var _i = 0, _a = dayTableModel.headerDates; _i < _a.length; _i++) { 13507 var date = _a[_i]; 13508 ranges.push({ 13509 start: dateEnv.add(date, dateProfile.slotMinTime), 13510 end: dateEnv.add(date, dateProfile.slotMaxTime), 13511 }); 13512 } 13513 return ranges; 13514 } 13515 13516 // potential nice values for the slot-duration and interval-duration 13517 // from largest to smallest 13518 var STOCK_SUB_DURATIONS = [ 13519 { hours: 1 }, 13520 { minutes: 30 }, 13521 { minutes: 15 }, 13522 { seconds: 30 }, 13523 { seconds: 15 }, 13524 ]; 13525 function buildSlatMetas(slotMinTime, slotMaxTime, explicitLabelInterval, slotDuration, dateEnv) { 13526 var dayStart = new Date(0); 13527 var slatTime = slotMinTime; 13528 var slatIterator = createDuration(0); 13529 var labelInterval = explicitLabelInterval || computeLabelInterval(slotDuration); 13530 var metas = []; 13531 while (asRoughMs(slatTime) < asRoughMs(slotMaxTime)) { 13532 var date = dateEnv.add(dayStart, slatTime); 13533 var isLabeled = wholeDivideDurations(slatIterator, labelInterval) !== null; 13534 metas.push({ 13535 date: date, 13536 time: slatTime, 13537 key: date.toISOString(), 13538 isoTimeStr: formatIsoTimeString(date), 13539 isLabeled: isLabeled, 13540 }); 13541 slatTime = addDurations(slatTime, slotDuration); 13542 slatIterator = addDurations(slatIterator, slotDuration); 13543 } 13544 return metas; 13545 } 13546 // Computes an automatic value for slotLabelInterval 13547 function computeLabelInterval(slotDuration) { 13548 var i; 13549 var labelInterval; 13550 var slotsPerLabel; 13551 // find the smallest stock label interval that results in more than one slots-per-label 13552 for (i = STOCK_SUB_DURATIONS.length - 1; i >= 0; i -= 1) { 13553 labelInterval = createDuration(STOCK_SUB_DURATIONS[i]); 13554 slotsPerLabel = wholeDivideDurations(labelInterval, slotDuration);
13555 if (slotsPerLabel !== null && slotsPerLabel > 1) { 13556 return labelInterval; 13557 } 13558 } 13559 return slotDuration; // fall back 13560 } 13561 13562 var DayTimeColsView = /** @class */ (function (_super) { 13563 __extends(DayTimeColsView, _super); 13564 function DayTimeColsView() { 13565 var _this = _super !== null && _super.apply(this, arguments) || this; 13566 _this.buildTimeColsModel = memoize(buildTimeColsModel); 13567 _this.buildSlatMetas = memoize(buildSlatMetas); 13568 return _this; 13569 } 13570 DayTimeColsView.prototype.render = function () { 13571 var _this = this; 13572 var _a = this.context, options = _a.options, dateEnv = _a.dateEnv, dateProfileGenerator = _a.dateProfileGenerator; 13573 var props = this.props; 13574 var dateProfile = props.dateProfile; 13575 var dayTableModel = this.buildTimeColsModel(dateProfile, dateProfileGenerator); 13576 var splitProps = this.allDaySplitter.splitProps(props); 13577 var slatMetas = this.buildSlatMetas(dateProfile.slotMinTime, dateProfile.slotMaxTime, options.slotLabelInterval, options.slotDuration, dateEnv); 13578 var dayMinWidth = options.dayMinWidth; 13579 var hasAttachedAxis = !dayMinWidth; 13580 var hasDetachedAxis = dayMinWidth; 13581 var headerContent = options.dayHeaders && (createElement(DayHeader, { dates: dayTableModel.headerDates, dateProfile: dateProfile, datesRepDistinctDays: true, renderIntro: hasAttachedAxis ? this.renderHeadAxis : null })); 13582 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()))); }); 13583 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 }))); }; 13584 return hasDetachedAxis 13585 ? this.renderHScrollLayout(headerContent, allDayContent, timeGridContent, dayTableModel.colCnt, dayMinWidth, slatMetas, this.state.slatCoords) 13586 : this.renderSimpleLayout(headerContent, allDayContent, timeGridContent); 13587 }; 13588 return DayTimeColsView; 13589 }(TimeColsView));
13590 function buildTimeColsModel(dateProfile, dateProfileGenerator) { 13591 var daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator); 13592 return new DayTableModel(daySeries, false); 13593 } 13594 13595 var OPTION_REFINERS$2 = { 13596 allDaySlot: Boolean, 13597 }; 13598 13599 var timeGridPlugin = createPlugin({ 13600 initialView: 'timeGridWeek', 13601 optionRefiners: OPTION_REFINERS$2, 13602 views: { 13603 timeGrid: { 13604 component: DayTimeColsView, 13605 usesMinMaxTime: true, 13606 allDaySlot: true, 13607 slotDuration: '00:30:00', 13608 slotEventOverlap: true, 13609 }, 13610 timeGridDay: { 13611 type: 'timeGrid', 13612 duration: { days: 1 }, 13613 }, 13614 timeGridWeek: { 13615 type: 'timeGrid', 13616 duration: { weeks: 1 }, 13617 }, 13618 }, 13619 }); 13620 13621 var ListViewHeaderRow = /** @class */ (function (_super) { 13622 __extends(ListViewHeaderRow, _super); 13623 function ListViewHeaderRow() { 13624 return _super !== null && _super.apply(this, arguments) || this; 13625 } 13626 ListViewHeaderRow.prototype.render = function () { 13627 var _a = this.props, dayDate = _a.dayDate, todayRange = _a.todayRange; 13628 var _b = this.context, theme = _b.theme, dateEnv = _b.dateEnv, options = _b.options, viewApi = _b.viewApi; 13629 var dayMeta = getDateMeta(dayDate, todayRange); 13630 // will ever be falsy? 13631 var text = options.listDayFormat ? dateEnv.format(dayDate, options.listDayFormat) : ''; 13632 // will ever be falsy? also, BAD NAME "alt" 13633 var sideText = options.listDaySideFormat ? dateEnv.format(dayDate, options.listDaySideFormat) : ''; 13634 var navLinkData = options.navLinks 13635 ? buildNavLinkData(dayDate) 13636 : null; 13637 var hookProps = __assign({ date: dateEnv.toDate(dayDate), view: viewApi, text: text, 13638 sideText: sideText, 13639 navLinkData: navLinkData }, dayMeta); 13640 var classNames = ['fc-list-day'].concat(getDayClassNames(dayMeta, theme)); 13641 // TODO: make a reusable HOC for dayHeader (used in daygrid/timegrid too) 13642 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) }, 13643 createElement("th", { colSpan: 3 }, 13644 createElement("div", { className: 'fc-list-day-cushion ' + theme.getClass('tableCellShaded'), ref: innerElRef }, innerContent)))); })); 13645 }; 13646 return ListViewHeaderRow; 13647 }(BaseComponent)); 13648 function renderInnerContent$4(props) { 13649 var navLinkAttrs = props.navLinkData // is there a type for this? 13650 ? { 'data-navlink': props.navLinkData, tabIndex: 0 } 13651 : {}; 13652 return (createElement(Fragment, null, 13653 props.text && (createElement("a", __assign({ className: "fc-list-day-text" }, navLinkAttrs), props.text)), 13654 props.sideText && (createElement("a", __assign({ className: "fc-list-day-side-text" }, navLinkAttrs), props.sideText)))); 13655 } 13656 13657 var DEFAULT_TIME_FORMAT$1 = createFormatter({ 13658 hour: 'numeric', 13659 minute: '2-digit', 13660 meridiem: 'short', 13661 }); 13662 var ListViewEventRow = /** @class */ (function (_super) { 13663 __extends(ListViewEventRow, _super); 13664 function ListViewEventRow() { 13665 return _super !== null && _super.apply(this, arguments) || this; 13666 } 13667 ListViewEventRow.prototype.render = function () { 13668 var _a = this, props = _a.props, context = _a.context; 13669 var seg = props.seg; 13670 var timeFormat = context.options.eventTimeFormat || DEFAULT_TIME_FORMAT$1; 13671 return (createElement(EventRoot, { seg: seg, timeText: "" // BAD. because of all-day content 13672 , 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 }, 13673 buildTimeContent(seg, timeFormat, context), 13674 createElement("td", { className: "fc-list-event-graphic" }, 13675 createElement("span", { className: "fc-list-event-dot", style: { borderColor: hookProps.borderColor || hookProps.backgroundColor } })), 13676 createElement("td", { className: "fc-list-event-title", ref: innerElRef }, innerContent))); })); 13677 }; 13678 return ListViewEventRow; 13679 }(BaseComponent)); 13680 function renderEventInnerContent(props) { 13681 var event = props.event; 13682 var url = event.url; 13683 var anchorAttrs = url ? { href: url } : {}; 13684 return (createElement("a", __assign({}, anchorAttrs), event.title)); 13685 } 13686 function buildTimeContent(seg, timeFormat, context) { 13687 var options = context.options; 13688 if (options.displayEventTime !== false) { 13689 var eventDef = seg.eventRange.def; 13690 var eventInstance = seg.eventRange.instance; 13691 var doAllDay = false;
13692 var timeText = void 0; 13693 if (eventDef.allDay) { 13694 doAllDay = true; 13695 } 13696 else if (isMultiDayRange(seg.eventRange.range)) { // TODO: use (!isStart || !isEnd) instead? 13697 if (seg.isStart) { 13698 timeText = buildSegTimeText(seg, timeFormat, context, null, null, eventInstance.range.start, seg.end); 13699 } 13700 else if (seg.isEnd) { 13701 timeText = buildSegTimeText(seg, timeFormat, context, null, null, seg.start, eventInstance.range.end); 13702 } 13703 else { 13704 doAllDay = true; 13705 } 13706 } 13707 else { 13708 timeText = buildSegTimeText(seg, timeFormat, context); 13709 } 13710 if (doAllDay) { 13711 var hookProps = { 13712 text: context.options.allDayText, 13713 view: context.viewApi, 13714 }; 13715 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)); })); 13716 } 13717 return (createElement("td", { className: "fc-list-event-time" }, timeText)); 13718 } 13719 return null; 13720 } 13721 function renderAllDayInner$1(hookProps) { 13722 return hookProps.text; 13723 } 13724 13725 /* 13726 Responsible for the scroller, and forwarding event-related actions into the "grid". 13727 */ 13728 var ListView = /** @class */ (function (_super) { 13729 __extends(ListView, _super); 13730 function ListView() { 13731 var _this = _super !== null && _super.apply(this, arguments) || this; 13732 _this.computeDateVars = memoize(computeDateVars); 13733 _this.eventStoreToSegs = memoize(_this._eventStoreToSegs); 13734 _this.setRootEl = function (rootEl) { 13735 if (rootEl) { 13736 _this.context.registerInteractiveComponent(_this, { 13737 el: rootEl, 13738 }); 13739 } 13740 else { 13741 _this.context.unregisterInteractiveComponent(_this); 13742 } 13743 }; 13744 return _this; 13745 } 13746 ListView.prototype.render = function () { 13747 var _this = this; 13748 var _a = this, props = _a.props, context = _a.context; 13749 var extraClassNames = [ 13750 'fc-list', 13751 context.theme.getClass('table'), 13752 context.options.stickyHeaderDates !== false ? 'fc-list-sticky' : '', 13753 ]; 13754 var _b = this.computeDateVars(props.dateProfile), dayDates = _b.dayDates, dayRanges = _b.dayRanges; 13755 var eventSegs = this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges); 13756 return (createElement(ViewRoot, { viewSpec: context.viewSpec, elRef: this.setRootEl }, function (rootElRef, classNames) { return (createElement("div", { ref: rootElRef, className: extraClassNames.concat(classNames).join(' ') }, 13757 createElement(Scroller, { liquid: !props.isHeightAuto, overflowX: props.isHeightAuto ? 'visible' : 'hidden', overflowY: props.isHeightAuto ? 'visible' : 'auto' }, eventSegs.length > 0 ? 13758 _this.renderSegList(eventSegs, dayDates) : 13759 _this.renderEmptyMessage()))); })); 13760 }; 13761 ListView.prototype.renderEmptyMessage = function () { 13762 var _a = this.context, options = _a.options, viewApi = _a.viewApi; 13763 var hookProps = { 13764 text: options.noEventsText, 13765 view: viewApi, 13766 }; 13767 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 }, 13768 createElement("div", { className: "fc-list-empty-cushion", ref: innerElRef }, innerContent))); })); 13769 }; 13770 ListView.prototype.renderSegList = function (allSegs, dayDates) { 13771 var _a = this.context, theme = _a.theme, options = _a.options; 13772 var segsByDay = groupSegsByDay(allSegs); // sparse array 13773 return (createElement(NowTimer, { unit: "day" }, function (nowDate, todayRange) { 13774 var innerNodes = []; 13775 for (var dayIndex = 0; dayIndex < segsByDay.length; dayIndex += 1) { 13776 var daySegs = segsByDay[dayIndex]; 13777 if (daySegs) { // sparse array, so might be undefined 13778 var dayStr = dayDates[dayIndex].toISOString(); 13779 // append a day header 13780 innerNodes.push(createElement(ListViewHeaderRow, { key: dayStr, dayDate: dayDates[dayIndex], todayRange: todayRange })); 13781 daySegs = sortEventSegs(daySegs, options.eventOrder);
13782 for (var _i = 0, daySegs_1 = daySegs; _i < daySegs_1.length; _i++) { 13783 var seg = daySegs_1[_i]; 13784 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)))); 13785 } 13786 } 13787 } 13788 return (createElement("table", { className: 'fc-list-table ' + theme.getClass('table') }, 13789 createElement("tbody", null, innerNodes))); 13790 })); 13791 }; 13792 ListView.prototype._eventStoreToSegs = function (eventStore, eventUiBases, dayRanges) { 13793 return this.eventRangesToSegs(sliceEventStore(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.context.options.nextDayThreshold).fg, dayRanges); 13794 }; 13795 ListView.prototype.eventRangesToSegs = function (eventRanges, dayRanges) { 13796 var segs = []; 13797 for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) { 13798 var eventRange = eventRanges_1[_i]; 13799 segs.push.apply(segs, this.eventRangeToSegs(eventRange, dayRanges)); 13800 } 13801 return segs; 13802 }; 13803 ListView.prototype.eventRangeToSegs = function (eventRange, dayRanges) { 13804 var dateEnv = this.context.dateEnv; 13805 var nextDayThreshold = this.context.options.nextDayThreshold; 13806 var range = eventRange.range; 13807 var allDay = eventRange.def.allDay; 13808 var dayIndex; 13809 var segRange; 13810 var seg; 13811 var segs = []; 13812 for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex += 1) { 13813 segRange = intersectRanges(range, dayRanges[dayIndex]); 13814 if (segRange) { 13815 seg = { 13816 component: this, 13817 eventRange: eventRange, 13818 start: segRange.start, 13819 end: segRange.end, 13820 isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(), 13821 isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(), 13822 dayIndex: dayIndex, 13823 }; 13824 segs.push(seg); 13825 // detect when range won't go fully into the next day, 13826 // and mutate the latest seg to the be the end. 13827 if (!seg.isEnd && !allDay && 13828 dayIndex + 1 < dayRanges.length && 13829 range.end < 13830 dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) { 13831 seg.end = range.end; 13832 seg.isEnd = true; 13833 break; 13834 } 13835 } 13836 } 13837 return segs; 13838 }; 13839 return ListView; 13840 }(DateComponent)); 13841 function renderNoEventsInner(hookProps) { 13842 return hookProps.text; 13843 } 13844 function computeDateVars(dateProfile) { 13845 var dayStart = startOfDay(dateProfile.renderRange.start); 13846 var viewEnd = dateProfile.renderRange.end; 13847 var dayDates = []; 13848 var dayRanges = []; 13849 while (dayStart < viewEnd) { 13850 dayDates.push(dayStart); 13851 dayRanges.push({ 13852 start: dayStart, 13853 end: addDays(dayStart, 1), 13854 }); 13855 dayStart = addDays(dayStart, 1); 13856 } 13857 return { dayDates: dayDates, dayRanges: dayRanges }; 13858 } 13859 // Returns a sparse array of arrays, segs grouped by their dayIndex 13860 function groupSegsByDay(segs) { 13861 var segsByDay = []; // sparse array 13862 var i; 13863 var seg; 13864 for (i = 0; i < segs.length; i += 1) { 13865 seg = segs[i]; 13866 (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = [])) 13867 .push(seg); 13868 } 13869 return segsByDay; 13870 } 13871 13872 var OPTION_REFINERS$3 = { 13873 listDayFormat: createFalsableFormatter, 13874 listDaySideFormat: createFalsableFormatter, 13875 noEventsClassNames: identity, 13876 noEventsContent: identity, 13877 noEventsDidMount: identity, 13878 noEventsWillUnmount: identity, 13879 }; 13880 function createFalsableFormatter(input) { 13881 return input === false ? null : createFormatter(input); 13882 } 13883 13884 var listPlugin = createPlugin({ 13885 optionRefiners: OPTION_REFINERS$3, 13886 views: { 13887 list: { 13888 component: ListView, 13889 buttonTextKey: 'list', 13890 listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' }, 13891 }, 13892 listDay: { 13893 type: 'list', 13894 duration: { days: 1 }, 13895 listDayFormat: { weekday: 'long' }, 13896 }, 13897 listWeek: { 13898 type: 'list', 13899 duration: { weeks: 1 }, 13900 listDayFormat: { weekday: 'long' }, 13901 listDaySideFormat: { month: 'long', day: 'numeric', year: 'numeric' }, 13902 }, 13903 listMonth: { 13904 type: 'list', 13905 duration: { month: 1 }, 13906 listDaySideFormat: { weekday: 'long' }, 13907 }, 13908 listYear: { 13909 type: 'list', 13910 duration: { year: 1 }, 13911 listDaySideFormat: { weekday: 'long' }, 13912 }, 13913 }, 13914 }); 13915 13916 var BootstrapTheme = /** @class */ (function (_super) { 13917 __extends(BootstrapTheme, _super); 13918 function BootstrapTheme() { 13919 return _super !== null && _super.apply(this, arguments) || this; 13920 } 13921 return BootstrapTheme; 13922 }(Theme)); 13923 BootstrapTheme.prototype.classes = { 13924 root: 'fc-theme-bootstrap', 13925 table: 'table-bordered', 13926 tableCellShaded: 'table-active', 13927 buttonGroup: 'btn-group', 13928 button: 'btn btn-primary', 13929 buttonActive: 'active', 13930 popover: 'popover', 13931 popoverHeader: 'popover-header', 13932 popoverContent: 'popover-body', 13933 }; 13934 BootstrapTheme.prototype.baseIconClass = 'fa'; 13935 BootstrapTheme.prototype.iconClasses = { 13936 close: 'fa-times', 13937 prev: 'fa-chevron-left', 13938 next: 'fa-chevron-right', 13939 prevYear: 'fa-angle-double-left', 13940 nextYear: 'fa-angle-double-right', 13941 }; 13942 BootstrapTheme.prototype.rtlIconClasses = { 13943 prev: 'fa-chevron-right', 13944 next: 'fa-chevron-left', 13945 prevYear: 'fa-angle-double-right', 13946 nextYear: 'fa-angle-double-left', 13947 }; 13948 BootstrapTheme.prototype.iconOverrideOption = 'bootstrapFontAwesome';
13948 // TODO: make TS-friendly. move the option-processing into this plugin 13949 BootstrapTheme.prototype.iconOverrideCustomButtonOption = 'bootstrapFontAwesome'; 13950 BootstrapTheme.prototype.iconOverridePrefix = 'fa-'; 13951 var plugin = createPlugin({ 13952 themeClasses: { 13953 bootstrap: BootstrapTheme, 13954 }, 13955 }); 13956 13957 // rename this file to options.ts like other packages? 13958 var OPTION_REFINERS$4 = { 13959 googleCalendarApiKey: String, 13960 }; 13961 13962 var EVENT_SOURCE_REFINERS$1 = { 13963 googleCalendarApiKey: String, 13964 googleCalendarId: String, 13965 googleCalendarApiBase: String, 13966 extraParams: identity, 13967 }; 13968 13969 // TODO: expose somehow 13970 var API_BASE = 'https://www.googleapis.com/calendar/v3/calendars'; 13971 var eventSourceDef$3 = { 13972 parseMeta: function (refined) { 13973 var googleCalendarId = refined.googleCalendarId; 13974 if (!googleCalendarId && refined.url) { 13975 googleCalendarId = parseGoogleCalendarId(refined.url); 13976 } 13977 if (googleCalendarId) { 13978 return { 13979 googleCalendarId: googleCalendarId, 13980 googleCalendarApiKey: refined.googleCalendarApiKey, 13981 googleCalendarApiBase: refined.googleCalendarApiBase, 13982 extraParams: refined.extraParams, 13983 }; 13984 } 13985 return null; 13986 }, 13987 fetch: function (arg, onSuccess, onFailure) { 13988 var _a = arg.context, dateEnv = _a.dateEnv, options = _a.options; 13989 var meta = arg.eventSource.meta; 13990 var apiKey = meta.googleCalendarApiKey || options.googleCalendarApiKey; 13991 if (!apiKey) { 13992 onFailure({ 13993 message: 'Specify a googleCalendarApiKey. See http://fullcalendar.io/docs/google_calendar/', 13994 }); 13995 } 13996 else { 13997 var url = buildUrl(meta); 13998 // TODO: make DRY with json-feed-event-source 13999 var extraParams = meta.extraParams; 14000 var extraParamsObj = typeof extraParams === 'function' ? extraParams() : extraParams; 14001 var requestParams_1 = buildRequestParams$1(arg.range, apiKey, extraParamsObj, dateEnv); 14002 requestJson('GET', url, requestParams_1, function (body, xhr) { 14003 if (body.error) { 14004 onFailure({ 14005 message: 'Google Calendar API: ' + body.error.message, 14006 errors: body.error.errors, 14007 xhr: xhr, 14008 }); 14009 } 14010 else { 14011 onSuccess({ 14012 rawEvents: gcalItemsToRawEventDefs(body.items, requestParams_1.timeZone), 14013 xhr: xhr, 14014 }); 14015 } 14016 }, function (message, xhr) { 14017 onFailure({ message: message, xhr: xhr }); 14018 }); 14019 } 14020 }, 14021 }; 14022 function parseGoogleCalendarId(url) { 14023 var match; 14024 // detect if the ID was specified as a single string. 14025 // will match calendars like "[email protected]" in addition to person email calendars. 14026 if (/^[^/]+@([^/.]+\.)*(google|googlemail|gmail)\.com$/.test(url)) { 14027 return url; 14028 } 14029 if ((match = /^https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/([^/]*)/.exec(url)) || 14030 (match = /^https?:\/\/www.google.com\/calendar\/feeds\/([^/]*)/.exec(url))) { 14031 return decodeURIComponent(match[1]); 14032 } 14033 return null; 14034 } 14035 function buildUrl(meta) { 14036 var apiBase = meta.googleCalendarApiBase; 14037 if (!apiBase) { 14038 apiBase = API_BASE; 14039 } 14040 return apiBase + '/' + encodeURIComponent(meta.googleCalendarId) + '/events'; 14041 } 14042 function buildRequestParams$1(range, apiKey, extraParams, dateEnv) { 14043 var params; 14044 var startStr; 14045 var endStr; 14046 if (dateEnv.canComputeOffset) { 14047 // strings will naturally have offsets, which GCal needs 14048 startStr = dateEnv.formatIso(range.start); 14049 endStr = dateEnv.formatIso(range.end); 14050 } 14051 else {
14052 // when timezone isn't known, we don't know what the UTC offset should be, so ask for +/- 1 day 14053 // from the UTC day-start to guarantee we're getting all the events 14054 // (start/end will be UTC-coerced dates, so toISOString is okay) 14055 startStr = addDays(range.start, -1).toISOString(); 14056 endStr = addDays(range.end, 1).toISOString(); 14057 } 14058 params = __assign(__assign({}, (extraParams || {})), { key: apiKey, timeMin: startStr, timeMax: endStr, singleEvents: true, maxResults: 9999 }); 14059 if (dateEnv.timeZone !== 'local') { 14060 params.timeZone = dateEnv.timeZone; 14061 } 14062 return params; 14063 } 14064 function gcalItemsToRawEventDefs(items, gcalTimezone) { 14065 return items.map(function (item) { return gcalItemToRawEventDef(item, gcalTimezone); }); 14066 } 14067 function gcalItemToRawEventDef(item, gcalTimezone) { 14068 var url = item.htmlLink || null; 14069 // make the URLs for each event show times in the correct timezone 14070 if (url && gcalTimezone) { 14071 url = injectQsComponent(url, 'ctz=' + gcalTimezone); 14072 } 14073 return { 14074 id: item.id, 14075 title: item.summary, 14076 start: item.start.dateTime || item.start.date, 14077 end: item.end.dateTime || item.end.date, 14078 url: url, 14079 location: item.location, 14080 description: item.description, 14081 }; 14082 } 14083 // Injects a string like "arg=value" into the querystring of a URL 14084 // TODO: move to a general util file? 14085 function injectQsComponent(url, component) { 14086 // inject it after the querystring but before the fragment 14087 return url.replace(/(\?.*?)?(#|$)/, function (whole, qs, hash) { return (qs ? qs + '&' : '?') + component + hash; }); 14088 } 14089 var googleCalendarPlugin = createPlugin({ 14090 eventSourceDefs: [eventSourceDef$3], 14091 optionRefiners: OPTION_REFINERS$4, 14092 eventSourceRefiners: EVENT_SOURCE_REFINERS$1, 14093 }); 14094 14095 globalPlugins.push(interactionPlugin, dayGridPlugin, timeGridPlugin, listPlugin, plugin, googleCalendarPlugin); 14096 14097 exports.BASE_OPTION_DEFAULTS = BASE_OPTION_DEFAULTS; 14098 exports.BASE_OPTION_REFINERS = BASE_OPTION_REFINERS; 14099 exports.BaseComponent = BaseComponent; 14100 exports.BgEvent = BgEvent; 14101 exports.BootstrapTheme = BootstrapTheme; 14102 exports.Calendar = Calendar; 14103 exports.CalendarApi = CalendarApi; 14104 exports.CalendarContent = CalendarContent; 14105 exports.CalendarDataManager = CalendarDataManager; 14106 exports.CalendarDataProvider = CalendarDataProvider; 14107 exports.CalendarRoot = CalendarRoot; 14108 exports.Component = Component; 14109 exports.ContentHook = ContentHook; 14110 exports.CustomContentRenderContext = CustomContentRenderContext; 14111 exports.DateComponent = DateComponent; 14112 exports.DateEnv = DateEnv; 14113 exports.DateProfileGenerator = DateProfileGenerator; 14114 exports.DayCellContent = DayCellContent; 14115 exports.DayCellRoot = DayCellRoot; 14116 exports.DayGridView = DayTableView; 14117 exports.DayHeader = DayHeader;
14118 exports.DaySeriesModel = DaySeriesModel; 14119 exports.DayTable = DayTable; 14120 exports.DayTableModel = DayTableModel; 14121 exports.DayTableSlicer = DayTableSlicer; 14122 exports.DayTimeCols = DayTimeCols; 14123 exports.DayTimeColsSlicer = DayTimeColsSlicer; 14124 exports.DayTimeColsView = DayTimeColsView; 14125 exports.DelayedRunner = DelayedRunner; 14126 exports.Draggable = ExternalDraggable; 14127 exports.ElementDragging = ElementDragging; 14128 exports.ElementScrollController = ElementScrollController; 14129 exports.Emitter = Emitter; 14130 exports.EventApi = EventApi; 14131 exports.EventRoot = EventRoot; 14132 exports.EventSourceApi = EventSourceApi; 14133 exports.FeaturefulElementDragging = FeaturefulElementDragging; 14134 exports.Fragment = Fragment; 14135 exports.Interaction = Interaction; 14136 exports.ListView = ListView; 14137 exports.MountHook = MountHook; 14138 exports.NamedTimeZoneImpl = NamedTimeZoneImpl; 14139 exports.NowIndicatorRoot = NowIndicatorRoot; 14140 exports.NowTimer = NowTimer; 14141 exports.PointerDragging = PointerDragging; 14142 exports.PositionCache = PositionCache; 14143 exports.RefMap = RefMap; 14144 exports.RenderHook = RenderHook; 14145 exports.ScrollController = ScrollController; 14146 exports.ScrollResponder = ScrollResponder; 14147 exports.Scroller = Scroller; 14148 exports.SimpleScrollGrid = SimpleScrollGrid; 14149 exports.Slicer = Slicer; 14150 exports.Splitter = Splitter; 14151 exports.StandardEvent = StandardEvent; 14152 exports.Table = Table; 14153 exports.TableDateCell = TableDateCell; 14154 exports.TableDowCell = TableDowCell; 14155 exports.TableView = TableView; 14156 exports.Theme = Theme; 14157 exports.ThirdPartyDraggable = ThirdPartyDraggable; 14158 exports.TimeCols = TimeCols; 14159 exports.TimeColsSlatsCoords = TimeColsSlatsCoords; 14160 exports.TimeColsView = TimeColsView; 14161 exports.ViewApi = ViewApi; 14162 exports.ViewContextType = ViewContextType; 14163 exports.ViewRoot = ViewRoot; 14164 exports.WeekNumberRoot = WeekNumberRoot; 14165 exports.WindowScrollController = WindowScrollController; 14166 exports.addDays = addDays; 14167 exports.addDurations = addDurations; 14168 exports.addMs = addMs; 14169 exports.addWeeks = addWeeks; 14170 exports.allowContextMenu = allowContextMenu; 14171 exports.allowSelection = allowSelection; 14172 exports.applyMutationToEventStore = applyMutationToEventStore; 14173 exports.applyStyle = applyStyle; 14174 exports.applyStyleProp = applyStyleProp; 14175 exports.asCleanDays = asCleanDays; 14176 exports.asRoughMinutes = asRoughMinutes; 14177 exports.asRoughMs = asRoughMs; 14178 exports.asRoughSeconds = asRoughSeconds; 14179 exports.buildClassNameNormalizer = buildClassNameNormalizer; 14180 exports.buildDayRanges = buildDayRanges; 14181 exports.buildDayTableModel = buildDayTableModel; 14182 exports.buildEventApis = buildEventApis; 14183 exports.buildEventRangeKey = buildEventRangeKey; 14184 exports.buildHashFromArray = buildHashFromArray; 14185 exports.buildNavLinkData = buildNavLinkData; 14186 exports.buildSegCompareObj = buildSegCompareObj; 14187 exports.buildSegTimeText = buildSegTimeText; 14188 exports.buildSlatMetas = buildSlatMetas; 14189 exports.buildTimeColsModel = buildTimeColsModel; 14190 exports.collectFromHash = collectFromHash; 14191 exports.combineEventUis = combineEventUis; 14192 exports.compareByFieldSpec = compareByFieldSpec; 14193 exports.compareByFieldSpecs = compareByFieldSpecs; 14194 exports.compareNumbers = compareNumbers; 14195 exports.compareObjs = compareObjs; 14196 exports.computeEdges = computeEdges; 14197 exports.computeFallbackHeaderFormat = computeFallbackHeaderFormat; 14198 exports.computeHeightAndMargins = computeHeightAndMargins; 14199 exports.computeInnerRect = computeInnerRect; 14200 exports.computeRect = computeRect; 14201 exports.computeSegDraggable = computeSegDraggable; 14202 exports.computeSegEndResizable = computeSegEndResizable; 14203 exports.computeSegStartResizable = computeSegStartResizable; 14204 exports.computeShrinkWidth = computeShrinkWidth; 14205 exports.computeSmallestCellWidth = computeSmallestCellWidth; 14206 exports.computeVisibleDayRange = computeVisibleDayRange; 14207 exports.config = config; 14208 exports.constrainPoint = constrainPoint; 14209 exports.createContext = createContext$1; 14210 exports.createDuration = createDuration; 14211 exports.createElement = createElement; 14212 exports.createEmptyEventStore = createEmptyEventStore; 14213 exports.createEventInstance = createEventInstance; 14214 exports.createEventUi = createEventUi; 14215 exports.createFormatter = createFormatter; 14216 exports.createPlugin = createPlugin; 14217 exports.createRef = createRef; 14218 exports.diffDates = diffDates; 14219 exports.diffDayAndTime = diffDayAndTime; 14220 exports.diffDays = diffDays; 14221 exports.diffPoints = diffPoints; 14222 exports.diffWeeks = diffWeeks; 14223 exports.diffWholeDays = diffWholeDays; 14224 exports.diffWholeWeeks = diffWholeWeeks; 14225 exports.disableCursor = disableCursor; 14226 exports.elementClosest = elementClosest; 14227 exports.elementMatches = elementMatches; 14228 exports.enableCursor = enableCursor; 14229 exports.eventTupleToStore = eventTupleToStore; 14230 exports.filterEventStoreDefs = filterEventStoreDefs; 14231 exports.filterHash = filterHash; 14232 exports.findDirectChildren = findDirectChildren; 14233 exports.findElements = findElements; 14234 exports.flexibleCompare = flexibleCompare; 14235 exports.flushToDom = flushToDom$1; 14236 exports.formatDate = formatDate; 14237 exports.formatDayString = formatDayString; 14238 exports.formatIsoTimeString = formatIsoTimeString; 14239 exports.formatRange = formatRange; 14240 exports.getAllowYScrolling = getAllowYScrolling; 14241 exports.getCanVGrowWithinCell = getCanVGrowWithinCell; 14242 exports.getClippingParents = getClippingParents; 14243 exports.getDateMeta = getDateMeta; 14244 exports.getDayClassNames = getDayClassNames; 14245 exports.getDefaultEventEnd = getDefaultEventEnd; 14246 exports.getElSeg = getElSeg; 14247 exports.getEventClassNames = getEventClassNames; 14248 exports.getIsRtlScrollbarOnLeft = getIsRtlScrollbarOnLeft; 14249 exports.getRectCenter = getRectCenter; 14250 exports.getRelevantEvents = getRelevantEvents; 14251 exports.getScrollGridClassNames = getScrollGridClassNames;
14252 exports.getScrollbarWidths = getScrollbarWidths; 14253 exports.getSectionClassNames = getSectionClassNames; 14254 exports.getSectionHasLiquidHeight = getSectionHasLiquidHeight; 14255 exports.getSegMeta = getSegMeta; 14256 exports.getSlotClassNames = getSlotClassNames; 14257 exports.getStickyFooterScrollbar = getStickyFooterScrollbar; 14258 exports.getStickyHeaderDates = getStickyHeaderDates; 14259 exports.getUnequalProps = getUnequalProps; 14260 exports.globalLocales = globalLocales; 14261 exports.globalPlugins = globalPlugins; 14262 exports.greatestDurationDenominator = greatestDurationDenominator; 14263 exports.guid = guid; 14264 exports.hasBgRendering = hasBgRendering; 14265 exports.hasShrinkWidth = hasShrinkWidth; 14266 exports.identity = identity; 14267 exports.interactionSettingsStore = interactionSettingsStore; 14268 exports.interactionSettingsToStore = interactionSettingsToStore; 14269 exports.intersectRanges = intersectRanges; 14270 exports.intersectRects = intersectRects; 14271 exports.isArraysEqual = isArraysEqual; 14272 exports.isColPropsEqual = isColPropsEqual; 14273 exports.isDateSpansEqual = isDateSpansEqual; 14274 exports.isInt = isInt; 14275 exports.isInteractionValid = isInteractionValid; 14276 exports.isMultiDayRange = isMultiDayRange; 14277 exports.isPropsEqual = isPropsEqual; 14278 exports.isPropsValid = isPropsValid; 14279 exports.isValidDate = isValidDate; 14280 exports.listenBySelector = listenBySelector; 14281 exports.mapHash = mapHash; 14282 exports.memoize = memoize; 14283 exports.memoizeArraylike = memoizeArraylike; 14284 exports.memoizeHashlike = memoizeHashlike; 14285 exports.memoizeObjArg = memoizeObjArg; 14286 exports.mergeEventStores = mergeEventStores; 14287 exports.multiplyDuration = multiplyDuration; 14288 exports.padStart = padStart; 14289 exports.parseBusinessHours = parseBusinessHours; 14290 exports.parseClassNames = parseClassNames; 14291 exports.parseDragMeta = parseDragMeta; 14292 exports.parseEventDef = parseEventDef; 14293 exports.parseFieldSpecs = parseFieldSpecs; 14294 exports.parseMarker = parse; 14295 exports.pointInsideRect = pointInsideRect; 14296 exports.preventContextMenu = preventContextMenu; 14297 exports.preventDefault = preventDefault; 14298 exports.preventSelection = preventSelection; 14299 exports.rangeContainsMarker = rangeContainsMarker; 14300 exports.rangeContainsRange = rangeContainsRange; 14301 exports.rangesEqual = rangesEqual; 14302 exports.rangesIntersect = rangesIntersect; 14303 exports.refineEventDef = refineEventDef; 14304 exports.refineProps = refineProps; 14305 exports.removeElement = removeElement; 14306 exports.removeExact = removeExact; 14307 exports.render = render; 14308 exports.renderChunkContent = renderChunkContent; 14309 exports.renderFill = renderFill; 14310 exports.renderMicroColGroup = renderMicroColGroup; 14311 exports.renderScrollShim = renderScrollShim; 14312 exports.requestJson = requestJson; 14313 exports.sanitizeShrinkWidth = sanitizeShrinkWidth; 14314 exports.setElSeg = setElSeg; 14315 exports.setRef = setRef; 14316 exports.sliceEventStore = sliceEventStore; 14317 exports.sliceEvents = sliceEvents; 14318 exports.sortEventSegs = sortEventSegs; 14319 exports.startOfDay = startOfDay; 14320 exports.translateRect = translateRect; 14321 exports.triggerDateSelect = triggerDateSelect; 14322 exports.unmountComponentAtNode = unmountComponentAtNode$1; 14323 exports.unpromisify = unpromisify; 14324 exports.version = version; 14325 exports.whenTransitionDone = whenTransitionDone; 14326 exports.wholeDivideDurations = wholeDivideDurations; 14327 14328 Object.defineProperty(exports, '__esModule', { value: true }); 14329 14330 return exports; 14331 14332}({}));
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.