PageSourceSearch

https://stuvoloods.be/frontend/js/plugins/fullcalendar-6.0.0.js

js stuvoloods.be collected 2026-10-06 04:17:37 UTC 658,961 bytes, 14,041 lines download raw bytes

vendor: 5,217 bytes, lines 1-9
1/*!
2FullCalendar Standard Bundle v6.0.0
3Docs & License: https://fullcalendar.io/docs/initialize-globals
4(c) 2022 Adam Shaw
5*/
6var FullCalendar = (function (exports) {
7    'use strict';
8
9    var n,l$1,u$1,i$1,t,o,r$1,f$1={},e$1=[],c$1=/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$1(n){var l=n.parentNode;l&&l.removeChild(n);}function h(l,u,i){var t,o,r,f={};for(r in u)"key"==r?t=u[r]:"ref"==r?o=u[r]:f[r]=u[r];if(arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),"function"==typeof l&&null!=l.defaultProps)for(r in l.defaultProps)void 0===f[r]&&(f[r]=l.defaultProps[r]);return v$1(l,f,t,o,null)}function v$1(n,i,t,o,r){var f={type:n,props:i,key:t,ref:o,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==r?++u$1:r};return null==r&&null!=l$1.vnode&&l$1.vnode(f),f}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 k$1(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return k$1(n)}}function b$1(n){(!n.__d&&(n.__d=!0)&&t.push(n)&&!g$2.__r++||o!==l$1.debounceRendering)&&((o=l$1.debounceRendering)||setTimeout)(g$2);}function g$2(){for(var n;g$2.__r=t.length;)n=t.sort(function(n,l){return n.__v.__b-l.__v.__b}),t=[],n.some(function(n){var l,u,i,t,o,r;n.__d&&(o=(t=(l=n).__v).__e,(r=l.__P)&&(u=[],(i=s({},t)).__v=t.__v+1,j$2(r,t,i,l.__n,void 0!==r.ownerSVGElement,null!=t.__h?[o]:null,u,null==o?_(t):o,t.__h),z$1(u,t),t.__e!=o&&k$1(t)));});}function w$2(n,l,u,i,t,o,r,c,s,a){var h,y,d,k,b,g,w,x=i&&i.__k||e$1,C=x.length;for(u.__k=[],h=0;h<l.length;h++)if(null!=(k=u.__k[h]=null==(k=l[h])||"boolean"==typeof k?null:"string"==typeof k||"number"==typeof k||"bigint"==typeof k?v$1(null,k,null,null,k):Array.isArray(k)?v$1(p,{children:k},null,null,null):k.__b>0?v$1(k.type,k.props,k.key,k.ref?k.ref:null,k.__v):k)){if(k.__=u,k.__b=u.__b+1,null===(d=x[h])||d&&k.key==d.key&&k.type===d.type)x[h]=void 0;else for(y=0;y<C;y++){if((d=x[y])&&k.key==d.key&&k.type===d.type){x[y]=void 0;break}d=null;}j$2(n,k,d=d||f$1,t,o,r,c,s,a),b=k.__e,(y=k.ref)&&d.ref!=y&&(w||(w=[]),d.ref&&w.push(d.ref,null,k),w.push(y,k.__c||b,k)),null!=b?(null==g&&(g=b),"function"==typeof k.type&&k.__k===d.__k?k.__d=s=m$1(k,s,n):s=A(n,k,d,x,b,s),"function"==typeof u.type&&(u.__d=s)):s&&d.__e==s&&s.parentNode!=n&&(s=_(d));}for(u.__e=g,h=C;h--;)null!=x[h]&&N(x[h],x[h]);if(w)for(h=0;h<w.length;h++)M(w[h],w[++h],w[++h]);}function m$1(n,l,u){for(var i,t=n.__k,o=0;t&&o<t.length;o++)(i=t[o])&&(i.__=n,l="function"==typeof i.type?m$1(i,l,u):A(u,i,i,t,i.__e,l));return l}function x$1(n,l){return l=l||[],null==n||"boolean"==typeof n||(Array.isArray(n)?n.some(function(n){x$1(n,l);}):l.push(n)),l}function A(n,l,u,i,t,o){var r,f,e;if(void 0!==l.__d)r=l.__d,l.__d=void 0;else if(null==u||t!=o||null==t.parentNode)n:if(null==o||o.parentNode!==n)n.appendChild(t),r=null;else {for(f=o,e=0;(f=f.nextSibling)&&e<i.length;e+=1)if(f==t)break n;n.insertBefore(t,o),r=o;}return void 0!==r?r:t.nextSibling}function C$1(n,l,u,i,t){var o;for(o in u)"children"===o||"key"===o||o in l||H$1(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]||H$1(n,o,l[o],u[o],i);}function $$1(n,l,u){"-"===l[0]?n.setProperty(l,u):n[l]=null==u?"":"number"!=typeof u||c$1.test(l)?u:u+"px";}function H$1(n,l,u,i,t){var o;n:if("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||$$1(n.style,l,"");if(u)for(l in u)i&&u[l]===i[l]||$$1(n.style,l,u[l]);}else if("o"===l[0]&&"n"===l[1])o=l!==(l=l.replace(/Capture$/,"")),l=l.toLowerCase()in n?l.toLowerCase().slice(2):l.slice(2),n.l||(n.l={}),n.l[l+o]=u,u?i||n.addEventListener(l,o?T$1:I$1,o):n.removeEventListener(l,o?T$1:I$1,o);else if("dangerouslySetInnerHTML"!==l){if(t)l=l.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("href"!==l&&"list"!==l&&"form"!==l&&"tabIndex"!==l&&"download"!==l&&l in n)try{n[l]=null==u?"":u;break n}catch(n){}"function"==typeof u||(null==u||!1===u&&-1==l.indexOf("-")?n.removeAttribute(l):n.setAttribute(l,u));}}function I$1(n){this.l[n.type+!1](l$1.event?l$1.event(n):n);}function T$1(n){this.l[n.type+!0](l$1.event?l$1.event(n):n);}function j$2(n,u,i,t,o,r,f,e,c){var a,h,v,y,_,k,b,g,m,x,A,C,$,H,I,T=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=l$1.__b)&&a(u);try{n:if("function"==typeof T){if(g=u.props,m=(a=T.contextType)&&t[a.__c],x=a?m?m.props.value:a.__:t,i.__c?b=(h=u.__c=i.__c).__=h.__E:("prototype"in T&&T.prototype.render?u.__c=h=new T(g,x):(u.__c=h=new d(g,x),h.constructor=T,h.render=O),m&&m.sub(h),h.props=g,h.state||(h.state={}),h.context=x,h.__n=t,v=h.__d=!0,h.__h=[],h._sb=[]),null==h.__s&&(h.__s=h.state),null!=T.getDerivedStateFromProps&&(h.__s==h.state&&(h.__s=s({}
vendor: 17,552 bytes, lines 9-179
9,h.__s)),s(h.__s,T.getDerivedStateFromProps(g,h.__s))),y=h.props,_=h.state,v)null==T.getDerivedStateFromProps&&null!=h.componentWillMount&&h.componentWillMount(),null!=h.componentDidMount&&h.__h.push(h.componentDidMount);else {if(null==T.getDerivedStateFromProps&&g!==y&&null!=h.componentWillReceiveProps&&h.componentWillReceiveProps(g,x),!h.__e&&null!=h.shouldComponentUpdate&&!1===h.shouldComponentUpdate(g,h.__s,x)||u.__v===i.__v){for(h.props=g,h.state=h.__s,u.__v!==i.__v&&(h.__d=!1),h.__v=u,u.__e=i.__e,u.__k=i.__k,u.__k.forEach(function(n){n&&(n.__=u);}),A=0;A<h._sb.length;A++)h.__h.push(h._sb[A]);h._sb=[],h.__h.length&&f.push(h);break n}null!=h.componentWillUpdate&&h.componentWillUpdate(g,h.__s,x),null!=h.componentDidUpdate&&h.__h.push(function(){h.componentDidUpdate(y,_,k);});}if(h.context=x,h.props=g,h.__v=u,h.__P=n,C=l$1.__r,$=0,"prototype"in T&&T.prototype.render){for(h.state=h.__s,h.__d=!1,C&&C(u),a=h.render(h.props,h.state,h.context),H=0;H<h._sb.length;H++)h.__h.push(h._sb[H]);h._sb=[];}else do{h.__d=!1,C&&C(u),a=h.render(h.props,h.state,h.context),h.state=h.__s;}while(h.__d&&++$<25);h.state=h.__s,null!=h.getChildContext&&(t=s(s({},t),h.getChildContext())),v||null==h.getSnapshotBeforeUpdate||(k=h.getSnapshotBeforeUpdate(y,_)),I=null!=a&&a.type===p&&null==a.key?a.props.children:a,w$2(n,Array.isArray(I)?I:[I],u,i,t,o,r,f,e,c),h.base=u.__e,u.__h=null,h.__h.length&&f.push(h),b&&(h.__E=h.__=null),h.__e=!1;}else null==r&&u.__v===i.__v?(u.__k=i.__k,u.__e=i.__e):u.__e=L$1(i.__e,u,i,t,o,r,f,c);(a=l$1.diffed)&&a(u);}catch(n){u.__v=null,(c||null!=r)&&(u.__e=e,u.__h=!!c,r[r.indexOf(e)]=null),l$1.__e(n,u,i);}}function z$1(n,u){l$1.__c&&l$1.__c(u,n),n.some(function(u){try{n=u.__h,u.__h=[],n.some(function(n){n.call(u);});}catch(n){l$1.__e(n,u.__v);}});}function L$1(l,u,i,t,o,r,e,c){var s,h,v,y=i.props,p=u.props,d=u.type,k=0;if("svg"===d&&(o=!0),null!=r)for(;k<r.length;k++)if((s=r[k])&&"setAttribute"in s==!!d&&(d?s.localName===d:3===s.nodeType)){l=s,r[k]=null;break}if(null==l){if(null===d)return document.createTextNode(p);l=o?document.createElementNS("http://www.w3.org/2000/svg",d):document.createElement(d,p.is&&p),r=null,c=!1;}if(null===d)y===p||c&&l.data===p||(l.data=p);else {if(r=r&&n.call(l.childNodes),h=(y=i.props||f$1).dangerouslySetInnerHTML,v=p.dangerouslySetInnerHTML,!c){if(null!=r)for(y={},k=0;k<l.attributes.length;k++)y[l.attributes[k].name]=l.attributes[k].value;(v||h)&&(v&&(h&&v.__html==h.__html||v.__html===l.innerHTML)||(l.innerHTML=v&&v.__html||""));}if(C$1(l,p,y,o,c),v)u.__k=[];else if(k=u.props.children,w$2(l,Array.isArray(k)?k:[k],u,i,t,o&&"foreignObject"!==d,r,e,r?r[0]:i.__k&&_(i,0),c),null!=r)for(k=r.length;k--;)null!=r[k]&&a$1(r[k]);c||("value"in p&&void 0!==(k=p.value)&&(k!==l.value||"progress"===d&&!k||"option"===d&&k!==y.value)&&H$1(l,"value",k,y.value,!1),"checked"in p&&void 0!==(k=p.checked)&&k!==l.checked&&H$1(l,"checked",k,y.checked,!1));}return l}function M(n,u,i){try{"function"==typeof n?n(u):n.current=u;}catch(n){l$1.__e(n,i);}}function N(n,u,i){var t,o;if(l$1.unmount&&l$1.unmount(n),(t=n.ref)&&(t.current&&t.current!==n.__e||M(t,null,u)),null!=(t=n.__c)){if(t.componentWillUnmount)try{t.componentWillUnmount();}catch(n){l$1.__e(n,u);}t.base=t.__P=null,n.__c=void 0;}if(t=n.__k)for(o=0;o<t.length;o++)t[o]&&N(t[o],u,i||"function"!=typeof n.type);i||null==n.__e||a$1(n.__e),n.__=n.__e=n.__d=void 0;}function O(n,l,u){return this.constructor(n,u)}function P$1(u,i,t){var o,r,e;l$1.__&&l$1.__(u,i),r=(o="function"==typeof t)?null:t&&t.__k||i.__k,e=[],j$2(i,u=(!o&&t||i).__k=h(p,null,[u]),r||f$1,f$1,void 0!==i.ownerSVGElement,!o&&t?[t]:r?null:i.firstChild?n.call(i.childNodes):null,e,!o&&t?t:r?r.__e:i.firstChild,o),z$1(e,u);}function B$1(n,l){var u={__c:l="__cC"+r$1++,__:n,Consumer:function(n,l){return n.children(l)},Provider:function(n){var 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(b$1);},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$1.slice,l$1={__e:function(n,l,u,i){for(var t,o,r;l=l.__;)if((t=l.__c)&&!t.__)try{if((o=t.constructor)&&null!=o.getDerivedStateFromError&&(t.setState(o.getDerivedStateFromError(n)),r=t.__d),null!=t.componentDidCatch&&(t.componentDidCatch(n,i||{}),r=t.__d),r)return t.__E=t}catch(l){n=l;}throw n}},u$1=0,i$1=function(n){return null!=n&&void 0===n.constructor},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._sb.push(l),b$1(this));},d.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),b$1(this));},d.prototype.render=p,t=[],g$2.__r=0,r$1=0;
10
11    var r,u,i,f=[],c=[],e=l$1.__b,a=l$1.__r,v=l$1.diffed,l=l$1.__c,m=l$1.unmount;function b(){for(var t;t=f.shift();)if(t.__P&&t.__H)try{t.__H.__h.forEach(k),t.__H.__h.forEach(w$1),t.__H.__h=[];}catch(r){t.__H.__h=[],l$1.__e(r,t.__v);}}l$1.__b=function(n){r=null,e&&e(n);},l$1.__r=function(n){a&&a(n);var i=(r=n.__c).__H;i&&(u===r?(i.__h=[],r.__h=[],i.__.forEach(function(n){n.__N&&(n.__=n.__N),n.__V=c,n.__N=n.i=void 0;})):(i.__h.forEach(k),i.__h.forEach(w$1),i.__h=[])),u=r;},l$1.diffed=function(t){v&&v(t);var o=t.__c;o&&o.__H&&(o.__H.__h.length&&(1!==f.push(o)&&i===l$1.requestAnimationFrame||((i=l$1.requestAnimationFrame)||j$1)(b)),o.__H.__.forEach(function(n){n.i&&(n.__H=n.i),n.__V!==c&&(n.__=n.__V),n.i=void 0,n.__V=c;})),u=r=null;},l$1.__c=function(t,r){r.some(function(t){try{t.__h.forEach(k),t.__h=t.__h.filter(function(n){return !n.__||w$1(n)});}catch(u){r.some(function(n){n.__h&&(n.__h=[]);}),r=[],l$1.__e(u,t.__v);}}),l&&l(t,r);},l$1.unmount=function(t){m&&m(t);var r,u=t.__c;u&&u.__H&&(u.__H.__.forEach(function(n){try{k(n);}catch(n){r=n;}}),u.__H=void 0,r&&l$1.__e(r,u.__v));};var g$1="function"==typeof requestAnimationFrame;function j$1(n){var t,r=function(){clearTimeout(u),g$1&&cancelAnimationFrame(t),setTimeout(n);},u=setTimeout(r,100);g$1&&(t=requestAnimationFrame(r));}function k(n){var t=r,u=n.__c;"function"==typeof u&&(n.__c=void 0,u()),r=t;}function w$1(n){var t=r;n.__c=n.__(),r=t;}
12
13    function g(n,t){for(var e in t)n[e]=t[e];return n}function C(n,t){for(var e in n)if("__source"!==e&&!(e in t))return !0;for(var r in t)if("__source"!==r&&n[r]!==t[r])return !0;return !1}function w(n){this.props=n;}(w.prototype=new d).isPureReactComponent=!0,w.prototype.shouldComponentUpdate=function(n,t){return C(this.props,n)||C(this.state,t)};var x=l$1.__b;l$1.__b=function(n){n.type&&n.type.__f&&n.ref&&(n.props.ref=n.ref,n.ref=null),x&&x(n);};var T=l$1.__e;l$1.__e=function(n,t,e,r){if(n.then)for(var u,o=t;o=o.__;)if((u=o.__c)&&u.__c)return null==t.__e&&(t.__e=e.__e,t.__k=e.__k),u.__c(n,t);T(n,t,e,r);};var I=l$1.unmount;function L(n,t,e){return n&&(n.__c&&n.__c.__H&&(n.__c.__H.__.forEach(function(n){"function"==typeof n.__c&&n.__c();}),n.__c.__H=null),null!=(n=g({},n)).__c&&(n.__c.__P===e&&(n.__c.__P=t),n.__c=null),n.__k=n.__k&&n.__k.map(function(n){return L(n,t,e)})),n}function U(n,t,e){return n&&(n.__v=null,n.__k=n.__k&&n.__k.map(function(n){return U(n,t,e)}),n.__c&&n.__c.__P===t&&(n.__e&&e.insertBefore(n.__e,n.__d),n.__c.__e=!0,n.__c.__P=e)),n}function D(){this.__u=0,this.t=null,this.__b=null;}function F(n){var t=n.__.__c;return t&&t.__a&&t.__a(n)}function V(){this.u=null,this.o=null;}l$1.unmount=function(n){var t=n.__c;t&&t.__R&&t.__R(),t&&!0===n.__h&&(n.type=null),I&&I(n);},(D.prototype=new d).__c=function(n,t){var e=t.__c,r=this;null==r.t&&(r.t=[]),r.t.push(e);var u=F(r.__v),o=!1,i=function(){o||(o=!0,e.__R=null,u?u(l):l());};e.__R=i;var l=function(){if(!--r.__u){if(r.state.__a){var n=r.state.__a;r.__v.__k[0]=U(n,n.__c.__P,n.__c.__O);}var t;for(r.setState({__a:r.__b=null});t=r.t.pop();)t.forceUpdate();}},c=!0===t.__h;r.__u++||c||r.setState({__a:r.__b=r.__v.__k[0]}),n.then(i,i);},D.prototype.componentWillUnmount=function(){this.t=[];},D.prototype.render=function(n,e){if(this.__b){if(this.__v.__k){var r=document.createElement("div"),o=this.__v.__k[0].__c;this.__v.__k[0]=L(this.__b,r,o.__O=o.__P);}this.__b=null;}var i=e.__a&&h(p,null,n.fallback);return i&&(i.__h=null),[h(p,null,e.__a?null:n.children),i]};var W=function(n,t,e){if(++e[1]===e[0]&&n.o.delete(t),n.props.revealOrder&&("t"!==n.props.revealOrder[0]||!n.o.size))for(e=n.u;e;){for(;e.length>3;)e.pop()();if(e[1]<e[0])break;n.u=e=e[2];}};function P(n){return this.getChildContext=function(){return n.context},n.children}function $(n){var e=this,r=n.i;e.componentWillUnmount=function(){P$1(null,e.l),e.l=null,e.i=null;},e.i&&e.i!==r&&e.componentWillUnmount(),n.__v?(e.l||(e.i=r,e.l={nodeType:1,parentNode:r,childNodes:[],appendChild:function(n){this.childNodes.push(n),e.i.appendChild(n);},insertBefore:function(n,t){this.childNodes.push(n),e.i.appendChild(n);},removeChild:function(n){this.childNodes.splice(this.childNodes.indexOf(n)>>>1,1),e.i.removeChild(n);}}),P$1(h(P,{context:e.context},n.__v),e.l)):e.l&&e.componentWillUnmount();}function j(n,e){var r=h($,{__v:n,i:e});return r.containerInfo=e,r}(V.prototype=new d).__a=function(n){var t=this,e=F(t.__v),r=t.o.get(n);return r[0]++,function(u){var o=function(){t.props.revealOrder?(r.push(u),W(t,n,r)):u();};e?e(o):o();}},V.prototype.render=function(n){this.u=null,this.o=new Map;var t=x$1(n.children);n.revealOrder&&"b"===n.revealOrder[0]&&t.reverse();for(var e=t.length;e--;)this.o.set(t[e],this.u=[1,0,this.u]);return n.children},V.prototype.componentDidUpdate=V.prototype.componentDidMount=function(){var n=this;this.o.forEach(function(t,e){W(n,e,t);});};var z="undefined"!=typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103,B=/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|image|letter|lighting|marker(?!H|W|U)|overline|paint|pointer|shape|stop|strikethrough|stroke|text(?!L)|transform|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,H="undefined"!=typeof document,Z=function(n){return ("undefined"!=typeof Symbol&&"symbol"==typeof Symbol()?/fil|che|rad/i:/fil|che|ra/i).test(n)};d.prototype.isReactComponent={},["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach(function(t){Object.defineProperty(d.prototype,t,{configurable:!0,get:function(){return this["UNSAFE_"+t]},set:function(n){Object.defineProperty(this,t,{configurable:!0,writable:!0,value:n});}});});var G=l$1.event;function J(){}function K(){return this.cancelBubble}function Q(){return this.defaultPrevented}l$1.event=function(n){return G&&(n=G(n)),n.persist=J,n.isPropagationStopped=K,n.isDefaultPrevented=Q,n.nativeEvent=n};var nn={configurable:!0,get:function(){return this.class}},tn=l$1.vnode;l$1.vnode=function(n){var t=n.type,e=n.props,u=e;if("string"==typeof t){var o=-1===t.indexOf("-");for(var i in u={},e){var l=e[i];H&&"children"===i&&"noscript"===t||"value"===i&&"defaultValue"in e&&null==l||("defaultValue"===i&&"value"in e&&null==e.value?i="value":"download"===i&&!0===l?l="":/ondoubleclick/i.test(i)?i="ondblclick":/^onchange(textarea|input)/i.test(i+t)&&!Z(e.type)?i="oninput":/^onfocus$/i.test(i)?i="onfocusin":/^onblur$/i.test(i)?i="onfocusout":/^on(Ani|Tra|Tou|BeforeInp|Compo)/.test(i)?i=i.toLowerCase():o&&B.test(i)?i=i.replace(/[A-Z0-9]/g,"-$&").toLowerCase():null===l&&(l=void 0),/^oninput$/i.test(i)&&(i=i.toLowerCase(),u[i]&&(i="oninputCapture")),u[i]=l);}"select"==t&&u.multiple&&Array.isArray(u.value)&&(u.value=x$1(e.children).forEach(function(n){n.props.selected=-1!=u.value.indexOf(n.props.value);})),"select"==t&&null!=u.defaultValue&&(u.value=x$1(e.children).forEach(function(n){n.props.selected=u.multiple?-1!=u.defaultValue.indexOf(n.props.value):u.defaultValue==n.props.value;})),n.props=u,e.class!=e.className&&(nn.enumerable="className"in e,null!=e.className&&(u.class=e.className),Object.defineProperty(u,"className",nn));}n.$$typeof=z,tn&&tn(n);};var en=l$1.__r;l$1.__r=function(n){en&&en(n),n.__c;};
14
15    function injectStyles(css) {
16        if (!css || typeof document === 'undefined') {
17            return;
18        }
19        const head = document.head || document.getElementsByTagName('head')[0];
20        const style = document.createElement('style');
21        style.type = 'text/css';
22        head.appendChild(style);
23        if (style.styleSheet) {
24            style.styleSheet.cssText = css;
25        }
26        else {
27            style.appendChild(document.createTextNode(css));
28        }
29    }
30
31    class DelayedRunner {
32        constructor(drainedOption) {
33            this.drainedOption = drainedOption;
34            this.isRunning = false;
35            this.isDirty = false;
36            this.pauseDepths = {};
37            this.timeoutId = 0;
38        }
39        request(delay) {
40            this.isDirty = true;
41            if (!this.isPaused()) {
42                this.clearTimeout();
43                if (delay == null) {
44                    this.tryDrain();
45                }
46                else {
47                    this.timeoutId = setTimeout(// NOT OPTIMAL! TODO: look at debounce
48                    this.tryDrain.bind(this), delay);
49                }
50            }
51        }
52        pause(scope = '') {
53            let { pauseDepths } = this;
54            pauseDepths[scope] = (pauseDepths[scope] || 0) + 1;
55            this.clearTimeout();
56        }
57        resume(scope = '', force) {
58            let { pauseDepths } = this;
59            if (scope in pauseDepths) {
60                if (force) {
61                    delete pauseDepths[scope];
62                }
63                else {
64                    pauseDepths[scope] -= 1;
65                    let depth = pauseDepths[scope];
66                    if (depth <= 0) {
67                        delete pauseDepths[scope];
68                    }
69                }
70                this.tryDrain();
71            }
72        }
73        isPaused() {
74            return Object.keys(this.pauseDepths).length;
75        }
76        tryDrain() {
77            if (!this.isRunning && !this.isPaused()) {
78                this.isRunning = true;
79                while (this.isDirty) {
80                    this.isDirty = false;
81                    this.drained(); // might set isDirty to true again
82                }
83                this.isRunning = false;
84            }
85        }
86        clear() {
87            this.clearTimeout();
88            this.isDirty = false;
89            this.pauseDepths = {};
90        }
91        clearTimeout() {
92            if (this.timeoutId) {
93                clearTimeout(this.timeoutId);
94                this.timeoutId = 0;
95            }
96        }
97        drained() {
98            if (this.drainedOption) {
99                this.drainedOption();
100            }
101        }
102    }
103
104    const { hasOwnProperty } = Object.prototype;
105    // Merges an array of objects into a single object.
106    // The second argument allows for an array of property names who's object values will be merged together.
107    function mergeProps(propObjs, complexPropsMap) {
108        let dest = {};
109        if (complexPropsMap) {
110            for (let name in complexPropsMap) {
111                let complexObjs = [];
112                // collect the trailing object values, stopping when a non-object is discovered
113                for (let i = propObjs.length - 1; i >= 0; i -= 1) {
114                    let val = propObjs[i][name];
115                    if (typeof val === 'object' && val) { // non-null object
116                        complexObjs.unshift(val);
117                    }
118                    else if (val !== undefined) {
119                        dest[name] = val; // if there were no objects, this value will be used
120                        break;
121                    }
122                }
123                // if the trailing values were objects, use the merged value
124                if (complexObjs.length) {
125                    dest[name] = mergeProps(complexObjs);
126                }
127            }
128        }
129        // copy values into the destination, going from last to first
130        for (let i = propObjs.length - 1; i >= 0; i -= 1) {
131            let props = propObjs[i];
132            for (let name in props) {
133                if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign
134                    dest[name] = props[name];
135                }
136            }
137        }
138        return dest;
139    }
140    function filterHash(hash, func) {
141        let filtered = {};
142        for (let key in hash) {
143            if (func(hash[key], key)) {
144                filtered[key] = hash[key];
145            }
146        }
147        return filtered;
148    }
149    function mapHash(hash, func) {
150        let newHash = {};
151        for (let key in hash) {
152            newHash[key] = func(hash[key], key);
153        }
154        return newHash;
155    }
156    function arrayToHash(a) {
157        let hash = {};
158        for (let item of a) {
159            hash[item] = true;
160        }
161        return hash;
162    }
163    // TODO: reassess browser support
164    // https://caniuse.com/?search=object.values
165    function hashValuesToArray(obj) {
166        let a = [];
167        for (let key in obj) {
168            a.push(obj[key]);
169        }
170        return a;
171    }
172    function isPropsEqual(obj0, obj1) {
173        if (obj0 === obj1) {
174            return true;
175        }
176        for (let key in obj0) {
177            if (hasOwnProperty.call(obj0, key)) {
178                if (!(key in obj1)) {
179                    return false;
vendor: 11,027 bytes, lines 180-493
180                }
181            }
182        }
183        for (let key in obj1) {
184            if (hasOwnProperty.call(obj1, key)) {
185                if (obj0[key] !== obj1[key]) {
186                    return false;
187                }
188            }
189        }
190        return true;
191    }
192    function getUnequalProps(obj0, obj1) {
193        let keys = [];
194        for (let key in obj0) {
195            if (hasOwnProperty.call(obj0, key)) {
196                if (!(key in obj1)) {
197                    keys.push(key);
198                }
199            }
200        }
201        for (let key in obj1) {
202            if (hasOwnProperty.call(obj1, key)) {
203                if (obj0[key] !== obj1[key]) {
204                    keys.push(key);
205                }
206            }
207        }
208        return keys;
209    }
210    function compareObjs(oldProps, newProps, equalityFuncs = {}) {
211        if (oldProps === newProps) {
212            return true;
213        }
214        for (let key in newProps) {
215            if (key in oldProps && isObjValsEqual(oldProps[key], newProps[key], equalityFuncs[key])) ;
216            else {
217                return false;
218            }
219        }
220        // check for props that were omitted in the new
221        for (let key in oldProps) {
222            if (!(key in newProps)) {
223                return false;
224            }
225        }
226        return true;
227    }
228    /*
229    assumed "true" equality for handler names like "onReceiveSomething"
230    */
231    function isObjValsEqual(val0, val1, comparator) {
232        if (val0 === val1 || comparator === true) {
233            return true;
234        }
235        if (comparator) {
236            return comparator(val0, val1);
237        }
238        return false;
239    }
240    function collectFromHash(hash, startIndex = 0, endIndex, step = 1) {
241        let res = [];
242        if (endIndex == null) {
243            endIndex = Object.keys(hash).length;
244        }
245        for (let i = startIndex; i < endIndex; i += step) {
246            let val = hash[i];
247            if (val !== undefined) { // will disregard undefined for sparse arrays
248                res.push(val);
249            }
250        }
251        return res;
252    }
253
254    const globalLocales = [];
255
256    // TODO: new util arrayify?
257    function removeExact(array, exactVal) {
258        let removeCnt = 0;
259        let i = 0;
260        while (i < array.length) {
261            if (array[i] === exactVal) {
262                array.splice(i, 1);
263                removeCnt += 1;
264            }
265            else {
266                i += 1;
267            }
268        }
269        return removeCnt;
270    }
271    function isArraysEqual(a0, a1, equalityFunc) {
272        if (a0 === a1) {
273            return true;
274        }
275        let len = a0.length;
276        let i;
277        if (len !== a1.length) { // not array? or not same length?
278            return false;
279        }
280        for (i = 0; i < len; i += 1) {
281            if (!(equalityFunc ? equalityFunc(a0[i], a1[i]) : a0[i] === a1[i])) {
282                return false;
283            }
284        }
285        return true;
286    }
287
288    function memoize(workerFunc, resEquality, teardownFunc) {
289        let currentArgs;
290        let currentRes;
291        return function (...newArgs) {
292            if (!currentArgs) {
293                currentRes = workerFunc.apply(this, newArgs);
294            }
295            else if (!isArraysEqual(currentArgs, newArgs)) {
296                if (teardownFunc) {
297                    teardownFunc(currentRes);
298                }
299                let res = workerFunc.apply(this, newArgs);
300                if (!resEquality || !resEquality(res, currentRes)) {
301                    currentRes = res;
302                }
303            }
304            currentArgs = newArgs;
305            return currentRes;
306        };
307    }
308    function memoizeObjArg(workerFunc, resEquality, teardownFunc) {
309        let currentArg;
310        let currentRes;
311        return (newArg) => {
312            if (!currentArg) {
313                currentRes = workerFunc.call(this, newArg);
314            }
315            else if (!isPropsEqual(currentArg, newArg)) {
316                if (teardownFunc) {
317                    teardownFunc(currentRes);
318                }
319                let res = workerFunc.call(this, newArg);
320                if (!resEquality || !resEquality(res, currentRes)) {
321                    currentRes = res;
322                }
323            }
324            currentArg = newArg;
325            return currentRes;
326        };
327    }
328    function memoizeArraylike(// used at all?
329    workerFunc, resEquality, teardownFunc) {
330        let currentArgSets = [];
331        let currentResults = [];
332        return (newArgSets) => {
333            let currentLen = currentArgSets.length;
334            let newLen = newArgSets.length;
335            let i = 0;
336            for (; i < currentLen; i += 1) {
337                if (!newArgSets[i]) { // one of the old sets no longer exists
338                    if (teardownFunc) {
339                        teardownFunc(currentResults[i]);
340                    }
341                }
342                else if (!isArraysEqual(currentArgSets[i], newArgSets[i])) {
343                    if (teardownFunc) {
344                        teardownFunc(currentResults[i]);
345                    }
346                    let res = workerFunc.apply(this, newArgSets[i]);
347                    if (!resEquality || !resEquality(res, currentResults[i])) {
348                        currentResults[i] = res;
349                    }
350                }
351            }
352            for (; i < newLen; i += 1) {
353                currentResults[i] = workerFunc.apply(this, newArgSets[i]);
354            }
355            currentArgSets = newArgSets;
356            currentResults.splice(newLen); // remove excess
357            return currentResults;
358        };
359    }
360    function memoizeHashlike(workerFunc, resEquality, teardownFunc) {
361        let currentArgHash = {};
362        let currentResHash = {};
363        return (newArgHash) => {
364            let newResHash = {};
365            for (let key in newArgHash) {
366                if (!currentResHash[key]) {
367                    newResHash[key] = workerFunc.apply(this, newArgHash[key]);
368                }
369                else if (!isArraysEqual(currentArgHash[key], newArgHash[key])) {
370                    if (teardownFunc) {
371                        teardownFunc(currentResHash[key]);
372                    }
373                    let res = workerFunc.apply(this, newArgHash[key]);
374                    newResHash[key] = (resEquality && resEquality(res, currentResHash[key]))
375                        ? currentResHash[key]
376                        : res;
377                }
378                else {
379                    newResHash[key] = currentResHash[key];
380                }
381            }
382            currentArgHash = newArgHash;
383            currentResHash = newResHash;
384            return newResHash;
385        };
386    }
387
388    function removeElement(el) {
389        if (el.parentNode) {
390            el.parentNode.removeChild(el);
391        }
392    }
393    // Querying
394    // ----------------------------------------------------------------------------------------------------------------
395    function elementClosest(el, selector) {
396        if (el.closest) {
397            return el.closest(selector);
398            // really bad fallback for IE
399            // from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
400        }
401        if (!document.documentElement.contains(el)) {
402            return null;
403        }
404        do {
405            if (elementMatches(el, selector)) {
406                return el;
407            }
408            el = (el.parentElement || el.parentNode);
409        } while (el !== null && el.nodeType === 1);
410        return null;
411    }
412    function elementMatches(el, selector) {
413        let method = el.matches || el.matchesSelector || el.msMatchesSelector;
414        return method.call(el, selector);
415    }
416    // accepts multiple subject els
417    // returns a real array. good for methods like forEach
418    // TODO: accept the document
419    function findElements(container, selector) {
420        let containers = container instanceof HTMLElement ? [container] : container;
421        let allMatches = [];
422        for (let i = 0; i < containers.length; i += 1) {
423            let matches = containers[i].querySelectorAll(selector);
424            for (let j = 0; j < matches.length; j += 1) {
425                allMatches.push(matches[j]);
426            }
427        }
428        return allMatches;
429    }
430    // accepts multiple subject els
431    // only queries direct child elements // TODO: rename to findDirectChildren!
432    function findDirectChildren(parent, selector) {
433        let parents = parent instanceof HTMLElement ? [parent] : parent;
434        let allMatches = [];
435        for (let i = 0; i < parents.length; i += 1) {
436            let childNodes = parents[i].children; // only ever elements
437            for (let j = 0; j < childNodes.length; j += 1) {
438                let childNode = childNodes[j];
439                if (!selector || elementMatches(childNode, selector)) {
440                    allMatches.push(childNode);
441                }
442            }
443        }
444        return allMatches;
445    }
446    // Style
447    // ----------------------------------------------------------------------------------------------------------------
448    const PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i;
449    function applyStyle(el, props) {
450        for (let propName in props) {
451            applyStyleProp(el, propName, props[propName]);
452        }
453    }
454    function applyStyleProp(el, name, val) {
455        if (val == null) {
456            el.style[name] = '';
457        }
458        else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) {
459            el.style[name] = `${val}px`;
460        }
461        else {
462            el.style[name] = val;
463        }
464    }
465    // Event Handling
466    // ----------------------------------------------------------------------------------------------------------------
467    // if intercepting bubbled events at the document/window/body level,
468    // and want to see originating element (the 'target'), use this util instead
469    // of `ev.target` because it goes within web-component boundaries.
470    function getEventTargetViaRoot(ev) {
471        var _a, _b;
472        return (_b = (_a = ev.composedPath) === null || _a === void 0 ? void 0 : _a.call(ev)[0]) !== null && _b !== void 0 ? _b : ev.target;
473    }
474    // Shadow DOM consuderations
475    // ----------------------------------------------------------------------------------------------------------------
476    function getElRoot(el) {
477        return el.getRootNode ? el.getRootNode() : document;
478    }
479    // Unique ID for DOM attribute
480    let guid$1 = 0;
481    function getUniqueDomId() {
482        guid$1 += 1;
483        return 'fc-dom-' + guid$1;
484    }
485
486    // Stops a mouse/touch event from doing it's native browser action
487    function preventDefault(ev) {
488        ev.preventDefault();
489    }
490    // Event Delegation
491    // ----------------------------------------------------------------------------------------------------------------
492    function buildDelegationHandler(selector, handler) {
493        return (ev) => {
vendor: 14,727 bytes, lines 494-826
494            let matchedChild = elementClosest(ev.target, selector);
495            if (matchedChild) {
496                handler.call(matchedChild, ev, matchedChild);
497            }
498        };
499    }
500    function listenBySelector(container, eventType, selector, handler) {
501        let attachedHandler = buildDelegationHandler(selector, handler);
502        container.addEventListener(eventType, attachedHandler);
503        return () => {
504            container.removeEventListener(eventType, attachedHandler);
505        };
506    }
507    function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) {
508        let currentMatchedChild;
509        return listenBySelector(container, 'mouseover', selector, (mouseOverEv, matchedChild) => {
510            if (matchedChild !== currentMatchedChild) {
511                currentMatchedChild = matchedChild;
512                onMouseEnter(mouseOverEv, matchedChild);
513                let realOnMouseLeave = (mouseLeaveEv) => {
514                    currentMatchedChild = null;
515                    onMouseLeave(mouseLeaveEv, matchedChild);
516                    matchedChild.removeEventListener('mouseleave', realOnMouseLeave);
517                };
518                // listen to the next mouseleave, and then unattach
519                matchedChild.addEventListener('mouseleave', realOnMouseLeave);
520            }
521        });
522    }
523    // Animation
524    // ----------------------------------------------------------------------------------------------------------------
525    const transitionEventNames = [
526        'webkitTransitionEnd',
527        'otransitionend',
528        'oTransitionEnd',
529        'msTransitionEnd',
530        'transitionend',
531    ];
532    // triggered only when the next single subsequent transition finishes
533    function whenTransitionDone(el, callback) {
534        let realCallback = (ev) => {
535            callback(ev);
536            transitionEventNames.forEach((eventName) => {
537                el.removeEventListener(eventName, realCallback);
538            });
539        };
540        transitionEventNames.forEach((eventName) => {
541            el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes
542        });
543    }
544    // ARIA workarounds
545    // ----------------------------------------------------------------------------------------------------------------
546    function createAriaClickAttrs(handler) {
547        return Object.assign({ onClick: handler }, createAriaKeyboardAttrs(handler));
548    }
549    function createAriaKeyboardAttrs(handler) {
550        return {
551            tabIndex: 0,
552            onKeyDown(ev) {
553                if (ev.key === 'Enter' || ev.key === ' ') {
554                    handler(ev);
555                    ev.preventDefault(); // if space, don't scroll down page
556                }
557            },
558        };
559    }
560
561    let guidNumber = 0;
562    function guid() {
563        guidNumber += 1;
564        return String(guidNumber);
565    }
566    /* FullCalendar-specific DOM Utilities
567    ----------------------------------------------------------------------------------------------------------------------*/
568    // Make the mouse cursor express that an event is not allowed in the current area
569    function disableCursor() {
570        document.body.classList.add('fc-not-allowed');
571    }
572    // Returns the mouse cursor to its original look
573    function enableCursor() {
574        document.body.classList.remove('fc-not-allowed');
575    }
576    /* Selection
577    ----------------------------------------------------------------------------------------------------------------------*/
578    function preventSelection(el) {
579        el.classList.add('fc-unselectable');
580        el.addEventListener('selectstart', preventDefault);
581    }
582    function allowSelection(el) {
583        el.classList.remove('fc-unselectable');
584        el.removeEventListener('selectstart', preventDefault);
585    }
586    /* Context Menu
587    ----------------------------------------------------------------------------------------------------------------------*/
588    function preventContextMenu(el) {
589        el.addEventListener('contextmenu', preventDefault);
590    }
591    function allowContextMenu(el) {
592        el.removeEventListener('contextmenu', preventDefault);
593    }
594    function parseFieldSpecs(input) {
595        let specs = [];
596        let tokens = [];
597        let i;
598        let token;
599        if (typeof input === 'string') {
600            tokens = input.split(/\s*,\s*/);
601        }
602        else if (typeof input === 'function') {
603            tokens = [input];
604        }
605        else if (Array.isArray(input)) {
606            tokens = input;
607        }
608        for (i = 0; i < tokens.length; i += 1) {
609            token = tokens[i];
610            if (typeof token === 'string') {
611                specs.push(token.charAt(0) === '-' ?
612                    { field: token.substring(1), order: -1 } :
613                    { field: token, order: 1 });
614            }
615            else if (typeof token === 'function') {
616                specs.push({ func: token });
617            }
618        }
619        return specs;
620    }
621    function compareByFieldSpecs(obj0, obj1, fieldSpecs) {
622        let i;
623        let cmp;
624        for (i = 0; i < fieldSpecs.length; i += 1) {
625            cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]);
626            if (cmp) {
627                return cmp;
628            }
629        }
630        return 0;
631    }
632    function compareByFieldSpec(obj0, obj1, fieldSpec) {
633        if (fieldSpec.func) {
634            return fieldSpec.func(obj0, obj1);
635        }
636        return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field])
637            * (fieldSpec.order || 1);
638    }
639    function flexibleCompare(a, b) {
640        if (!a && !b) {
641            return 0;
642        }
643        if (b == null) {
644            return -1;
645        }
646        if (a == null) {
647            return 1;
648        }
649        if (typeof a === 'string' || typeof b === 'string') {
650            return String(a).localeCompare(String(b));
651        }
652        return a - b;
653    }
654    /* String Utilities
655    ----------------------------------------------------------------------------------------------------------------------*/
656    function padStart(val, len) {
657        let s = String(val);
658        return '000'.substr(0, len - s.length) + s;
659    }
660    function formatWithOrdinals(formatter, args, fallbackText) {
661        if (typeof formatter === 'function') {
662            return formatter(...args);
663        }
664        if (typeof formatter === 'string') { // non-blank string
665            return args.reduce((str, arg, index) => (str.replace('$' + index, arg || '')), formatter);
666        }
667        return fallbackText;
668    }
669    /* Number Utilities
670    ----------------------------------------------------------------------------------------------------------------------*/
671    function compareNumbers(a, b) {
672        return a - b;
673    }
674    function isInt(n) {
675        return n % 1 === 0;
676    }
677    /* FC-specific DOM dimension stuff
678    ----------------------------------------------------------------------------------------------------------------------*/
679    function computeSmallestCellWidth(cellEl) {
680        let allWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-frame');
681        let contentWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-cushion');
682        if (!allWidthEl) {
683            throw new Error('needs fc-scrollgrid-shrink-frame className'); // TODO: use const
684        }
685        if (!contentWidthEl) {
686            throw new Error('needs fc-scrollgrid-shrink-cushion className');
687        }
688        return cellEl.getBoundingClientRect().width - allWidthEl.getBoundingClientRect().width + // the cell padding+border
689            contentWidthEl.getBoundingClientRect().width;
690    }
691
692    // TODO: easier way to add new hooks? need to update a million things
693    function createPlugin(input) {
694        return {
695            id: guid(),
696            name: input.name,
697            premiumReleaseDate: input.premiumReleaseDate ? new Date(input.premiumReleaseDate) : undefined,
698            deps: input.deps || [],
699            reducers: input.reducers || [],
700            isLoadingFuncs: input.isLoadingFuncs || [],
701            contextInit: [].concat(input.contextInit || []),
702            eventRefiners: input.eventRefiners || {},
703            eventDefMemberAdders: input.eventDefMemberAdders || [],
704            eventSourceRefiners: input.eventSourceRefiners || {},
705            isDraggableTransformers: input.isDraggableTransformers || [],
706            eventDragMutationMassagers: input.eventDragMutationMassagers || [],
707            eventDefMutationAppliers: input.eventDefMutationAppliers || [],
708            dateSelectionTransformers: input.dateSelectionTransformers || [],
709            datePointTransforms: input.datePointTransforms || [],
710            dateSpanTransforms: input.dateSpanTransforms || [],
711            views: input.views || {},
712            viewPropsTransformers: input.viewPropsTransformers || [],
713            isPropsValid: input.isPropsValid || null,
714            externalDefTransforms: input.externalDefTransforms || [],
715            viewContainerAppends: input.viewContainerAppends || [],
716            eventDropTransformers: input.eventDropTransformers || [],
717            componentInteractions: input.componentInteractions || [],
718            calendarInteractions: input.calendarInteractions || [],
719            themeClasses: input.themeClasses || {},
720            eventSourceDefs: input.eventSourceDefs || [],
721            cmdFormatter: input.cmdFormatter,
722            recurringTypes: input.recurringTypes || [],
723            namedTimeZonedImpl: input.namedTimeZonedImpl,
724            initialView: input.initialView || '',
725            elementDraggingImpl: input.elementDraggingImpl,
726            optionChangeHandlers: input.optionChangeHandlers || {},
727            scrollGridImpl: input.scrollGridImpl || null,
728            listenerRefiners: input.listenerRefiners || {},
729            optionRefiners: input.optionRefiners || {},
730            propSetHandlers: input.propSetHandlers || {},
731        };
732    }
733    function buildPluginHooks(pluginDefs, globalDefs) {
734        let currentPluginIds = {};
735        let hooks = {
736            premiumReleaseDate: undefined,
737            reducers: [],
738            isLoadingFuncs: [],
739            contextInit: [],
740            eventRefiners: {},
741            eventDefMemberAdders: [],
742            eventSourceRefiners: {},
743            isDraggableTransformers: [],
744            eventDragMutationMassagers: [],
745            eventDefMutationAppliers: [],
746            dateSelectionTransformers: [],
747            datePointTransforms: [],
748            dateSpanTransforms: [],
749            views: {},
750            viewPropsTransformers: [],
751            isPropsValid: null,
752            externalDefTransforms: [],
753            viewContainerAppends: [],
754            eventDropTransformers: [],
755            componentInteractions: [],
756            calendarInteractions: [],
757            themeClasses: {},
758            eventSourceDefs: [],
759            cmdFormatter: null,
760            recurringTypes: [],
761            namedTimeZonedImpl: null,
762            initialView: '',
763            elementDraggingImpl: null,
764            optionChangeHandlers: {},
765            scrollGridImpl: null,
766            listenerRefiners: {},
767            optionRefiners: {},
768            propSetHandlers: {},
769        };
770        function addDefs(defs) {
771            for (let def of defs) {
772                const pluginName = def.name;
773                const currentId = currentPluginIds[pluginName];
774                if (currentId === undefined) {
775                    currentPluginIds[pluginName] = def.id;
776                    addDefs(def.deps);
777                    hooks = combineHooks(hooks, def);
778                }
779                else if (currentId !== def.id) {
780                    // different ID than the one already added
781                    console.warn(`Duplicate plugin '${pluginName}'`);
782                }
783            }
784        }
785        if (pluginDefs) {
786            addDefs(pluginDefs);
787        }
788        addDefs(globalDefs);
789        return hooks;
790    }
791    function buildBuildPluginHooks() {
792        let currentOverrideDefs = [];
793        let currentGlobalDefs = [];
794        let currentHooks;
795        return (overrideDefs, globalDefs) => {
796            if (!currentHooks || !isArraysEqual(overrideDefs, currentOverrideDefs) || !isArraysEqual(globalDefs, currentGlobalDefs)) {
797                currentHooks = buildPluginHooks(overrideDefs, globalDefs);
798            }
799            currentOverrideDefs = overrideDefs;
800            currentGlobalDefs = globalDefs;
801            return currentHooks;
802        };
803    }
804    function combineHooks(hooks0, hooks1) {
805        return {
806            premiumReleaseDate: compareOptionalDates(hooks0.premiumReleaseDate, hooks1.premiumReleaseDate),
807            reducers: hooks0.reducers.concat(hooks1.reducers),
808            isLoadingFuncs: hooks0.isLoadingFuncs.concat(hooks1.isLoadingFuncs),
809            contextInit: hooks0.contextInit.concat(hooks1.contextInit),
810            eventRefiners: Object.assign(Object.assign({}, hooks0.eventRefiners), hooks1.eventRefiners),
811            eventDefMemberAdders: hooks0.eventDefMemberAdders.concat(hooks1.eventDefMemberAdders),
812            eventSourceRefiners: Object.assign(Object.assign({}, hooks0.eventSourceRefiners), hooks1.eventSourceRefiners),
813            isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers),
814            eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers),
815            eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers),
816            dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers),
817            datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms),
818            dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms),
819            views: Object.assign(Object.assign({}, hooks0.views), hooks1.views),
820            viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers),
821            isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid,
822            externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms),
823            viewContainerAppends: hooks0.viewContainerAppends.concat(hooks1.viewContainerAppends),
824            eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers),
825            calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions),
826            componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions),
vendor: 52,447 bytes, lines 827-2246
827            themeClasses: Object.assign(Object.assign({}, hooks0.themeClasses), hooks1.themeClasses),
828            eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs),
829            cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter,
830            recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes),
831            namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl,
832            initialView: hooks0.initialView || hooks1.initialView,
833            elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl,
834            optionChangeHandlers: Object.assign(Object.assign({}, hooks0.optionChangeHandlers), hooks1.optionChangeHandlers),
835            scrollGridImpl: hooks1.scrollGridImpl || hooks0.scrollGridImpl,
836            listenerRefiners: Object.assign(Object.assign({}, hooks0.listenerRefiners), hooks1.listenerRefiners),
837            optionRefiners: Object.assign(Object.assign({}, hooks0.optionRefiners), hooks1.optionRefiners),
838            propSetHandlers: Object.assign(Object.assign({}, hooks0.propSetHandlers), hooks1.propSetHandlers),
839        };
840    }
841    function compareOptionalDates(date0, date1) {
842        if (date0 === undefined) {
843            return date1;
844        }
845        if (date1 === undefined) {
846            return date0;
847        }
848        return new Date(Math.max(date0.valueOf(), date1.valueOf()));
849    }
850
851    const DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
852    // Adding
853    function addWeeks(m, n) {
854        let a = dateToUtcArray(m);
855        a[2] += n * 7;
856        return arrayToUtcDate(a);
857    }
858    function addDays(m, n) {
859        let a = dateToUtcArray(m);
860        a[2] += n;
861        return arrayToUtcDate(a);
862    }
863    function addMs(m, n) {
864        let a = dateToUtcArray(m);
865        a[6] += n;
866        return arrayToUtcDate(a);
867    }
868    // Diffing (all return floats)
869    // TODO: why not use ranges?
870    function diffWeeks(m0, m1) {
871        return diffDays(m0, m1) / 7;
872    }
873    function diffDays(m0, m1) {
874        return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24);
875    }
876    function diffHours(m0, m1) {
877        return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60);
878    }
879    function diffMinutes(m0, m1) {
880        return (m1.valueOf() - m0.valueOf()) / (1000 * 60);
881    }
882    function diffSeconds(m0, m1) {
883        return (m1.valueOf() - m0.valueOf()) / 1000;
884    }
885    function diffDayAndTime(m0, m1) {
886        let m0day = startOfDay(m0);
887        let m1day = startOfDay(m1);
888        return {
889            years: 0,
890            months: 0,
891            days: Math.round(diffDays(m0day, m1day)),
892            milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()),
893        };
894    }
895    // Diffing Whole Units
896    function diffWholeWeeks(m0, m1) {
897        let d = diffWholeDays(m0, m1);
898        if (d !== null && d % 7 === 0) {
899            return d / 7;
900        }
901        return null;
902    }
903    function diffWholeDays(m0, m1) {
904        if (timeAsMs(m0) === timeAsMs(m1)) {
905            return Math.round(diffDays(m0, m1));
906        }
907        return null;
908    }
909    // Start-Of
910    function startOfDay(m) {
911        return arrayToUtcDate([
912            m.getUTCFullYear(),
913            m.getUTCMonth(),
914            m.getUTCDate(),
915        ]);
916    }
917    function startOfHour(m) {
918        return arrayToUtcDate([
919            m.getUTCFullYear(),
920            m.getUTCMonth(),
921            m.getUTCDate(),
922            m.getUTCHours(),
923        ]);
924    }
925    function startOfMinute(m) {
926        return arrayToUtcDate([
927            m.getUTCFullYear(),
928            m.getUTCMonth(),
929            m.getUTCDate(),
930            m.getUTCHours(),
931            m.getUTCMinutes(),
932        ]);
933    }
934    function startOfSecond(m) {
935        return arrayToUtcDate([
936            m.getUTCFullYear(),
937            m.getUTCMonth(),
938            m.getUTCDate(),
939            m.getUTCHours(),
940            m.getUTCMinutes(),
941            m.getUTCSeconds(),
942        ]);
943    }
944    // Week Computation
945    function weekOfYear(marker, dow, doy) {
946        let y = marker.getUTCFullYear();
947        let w = weekOfGivenYear(marker, y, dow, doy);
948        if (w < 1) {
949            return weekOfGivenYear(marker, y - 1, dow, doy);
950        }
951        let nextW = weekOfGivenYear(marker, y + 1, dow, doy);
952        if (nextW >= 1) {
953            return Math.min(w, nextW);
954        }
955        return w;
956    }
957    function weekOfGivenYear(marker, year, dow, doy) {
958        let firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]);
959        let dayStart = startOfDay(marker);
960        let days = Math.round(diffDays(firstWeekStart, dayStart));
961        return Math.floor(days / 7) + 1; // zero-indexed
962    }
963    // start-of-first-week - start-of-year
964    function firstWeekOffset(year, dow, doy) {
965        // first-week day -- which january is always in the first week (4 for iso, 1 for other)
966        let fwd = 7 + dow - doy;
967        // first-week day local weekday -- which local weekday is fwd
968        let fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7;
969        return -fwdlw + fwd - 1;
970    }
971    // Array Conversion
972    function dateToLocalArray(date) {
973        return [
974            date.getFullYear(),
975            date.getMonth(),
976            date.getDate(),
977            date.getHours(),
978            date.getMinutes(),
979            date.getSeconds(),
980            date.getMilliseconds(),
981        ];
982    }
983    function arrayToLocalDate(a) {
984        return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month
985        a[3] || 0, a[4] || 0, a[5] || 0);
986    }
987    function dateToUtcArray(date) {
988        return [
989            date.getUTCFullYear(),
990            date.getUTCMonth(),
991            date.getUTCDate(),
992            date.getUTCHours(),
993            date.getUTCMinutes(),
994            date.getUTCSeconds(),
995            date.getUTCMilliseconds(),
996        ];
997    }
998    function arrayToUtcDate(a) {
999        // according to web standards (and Safari), a month index is required.
1000        // massage if only given a year.
1001        if (a.length === 1) {
1002            a = a.concat([0]);
1003        }
1004        return new Date(Date.UTC(...a));
1005    }
1006    // Other Utils
1007    function isValidDate(m) {
1008        return !isNaN(m.valueOf());
1009    }
1010    function timeAsMs(m) {
1011        return m.getUTCHours() * 1000 * 60 * 60 +
1012            m.getUTCMinutes() * 1000 * 60 +
1013            m.getUTCSeconds() * 1000 +
1014            m.getUTCMilliseconds();
1015    }
1016
1017    let calendarSystemClassMap = {};
1018    function registerCalendarSystem(name, theClass) {
1019        calendarSystemClassMap[name] = theClass;
1020    }
1021    function createCalendarSystem(name) {
1022        return new calendarSystemClassMap[name]();
1023    }
1024    class GregorianCalendarSystem {
1025        getMarkerYear(d) {
1026            return d.getUTCFullYear();
1027        }
1028        getMarkerMonth(d) {
1029            return d.getUTCMonth();
1030        }
1031        getMarkerDay(d) {
1032            return d.getUTCDate();
1033        }
1034        arrayToMarker(arr) {
1035            return arrayToUtcDate(arr);
1036        }
1037        markerToArray(marker) {
1038            return dateToUtcArray(marker);
1039        }
1040    }
1041    registerCalendarSystem('gregory', GregorianCalendarSystem);
1042
1043    const INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];
1044    const PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/;
1045    // Parsing and Creation
1046    function createDuration(input, unit) {
1047        if (typeof input === 'string') {
1048            return parseString(input);
1049        }
1050        if (typeof input === 'object' && input) { // non-null object
1051            return parseObject(input);
1052        }
1053        if (typeof input === 'number') {
1054            return parseObject({ [unit || 'milliseconds']: input });
1055        }
1056        return null;
1057    }
1058    function parseString(s) {
1059        let m = PARSE_RE.exec(s);
1060        if (m) {
1061            let sign = m[1] ? -1 : 1;
1062            return {
1063                years: 0,
1064                months: 0,
1065                days: sign * (m[2] ? parseInt(m[2], 10) : 0),
1066                milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours
1067                    (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes
1068                    (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds
1069                    (m[6] ? parseInt(m[6], 10) : 0) // ms
1070                ),
1071            };
1072        }
1073        return null;
1074    }
1075    function parseObject(obj) {
1076        let duration = {
1077            years: obj.years || obj.year || 0,
1078            months: obj.months || obj.month || 0,
1079            days: obj.days || obj.day || 0,
1080            milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours
1081                (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes
1082                (obj.seconds || obj.second || 0) * 1000 + // seconds
1083                (obj.milliseconds || obj.millisecond || obj.ms || 0), // ms
1084        };
1085        let weeks = obj.weeks || obj.week;
1086        if (weeks) {
1087            duration.days += weeks * 7;
1088            duration.specifiedWeeks = true;
1089        }
1090        return duration;
1091    }
1092    // Equality
1093    function durationsEqual(d0, d1) {
1094        return d0.years === d1.years &&
1095            d0.months === d1.months &&
1096            d0.days === d1.days &&
1097            d0.milliseconds === d1.milliseconds;
1098    }
1099    function asCleanDays(dur) {
1100        if (!dur.years && !dur.months && !dur.milliseconds) {
1101            return dur.days;
1102        }
1103        return 0;
1104    }
1105    // Simple Math
1106    function addDurations(d0, d1) {
1107        return {
1108            years: d0.years + d1.years,
1109            months: d0.months + d1.months,
1110            days: d0.days + d1.days,
1111            milliseconds: d0.milliseconds + d1.milliseconds,
1112        };
1113    }
1114    function subtractDurations(d1, d0) {
1115        return {
1116            years: d1.years - d0.years,
1117            months: d1.months - d0.months,
1118            days: d1.days - d0.days,
1119            milliseconds: d1.milliseconds - d0.milliseconds,
1120        };
1121    }
1122    function multiplyDuration(d, n) {
1123        return {
1124            years: d.years * n,
1125            months: d.months * n,
1126            days: d.days * n,
1127            milliseconds: d.milliseconds * n,
1128        };
1129    }
1130    // Conversions
1131    // "Rough" because they are based on average-case Gregorian months/years
1132    function asRoughYears(dur) {
1133        return asRoughDays(dur) / 365;
1134    }
1135    function asRoughMonths(dur) {
1136        return asRoughDays(dur) / 30;
1137    }
1138    function asRoughDays(dur) {
1139        return asRoughMs(dur) / 864e5;
1140    }
1141    function asRoughMinutes(dur) {
1142        return asRoughMs(dur) / (1000 * 60);
1143    }
1144    function asRoughSeconds(dur) {
1145        return asRoughMs(dur) / 1000;
1146    }
1147    function asRoughMs(dur) {
1148        return dur.years * (365 * 864e5) +
1149            dur.months * (30 * 864e5) +
1150            dur.days * 864e5 +
1151            dur.milliseconds;
1152    }
1153    // Advanced Math
1154    function wholeDivideDurations(numerator, denominator) {
1155        let res = null;
1156        for (let i = 0; i < INTERNAL_UNITS.length; i += 1) {
1157            let unit = INTERNAL_UNITS[i];
1158            if (denominator[unit]) {
1159                let localRes = numerator[unit] / denominator[unit];
1160                if (!isInt(localRes) || (res !== null && res !== localRes)) {
1161                    return null;
1162                }
1163                res = localRes;
1164            }
1165            else if (numerator[unit]) {
1166                // needs to divide by something but can't!
1167                return null;
1168            }
1169        }
1170        return res;
1171    }
1172    function greatestDurationDenominator(dur) {
1173        let ms = dur.milliseconds;
1174        if (ms) {
1175            if (ms % 1000 !== 0) {
1176                return { unit: 'millisecond', value: ms };
1177            }
1178            if (ms % (1000 * 60) !== 0) {
1179                return { unit: 'second', value: ms / 1000 };
1180            }
1181            if (ms % (1000 * 60 * 60) !== 0) {
1182                return { unit: 'minute', value: ms / (1000 * 60) };
1183            }
1184            if (ms) {
1185                return { unit: 'hour', value: ms / (1000 * 60 * 60) };
1186            }
1187        }
1188        if (dur.days) {
1189            if (dur.specifiedWeeks && dur.days % 7 === 0) {
1190                return { unit: 'week', value: dur.days / 7 };
1191            }
1192            return { unit: 'day', value: dur.days };
1193        }
1194        if (dur.months) {
1195            return { unit: 'month', value: dur.months };
1196        }
1197        if (dur.years) {
1198            return { unit: 'year', value: dur.years };
1199        }
1200        return { unit: 'millisecond', value: 0 };
1201    }
1202
1203    // timeZoneOffset is in minutes
1204    function buildIsoString(marker, timeZoneOffset, stripZeroTime = false) {
1205        let s = marker.toISOString();
1206        s = s.replace('.000', '');
1207        if (stripZeroTime) {
1208            s = s.replace('T00:00:00Z', '');
1209        }
1210        if (s.length > 10) { // time part wasn't stripped, can add timezone info
1211            if (timeZoneOffset == null) {
1212                s = s.replace('Z', '');
1213            }
1214            else if (timeZoneOffset !== 0) {
1215                s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true));
1216            }
1217            // otherwise, its UTC-0 and we want to keep the Z
1218        }
1219        return s;
1220    }
1221    // formats the date, but with no time part
1222    // TODO: somehow merge with buildIsoString and stripZeroTime
1223    // TODO: rename. omit "string"
1224    function formatDayString(marker) {
1225        return marker.toISOString().replace(/T.*$/, '');
1226    }
1227    // TODO: use Date::toISOString and use everything after the T?
1228    function formatIsoTimeString(marker) {
1229        return padStart(marker.getUTCHours(), 2) + ':' +
1230            padStart(marker.getUTCMinutes(), 2) + ':' +
1231            padStart(marker.getUTCSeconds(), 2);
1232    }
1233    function formatTimeZoneOffset(minutes, doIso = false) {
1234        let sign = minutes < 0 ? '-' : '+';
1235        let abs = Math.abs(minutes);
1236        let hours = Math.floor(abs / 60);
1237        let mins = Math.round(abs % 60);
1238        if (doIso) {
1239            return `${sign + padStart(hours, 2)}:${padStart(mins, 2)}`;
1240        }
1241        return `GMT${sign}${hours}${mins ? `:${padStart(mins, 2)}` : ''}`;
1242    }
1243
1244    const ISO_RE = /^\s*(\d{4})(-?(\d{2})(-?(\d{2})([T ](\d{2}):?(\d{2})(:?(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/;
1245    function parse(str) {
1246        let m = ISO_RE.exec(str);
1247        if (m) {
1248            let 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));
1249            if (isValidDate(marker)) {
1250                let timeZoneOffset = null;
1251                if (m[13]) {
1252                    timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 +
1253                        Number(m[18] || 0));
1254                }
1255                return {
1256                    marker,
1257                    isTimeUnspecified: !m[6],
1258                    timeZoneOffset,
1259                };
1260            }
1261        }
1262        return null;
1263    }
1264
1265    class DateEnv {
1266        constructor(settings) {
1267            let timeZone = this.timeZone = settings.timeZone;
1268            let isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC';
1269            if (settings.namedTimeZoneImpl && isNamedTimeZone) {
1270                this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone);
1271            }
1272            this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl);
1273            this.calendarSystem = createCalendarSystem(settings.calendarSystem);
1274            this.locale = settings.locale;
1275            this.weekDow = settings.locale.week.dow;
1276            this.weekDoy = settings.locale.week.doy;
1277            if (settings.weekNumberCalculation === 'ISO') {
1278                this.weekDow = 1;
1279                this.weekDoy = 4;
1280            }
1281            if (typeof settings.firstDay === 'number') {
1282                this.weekDow = settings.firstDay;
1283            }
1284            if (typeof settings.weekNumberCalculation === 'function') {
1285                this.weekNumberFunc = settings.weekNumberCalculation;
1286            }
1287            this.weekText = settings.weekText != null ? settings.weekText : settings.locale.options.weekText;
1288            this.weekTextLong = (settings.weekTextLong != null ? settings.weekTextLong : settings.locale.options.weekTextLong) || this.weekText;
1289            this.cmdFormatter = settings.cmdFormatter;
1290            this.defaultSeparator = settings.defaultSeparator;
1291        }
1292        // Creating / Parsing
1293        createMarker(input) {
1294            let meta = this.createMarkerMeta(input);
1295            if (meta === null) {
1296                return null;
1297            }
1298            return meta.marker;
1299        }
1300        createNowMarker() {
1301            if (this.canComputeOffset) {
1302                return this.timestampToMarker(new Date().valueOf());
1303            }
1304            // if we can't compute the current date val for a timezone,
1305            // better to give the current local date vals than UTC
1306            return arrayToUtcDate(dateToLocalArray(new Date()));
1307        }
1308        createMarkerMeta(input) {
1309            if (typeof input === 'string') {
1310                return this.parse(input);
1311            }
1312            let marker = null;
1313            if (typeof input === 'number') {
1314                marker = this.timestampToMarker(input);
1315            }
1316            else if (input instanceof Date) {
1317                input = input.valueOf();
1318                if (!isNaN(input)) {
1319                    marker = this.timestampToMarker(input);
1320                }
1321            }
1322            else if (Array.isArray(input)) {
1323                marker = arrayToUtcDate(input);
1324            }
1325            if (marker === null || !isValidDate(marker)) {
1326                return null;
1327            }
1328            return { marker, isTimeUnspecified: false, forcedTzo: null };
1329        }
1330        parse(s) {
1331            let parts = parse(s);
1332            if (parts === null) {
1333                return null;
1334            }
1335            let { marker } = parts;
1336            let forcedTzo = null;
1337            if (parts.timeZoneOffset !== null) {
1338                if (this.canComputeOffset) {
1339                    marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000);
1340                }
1341                else {
1342                    forcedTzo = parts.timeZoneOffset;
1343                }
1344            }
1345            return { marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo };
1346        }
1347        // Accessors
1348        getYear(marker) {
1349            return this.calendarSystem.getMarkerYear(marker);
1350        }
1351        getMonth(marker) {
1352            return this.calendarSystem.getMarkerMonth(marker);
1353        }
1354        // Adding / Subtracting
1355        add(marker, dur) {
1356            let a = this.calendarSystem.markerToArray(marker);
1357            a[0] += dur.years;
1358            a[1] += dur.months;
1359            a[2] += dur.days;
1360            a[6] += dur.milliseconds;
1361            return this.calendarSystem.arrayToMarker(a);
1362        }
1363        subtract(marker, dur) {
1364            let a = this.calendarSystem.markerToArray(marker);
1365            a[0] -= dur.years;
1366            a[1] -= dur.months;
1367            a[2] -= dur.days;
1368            a[6] -= dur.milliseconds;
1369            return this.calendarSystem.arrayToMarker(a);
1370        }
1371        addYears(marker, n) {
1372            let a = this.calendarSystem.markerToArray(marker);
1373            a[0] += n;
1374            return this.calendarSystem.arrayToMarker(a);
1375        }
1376        addMonths(marker, n) {
1377            let a = this.calendarSystem.markerToArray(marker);
1378            a[1] += n;
1379            return this.calendarSystem.arrayToMarker(a);
1380        }
1381        // Diffing Whole Units
1382        diffWholeYears(m0, m1) {
1383            let { calendarSystem } = this;
1384            if (timeAsMs(m0) === timeAsMs(m1) &&
1385                calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) &&
1386                calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) {
1387                return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0);
1388            }
1389            return null;
1390        }
1391        diffWholeMonths(m0, m1) {
1392            let { calendarSystem } = this;
1393            if (timeAsMs(m0) === timeAsMs(m1) &&
1394                calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) {
1395                return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) +
1396                    (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12;
1397            }
1398            return null;
1399        }
1400        // Range / Duration
1401        greatestWholeUnit(m0, m1) {
1402            let n = this.diffWholeYears(m0, m1);
1403            if (n !== null) {
1404                return { unit: 'year', value: n };
1405            }
1406            n = this.diffWholeMonths(m0, m1);
1407            if (n !== null) {
1408                return { unit: 'month', value: n };
1409            }
1410            n = diffWholeWeeks(m0, m1);
1411            if (n !== null) {
1412                return { unit: 'week', value: n };
1413            }
1414            n = diffWholeDays(m0, m1);
1415            if (n !== null) {
1416                return { unit: 'day', value: n };
1417            }
1418            n = diffHours(m0, m1);
1419            if (isInt(n)) {
1420                return { unit: 'hour', value: n };
1421            }
1422            n = diffMinutes(m0, m1);
1423            if (isInt(n)) {
1424                return { unit: 'minute', value: n };
1425            }
1426            n = diffSeconds(m0, m1);
1427            if (isInt(n)) {
1428                return { unit: 'second', value: n };
1429            }
1430            return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() };
1431        }
1432        countDurationsBetween(m0, m1, d) {
1433            // TODO: can use greatestWholeUnit
1434            let diff;
1435            if (d.years) {
1436                diff = this.diffWholeYears(m0, m1);
1437                if (diff !== null) {
1438                    return diff / asRoughYears(d);
1439                }
1440            }
1441            if (d.months) {
1442                diff = this.diffWholeMonths(m0, m1);
1443                if (diff !== null) {
1444                    return diff / asRoughMonths(d);
1445                }
1446            }
1447            if (d.days) {
1448                diff = diffWholeDays(m0, m1);
1449                if (diff !== null) {
1450                    return diff / asRoughDays(d);
1451                }
1452            }
1453            return (m1.valueOf() - m0.valueOf()) / asRoughMs(d);
1454        }
1455        // Start-Of
1456        // these DON'T return zoned-dates. only UTC start-of dates
1457        startOf(m, unit) {
1458            if (unit === 'year') {
1459                return this.startOfYear(m);
1460            }
1461            if (unit === 'month') {
1462                return this.startOfMonth(m);
1463            }
1464            if (unit === 'week') {
1465                return this.startOfWeek(m);
1466            }
1467            if (unit === 'day') {
1468                return startOfDay(m);
1469            }
1470            if (unit === 'hour') {
1471                return startOfHour(m);
1472            }
1473            if (unit === 'minute') {
1474                return startOfMinute(m);
1475            }
1476            if (unit === 'second') {
1477                return startOfSecond(m);
1478            }
1479            return null;
1480        }
1481        startOfYear(m) {
1482            return this.calendarSystem.arrayToMarker([
1483                this.calendarSystem.getMarkerYear(m),
1484            ]);
1485        }
1486        startOfMonth(m) {
1487            return this.calendarSystem.arrayToMarker([
1488                this.calendarSystem.getMarkerYear(m),
1489                this.calendarSystem.getMarkerMonth(m),
1490            ]);
1491        }
1492        startOfWeek(m) {
1493            return this.calendarSystem.arrayToMarker([
1494                this.calendarSystem.getMarkerYear(m),
1495                this.calendarSystem.getMarkerMonth(m),
1496                m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7),
1497            ]);
1498        }
1499        // Week Number
1500        computeWeekNumber(marker) {
1501            if (this.weekNumberFunc) {
1502                return this.weekNumberFunc(this.toDate(marker));
1503            }
1504            return weekOfYear(marker, this.weekDow, this.weekDoy);
1505        }
1506        // TODO: choke on timeZoneName: long
1507        format(marker, formatter, dateOptions = {}) {
1508            return formatter.format({
1509                marker,
1510                timeZoneOffset: dateOptions.forcedTzo != null ?
1511                    dateOptions.forcedTzo :
1512                    this.offsetForMarker(marker),
1513            }, this);
1514        }
1515        formatRange(start, end, formatter, dateOptions = {}) {
1516            if (dateOptions.isEndExclusive) {
1517                end = addMs(end, -1);
1518            }
1519            return formatter.formatRange({
1520                marker: start,
1521                timeZoneOffset: dateOptions.forcedStartTzo != null ?
1522                    dateOptions.forcedStartTzo :
1523                    this.offsetForMarker(start),
1524            }, {
1525                marker: end,
1526                timeZoneOffset: dateOptions.forcedEndTzo != null ?
1527                    dateOptions.forcedEndTzo :
1528                    this.offsetForMarker(end),
1529            }, this, dateOptions.defaultSeparator);
1530        }
1531        /*
1532        DUMB: the omitTime arg is dumb. if we omit the time, we want to omit the timezone offset. and if we do that,
1533        might as well use buildIsoString or some other util directly
1534        */
1535        formatIso(marker, extraOptions = {}) {
1536            let timeZoneOffset = null;
1537            if (!extraOptions.omitTimeZoneOffset) {
1538                if (extraOptions.forcedTzo != null) {
1539                    timeZoneOffset = extraOptions.forcedTzo;
1540                }
1541                else {
1542                    timeZoneOffset = this.offsetForMarker(marker);
1543                }
1544            }
1545            return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime);
1546        }
1547        // TimeZone
1548        timestampToMarker(ms) {
1549            if (this.timeZone === 'local') {
1550                return arrayToUtcDate(dateToLocalArray(new Date(ms)));
1551            }
1552            if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) {
1553                return new Date(ms);
1554            }
1555            return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms));
1556        }
1557        offsetForMarker(m) {
1558            if (this.timeZone === 'local') {
1559                return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset
1560            }
1561            if (this.timeZone === 'UTC') {
1562                return 0;
1563            }
1564            if (this.namedTimeZoneImpl) {
1565                return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m));
1566            }
1567            return null;
1568        }
1569        // Conversion
1570        toDate(m, forcedTzo) {
1571            if (this.timeZone === 'local') {
1572                return arrayToLocalDate(dateToUtcArray(m));
1573            }
1574            if (this.timeZone === 'UTC') {
1575                return new Date(m.valueOf()); // make sure it's a copy
1576            }
1577            if (!this.namedTimeZoneImpl) {
1578                return new Date(m.valueOf() - (forcedTzo || 0));
1579            }
1580            return new Date(m.valueOf() -
1581                this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60);
1582        }
1583    }
1584
1585    class Theme {
1586        constructor(calendarOptions) {
1587            if (this.iconOverrideOption) {
1588                this.setIconOverride(calendarOptions[this.iconOverrideOption]);
1589            }
1590        }
1591        setIconOverride(iconOverrideHash) {
1592            let iconClassesCopy;
1593            let buttonName;
1594            if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object
1595                iconClassesCopy = Object.assign({}, this.iconClasses);
1596                for (buttonName in iconOverrideHash) {
1597                    iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]);
1598                }
1599                this.iconClasses = iconClassesCopy;
1600            }
1601            else if (iconOverrideHash === false) {
1602                this.iconClasses = {};
1603            }
1604        }
1605        applyIconOverridePrefix(className) {
1606            let prefix = this.iconOverridePrefix;
1607            if (prefix && className.indexOf(prefix) !== 0) { // if not already present
1608                className = prefix + className;
1609            }
1610            return className;
1611        }
1612        getClass(key) {
1613            return this.classes[key] || '';
1614        }
1615        getIconClass(buttonName, isRtl) {
1616            let className;
1617            if (isRtl && this.rtlIconClasses) {
1618                className = this.rtlIconClasses[buttonName] || this.iconClasses[buttonName];
1619            }
1620            else {
1621                className = this.iconClasses[buttonName];
1622            }
1623            if (className) {
1624                return `${this.baseIconClass} ${className}`;
1625            }
1626            return '';
1627        }
1628        getCustomButtonIconClass(customButtonProps) {
1629            let className;
1630            if (this.iconOverrideCustomButtonOption) {
1631                className = customButtonProps[this.iconOverrideCustomButtonOption];
1632                if (className) {
1633                    return `${this.baseIconClass} ${this.applyIconOverridePrefix(className)}`;
1634                }
1635            }
1636            return '';
1637        }
1638    }
1639    Theme.prototype.classes = {};
1640    Theme.prototype.iconClasses = {};
1641    Theme.prototype.baseIconClass = '';
1642    Theme.prototype.iconOverridePrefix = '';
1643
1644    const EXTENDED_SETTINGS_AND_SEVERITIES = {
1645        week: 3,
1646        separator: 0,
1647        omitZeroMinute: 0,
1648        meridiem: 0,
1649        omitCommas: 0,
1650    };
1651    const STANDARD_DATE_PROP_SEVERITIES = {
1652        timeZoneName: 7,
1653        era: 6,
1654        year: 5,
1655        month: 4,
1656        day: 2,
1657        weekday: 2,
1658        hour: 1,
1659        minute: 1,
1660        second: 1,
1661    };
1662    const MERIDIEM_RE = /\s*([ap])\.?m\.?/i; // eats up leading spaces too
1663    const COMMA_RE = /,/g; // we need re for globalness
1664    const MULTI_SPACE_RE = /\s+/g;
1665    const LTR_RE = /\u200e/g; // control character
1666    const UTC_RE = /UTC|GMT/;
1667    class NativeFormatter {
1668        constructor(formatSettings) {
1669            let standardDateProps = {};
1670            let extendedSettings = {};
1671            let severity = 0;
1672            for (let name in formatSettings) {
1673                if (name in EXTENDED_SETTINGS_AND_SEVERITIES) {
1674                    extendedSettings[name] = formatSettings[name];
1675                    severity = Math.max(EXTENDED_SETTINGS_AND_SEVERITIES[name], severity);
1676                }
1677                else {
1678                    standardDateProps[name] = formatSettings[name];
1679                    if (name in STANDARD_DATE_PROP_SEVERITIES) { // TODO: what about hour12? no severity
1680                        severity = Math.max(STANDARD_DATE_PROP_SEVERITIES[name], severity);
1681                    }
1682                }
1683            }
1684            this.standardDateProps = standardDateProps;
1685            this.extendedSettings = extendedSettings;
1686            this.severity = severity;
1687            this.buildFormattingFunc = memoize(buildFormattingFunc);
1688        }
1689        format(date, context) {
1690            return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date);
1691        }
1692        formatRange(start, end, context, betterDefaultSeparator) {
1693            let { standardDateProps, extendedSettings } = this;
1694            let diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem);
1695            if (!diffSeverity) {
1696                return this.format(start, context);
1697            }
1698            let biggestUnitForPartial = diffSeverity;
1699            if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time
1700                (standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') &&
1701                (standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') &&
1702                (standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) {
1703                biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time
1704            }
1705            let full0 = this.format(start, context);
1706            let full1 = this.format(end, context);
1707            if (full0 === full1) {
1708                return full0;
1709            }
1710            let partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForPartial);
1711            let partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context);
1712            let partial0 = partialFormattingFunc(start);
1713            let partial1 = partialFormattingFunc(end);
1714            let insertion = findCommonInsertion(full0, partial0, full1, partial1);
1715            let separator = extendedSettings.separator || betterDefaultSeparator || context.defaultSeparator || '';
1716            if (insertion) {
1717                return insertion.before + partial0 + separator + partial1 + insertion.after;
1718            }
1719            return full0 + separator + full1;
1720        }
1721        getLargestUnit() {
1722            switch (this.severity) {
1723                case 7:
1724                case 6:
1725                case 5:
1726                    return 'year';
1727                case 4:
1728                    return 'month';
1729                case 3:
1730                    return 'week';
1731                case 2:
1732                    return 'day';
1733                default:
1734                    return 'time'; // really?
1735            }
1736        }
1737    }
1738    function buildFormattingFunc(standardDateProps, extendedSettings, context) {
1739        let standardDatePropCnt = Object.keys(standardDateProps).length;
1740        if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') {
1741            return (date) => (formatTimeZoneOffset(date.timeZoneOffset));
1742        }
1743        if (standardDatePropCnt === 0 && extendedSettings.week) {
1744            return (date) => (formatWeekNumber(context.computeWeekNumber(date.marker), context.weekText, context.weekTextLong, context.locale, extendedSettings.week));
1745        }
1746        return buildNativeFormattingFunc(standardDateProps, extendedSettings, context);
1747    }
1748    function buildNativeFormattingFunc(standardDateProps, extendedSettings, context) {
1749        standardDateProps = Object.assign({}, standardDateProps); // copy
1750        extendedSettings = Object.assign({}, extendedSettings); // copy
1751        sanitizeSettings(standardDateProps, extendedSettings);
1752        standardDateProps.timeZone = 'UTC'; // we leverage the only guaranteed timeZone for our UTC markers
1753        let normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps);
1754        let zeroFormat; // needed?
1755        if (extendedSettings.omitZeroMinute) {
1756            let zeroProps = Object.assign({}, standardDateProps);
1757            delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings
1758            zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps);
1759        }
1760        return (date) => {
1761            let { marker } = date;
1762            let format;
1763            if (zeroFormat && !marker.getUTCMinutes()) {
1764                format = zeroFormat;
1765            }
1766            else {
1767                format = normalFormat;
1768            }
1769            let s = format.format(marker);
1770            return postProcess(s, date, standardDateProps, extendedSettings, context);
1771        };
1772    }
1773    function sanitizeSettings(standardDateProps, extendedSettings) {
1774        // deal with a browser inconsistency where formatting the timezone
1775        // requires that the hour/minute be present.
1776        if (standardDateProps.timeZoneName) {
1777            if (!standardDateProps.hour) {
1778                standardDateProps.hour = '2-digit';
1779            }
1780            if (!standardDateProps.minute) {
1781                standardDateProps.minute = '2-digit';
1782            }
1783        }
1784        // only support short timezone names
1785        if (standardDateProps.timeZoneName === 'long') {
1786            standardDateProps.timeZoneName = 'short';
1787        }
1788        // if requesting to display seconds, MUST display minutes
1789        if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) {
1790            delete extendedSettings.omitZeroMinute;
1791        }
1792    }
1793    function postProcess(s, date, standardDateProps, extendedSettings, context) {
1794        s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes
1795        if (standardDateProps.timeZoneName === 'short') {
1796            s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ?
1797                'UTC' : // important to normalize for IE, which does "GMT"
1798                formatTimeZoneOffset(date.timeZoneOffset));
1799        }
1800        if (extendedSettings.omitCommas) {
1801            s = s.replace(COMMA_RE, '').trim();
1802        }
1803        if (extendedSettings.omitZeroMinute) {
1804            s = s.replace(':00', ''); // zeroFormat doesn't always achieve this
1805        }
1806        // ^ do anything that might create adjacent spaces before this point,
1807        // because MERIDIEM_RE likes to eat up loading spaces
1808        if (extendedSettings.meridiem === false) {
1809            s = s.replace(MERIDIEM_RE, '').trim();
1810        }
1811        else if (extendedSettings.meridiem === 'narrow') { // a/p
1812            s = s.replace(MERIDIEM_RE, (m0, m1) => m1.toLocaleLowerCase());
1813        }
1814        else if (extendedSettings.meridiem === 'short') { // am/pm
1815            s = s.replace(MERIDIEM_RE, (m0, m1) => `${m1.toLocaleLowerCase()}m`);
1816        }
1817        else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase
1818            s = s.replace(MERIDIEM_RE, (m0) => m0.toLocaleLowerCase());
1819        }
1820        s = s.replace(MULTI_SPACE_RE, ' ');
1821        s = s.trim();
1822        return s;
1823    }
1824    function injectTzoStr(s, tzoStr) {
1825        let replaced = false;
1826        s = s.replace(UTC_RE, () => {
1827            replaced = true;
1828            return tzoStr;
1829        });
1830        // IE11 doesn't include UTC/GMT in the original string, so append to end
1831        if (!replaced) {
1832            s += ` ${tzoStr}`;
1833        }
1834        return s;
1835    }
1836    function formatWeekNumber(num, weekText, weekTextLong, locale, display) {
1837        let parts = [];
1838        if (display === 'long') {
1839            parts.push(weekTextLong);
1840        }
1841        else if (display === 'short' || display === 'narrow') {
1842            parts.push(weekText);
1843        }
1844        if (display === 'long' || display === 'short') {
1845            parts.push(' ');
1846        }
1847        parts.push(locale.simpleNumberFormat.format(num));
1848        if (locale.options.direction === 'rtl') { // TODO: use control characters instead?
1849            parts.reverse();
1850        }
1851        return parts.join('');
1852    }
1853    // Range Formatting Utils
1854    // 0 = exactly the same
1855    // 1 = different by time
1856    // and bigger
1857    function computeMarkerDiffSeverity(d0, d1, ca) {
1858        if (ca.getMarkerYear(d0) !== ca.getMarkerYear(d1)) {
1859            return 5;
1860        }
1861        if (ca.getMarkerMonth(d0) !== ca.getMarkerMonth(d1)) {
1862            return 4;
1863        }
1864        if (ca.getMarkerDay(d0) !== ca.getMarkerDay(d1)) {
1865            return 2;
1866        }
1867        if (timeAsMs(d0) !== timeAsMs(d1)) {
1868            return 1;
1869        }
1870        return 0;
1871    }
1872    function computePartialFormattingOptions(options, biggestUnit) {
1873        let partialOptions = {};
1874        for (let name in options) {
1875            if (!(name in STANDARD_DATE_PROP_SEVERITIES) || // not a date part prop (like timeZone)
1876                STANDARD_DATE_PROP_SEVERITIES[name] <= biggestUnit) {
1877                partialOptions[name] = options[name];
1878            }
1879        }
1880        return partialOptions;
1881    }
1882    function findCommonInsertion(full0, partial0, full1, partial1) {
1883        let i0 = 0;
1884        while (i0 < full0.length) {
1885            let found0 = full0.indexOf(partial0, i0);
1886            if (found0 === -1) {
1887                break;
1888            }
1889            let before0 = full0.substr(0, found0);
1890            i0 = found0 + partial0.length;
1891            let after0 = full0.substr(i0);
1892            let i1 = 0;
1893            while (i1 < full1.length) {
1894                let found1 = full1.indexOf(partial1, i1);
1895                if (found1 === -1) {
1896                    break;
1897                }
1898                let before1 = full1.substr(0, found1);
1899                i1 = found1 + partial1.length;
1900                let after1 = full1.substr(i1);
1901                if (before0 === before1 && after0 === after1) {
1902                    return {
1903                        before: before0,
1904                        after: after0,
1905                    };
1906                }
1907            }
1908        }
1909        return null;
1910    }
1911
1912    function expandZonedMarker(dateInfo, calendarSystem) {
1913        let a = calendarSystem.markerToArray(dateInfo.marker);
1914        return {
1915            marker: dateInfo.marker,
1916            timeZoneOffset: dateInfo.timeZoneOffset,
1917            array: a,
1918            year: a[0],
1919            month: a[1],
1920            day: a[2],
1921            hour: a[3],
1922            minute: a[4],
1923            second: a[5],
1924            millisecond: a[6],
1925        };
1926    }
1927
1928    function createVerboseFormattingArg(start, end, context, betterDefaultSeparator) {
1929        let startInfo = expandZonedMarker(start, context.calendarSystem);
1930        let endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null;
1931        return {
1932            date: startInfo,
1933            start: startInfo,
1934            end: endInfo,
1935            timeZone: context.timeZone,
1936            localeCodes: context.locale.codes,
1937            defaultSeparator: betterDefaultSeparator || context.defaultSeparator,
1938        };
1939    }
1940
1941    /*
1942    TODO: fix the terminology of "formatter" vs "formatting func"
1943    */
1944    /*
1945    At the time of instantiation, this object does not know which cmd-formatting system it will use.
1946    It receives this at the time of formatting, as a setting.
1947    */
1948    class CmdFormatter {
1949        constructor(cmdStr) {
1950            this.cmdStr = cmdStr;
1951        }
1952        format(date, context, betterDefaultSeparator) {
1953            return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, betterDefaultSeparator));
1954        }
1955        formatRange(start, end, context, betterDefaultSeparator) {
1956            return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, betterDefaultSeparator));
1957        }
1958    }
1959
1960    class FuncFormatter {
1961        constructor(func) {
1962            this.func = func;
1963        }
1964        format(date, context, betterDefaultSeparator) {
1965            return this.func(createVerboseFormattingArg(date, null, context, betterDefaultSeparator));
1966        }
1967        formatRange(start, end, context, betterDefaultSeparator) {
1968            return this.func(createVerboseFormattingArg(start, end, context, betterDefaultSeparator));
1969        }
1970    }
1971
1972    function createFormatter(input) {
1973        if (typeof input === 'object' && input) { // non-null object
1974            return new NativeFormatter(input);
1975        }
1976        if (typeof input === 'string') {
1977            return new CmdFormatter(input);
1978        }
1979        if (typeof input === 'function') {
1980            return new FuncFormatter(input);
1981        }
1982        return null;
1983    }
1984
1985    // base options
1986    // ------------
1987    const BASE_OPTION_REFINERS = {
1988        navLinkDayClick: identity,
1989        navLinkWeekClick: identity,
1990        duration: createDuration,
1991        bootstrapFontAwesome: identity,
1992        buttonIcons: identity,
1993        customButtons: identity,
1994        defaultAllDayEventDuration: createDuration,
1995        defaultTimedEventDuration: createDuration,
1996        nextDayThreshold: createDuration,
1997        scrollTime: createDuration,
1998        scrollTimeReset: Boolean,
1999        slotMinTime: createDuration,
2000        slotMaxTime: createDuration,
2001        dayPopoverFormat: createFormatter,
2002        slotDuration: createDuration,
2003        snapDuration: createDuration,
2004        headerToolbar: identity,
2005        footerToolbar: identity,
2006        defaultRangeSeparator: String,
2007        titleRangeSeparator: String,
2008        forceEventDuration: Boolean,
2009        dayHeaders: Boolean,
2010        dayHeaderFormat: createFormatter,
2011        dayHeaderClassNames: identity,
2012        dayHeaderContent: identity,
2013        dayHeaderDidMount: identity,
2014        dayHeaderWillUnmount: identity,
2015        dayCellClassNames: identity,
2016        dayCellContent: identity,
2017        dayCellDidMount: identity,
2018        dayCellWillUnmount: identity,
2019        initialView: String,
2020        aspectRatio: Number,
2021        weekends: Boolean,
2022        weekNumberCalculation: identity,
2023        weekNumbers: Boolean,
2024        weekNumberClassNames: identity,
2025        weekNumberContent: identity,
2026        weekNumberDidMount: identity,
2027        weekNumberWillUnmount: identity,
2028        editable: Boolean,
2029        viewClassNames: identity,
2030        viewDidMount: identity,
2031        viewWillUnmount: identity,
2032        nowIndicator: Boolean,
2033        nowIndicatorClassNames: identity,
2034        nowIndicatorContent: identity,
2035        nowIndicatorDidMount: identity,
2036        nowIndicatorWillUnmount: identity,
2037        showNonCurrentDates: Boolean,
2038        lazyFetching: Boolean,
2039        startParam: String,
2040        endParam: String,
2041        timeZoneParam: String,
2042        timeZone: String,
2043        locales: identity,
2044        locale: identity,
2045        themeSystem: String,
2046        dragRevertDuration: Number,
2047        dragScroll: Boolean,
2048        allDayMaintainDuration: Boolean,
2049        unselectAuto: Boolean,
2050        dropAccept: identity,
2051        eventOrder: parseFieldSpecs,
2052        eventOrderStrict: Boolean,
2053        handleWindowResize: Boolean,
2054        windowResizeDelay: Number,
2055        longPressDelay: Number,
2056        eventDragMinDistance: Number,
2057        expandRows: Boolean,
2058        height: identity,
2059        contentHeight: identity,
2060        direction: String,
2061        weekNumberFormat: createFormatter,
2062        eventResizableFromStart: Boolean,
2063        displayEventTime: Boolean,
2064        displayEventEnd: Boolean,
2065        weekText: String,
2066        weekTextLong: String,
2067        progressiveEventRendering: Boolean,
2068        businessHours: identity,
2069        initialDate: identity,
2070        now: identity,
2071        eventDataTransform: identity,
2072        stickyHeaderDates: identity,
2073        stickyFooterScrollbar: identity,
2074        viewHeight: identity,
2075        defaultAllDay: Boolean,
2076        eventSourceFailure: identity,
2077        eventSourceSuccess: identity,
2078        eventDisplay: String,
2079        eventStartEditable: Boolean,
2080        eventDurationEditable: Boolean,
2081        eventOverlap: identity,
2082        eventConstraint: identity,
2083        eventAllow: identity,
2084        eventBackgroundColor: String,
2085        eventBorderColor: String,
2086        eventTextColor: String,
2087        eventColor: String,
2088        eventClassNames: identity,
2089        eventContent: identity,
2090        eventDidMount: identity,
2091        eventWillUnmount: identity,
2092        selectConstraint: identity,
2093        selectOverlap: identity,
2094        selectAllow: identity,
2095        droppable: Boolean,
2096        unselectCancel: String,
2097        slotLabelFormat: identity,
2098        slotLaneClassNames: identity,
2099        slotLaneContent: identity,
2100        slotLaneDidMount: identity,
2101        slotLaneWillUnmount: identity,
2102        slotLabelClassNames: identity,
2103        slotLabelContent: identity,
2104        slotLabelDidMount: identity,
2105        slotLabelWillUnmount: identity,
2106        dayMaxEvents: identity,
2107        dayMaxEventRows: identity,
2108        dayMinWidth: Number,
2109        slotLabelInterval: createDuration,
2110        allDayText: String,
2111        allDayClassNames: identity,
2112        allDayContent: identity,
2113        allDayDidMount: identity,
2114        allDayWillUnmount: identity,
2115        slotMinWidth: Number,
2116        navLinks: Boolean,
2117        eventTimeFormat: createFormatter,
2118        rerenderDelay: Number,
2119        moreLinkText: identity,
2120        moreLinkHint: identity,
2121        selectMinDistance: Number,
2122        selectable: Boolean,
2123        selectLongPressDelay: Number,
2124        eventLongPressDelay: Number,
2125        selectMirror: Boolean,
2126        eventMaxStack: Number,
2127        eventMinHeight: Number,
2128        eventMinWidth: Number,
2129        eventShortHeight: Number,
2130        slotEventOverlap: Boolean,
2131        plugins: identity,
2132        firstDay: Number,
2133        dayCount: Number,
2134        dateAlignment: String,
2135        dateIncrement: createDuration,
2136        hiddenDays: identity,
2137        monthMode: Boolean,
2138        fixedWeekCount: Boolean,
2139        validRange: identity,
2140        visibleRange: identity,
2141        titleFormat: identity,
2142        eventInteractive: Boolean,
2143        // only used by list-view, but languages define the value, so we need it in base options
2144        noEventsText: String,
2145        viewHint: identity,
2146        navLinkHint: identity,
2147        closeHint: String,
2148        timeHint: String,
2149        eventHint: String,
2150        moreLinkClick: identity,
2151        moreLinkClassNames: identity,
2152        moreLinkContent: identity,
2153        moreLinkDidMount: identity,
2154        moreLinkWillUnmount: identity,
2155        // for connectors
2156        // (can't be part of plugin system b/c must be provided at runtime)
2157        handleCustomRendering: identity,
2158        customRenderingMetaMap: identity,
2159        customRenderingReplacesEl: Boolean,
2160    };
2161    // do NOT give a type here. need `typeof BASE_OPTION_DEFAULTS` to give real results.
2162    // raw values.
2163    const BASE_OPTION_DEFAULTS = {
2164        eventDisplay: 'auto',
2165        defaultRangeSeparator: ' - ',
2166        titleRangeSeparator: ' \u2013 ',
2167        defaultTimedEventDuration: '01:00:00',
2168        defaultAllDayEventDuration: { day: 1 },
2169        forceEventDuration: false,
2170        nextDayThreshold: '00:00:00',
2171        dayHeaders: true,
2172        initialView: '',
2173        aspectRatio: 1.35,
2174        headerToolbar: {
2175            start: 'title',
2176            center: '',
2177            end: 'today prev,next',
2178        },
2179        weekends: true,
2180        weekNumbers: false,
2181        weekNumberCalculation: 'local',
2182        editable: false,
2183        nowIndicator: false,
2184        scrollTime: '06:00:00',
2185        scrollTimeReset: true,
2186        slotMinTime: '00:00:00',
2187        slotMaxTime: '24:00:00',
2188        showNonCurrentDates: true,
2189        lazyFetching: true,
2190        startParam: 'start',
2191        endParam: 'end',
2192        timeZoneParam: 'timeZone',
2193        timeZone: 'local',
2194        locales: [],
2195        locale: '',
2196        themeSystem: 'standard',
2197        dragRevertDuration: 500,
2198        dragScroll: true,
2199        allDayMaintainDuration: false,
2200        unselectAuto: true,
2201        dropAccept: '*',
2202        eventOrder: 'start,-duration,allDay,title',
2203        dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' },
2204        handleWindowResize: true,
2205        windowResizeDelay: 100,
2206        longPressDelay: 1000,
2207        eventDragMinDistance: 5,
2208        expandRows: false,
2209        navLinks: false,
2210        selectable: false,
2211        eventMinHeight: 15,
2212        eventMinWidth: 30,
2213        eventShortHeight: 30,
2214    };
2215    // calendar listeners
2216    // ------------------
2217    const CALENDAR_LISTENER_REFINERS = {
2218        datesSet: identity,
2219        eventsSet: identity,
2220        eventAdd: identity,
2221        eventChange: identity,
2222        eventRemove: identity,
2223        windowResize: identity,
2224        eventClick: identity,
2225        eventMouseEnter: identity,
2226        eventMouseLeave: identity,
2227        select: identity,
2228        unselect: identity,
2229        loading: identity,
2230        // internal
2231        _unmount: identity,
2232        _beforeprint: identity,
2233        _afterprint: identity,
2234        _noEventDrop: identity,
2235        _noEventResize: identity,
2236        _resize: identity,
2237        _scrollRequest: identity,
2238    };
2239    // calendar-specific options
2240    // -------------------------
2241    const CALENDAR_OPTION_REFINERS = {
2242        buttonText: identity,
2243        buttonHints: identity,
2244        views: identity,
2245        plugins: identity,
2246        initialEvents: identity,
vendor: 6,050 bytes, lines 2247-2419
2247        events: identity,
2248        eventSources: identity,
2249    };
2250    const COMPLEX_OPTION_COMPARATORS = {
2251        headerToolbar: isMaybeObjectsEqual,
2252        footerToolbar: isMaybeObjectsEqual,
2253        buttonText: isMaybeObjectsEqual,
2254        buttonHints: isMaybeObjectsEqual,
2255        buttonIcons: isMaybeObjectsEqual,
2256        dateIncrement: isMaybeObjectsEqual,
2257    };
2258    function isMaybeObjectsEqual(a, b) {
2259        if (typeof a === 'object' && typeof b === 'object' && a && b) { // both non-null objects
2260            return isPropsEqual(a, b);
2261        }
2262        return a === b;
2263    }
2264    // view-specific options
2265    // ---------------------
2266    const VIEW_OPTION_REFINERS = {
2267        type: String,
2268        component: identity,
2269        buttonText: String,
2270        buttonTextKey: String,
2271        dateProfileGeneratorClass: identity,
2272        usesMinMaxTime: Boolean,
2273        classNames: identity,
2274        content: identity,
2275        didMount: identity,
2276        willUnmount: identity,
2277    };
2278    // util funcs
2279    // ----------------------------------------------------------------------------------------------------
2280    function mergeRawOptions(optionSets) {
2281        return mergeProps(optionSets, COMPLEX_OPTION_COMPARATORS);
2282    }
2283    function refineProps(input, refiners) {
2284        let refined = {};
2285        let extra = {};
2286        for (let propName in refiners) {
2287            if (propName in input) {
2288                refined[propName] = refiners[propName](input[propName]);
2289            }
2290        }
2291        for (let propName in input) {
2292            if (!(propName in refiners)) {
2293                extra[propName] = input[propName];
2294            }
2295        }
2296        return { refined, extra };
2297    }
2298    function identity(raw) {
2299        return raw;
2300    }
2301
2302    /*
2303    NOTE: this can be a public API, especially createElement for hooks.
2304    See examples/typescript-scheduler/src/index.ts
2305    */
2306    function flushSync(runBeforeFlush) {
2307        runBeforeFlush();
2308        let oldDebounceRendering = l$1.debounceRendering; // orig
2309        let callbackQ = [];
2310        function execCallbackSync(callback) {
2311            callbackQ.push(callback);
2312        }
2313        l$1.debounceRendering = execCallbackSync;
2314        P$1(h(FakeComponent, {}), document.createElement('div'));
2315        while (callbackQ.length) {
2316            callbackQ.shift()();
2317        }
2318        l$1.debounceRendering = oldDebounceRendering;
2319    }
2320    class FakeComponent extends d {
2321        render() { return h('div', {}); }
2322        componentDidMount() { this.setState({}); }
2323    }
2324    // TODO: use preact/compat instead?
2325    function createContext(defaultValue) {
2326        let ContextType = B$1(defaultValue);
2327        let origProvider = ContextType.Provider;
2328        ContextType.Provider = function () {
2329            let isNew = !this.getChildContext;
2330            let children = origProvider.apply(this, arguments); // eslint-disable-line prefer-rest-params
2331            if (isNew) {
2332                let subs = [];
2333                this.shouldComponentUpdate = (_props) => {
2334                    if (this.props.value !== _props.value) {
2335                        subs.forEach((c) => {
2336                            c.context = _props.value;
2337                            c.forceUpdate();
2338                        });
2339                    }
2340                };
2341                this.sub = (c) => {
2342                    subs.push(c);
2343                    let old = c.componentWillUnmount;
2344                    c.componentWillUnmount = () => {
2345                        subs.splice(subs.indexOf(c), 1);
2346                        old && old.call(c);
2347                    };
2348                };
2349            }
2350            return children;
2351        };
2352        return ContextType;
2353    }
2354
2355    class ScrollResponder {
2356        constructor(execFunc, emitter, scrollTime, scrollTimeReset) {
2357            this.execFunc = execFunc;
2358            this.emitter = emitter;
2359            this.scrollTime = scrollTime;
2360            this.scrollTimeReset = scrollTimeReset;
2361            this.handleScrollRequest = (request) => {
2362                this.queuedRequest = Object.assign({}, this.queuedRequest || {}, request);
2363                this.drain();
2364            };
2365            emitter.on('_scrollRequest', this.handleScrollRequest);
2366            this.fireInitialScroll();
2367        }
2368        detach() {
2369            this.emitter.off('_scrollRequest', this.handleScrollRequest);
2370        }
2371        update(isDatesNew) {
2372            if (isDatesNew && this.scrollTimeReset) {
2373                this.fireInitialScroll(); // will drain
2374            }
2375            else {
2376                this.drain();
2377            }
2378        }
2379        fireInitialScroll() {
2380            this.handleScrollRequest({
2381                time: this.scrollTime,
2382            });
2383        }
2384        drain() {
2385            if (this.queuedRequest && this.execFunc(this.queuedRequest)) {
2386                this.queuedRequest = null;
2387            }
2388        }
2389    }
2390
2391    const ViewContextType = createContext({}); // for Components
2392    function buildViewContext(viewSpec, viewApi, viewOptions, dateProfileGenerator, dateEnv, theme, pluginHooks, dispatch, getCurrentData, emitter, calendarApi, registerInteractiveComponent, unregisterInteractiveComponent) {
2393        return {
2394            dateEnv,
2395            options: viewOptions,
2396            pluginHooks,
2397            emitter,
2398            dispatch,
2399            getCurrentData,
2400            calendarApi,
2401            viewSpec,
2402            viewApi,
2403            dateProfileGenerator,
2404            theme,
2405            isRtl: viewOptions.direction === 'rtl',
2406            addResizeHandler(handler) {
2407                emitter.on('_resize', handler);
2408            },
2409            removeResizeHandler(handler) {
2410                emitter.off('_resize', handler);
2411            },
2412            createScrollResponder(execFunc) {
2413                return new ScrollResponder(execFunc, emitter, createDuration(viewOptions.scrollTime), viewOptions.scrollTimeReset);
2414            },
2415            registerInteractiveComponent,
2416            unregisterInteractiveComponent,
2417        };
2418    }
2419
2420    /* eslint max-classes-per-file: off */
2421    class PureComponent extends d {
2422        shouldComponentUpdate(nextProps, nextState) {
2423            if (this.debug) {
2424                // eslint-disable-next-line no-console
2425                console.log(getUnequalProps(nextProps, this.props), getUnequalProps(nextState, this.state));
2426            }
2427            return !compareObjs(this.props, nextProps, this.propEquality) ||
2428                !compareObjs(this.state, nextState, this.stateEquality);
2429        }
2430        // HACK for freakin' React StrictMode
2431        safeSetState(newState) {
2432            if (!compareObjs(this.state, Object.assign(Object.assign({}, this.state), newState), this.stateEquality)) {
2433                this.setState(newState);
2434            }
2435        }
2436    }
2437    PureComponent.addPropsEquality = addPropsEquality;
2438    PureComponent.addStateEquality = addStateEquality;
2439    PureComponent.contextType = ViewContextType;
2440    PureComponent.prototype.propEquality = {};
2441    PureComponent.prototype.stateEquality = {};
2442    class BaseComponent extends PureComponent {
2443    }
2444    BaseComponent.contextType = ViewContextType;
2445    function addPropsEquality(propEquality) {
2446        let hash = Object.create(this.prototype.propEquality);
2447        Object.assign(hash, propEquality);
2448        this.prototype.propEquality = hash;
2449    }
2450    function addStateEquality(stateEquality) {
2451        let hash = Object.create(this.prototype.stateEquality);
2452        Object.assign(hash, stateEquality);
2453        this.prototype.stateEquality = hash;
2454    }
2455    // use other one
2456    function setRef(ref, current) {
2457        if (typeof ref === 'function') {
2458            ref(current);
2459        }
2460        else if (ref) {
2461            // see https://github.com/facebook/react/issues/13029
2462            ref.current = current;
2463        }
2464    }
2465
2466    class ContentInjector extends BaseComponent {
2467        constructor() {
2468            super(...arguments);
2469            this.id = guid();
2470            this.currentDomNodes = [];
2471            this.queuedDomNodes = [];
2472            this.handleEl = (el) => {
2473                if (this.props.elRef) {
2474                    setRef(this.props.elRef, el);
2475                }
2476            };
2477        }
2478        render() {
2479            const { props, context } = this;
2480            const { options } = context;
2481            const { generator, renderProps } = props;
2482            const attrs = buildElAttrs(props);
2483            let innerContent;
2484            let queuedDomNodes = [];
2485            if (hasCustomRenderingHandler(props.generatorName, options)) {
2486                if (options.customRenderingReplacesEl) {
2487                    delete attrs.elRef; // because handleEl will be used
2488                }
2489            }
2490            else {
2491                const customContent = typeof generator === 'function' ?
2492                    generator(renderProps, h) :
2493                    generator;
2494                if (typeof customContent === 'string' ||
2495                    i$1(customContent) ||
2496                    Array.isArray(customContent)) {
2497                    innerContent = customContent;
2498                }
2499                else if (typeof customContent === 'object') {
2500                    if ('html' in customContent) {
2501                        attrs.dangerouslySetInnerHTML = { __html: customContent.html };
2502                    }
2503                    else if ('domNodes' in customContent) {
2504                        queuedDomNodes = Array.prototype.slice.call(customContent.domNodes);
2505                    }
2506                }
2507            }
2508            this.queuedDomNodes = queuedDomNodes;
2509            return h(props.elTag, attrs, innerContent);
2510        }
2511        componentDidMount() {
2512            this.applyQueueudDomNodes();
2513            this.triggerCustomRendering(true);
2514        }
2515        componentDidUpdate() {
2516            this.applyQueueudDomNodes();
2517            this.triggerCustomRendering(true);
2518        }
2519        componentWillUnmount() {
2520            this.triggerCustomRendering(false); // TODO: different API for removal?
2521        }
2522        triggerCustomRendering(isActive) {
2523            const { props, context } = this;
2524            const { handleCustomRendering, customRenderingMetaMap } = context.options;
2525            if (handleCustomRendering) {
2526                const customRenderingMeta = customRenderingMetaMap === null || customRenderingMetaMap === void 0 ? void 0 : customRenderingMetaMap[props.generatorName];
2527                if (customRenderingMeta) {
2528                    handleCustomRendering(Object.assign({ id: this.id, isActive, containerEl: this.base, reportNewContainerEl: this.handleEl, generatorMeta: customRenderingMeta }, props));
2529                }
2530            }
2531        }
2532        applyQueueudDomNodes() {
2533            const { queuedDomNodes, currentDomNodes } = this;
2534            const el = this.base;
2535            if (!isArraysEqual(queuedDomNodes, currentDomNodes)) {
vendor: 9,384 bytes, lines 2536-2751
2536                currentDomNodes.forEach(removeElement);
2537                for (let newNode of queuedDomNodes) {
2538                    el.appendChild(newNode);
2539                }
2540                this.currentDomNodes = queuedDomNodes;
2541            }
2542        }
2543    }
2544    ContentInjector.addPropsEquality({
2545        elClasses: isArraysEqual,
2546        elStyle: isPropsEqual,
2547        elAttrs: isPropsEqual,
2548        renderProps: isPropsEqual,
2549    });
2550    // Util
2551    function hasCustomRenderingHandler(generatorName, options) {
2552        var _a;
2553        return Boolean(options.handleCustomRendering &&
2554            generatorName &&
2555            ((_a = options.customRenderingMetaMap) === null || _a === void 0 ? void 0 : _a[generatorName]));
2556    }
2557    function buildElAttrs(props, extraClassNames) {
2558        const attrs = Object.assign(Object.assign({}, props.elAttrs), { ref: props.elRef });
2559        if (props.elClasses || extraClassNames) {
2560            attrs.className = (props.elClasses || [])
2561                .concat(extraClassNames || [])
2562                .concat(attrs.className || [])
2563                .filter(Boolean)
2564                .join(' ');
2565        }
2566        if (props.elStyle) {
2567            attrs.style = props.elStyle;
2568        }
2569        return attrs;
2570    }
2571
2572    const RenderId = createContext(0);
2573
2574    class ContentContainer extends d {
2575        constructor() {
2576            super(...arguments);
2577            this.InnerContent = InnerContentInjector.bind(undefined, this);
2578        }
2579        render() {
2580            const { props } = this;
2581            const generatedClassNames = generateClassNames(props.classNameGenerator, props.renderProps);
2582            if (props.children) {
2583                const elAttrs = buildElAttrs(props, generatedClassNames);
2584                const children = props.children(this.InnerContent, props.renderProps, elAttrs);
2585                if (props.elTag) {
2586                    return h(props.elTag, elAttrs, children);
2587                }
2588                else {
2589                    return children;
2590                }
2591            }
2592            else {
2593                return h((ContentInjector), Object.assign(Object.assign({}, props), { elTag: props.elTag || 'div', elClasses: (props.elClasses || []).concat(generatedClassNames), renderId: this.context }));
2594            }
2595        }
2596        componentDidMount() {
2597            var _a, _b;
2598            (_b = (_a = this.props).didMount) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.props.renderProps), { el: this.base }));
2599        }
2600        componentWillUnmount() {
2601            var _a, _b;
2602            (_b = (_a = this.props).willUnmount) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.props.renderProps), { el: this.base }));
2603        }
2604    }
2605    ContentContainer.contextType = RenderId;
2606    function InnerContentInjector(containerComponent, props) {
2607        const parentProps = containerComponent.props;
2608        return h((ContentInjector), Object.assign({ renderProps: parentProps.renderProps, generatorName: parentProps.generatorName, generator: parentProps.generator, renderId: containerComponent.context }, props));
2609    }
2610    // Utils
2611    function generateClassNames(classNameGenerator, renderProps) {
2612        const classNames = typeof classNameGenerator === 'function' ?
2613            classNameGenerator(renderProps) :
2614            classNameGenerator || [];
2615        return typeof classNames === 'string' ? [classNames] : classNames;
2616    }
2617
2618    class ViewContainer$1 extends BaseComponent {
2619        render() {
2620            let { props, context } = this;
2621            let { options } = context;
2622            let renderProps = { view: context.viewApi };
2623            return (h(ContentContainer, Object.assign({}, props, { elTag: props.elTag || 'div', elClasses: [
2624                    ...buildViewClassNames(props.viewSpec),
2625                    ...(props.elClasses || []),
2626                ], renderProps: renderProps, classNameGenerator: options.viewClassNames, generatorName: undefined, generator: undefined, didMount: options.viewDidMount, willUnmount: options.viewWillUnmount }), () => props.children));
2627        }
2628    }
2629    function buildViewClassNames(viewSpec) {
2630        return [
2631            `fc-${viewSpec.type}-view`,
2632            'fc-view',
2633        ];
2634    }
2635
2636    function parseRange(input, dateEnv) {
2637        let start = null;
2638        let end = null;
2639        if (input.start) {
2640            start = dateEnv.createMarker(input.start);
2641        }
2642        if (input.end) {
2643            end = dateEnv.createMarker(input.end);
2644        }
2645        if (!start && !end) {
2646            return null;
2647        }
2648        if (start && end && end < start) {
2649            return null;
2650        }
2651        return { start, end };
2652    }
2653    // SIDE-EFFECT: will mutate ranges.
2654    // Will return a new array result.
2655    function invertRanges(ranges, constraintRange) {
2656        let invertedRanges = [];
2657        let { start } = constraintRange; // the end of the previous range. the start of the new range
2658        let i;
2659        let dateRange;
2660        // ranges need to be in order. required for our date-walking algorithm
2661        ranges.sort(compareRanges);
2662        for (i = 0; i < ranges.length; i += 1) {
2663            dateRange = ranges[i];
2664            // add the span of time before the event (if there is any)
2665            if (dateRange.start > start) { // compare millisecond time (skip any ambig logic)
2666                invertedRanges.push({ start, end: dateRange.start });
2667            }
2668            if (dateRange.end > start) {
2669                start = dateRange.end;
2670            }
2671        }
2672        // add the span of time after the last event (if there is any)
2673        if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic)
2674            invertedRanges.push({ start, end: constraintRange.end });
2675        }
2676        return invertedRanges;
2677    }
2678    function compareRanges(range0, range1) {
2679        return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first
2680    }
2681    function intersectRanges(range0, range1) {
2682        let { start, end } = range0;
2683        let newRange = null;
2684        if (range1.start !== null) {
2685            if (start === null) {
2686                start = range1.start;
2687            }
2688            else {
2689                start = new Date(Math.max(start.valueOf(), range1.start.valueOf()));
2690            }
2691        }
2692        if (range1.end != null) {
2693            if (end === null) {
2694                end = range1.end;
2695            }
2696            else {
2697                end = new Date(Math.min(end.valueOf(), range1.end.valueOf()));
2698            }
2699        }
2700        if (start === null || end === null || start < end) {
2701            newRange = { start, end };
2702        }
2703        return newRange;
2704    }
2705    function rangesEqual(range0, range1) {
2706        return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) &&
2707            (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf());
2708    }
2709    function rangesIntersect(range0, range1) {
2710        return (range0.end === null || range1.start === null || range0.end > range1.start) &&
2711            (range0.start === null || range1.end === null || range0.start < range1.end);
2712    }
2713    function rangeContainsRange(outerRange, innerRange) {
2714        return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) &&
2715            (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end));
2716    }
2717    function rangeContainsMarker(range, date) {
2718        return (range.start === null || date >= range.start) &&
2719            (range.end === null || date < range.end);
2720    }
2721    // If the given date is not within the given range, move it inside.
2722    // (If it's past the end, make it one millisecond before the end).
2723    function constrainMarkerToRange(date, range) {
2724        if (range.start != null && date < range.start) {
2725            return range.start;
2726        }
2727        if (range.end != null && date >= range.end) {
2728            return new Date(range.end.valueOf() - 1);
2729        }
2730        return date;
2731    }
2732
2733    /* Date stuff that doesn't belong in datelib core
2734    ----------------------------------------------------------------------------------------------------------------------*/
2735    // given a timed range, computes an all-day range that has the same exact duration,
2736    // but whose start time is aligned with the start of the day.
2737    function computeAlignedDayRange(timedRange) {
2738        let dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1;
2739        let start = startOfDay(timedRange.start);
2740        let end = addDays(start, dayCnt);
2741        return { start, end };
2742    }
2743    // given a timed range, computes an all-day range based on how for the end date bleeds into the next day
2744    // TODO: give nextDayThreshold a default arg
2745    function computeVisibleDayRange(timedRange, nextDayThreshold = createDuration(0)) {
2746        let startDay = null;
2747        let endDay = null;
2748        if (timedRange.end) {
2749            endDay = startOfDay(timedRange.end);
2750            let endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay`
2751            // If the end time is actually inclusively part of the next day and is equal to or
vendor: 14,668 bytes, lines 2752-3068
2752            // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.
2753            // Otherwise, leaving it as inclusive will cause it to exclude `endDay`.
2754            if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) {
2755                endDay = addDays(endDay, 1);
2756            }
2757        }
2758        if (timedRange.start) {
2759            startDay = startOfDay(timedRange.start); // the beginning of the day the range starts
2760            // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day.
2761            if (endDay && endDay <= startDay) {
2762                endDay = addDays(startDay, 1);
2763            }
2764        }
2765        return { start: startDay, end: endDay };
2766    }
2767    // spans from one day into another?
2768    function isMultiDayRange(range) {
2769        let visibleRange = computeVisibleDayRange(range);
2770        return diffDays(visibleRange.start, visibleRange.end) > 1;
2771    }
2772    function diffDates(date0, date1, dateEnv, largeUnit) {
2773        if (largeUnit === 'year') {
2774            return createDuration(dateEnv.diffWholeYears(date0, date1), 'year');
2775        }
2776        if (largeUnit === 'month') {
2777            return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month');
2778        }
2779        return diffDayAndTime(date0, date1); // returns a duration
2780    }
2781
2782    function reduceCurrentDate(currentDate, action) {
2783        switch (action.type) {
2784            case 'CHANGE_DATE':
2785                return action.dateMarker;
2786            default:
2787                return currentDate;
2788        }
2789    }
2790    function getInitialDate(options, dateEnv) {
2791        let initialDateInput = options.initialDate;
2792        // compute the initial ambig-timezone date
2793        if (initialDateInput != null) {
2794            return dateEnv.createMarker(initialDateInput);
2795        }
2796        return getNow(options.now, dateEnv); // getNow already returns unzoned
2797    }
2798    function getNow(nowInput, dateEnv) {
2799        if (typeof nowInput === 'function') {
2800            nowInput = nowInput();
2801        }
2802        if (nowInput == null) {
2803            return dateEnv.createNowMarker();
2804        }
2805        return dateEnv.createMarker(nowInput);
2806    }
2807
2808    class DateProfileGenerator {
2809        constructor(props) {
2810            this.props = props;
2811            this.nowDate = getNow(props.nowInput, props.dateEnv);
2812            this.initHiddenDays();
2813        }
2814        /* Date Range Computation
2815        ------------------------------------------------------------------------------------------------------------------*/
2816        // Builds a structure with info about what the dates/ranges will be for the "prev" view.
2817        buildPrev(currentDateProfile, currentDate, forceToValid) {
2818            let { dateEnv } = this.props;
2819            let prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
2820            currentDateProfile.dateIncrement);
2821            return this.build(prevDate, -1, forceToValid);
2822        }
2823        // Builds a structure with info about what the dates/ranges will be for the "next" view.
2824        buildNext(currentDateProfile, currentDate, forceToValid) {
2825            let { dateEnv } = this.props;
2826            let nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
2827            currentDateProfile.dateIncrement);
2828            return this.build(nextDate, 1, forceToValid);
2829        }
2830        // Builds a structure holding dates/ranges for rendering around the given date.
2831        // Optional direction param indicates whether the date is being incremented/decremented
2832        // from its previous value. decremented = -1, incremented = 1 (default).
2833        build(currentDate, direction, forceToValid = true) {
2834            let { props } = this;
2835            let validRange;
2836            let currentInfo;
2837            let isRangeAllDay;
2838            let renderRange;
2839            let activeRange;
2840            let isValid;
2841            validRange = this.buildValidRange();
2842            validRange = this.trimHiddenDays(validRange);
2843            if (forceToValid) {
2844                currentDate = constrainMarkerToRange(currentDate, validRange);
2845            }
2846            currentInfo = this.buildCurrentRangeInfo(currentDate, direction);
2847            isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit);
2848            renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay);
2849            renderRange = this.trimHiddenDays(renderRange);
2850            activeRange = renderRange;
2851            if (!props.showNonCurrentDates) {
2852                activeRange = intersectRanges(activeRange, currentInfo.range);
2853            }
2854            activeRange = this.adjustActiveRange(activeRange);
2855            activeRange = intersectRanges(activeRange, validRange); // might return null
2856            // it's invalid if the originally requested date is not contained,
2857            // or if the range is completely outside of the valid range.
2858            isValid = rangesIntersect(currentInfo.range, validRange);
2859            return {
2860                // constraint for where prev/next operations can go and where events can be dragged/resized to.
2861                // an object with optional start and end properties.
2862                validRange,
2863                // range the view is formally responsible for.
2864                // for example, a month view might have 1st-31st, excluding padded dates
2865                currentRange: currentInfo.range,
2866                // name of largest unit being displayed, like "month" or "week"
2867                currentRangeUnit: currentInfo.unit,
2868                isRangeAllDay,
2869                // dates that display events and accept drag-n-drop
2870                // will be `null` if no dates accept events
2871                activeRange,
2872                // date range with a rendered skeleton
2873                // includes not-active days that need some sort of DOM
2874                renderRange,
2875                // Duration object that denotes the first visible time of any given day
2876                slotMinTime: props.slotMinTime,
2877                // Duration object that denotes the exclusive visible end time of any given day
2878                slotMaxTime: props.slotMaxTime,
2879                isValid,
2880                // how far the current date will move for a prev/next operation
2881                dateIncrement: this.buildDateIncrement(currentInfo.duration),
2882                // pass a fallback (might be null) ^
2883            };
2884        }
2885        // Builds an object with optional start/end properties.
2886        // Indicates the minimum/maximum dates to display.
2887        // not responsible for trimming hidden days.
2888        buildValidRange() {
2889            let input = this.props.validRangeInput;
2890            let simpleInput = typeof input === 'function'
2891                ? input.call(this.props.calendarApi, this.nowDate)
2892                : input;
2893            return this.refineRange(simpleInput) ||
2894                { start: null, end: null }; // completely open-ended
2895        }
2896        // Builds a structure with info about the "current" range, the range that is
2897        // highlighted as being the current month for example.
2898        // See build() for a description of `direction`.
2899        // Guaranteed to have `range` and `unit` properties. `duration` is optional.
2900        buildCurrentRangeInfo(date, direction) {
2901            let { props } = this;
2902            let duration = null;
2903            let unit = null;
2904            let range = null;
2905            let dayCount;
2906            if (props.duration) {
2907                duration = props.duration;
2908                unit = props.durationUnit;
2909                range = this.buildRangeFromDuration(date, direction, duration, unit);
2910            }
2911            else if ((dayCount = this.props.dayCount)) {
2912                unit = 'day';
2913                range = this.buildRangeFromDayCount(date, direction, dayCount);
2914            }
2915            else if ((range = this.buildCustomVisibleRange(date))) {
2916                unit = props.dateEnv.greatestWholeUnit(range.start, range.end).unit;
2917            }
2918            else {
2919                duration = this.getFallbackDuration();
2920                unit = greatestDurationDenominator(duration).unit;
2921                range = this.buildRangeFromDuration(date, direction, duration, unit);
2922            }
2923            return { duration, unit, range };
2924        }
2925        getFallbackDuration() {
2926            return createDuration({ day: 1 });
2927        }
2928        // Returns a new activeRange to have time values (un-ambiguate)
2929        // slotMinTime or slotMaxTime causes the range to expand.
2930        adjustActiveRange(range) {
2931            let { dateEnv, usesMinMaxTime, slotMinTime, slotMaxTime } = this.props;
2932            let { start, end } = range;
2933            if (usesMinMaxTime) {
2934                // expand active range if slotMinTime is negative (why not when positive?)
2935                if (asRoughDays(slotMinTime) < 0) {
2936                    start = startOfDay(start); // necessary?
2937                    start = dateEnv.add(start, slotMinTime);
2938                }
2939                // expand active range if slotMaxTime is beyond one day (why not when negative?)
2940                if (asRoughDays(slotMaxTime) > 1) {
2941                    end = startOfDay(end); // necessary?
2942                    end = addDays(end, -1);
2943                    end = dateEnv.add(end, slotMaxTime);
2944                }
2945            }
2946            return { start, end };
2947        }
2948        // Builds the "current" range when it is specified as an explicit duration.
2949        // `unit` is the already-computed greatestDurationDenominator unit of duration.
2950        buildRangeFromDuration(date, direction, duration, unit) {
2951            let { dateEnv, dateAlignment } = this.props;
2952            let start;
2953            let end;
2954            let res;
2955            // compute what the alignment should be
2956            if (!dateAlignment) {
2957                let { dateIncrement } = this.props;
2958                if (dateIncrement) {
2959                    // use the smaller of the two units
2960                    if (asRoughMs(dateIncrement) < asRoughMs(duration)) {
2961                        dateAlignment = greatestDurationDenominator(dateIncrement).unit;
2962                    }
2963                    else {
2964                        dateAlignment = unit;
2965                    }
2966                }
2967                else {
2968                    dateAlignment = unit;
2969                }
2970            }
2971            // if the view displays a single day or smaller
2972            if (asRoughDays(duration) <= 1) {
2973                if (this.isHiddenDay(start)) {
2974                    start = this.skipHiddenDays(start, direction);
2975                    start = startOfDay(start);
2976                }
2977            }
2978            function computeRes() {
2979                start = dateEnv.startOf(date, dateAlignment);
2980                end = dateEnv.add(start, duration);
2981                res = { start, end };
2982            }
2983            computeRes();
2984            // if range is completely enveloped by hidden days, go past the hidden days
2985            if (!this.trimHiddenDays(res)) {
2986                date = this.skipHiddenDays(date, direction);
2987                computeRes();
2988            }
2989            return res;
2990        }
2991        // Builds the "current" range when a dayCount is specified.
2992        buildRangeFromDayCount(date, direction, dayCount) {
2993            let { dateEnv, dateAlignment } = this.props;
2994            let runningCount = 0;
2995            let start = date;
2996            let end;
2997            if (dateAlignment) {
2998                start = dateEnv.startOf(start, dateAlignment);
2999            }
3000            start = startOfDay(start);
3001            start = this.skipHiddenDays(start, direction);
3002            end = start;
3003            do {
3004                end = addDays(end, 1);
3005                if (!this.isHiddenDay(end)) {
3006                    runningCount += 1;
3007                }
3008            } while (runningCount < dayCount);
3009            return { start, end };
3010        }
3011        // Builds a normalized range object for the "visible" range,
3012        // which is a way to define the currentRange and activeRange at the same time.
3013        buildCustomVisibleRange(date) {
3014            let { props } = this;
3015            let input = props.visibleRangeInput;
3016            let simpleInput = typeof input === 'function'
3017                ? input.call(props.calendarApi, props.dateEnv.toDate(date))
3018                : input;
3019            let range = this.refineRange(simpleInput);
3020            if (range && (range.start == null || range.end == null)) {
3021                return null;
3022            }
3023            return range;
3024        }
3025        // Computes the range that will represent the element/cells for *rendering*,
3026        // but which may have voided days/times.
3027        // not responsible for trimming hidden days.
3028        buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
3029            return currentRange;
3030        }
3031        // Compute the duration value that should be added/substracted to the current date
3032        // when a prev/next operation happens.
3033        buildDateIncrement(fallback) {
3034            let { dateIncrement } = this.props;
3035            let customAlignment;
3036            if (dateIncrement) {
3037                return dateIncrement;
3038            }
3039            if ((customAlignment = this.props.dateAlignment)) {
3040                return createDuration(1, customAlignment);
3041            }
3042            if (fallback) {
3043                return fallback;
3044            }
3045            return createDuration({ days: 1 });
3046        }
3047        refineRange(rangeInput) {
3048            if (rangeInput) {
3049                let range = parseRange(rangeInput, this.props.dateEnv);
3050                if (range) {
3051                    range = computeVisibleDayRange(range);
3052                }
3053                return range;
3054            }
3055            return null;
3056        }
3057        /* Hidden Days
3058        ------------------------------------------------------------------------------------------------------------------*/
3059        // Initializes internal variables related to calculating hidden days-of-week
3060        initHiddenDays() {
3061            let hiddenDays = this.props.hiddenDays || []; // array of day-of-week indices that are hidden
3062            let isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool)
3063            let dayCnt = 0;
3064            let i;
3065            if (this.props.weekends === false) {
3066                hiddenDays.push(0, 6); // 0=sunday, 6=saturday
3067            }
3068            for (i = 0; i < 7; i += 1) {
vendor: 12,783 bytes, lines 3069-3385
3069                if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) {
3070                    dayCnt += 1;
3071                }
3072            }
3073            if (!dayCnt) {
3074                throw new Error('invalid hiddenDays'); // all days were hidden? bad.
3075            }
3076            this.isHiddenDayHash = isHiddenDayHash;
3077        }
3078        // Remove days from the beginning and end of the range that are computed as hidden.
3079        // If the whole range is trimmed off, returns null
3080        trimHiddenDays(range) {
3081            let { start, end } = range;
3082            if (start) {
3083                start = this.skipHiddenDays(start);
3084            }
3085            if (end) {
3086                end = this.skipHiddenDays(end, -1, true);
3087            }
3088            if (start == null || end == null || start < end) {
3089                return { start, end };
3090            }
3091            return null;
3092        }
3093        // Is the current day hidden?
3094        // `day` is a day-of-week index (0-6), or a Date (used for UTC)
3095        isHiddenDay(day) {
3096            if (day instanceof Date) {
3097                day = day.getUTCDay();
3098            }
3099            return this.isHiddenDayHash[day];
3100        }
3101        // Incrementing the current day until it is no longer a hidden day, returning a copy.
3102        // DOES NOT CONSIDER validRange!
3103        // If the initial value of `date` is not a hidden day, don't do anything.
3104        // Pass `isExclusive` as `true` if you are dealing with an end date.
3105        // `inc` defaults to `1` (increment one day forward each time)
3106        skipHiddenDays(date, inc = 1, isExclusive = false) {
3107            while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) {
3108                date = addDays(date, inc);
3109            }
3110            return date;
3111        }
3112    }
3113
3114    function createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) {
3115        return {
3116            instanceId: guid(),
3117            defId,
3118            range,
3119            forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo,
3120            forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo,
3121        };
3122    }
3123
3124    function parseRecurring(refined, defaultAllDay, dateEnv, recurringTypes) {
3125        for (let i = 0; i < recurringTypes.length; i += 1) {
3126            let parsed = recurringTypes[i].parse(refined, dateEnv);
3127            if (parsed) {
3128                let { allDay } = refined;
3129                if (allDay == null) {
3130                    allDay = defaultAllDay;
3131                    if (allDay == null) {
3132                        allDay = parsed.allDayGuess;
3133                        if (allDay == null) {
3134                            allDay = false;
3135                        }
3136                    }
3137                }
3138                return {
3139                    allDay,
3140                    duration: parsed.duration,
3141                    typeData: parsed.typeData,
3142                    typeId: i,
3143                };
3144            }
3145        }
3146        return null;
3147    }
3148    function expandRecurring(eventStore, framingRange, context) {
3149        let { dateEnv, pluginHooks, options } = context;
3150        let { defs, instances } = eventStore;
3151        // remove existing recurring instances
3152        // TODO: bad. always expand events as a second step
3153        instances = filterHash(instances, (instance) => !defs[instance.defId].recurringDef);
3154        for (let defId in defs) {
3155            let def = defs[defId];
3156            if (def.recurringDef) {
3157                let { duration } = def.recurringDef;
3158                if (!duration) {
3159                    duration = def.allDay ?
3160                        options.defaultAllDayEventDuration :
3161                        options.defaultTimedEventDuration;
3162                }
3163                let starts = expandRecurringRanges(def, duration, framingRange, dateEnv, pluginHooks.recurringTypes);
3164                for (let start of starts) {
3165                    let instance = createEventInstance(defId, {
3166                        start,
3167                        end: dateEnv.add(start, duration),
3168                    });
3169                    instances[instance.instanceId] = instance;
3170                }
3171            }
3172        }
3173        return { defs, instances };
3174    }
3175    /*
3176    Event MUST have a recurringDef
3177    */
3178    function expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) {
3179        let typeDef = recurringTypes[eventDef.recurringDef.typeId];
3180        let markers = typeDef.expand(eventDef.recurringDef.typeData, {
3181            start: dateEnv.subtract(framingRange.start, duration),
3182            end: framingRange.end,
3183        }, dateEnv);
3184        // the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to
3185        if (eventDef.allDay) {
3186            markers = markers.map(startOfDay);
3187        }
3188        return markers;
3189    }
3190
3191    const EVENT_NON_DATE_REFINERS = {
3192        id: String,
3193        groupId: String,
3194        title: String,
3195        url: String,
3196        interactive: Boolean,
3197    };
3198    const EVENT_DATE_REFINERS = {
3199        start: identity,
3200        end: identity,
3201        date: identity,
3202        allDay: Boolean,
3203    };
3204    const EVENT_REFINERS = Object.assign(Object.assign(Object.assign({}, EVENT_NON_DATE_REFINERS), EVENT_DATE_REFINERS), { extendedProps: identity });
3205    function parseEvent(raw, eventSource, context, allowOpenRange, refiners = buildEventRefiners(context)) {
3206        let { refined, extra } = refineEventDef(raw, context, refiners);
3207        let defaultAllDay = computeIsDefaultAllDay(eventSource, context);
3208        let recurringRes = parseRecurring(refined, defaultAllDay, context.dateEnv, context.pluginHooks.recurringTypes);
3209        if (recurringRes) {
3210            let def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', recurringRes.allDay, Boolean(recurringRes.duration), context);
3211            def.recurringDef = {
3212                typeId: recurringRes.typeId,
3213                typeData: recurringRes.typeData,
3214                duration: recurringRes.duration,
3215            };
3216            return { def, instance: null };
3217        }
3218        let singleRes = parseSingle(refined, defaultAllDay, context, allowOpenRange);
3219        if (singleRes) {
3220            let def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', singleRes.allDay, singleRes.hasEnd, context);
3221            let instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo);
3222            return { def, instance };
3223        }
3224        return null;
3225    }
3226    function refineEventDef(raw, context, refiners = buildEventRefiners(context)) {
3227        return refineProps(raw, refiners);
3228    }
3229    function buildEventRefiners(context) {
3230        return Object.assign(Object.assign(Object.assign({}, EVENT_UI_REFINERS), EVENT_REFINERS), context.pluginHooks.eventRefiners);
3231    }
3232    /*
3233    Will NOT populate extendedProps with the leftover properties.
3234    Will NOT populate date-related props.
3235    */
3236    function parseEventDef(refined, extra, sourceId, allDay, hasEnd, context) {
3237        let def = {
3238            title: refined.title || '',
3239            groupId: refined.groupId || '',
3240            publicId: refined.id || '',
3241            url: refined.url || '',
3242            recurringDef: null,
3243            defId: guid(),
3244            sourceId,
3245            allDay,
3246            hasEnd,
3247            interactive: refined.interactive,
3248            ui: createEventUi(refined, context),
3249            extendedProps: Object.assign(Object.assign({}, (refined.extendedProps || {})), extra),
3250        };
3251        for (let memberAdder of context.pluginHooks.eventDefMemberAdders) {
3252            Object.assign(def, memberAdder(refined));
3253        }
3254        // help out EventImpl from having user modify props
3255        Object.freeze(def.ui.classNames);
3256        Object.freeze(def.extendedProps);
3257        return def;
3258    }
3259    function parseSingle(refined, defaultAllDay, context, allowOpenRange) {
3260        let { allDay } = refined;
3261        let startMeta;
3262        let startMarker = null;
3263        let hasEnd = false;
3264        let endMeta;
3265        let endMarker = null;
3266        let startInput = refined.start != null ? refined.start : refined.date;
3267        startMeta = context.dateEnv.createMarkerMeta(startInput);
3268        if (startMeta) {
3269            startMarker = startMeta.marker;
3270        }
3271        else if (!allowOpenRange) {
3272            return null;
3273        }
3274        if (refined.end != null) {
3275            endMeta = context.dateEnv.createMarkerMeta(refined.end);
3276        }
3277        if (allDay == null) {
3278            if (defaultAllDay != null) {
3279                allDay = defaultAllDay;
3280            }
3281            else {
3282                // fall back to the date props LAST
3283                allDay = (!startMeta || startMeta.isTimeUnspecified) &&
3284                    (!endMeta || endMeta.isTimeUnspecified);
3285            }
3286        }
3287        if (allDay && startMarker) {
3288            startMarker = startOfDay(startMarker);
3289        }
3290        if (endMeta) {
3291            endMarker = endMeta.marker;
3292            if (allDay) {
3293                endMarker = startOfDay(endMarker);
3294            }
3295            if (startMarker && endMarker <= startMarker) {
3296                endMarker = null;
3297            }
3298        }
3299        if (endMarker) {
3300            hasEnd = true;
3301        }
3302        else if (!allowOpenRange) {
3303            hasEnd = context.options.forceEventDuration || false;
3304            endMarker = context.dateEnv.add(startMarker, allDay ?
3305                context.options.defaultAllDayEventDuration :
3306                context.options.defaultTimedEventDuration);
3307        }
3308        return {
3309            allDay,
3310            hasEnd,
3311            range: { start: startMarker, end: endMarker },
3312            forcedStartTzo: startMeta ? startMeta.forcedTzo : null,
3313            forcedEndTzo: endMeta ? endMeta.forcedTzo : null,
3314        };
3315    }
3316    function computeIsDefaultAllDay(eventSource, context) {
3317        let res = null;
3318        if (eventSource) {
3319            res = eventSource.defaultAllDay;
3320        }
3321        if (res == null) {
3322            res = context.options.defaultAllDay;
3323        }
3324        return res;
3325    }
3326
3327    function parseEvents(rawEvents, eventSource, context, allowOpenRange) {
3328        let eventStore = createEmptyEventStore();
3329        let eventRefiners = buildEventRefiners(context);
3330        for (let rawEvent of rawEvents) {
3331            let tuple = parseEvent(rawEvent, eventSource, context, allowOpenRange, eventRefiners);
3332            if (tuple) {
3333                eventTupleToStore(tuple, eventStore);
3334            }
3335        }
3336        return eventStore;
3337    }
3338    function eventTupleToStore(tuple, eventStore = createEmptyEventStore()) {
3339        eventStore.defs[tuple.def.defId] = tuple.def;
3340        if (tuple.instance) {
3341            eventStore.instances[tuple.instance.instanceId] = tuple.instance;
3342        }
3343        return eventStore;
3344    }
3345    // retrieves events that have the same groupId as the instance specified by `instanceId`
3346    // or they are the same as the instance.
3347    // why might instanceId not be in the store? an event from another calendar?
3348    function getRelevantEvents(eventStore, instanceId) {
3349        let instance = eventStore.instances[instanceId];
3350        if (instance) {
3351            let def = eventStore.defs[instance.defId];
3352            // get events/instances with same group
3353            let newStore = filterEventStoreDefs(eventStore, (lookDef) => isEventDefsGrouped(def, lookDef));
3354            // add the original
3355            // TODO: wish we could use eventTupleToStore or something like it
3356            newStore.defs[def.defId] = def;
3357            newStore.instances[instance.instanceId] = instance;
3358            return newStore;
3359        }
3360        return createEmptyEventStore();
3361    }
3362    function isEventDefsGrouped(def0, def1) {
3363        return Boolean(def0.groupId && def0.groupId === def1.groupId);
3364    }
3365    function createEmptyEventStore() {
3366        return { defs: {}, instances: {} };
3367    }
3368    function mergeEventStores(store0, store1) {
3369        return {
3370            defs: Object.assign(Object.assign({}, store0.defs), store1.defs),
3371            instances: Object.assign(Object.assign({}, store0.instances), store1.instances),
3372        };
3373    }
3374    function filterEventStoreDefs(eventStore, filterFunc) {
3375        let defs = filterHash(eventStore.defs, filterFunc);
3376        let instances = filterHash(eventStore.instances, (instance) => (defs[instance.defId] // still exists?
3377        ));
3378        return { defs, instances };
3379    }
3380    function excludeSubEventStore(master, sub) {
3381        let { defs, instances } = master;
3382        let filteredDefs = {};
3383        let filteredInstances = {};
3384        for (let defId in defs) {
3385            if (!sub.defs[defId]) { // not explicitly excluded
vendor: 6,832 bytes, lines 3386-3558
3386                filteredDefs[defId] = defs[defId];
3387            }
3388        }
3389        for (let instanceId in instances) {
3390            if (!sub.instances[instanceId] && // not explicitly excluded
3391                filteredDefs[instances[instanceId].defId] // def wasn't filtered away
3392            ) {
3393                filteredInstances[instanceId] = instances[instanceId];
3394            }
3395        }
3396        return {
3397            defs: filteredDefs,
3398            instances: filteredInstances,
3399        };
3400    }
3401
3402    function normalizeConstraint(input, context) {
3403        if (Array.isArray(input)) {
3404            return parseEvents(input, null, context, true); // allowOpenRange=true
3405        }
3406        if (typeof input === 'object' && input) { // non-null object
3407            return parseEvents([input], null, context, true); // allowOpenRange=true
3408        }
3409        if (input != null) {
3410            return String(input);
3411        }
3412        return null;
3413    }
3414
3415    function parseClassNames(raw) {
3416        if (Array.isArray(raw)) {
3417            return raw;
3418        }
3419        if (typeof raw === 'string') {
3420            return raw.split(/\s+/);
3421        }
3422        return [];
3423    }
3424
3425    // TODO: better called "EventSettings" or "EventConfig"
3426    // TODO: move this file into structs
3427    // TODO: separate constraint/overlap/allow, because selection uses only that, not other props
3428    const EVENT_UI_REFINERS = {
3429        display: String,
3430        editable: Boolean,
3431        startEditable: Boolean,
3432        durationEditable: Boolean,
3433        constraint: identity,
3434        overlap: identity,
3435        allow: identity,
3436        className: parseClassNames,
3437        classNames: parseClassNames,
3438        color: String,
3439        backgroundColor: String,
3440        borderColor: String,
3441        textColor: String,
3442    };
3443    const EMPTY_EVENT_UI = {
3444        display: null,
3445        startEditable: null,
3446        durationEditable: null,
3447        constraints: [],
3448        overlap: null,
3449        allows: [],
3450        backgroundColor: '',
3451        borderColor: '',
3452        textColor: '',
3453        classNames: [],
3454    };
3455    function createEventUi(refined, context) {
3456        let constraint = normalizeConstraint(refined.constraint, context);
3457        return {
3458            display: refined.display || null,
3459            startEditable: refined.startEditable != null ? refined.startEditable : refined.editable,
3460            durationEditable: refined.durationEditable != null ? refined.durationEditable : refined.editable,
3461            constraints: constraint != null ? [constraint] : [],
3462            overlap: refined.overlap != null ? refined.overlap : null,
3463            allows: refined.allow != null ? [refined.allow] : [],
3464            backgroundColor: refined.backgroundColor || refined.color || '',
3465            borderColor: refined.borderColor || refined.color || '',
3466            textColor: refined.textColor || '',
3467            classNames: (refined.className || []).concat(refined.classNames || []), // join singular and plural
3468        };
3469    }
3470    // TODO: prevent against problems with <2 args!
3471    function combineEventUis(uis) {
3472        return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI);
3473    }
3474    function combineTwoEventUis(item0, item1) {
3475        return {
3476            display: item1.display != null ? item1.display : item0.display,
3477            startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable,
3478            durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable,
3479            constraints: item0.constraints.concat(item1.constraints),
3480            overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap,
3481            allows: item0.allows.concat(item1.allows),
3482            backgroundColor: item1.backgroundColor || item0.backgroundColor,
3483            borderColor: item1.borderColor || item0.borderColor,
3484            textColor: item1.textColor || item0.textColor,
3485            classNames: item0.classNames.concat(item1.classNames),
3486        };
3487    }
3488
3489    const EVENT_SOURCE_REFINERS = {
3490        id: String,
3491        defaultAllDay: Boolean,
3492        url: String,
3493        format: String,
3494        events: identity,
3495        eventDataTransform: identity,
3496        // for any network-related sources
3497        success: identity,
3498        failure: identity,
3499    };
3500    function parseEventSource(raw, context, refiners = buildEventSourceRefiners(context)) {
3501        let rawObj;
3502        if (typeof raw === 'string') {
3503            rawObj = { url: raw };
3504        }
3505        else if (typeof raw === 'function' || Array.isArray(raw)) {
3506            rawObj = { events: raw };
3507        }
3508        else if (typeof raw === 'object' && raw) { // not null
3509            rawObj = raw;
3510        }
3511        if (rawObj) {
3512            let { refined, extra } = refineProps(rawObj, refiners);
3513            let metaRes = buildEventSourceMeta(refined, context);
3514            if (metaRes) {
3515                return {
3516                    _raw: raw,
3517                    isFetching: false,
3518                    latestFetchId: '',
3519                    fetchRange: null,
3520                    defaultAllDay: refined.defaultAllDay,
3521                    eventDataTransform: refined.eventDataTransform,
3522                    success: refined.success,
3523                    failure: refined.failure,
3524                    publicId: refined.id || '',
3525                    sourceId: guid(),
3526                    sourceDefId: metaRes.sourceDefId,
3527                    meta: metaRes.meta,
3528                    ui: createEventUi(refined, context),
3529                    extendedProps: extra,
3530                };
3531            }
3532        }
3533        return null;
3534    }
3535    function buildEventSourceRefiners(context) {
3536        return Object.assign(Object.assign(Object.assign({}, EVENT_UI_REFINERS), EVENT_SOURCE_REFINERS), context.pluginHooks.eventSourceRefiners);
3537    }
3538    function buildEventSourceMeta(raw, context) {
3539        let defs = context.pluginHooks.eventSourceDefs;
3540        for (let i = defs.length - 1; i >= 0; i -= 1) { // later-added plugins take precedence
3541            let def = defs[i];
3542            let meta = def.parseMeta(raw);
3543            if (meta) {
3544                return { sourceDefId: i, meta };
3545            }
3546        }
3547        return null;
3548    }
3549
3550    function initEventSources(calendarOptions, dateProfile, context) {
3551        let activeRange = dateProfile ? dateProfile.activeRange : null;
3552        return addSources({}, parseInitialSources(calendarOptions, context), activeRange, context);
3553    }
3554    function reduceEventSources(eventSources, action, dateProfile, context) {
3555        let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
3556        switch (action.type) {
3557            case 'ADD_EVENT_SOURCES': // already parsed
3558                return addSources(eventSources, action.sources, activeRange, context);
vendor: 4,373 bytes, lines 3559-3658
3559            case 'REMOVE_EVENT_SOURCE':
3560                return removeSource(eventSources, action.sourceId);
3561            case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
3562            case 'NEXT':
3563            case 'CHANGE_DATE':
3564            case 'CHANGE_VIEW_TYPE':
3565                if (dateProfile) {
3566                    return fetchDirtySources(eventSources, activeRange, context);
3567                }
3568                return eventSources;
3569            case 'FETCH_EVENT_SOURCES':
3570                return fetchSourcesByIds(eventSources, action.sourceIds ? // why no type?
3571                    arrayToHash(action.sourceIds) :
3572                    excludeStaticSources(eventSources, context), activeRange, action.isRefetch || false, context);
3573            case 'RECEIVE_EVENTS':
3574            case 'RECEIVE_EVENT_ERROR':
3575                return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange);
3576            case 'REMOVE_ALL_EVENT_SOURCES':
3577                return {};
3578            default:
3579                return eventSources;
3580        }
3581    }
3582    function reduceEventSourcesNewTimeZone(eventSources, dateProfile, context) {
3583        let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
3584        return fetchSourcesByIds(eventSources, excludeStaticSources(eventSources, context), activeRange, true, context);
3585    }
3586    function computeEventSourcesLoading(eventSources) {
3587        for (let sourceId in eventSources) {
3588            if (eventSources[sourceId].isFetching) {
3589                return true;
3590            }
3591        }
3592        return false;
3593    }
3594    function addSources(eventSourceHash, sources, fetchRange, context) {
3595        let hash = {};
3596        for (let source of sources) {
3597            hash[source.sourceId] = source;
3598        }
3599        if (fetchRange) {
3600            hash = fetchDirtySources(hash, fetchRange, context);
3601        }
3602        return Object.assign(Object.assign({}, eventSourceHash), hash);
3603    }
3604    function removeSource(eventSourceHash, sourceId) {
3605        return filterHash(eventSourceHash, (eventSource) => eventSource.sourceId !== sourceId);
3606    }
3607    function fetchDirtySources(sourceHash, fetchRange, context) {
3608        return fetchSourcesByIds(sourceHash, filterHash(sourceHash, (eventSource) => isSourceDirty(eventSource, fetchRange, context)), fetchRange, false, context);
3609    }
3610    function isSourceDirty(eventSource, fetchRange, context) {
3611        if (!doesSourceNeedRange(eventSource, context)) {
3612            return !eventSource.latestFetchId;
3613        }
3614        return !context.options.lazyFetching ||
3615            !eventSource.fetchRange ||
3616            eventSource.isFetching || // always cancel outdated in-progress fetches
3617            fetchRange.start < eventSource.fetchRange.start ||
3618            fetchRange.end > eventSource.fetchRange.end;
3619    }
3620    function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, isRefetch, context) {
3621        let nextSources = {};
3622        for (let sourceId in prevSources) {
3623            let source = prevSources[sourceId];
3624            if (sourceIdHash[sourceId]) {
3625                nextSources[sourceId] = fetchSource(source, fetchRange, isRefetch, context);
3626            }
3627            else {
3628                nextSources[sourceId] = source;
3629            }
3630        }
3631        return nextSources;
3632    }
3633    function fetchSource(eventSource, fetchRange, isRefetch, context) {
3634        let { options, calendarApi } = context;
3635        let sourceDef = context.pluginHooks.eventSourceDefs[eventSource.sourceDefId];
3636        let fetchId = guid();
3637        sourceDef.fetch({
3638            eventSource,
3639            range: fetchRange,
3640            isRefetch,
3641            context,
3642        }, (res) => {
3643            let { rawEvents } = res;
3644            if (options.eventSourceSuccess) {
3645                rawEvents = options.eventSourceSuccess.call(calendarApi, rawEvents, res.response) || rawEvents;
3646            }
3647            if (eventSource.success) {
3648                rawEvents = eventSource.success.call(calendarApi, rawEvents, res.response) || rawEvents;
3649            }
3650            context.dispatch({
3651                type: 'RECEIVE_EVENTS',
3652                sourceId: eventSource.sourceId,
3653                fetchId,
3654                fetchRange,
3655                rawEvents,
3656            });
3657        }, (error) => {
3658            let errorHandled = false;
vendor: 7,952 bytes, lines 3659-3840
3659            if (options.eventSourceFailure) {
3660                options.eventSourceFailure.call(calendarApi, error);
3661                errorHandled = true;
3662            }
3663            if (eventSource.failure) {
3664                eventSource.failure(error);
3665                errorHandled = true;
3666            }
3667            if (!errorHandled) {
3668                console.warn(error.message, error);
3669            }
3670            context.dispatch({
3671                type: 'RECEIVE_EVENT_ERROR',
3672                sourceId: eventSource.sourceId,
3673                fetchId,
3674                fetchRange,
3675                error,
3676            });
3677        });
3678        return Object.assign(Object.assign({}, eventSource), { isFetching: true, latestFetchId: fetchId });
3679    }
3680    function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) {
3681        let eventSource = sourceHash[sourceId];
3682        if (eventSource && // not already removed
3683            fetchId === eventSource.latestFetchId) {
3684            return Object.assign(Object.assign({}, sourceHash), { [sourceId]: Object.assign(Object.assign({}, eventSource), { isFetching: false, fetchRange }) });
3685        }
3686        return sourceHash;
3687    }
3688    function excludeStaticSources(eventSources, context) {
3689        return filterHash(eventSources, (eventSource) => doesSourceNeedRange(eventSource, context));
3690    }
3691    function parseInitialSources(rawOptions, context) {
3692        let refiners = buildEventSourceRefiners(context);
3693        let rawSources = [].concat(rawOptions.eventSources || []);
3694        let sources = []; // parsed
3695        if (rawOptions.initialEvents) {
3696            rawSources.unshift(rawOptions.initialEvents);
3697        }
3698        if (rawOptions.events) {
3699            rawSources.unshift(rawOptions.events);
3700        }
3701        for (let rawSource of rawSources) {
3702            let source = parseEventSource(rawSource, context, refiners);
3703            if (source) {
3704                sources.push(source);
3705            }
3706        }
3707        return sources;
3708    }
3709    function doesSourceNeedRange(eventSource, context) {
3710        let defs = context.pluginHooks.eventSourceDefs;
3711        return !defs[eventSource.sourceDefId].ignoreRange;
3712    }
3713
3714    function reduceEventStore(eventStore, action, eventSources, dateProfile, context) {
3715        switch (action.type) {
3716            case 'RECEIVE_EVENTS': // raw
3717                return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, context);
3718            case 'ADD_EVENTS': // already parsed, but not expanded
3719                return addEvent(eventStore, action.eventStore, // new ones
3720                dateProfile ? dateProfile.activeRange : null, context);
3721            case 'RESET_EVENTS':
3722                return action.eventStore;
3723            case 'MERGE_EVENTS': // already parsed and expanded
3724                return mergeEventStores(eventStore, action.eventStore);
3725            case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
3726            case 'NEXT':
3727            case 'CHANGE_DATE':
3728            case 'CHANGE_VIEW_TYPE':
3729                if (dateProfile) {
3730                    return expandRecurring(eventStore, dateProfile.activeRange, context);
3731                }
3732                return eventStore;
3733            case 'REMOVE_EVENTS':
3734                return excludeSubEventStore(eventStore, action.eventStore);
3735            case 'REMOVE_EVENT_SOURCE':
3736                return excludeEventsBySourceId(eventStore, action.sourceId);
3737            case 'REMOVE_ALL_EVENT_SOURCES':
3738                return filterEventStoreDefs(eventStore, (eventDef) => (!eventDef.sourceId // only keep events with no source id
3739                ));
3740            case 'REMOVE_ALL_EVENTS':
3741                return createEmptyEventStore();
3742            default:
3743                return eventStore;
3744        }
3745    }
3746    function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, context) {
3747        if (eventSource && // not already removed
3748            fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources
3749        ) {
3750            let subset = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context);
3751            if (fetchRange) {
3752                subset = expandRecurring(subset, fetchRange, context);
3753            }
3754            return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset);
3755        }
3756        return eventStore;
3757    }
3758    function transformRawEvents(rawEvents, eventSource, context) {
3759        let calEachTransform = context.options.eventDataTransform;
3760        let sourceEachTransform = eventSource ? eventSource.eventDataTransform : null;
3761        if (sourceEachTransform) {
3762            rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform);
3763        }
3764        if (calEachTransform) {
3765            rawEvents = transformEachRawEvent(rawEvents, calEachTransform);
3766        }
3767        return rawEvents;
3768    }
3769    function transformEachRawEvent(rawEvents, func) {
3770        let refinedEvents;
3771        if (!func) {
3772            refinedEvents = rawEvents;
3773        }
3774        else {
3775            refinedEvents = [];
3776            for (let rawEvent of rawEvents) {
3777                let refinedEvent = func(rawEvent);
3778                if (refinedEvent) {
3779                    refinedEvents.push(refinedEvent);
3780                }
3781                else if (refinedEvent == null) {
3782                    refinedEvents.push(rawEvent);
3783                } // if a different falsy value, do nothing
3784            }
3785        }
3786        return refinedEvents;
3787    }
3788    function addEvent(eventStore, subset, expandRange, context) {
3789        if (expandRange) {
3790            subset = expandRecurring(subset, expandRange, context);
3791        }
3792        return mergeEventStores(eventStore, subset);
3793    }
3794    function rezoneEventStoreDates(eventStore, oldDateEnv, newDateEnv) {
3795        let { defs } = eventStore;
3796        let instances = mapHash(eventStore.instances, (instance) => {
3797            let def = defs[instance.defId];
3798            if (def.allDay || def.recurringDef) {
3799                return instance; // isn't dependent on timezone
3800            }
3801            return Object.assign(Object.assign({}, instance), { range: {
3802                    start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)),
3803                    end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo)),
3804                }, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo });
3805        });
3806        return { defs, instances };
3807    }
3808    function excludeEventsBySourceId(eventStore, sourceId) {
3809        return filterEventStoreDefs(eventStore, (eventDef) => eventDef.sourceId !== sourceId);
3810    }
3811    // QUESTION: why not just return instances? do a general object-property-exclusion util
3812    function excludeInstances(eventStore, removals) {
3813        return {
3814            defs: eventStore.defs,
3815            instances: filterHash(eventStore.instances, (instance) => !removals[instance.instanceId]),
3816        };
3817    }
3818
3819    class Emitter {
3820        constructor() {
3821            this.handlers = {};
3822            this.thisContext = null;
3823        }
3824        setThisContext(thisContext) {
3825            this.thisContext = thisContext;
3826        }
3827        setOptions(options) {
3828            this.options = options;
3829        }
3830        on(type, handler) {
3831            addToHash(this.handlers, type, handler);
3832        }
3833        off(type, handler) {
3834            removeFromHash(this.handlers, type, handler);
3835        }
3836        trigger(type, ...args) {
3837            let attachedHandlers = this.handlers[type] || [];
3838            let optionHandler = this.options && this.options[type];
3839            let handlers = [].concat(optionHandler || [], attachedHandlers);
3840            for (let handler of handlers) {
vendor: 7,958 bytes, lines 3841-4039
3841                handler.apply(this.thisContext, args);
3842            }
3843        }
3844        hasHandlers(type) {
3845            return Boolean((this.handlers[type] && this.handlers[type].length) ||
3846                (this.options && this.options[type]));
3847        }
3848    }
3849    function addToHash(hash, type, handler) {
3850        (hash[type] || (hash[type] = []))
3851            .push(handler);
3852    }
3853    function removeFromHash(hash, type, handler) {
3854        if (handler) {
3855            if (hash[type]) {
3856                hash[type] = hash[type].filter((func) => func !== handler);
3857            }
3858        }
3859        else {
3860            delete hash[type]; // remove all handler funcs for this type
3861        }
3862    }
3863
3864    const DEF_DEFAULTS = {
3865        startTime: '09:00',
3866        endTime: '17:00',
3867        daysOfWeek: [1, 2, 3, 4, 5],
3868        display: 'inverse-background',
3869        classNames: 'fc-non-business',
3870        groupId: '_businessHours', // so multiple defs get grouped
3871    };
3872    /*
3873    TODO: pass around as EventDefHash!!!
3874    */
3875    function parseBusinessHours(input, context) {
3876        return parseEvents(refineInputs(input), null, context);
3877    }
3878    function refineInputs(input) {
3879        let rawDefs;
3880        if (input === true) {
3881            rawDefs = [{}]; // will get DEF_DEFAULTS verbatim
3882        }
3883        else if (Array.isArray(input)) {
3884            // if specifying an array, every sub-definition NEEDS a day-of-week
3885            rawDefs = input.filter((rawDef) => rawDef.daysOfWeek);
3886        }
3887        else if (typeof input === 'object' && input) { // non-null object
3888            rawDefs = [input];
3889        }
3890        else { // is probably false
3891            rawDefs = [];
3892        }
3893        rawDefs = rawDefs.map((rawDef) => (Object.assign(Object.assign({}, DEF_DEFAULTS), rawDef)));
3894        return rawDefs;
3895    }
3896
3897    let eventSourceDef$2 = {
3898        ignoreRange: true,
3899        parseMeta(refined) {
3900            if (Array.isArray(refined.events)) {
3901                return refined.events;
3902            }
3903            return null;
3904        },
3905        fetch(arg, successCallback) {
3906            successCallback({
3907                rawEvents: arg.eventSource.meta,
3908            });
3909        },
3910    };
3911    const arrayEventSourcePlugin = createPlugin({
3912        name: 'array-event-source',
3913        eventSourceDefs: [eventSourceDef$2],
3914    });
3915
3916    function triggerDateSelect(selection, pev, context) {
3917        context.emitter.trigger('select', Object.assign(Object.assign({}, buildDateSpanApiWithContext(selection, context)), { jsEvent: pev ? pev.origEvent : null, view: context.viewApi || context.calendarApi.view }));
3918    }
3919    function triggerDateUnselect(pev, context) {
3920        context.emitter.trigger('unselect', {
3921            jsEvent: pev ? pev.origEvent : null,
3922            view: context.viewApi || context.calendarApi.view,
3923        });
3924    }
3925    function buildDateSpanApiWithContext(dateSpan, context) {
3926        let props = {};
3927        for (let transform of context.pluginHooks.dateSpanTransforms) {
3928            Object.assign(props, transform(dateSpan, context));
3929        }
3930        Object.assign(props, buildDateSpanApi(dateSpan, context.dateEnv));
3931        return props;
3932    }
3933    // Given an event's allDay status and start date, return what its fallback end date should be.
3934    // TODO: rename to computeDefaultEventEnd
3935    function getDefaultEventEnd(allDay, marker, context) {
3936        let { dateEnv, options } = context;
3937        let end = marker;
3938        if (allDay) {
3939            end = startOfDay(end);
3940            end = dateEnv.add(end, options.defaultAllDayEventDuration);
3941        }
3942        else {
3943            end = dateEnv.add(end, options.defaultTimedEventDuration);
3944        }
3945        return end;
3946    }
3947
3948    // applies the mutation to ALL defs/instances within the event store
3949    function applyMutationToEventStore(eventStore, eventConfigBase, mutation, context) {
3950        let eventConfigs = compileEventUis(eventStore.defs, eventConfigBase);
3951        let dest = createEmptyEventStore();
3952        for (let defId in eventStore.defs) {
3953            let def = eventStore.defs[defId];
3954            dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, context);
3955        }
3956        for (let instanceId in eventStore.instances) {
3957            let instance = eventStore.instances[instanceId];
3958            let def = dest.defs[instance.defId]; // important to grab the newly modified def
3959            dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, context);
3960        }
3961        return dest;
3962    }
3963    function applyMutationToEventDef(eventDef, eventConfig, mutation, context) {
3964        let standardProps = mutation.standardProps || {};
3965        // if hasEnd has not been specified, guess a good value based on deltas.
3966        // if duration will change, there's no way the default duration will persist,
3967        // and thus, we need to mark the event as having a real end
3968        if (standardProps.hasEnd == null &&
3969            eventConfig.durationEditable &&
3970            (mutation.startDelta || mutation.endDelta)) {
3971            standardProps.hasEnd = true; // TODO: is this mutation okay?
3972        }
3973        let copy = Object.assign(Object.assign(Object.assign({}, eventDef), standardProps), { ui: Object.assign(Object.assign({}, eventDef.ui), standardProps.ui) });
3974        if (mutation.extendedProps) {
3975            copy.extendedProps = Object.assign(Object.assign({}, copy.extendedProps), mutation.extendedProps);
3976        }
3977        for (let applier of context.pluginHooks.eventDefMutationAppliers) {
3978            applier(copy, mutation, context);
3979        }
3980        if (!copy.hasEnd && context.options.forceEventDuration) {
3981            copy.hasEnd = true;
3982        }
3983        return copy;
3984    }
3985    function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef
3986    eventConfig, mutation, context) {
3987        let { dateEnv } = context;
3988        let forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true;
3989        let clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false;
3990        let copy = Object.assign({}, eventInstance);
3991        if (forceAllDay) {
3992            copy.range = computeAlignedDayRange(copy.range);
3993        }
3994        if (mutation.datesDelta && eventConfig.startEditable) {
3995            copy.range = {
3996                start: dateEnv.add(copy.range.start, mutation.datesDelta),
3997                end: dateEnv.add(copy.range.end, mutation.datesDelta),
3998            };
3999        }
4000        if (mutation.startDelta && eventConfig.durationEditable) {
4001            copy.range = {
4002                start: dateEnv.add(copy.range.start, mutation.startDelta),
4003                end: copy.range.end,
4004            };
4005        }
4006        if (mutation.endDelta && eventConfig.durationEditable) {
4007            copy.range = {
4008                start: copy.range.start,
4009                end: dateEnv.add(copy.range.end, mutation.endDelta),
4010            };
4011        }
4012        if (clearEnd) {
4013            copy.range = {
4014                start: copy.range.start,
4015                end: getDefaultEventEnd(eventDef.allDay, copy.range.start, context),
4016            };
4017        }
4018        // in case event was all-day but the supplied deltas were not
4019        // better util for this?
4020        if (eventDef.allDay) {
4021            copy.range = {
4022                start: startOfDay(copy.range.start),
4023                end: startOfDay(copy.range.end),
4024            };
4025        }
4026        // handle invalid durations
4027        if (copy.range.end < copy.range.start) {
4028            copy.range.end = getDefaultEventEnd(eventDef.allDay, copy.range.start, context);
4029        }
4030        return copy;
4031    }
4032
4033    class EventSourceImpl {
4034        constructor(context, internalEventSource) {
4035            this.context = context;
4036            this.internalEventSource = internalEventSource;
4037        }
4038        remove() {
4039            this.context.dispatch({
vendor: 26,379 bytes, lines 4040-4705
4040                type: 'REMOVE_EVENT_SOURCE',
4041                sourceId: this.internalEventSource.sourceId,
4042            });
4043        }
4044        refetch() {
4045            this.context.dispatch({
4046                type: 'FETCH_EVENT_SOURCES',
4047                sourceIds: [this.internalEventSource.sourceId],
4048                isRefetch: true,
4049            });
4050        }
4051        get id() {
4052            return this.internalEventSource.publicId;
4053        }
4054        get url() {
4055            return this.internalEventSource.meta.url;
4056        }
4057        get format() {
4058            return this.internalEventSource.meta.format; // TODO: bad. not guaranteed
4059        }
4060    }
4061
4062    class EventImpl {
4063        // instance will be null if expressing a recurring event that has no current instances,
4064        // OR if trying to validate an incoming external event that has no dates assigned
4065        constructor(context, def, instance) {
4066            this._context = context;
4067            this._def = def;
4068            this._instance = instance || null;
4069        }
4070        /*
4071        TODO: make event struct more responsible for this
4072        */
4073        setProp(name, val) {
4074            if (name in EVENT_DATE_REFINERS) {
4075                console.warn('Could not set date-related prop \'name\'. Use one of the date-related methods instead.');
4076                // TODO: make proper aliasing system?
4077            }
4078            else if (name === 'id') {
4079                val = EVENT_NON_DATE_REFINERS[name](val);
4080                this.mutate({
4081                    standardProps: { publicId: val }, // hardcoded internal name
4082                });
4083            }
4084            else if (name in EVENT_NON_DATE_REFINERS) {
4085                val = EVENT_NON_DATE_REFINERS[name](val);
4086                this.mutate({
4087                    standardProps: { [name]: val },
4088                });
4089            }
4090            else if (name in EVENT_UI_REFINERS) {
4091                let ui = EVENT_UI_REFINERS[name](val);
4092                if (name === 'color') {
4093                    ui = { backgroundColor: val, borderColor: val };
4094                }
4095                else if (name === 'editable') {
4096                    ui = { startEditable: val, durationEditable: val };
4097                }
4098                else {
4099                    ui = { [name]: val };
4100                }
4101                this.mutate({
4102                    standardProps: { ui },
4103                });
4104            }
4105            else {
4106                console.warn(`Could not set prop '${name}'. Use setExtendedProp instead.`);
4107            }
4108        }
4109        setExtendedProp(name, val) {
4110            this.mutate({
4111                extendedProps: { [name]: val },
4112            });
4113        }
4114        setStart(startInput, options = {}) {
4115            let { dateEnv } = this._context;
4116            let start = dateEnv.createMarker(startInput);
4117            if (start && this._instance) { // TODO: warning if parsed bad
4118                let instanceRange = this._instance.range;
4119                let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!?
4120                if (options.maintainDuration) {
4121                    this.mutate({ datesDelta: startDelta });
4122                }
4123                else {
4124                    this.mutate({ startDelta });
4125                }
4126            }
4127        }
4128        setEnd(endInput, options = {}) {
4129            let { dateEnv } = this._context;
4130            let end;
4131            if (endInput != null) {
4132                end = dateEnv.createMarker(endInput);
4133                if (!end) {
4134                    return; // TODO: warning if parsed bad
4135                }
4136            }
4137            if (this._instance) {
4138                if (end) {
4139                    let endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity);
4140                    this.mutate({ endDelta });
4141                }
4142                else {
4143                    this.mutate({ standardProps: { hasEnd: false } });
4144                }
4145            }
4146        }
4147        setDates(startInput, endInput, options = {}) {
4148            let { dateEnv } = this._context;
4149            let standardProps = { allDay: options.allDay };
4150            let start = dateEnv.createMarker(startInput);
4151            let end;
4152            if (!start) {
4153                return; // TODO: warning if parsed bad
4154            }
4155            if (endInput != null) {
4156                end = dateEnv.createMarker(endInput);
4157                if (!end) { // TODO: warning if parsed bad
4158                    return;
4159                }
4160            }
4161            if (this._instance) {
4162                let instanceRange = this._instance.range;
4163                // when computing the diff for an event being converted to all-day,
4164                // compute diff off of the all-day values the way event-mutation does.
4165                if (options.allDay === true) {
4166                    instanceRange = computeAlignedDayRange(instanceRange);
4167                }
4168                let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity);
4169                if (end) {
4170                    let endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity);
4171                    if (durationsEqual(startDelta, endDelta)) {
4172                        this.mutate({ datesDelta: startDelta, standardProps });
4173                    }
4174                    else {
4175                        this.mutate({ startDelta, endDelta, standardProps });
4176                    }
4177                }
4178                else { // means "clear the end"
4179                    standardProps.hasEnd = false;
4180                    this.mutate({ datesDelta: startDelta, standardProps });
4181                }
4182            }
4183        }
4184        moveStart(deltaInput) {
4185            let delta = createDuration(deltaInput);
4186            if (delta) { // TODO: warning if parsed bad
4187                this.mutate({ startDelta: delta });
4188            }
4189        }
4190        moveEnd(deltaInput) {
4191            let delta = createDuration(deltaInput);
4192            if (delta) { // TODO: warning if parsed bad
4193                this.mutate({ endDelta: delta });
4194            }
4195        }
4196        moveDates(deltaInput) {
4197            let delta = createDuration(deltaInput);
4198            if (delta) { // TODO: warning if parsed bad
4199                this.mutate({ datesDelta: delta });
4200            }
4201        }
4202        setAllDay(allDay, options = {}) {
4203            let standardProps = { allDay };
4204            let { maintainDuration } = options;
4205            if (maintainDuration == null) {
4206                maintainDuration = this._context.options.allDayMaintainDuration;
4207            }
4208            if (this._def.allDay !== allDay) {
4209                standardProps.hasEnd = maintainDuration;
4210            }
4211            this.mutate({ standardProps });
4212        }
4213        formatRange(formatInput) {
4214            let { dateEnv } = this._context;
4215            let instance = this._instance;
4216            let formatter = createFormatter(formatInput);
4217            if (this._def.hasEnd) {
4218                return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, {
4219                    forcedStartTzo: instance.forcedStartTzo,
4220                    forcedEndTzo: instance.forcedEndTzo,
4221                });
4222            }
4223            return dateEnv.format(instance.range.start, formatter, {
4224                forcedTzo: instance.forcedStartTzo,
4225            });
4226        }
4227        mutate(mutation) {
4228            let instance = this._instance;
4229            if (instance) {
4230                let def = this._def;
4231                let context = this._context;
4232                let { eventStore } = context.getCurrentData();
4233                let relevantEvents = getRelevantEvents(eventStore, instance.instanceId);
4234                let eventConfigBase = {
4235                    '': {
4236                        display: '',
4237                        startEditable: true,
4238                        durationEditable: true,
4239                        constraints: [],
4240                        overlap: null,
4241                        allows: [],
4242                        backgroundColor: '',
4243                        borderColor: '',
4244                        textColor: '',
4245                        classNames: [],
4246                    },
4247                };
4248                relevantEvents = applyMutationToEventStore(relevantEvents, eventConfigBase, mutation, context);
4249                let oldEvent = new EventImpl(context, def, instance); // snapshot
4250                this._def = relevantEvents.defs[def.defId];
4251                this._instance = relevantEvents.instances[instance.instanceId];
4252                context.dispatch({
4253                    type: 'MERGE_EVENTS',
4254                    eventStore: relevantEvents,
4255                });
4256                context.emitter.trigger('eventChange', {
4257                    oldEvent,
4258                    event: this,
4259                    relatedEvents: buildEventApis(relevantEvents, context, instance),
4260                    revert() {
4261                        context.dispatch({
4262                            type: 'RESET_EVENTS',
4263                            eventStore, // the ORIGINAL store
4264                        });
4265                    },
4266                });
4267            }
4268        }
4269        remove() {
4270            let context = this._context;
4271            let asStore = eventApiToStore(this);
4272            context.dispatch({
4273                type: 'REMOVE_EVENTS',
4274                eventStore: asStore,
4275            });
4276            context.emitter.trigger('eventRemove', {
4277                event: this,
4278                relatedEvents: [],
4279                revert() {
4280                    context.dispatch({
4281                        type: 'MERGE_EVENTS',
4282                        eventStore: asStore,
4283                    });
4284                },
4285            });
4286        }
4287        get source() {
4288            let { sourceId } = this._def;
4289            if (sourceId) {
4290                return new EventSourceImpl(this._context, this._context.getCurrentData().eventSources[sourceId]);
4291            }
4292            return null;
4293        }
4294        get start() {
4295            return this._instance ?
4296                this._context.dateEnv.toDate(this._instance.range.start) :
4297                null;
4298        }
4299        get end() {
4300            return (this._instance && this._def.hasEnd) ?
4301                this._context.dateEnv.toDate(this._instance.range.end) :
4302                null;
4303        }
4304        get startStr() {
4305            let instance = this._instance;
4306            if (instance) {
4307                return this._context.dateEnv.formatIso(instance.range.start, {
4308                    omitTime: this._def.allDay,
4309                    forcedTzo: instance.forcedStartTzo,
4310                });
4311            }
4312            return '';
4313        }
4314        get endStr() {
4315            let instance = this._instance;
4316            if (instance && this._def.hasEnd) {
4317                return this._context.dateEnv.formatIso(instance.range.end, {
4318                    omitTime: this._def.allDay,
4319                    forcedTzo: instance.forcedEndTzo,
4320                });
4321            }
4322            return '';
4323        }
4324        // computable props that all access the def
4325        // TODO: find a TypeScript-compatible way to do this at scale
4326        get id() { return this._def.publicId; }
4327        get groupId() { return this._def.groupId; }
4328        get allDay() { return this._def.allDay; }
4329        get title() { return this._def.title; }
4330        get url() { return this._def.url; }
4331        get display() { return this._def.ui.display || 'auto'; } // bad. just normalize the type earlier
4332        get startEditable() { return this._def.ui.startEditable; }
4333        get durationEditable() { return this._def.ui.durationEditable; }
4334        get constraint() { return this._def.ui.constraints[0] || null; }
4335        get overlap() { return this._def.ui.overlap; }
4336        get allow() { return this._def.ui.allows[0] || null; }
4337        get backgroundColor() { return this._def.ui.backgroundColor; }
4338        get borderColor() { return this._def.ui.borderColor; }
4339        get textColor() { return this._def.ui.textColor; }
4340        // NOTE: user can't modify these because Object.freeze was called in event-def parsing
4341        get classNames() { return this._def.ui.classNames; }
4342        get extendedProps() { return this._def.extendedProps; }
4343        toPlainObject(settings = {}) {
4344            let def = this._def;
4345            let { ui } = def;
4346            let { startStr, endStr } = this;
4347            let res = {};
4348            if (def.title) {
4349                res.title = def.title;
4350            }
4351            if (startStr) {
4352                res.start = startStr;
4353            }
4354            if (endStr) {
4355                res.end = endStr;
4356            }
4357            if (def.publicId) {
4358                res.id = def.publicId;
4359            }
4360            if (def.groupId) {
4361                res.groupId = def.groupId;
4362            }
4363            if (def.url) {
4364                res.url = def.url;
4365            }
4366            if (ui.display && ui.display !== 'auto') {
4367                res.display = ui.display;
4368            }
4369            // TODO: what about recurring-event properties???
4370            // TODO: include startEditable/durationEditable/constraint/overlap/allow
4371            if (settings.collapseColor && ui.backgroundColor && ui.backgroundColor === ui.borderColor) {
4372                res.color = ui.backgroundColor;
4373            }
4374            else {
4375                if (ui.backgroundColor) {
4376                    res.backgroundColor = ui.backgroundColor;
4377                }
4378                if (ui.borderColor) {
4379                    res.borderColor = ui.borderColor;
4380                }
4381            }
4382            if (ui.textColor) {
4383                res.textColor = ui.textColor;
4384            }
4385            if (ui.classNames.length) {
4386                res.classNames = ui.classNames;
4387            }
4388            if (Object.keys(def.extendedProps).length) {
4389                if (settings.collapseExtendedProps) {
4390                    Object.assign(res, def.extendedProps);
4391                }
4392                else {
4393                    res.extendedProps = def.extendedProps;
4394                }
4395            }
4396            return res;
4397        }
4398        toJSON() {
4399            return this.toPlainObject();
4400        }
4401    }
4402    function eventApiToStore(eventApi) {
4403        let def = eventApi._def;
4404        let instance = eventApi._instance;
4405        return {
4406            defs: { [def.defId]: def },
4407            instances: instance
4408                ? { [instance.instanceId]: instance }
4409                : {},
4410        };
4411    }
4412    function buildEventApis(eventStore, context, excludeInstance) {
4413        let { defs, instances } = eventStore;
4414        let eventApis = [];
4415        let excludeInstanceId = excludeInstance ? excludeInstance.instanceId : '';
4416        for (let id in instances) {
4417            let instance = instances[id];
4418            let def = defs[instance.defId];
4419            if (instance.instanceId !== excludeInstanceId) {
4420                eventApis.push(new EventImpl(context, def, instance));
4421            }
4422        }
4423        return eventApis;
4424    }
4425
4426    /*
4427    Specifying nextDayThreshold signals that all-day ranges should be sliced.
4428    */
4429    function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) {
4430        let inverseBgByGroupId = {};
4431        let inverseBgByDefId = {};
4432        let defByGroupId = {};
4433        let bgRanges = [];
4434        let fgRanges = [];
4435        let eventUis = compileEventUis(eventStore.defs, eventUiBases);
4436        for (let defId in eventStore.defs) {
4437            let def = eventStore.defs[defId];
4438            let ui = eventUis[def.defId];
4439            if (ui.display === 'inverse-background') {
4440                if (def.groupId) {
4441                    inverseBgByGroupId[def.groupId] = [];
4442                    if (!defByGroupId[def.groupId]) {
4443                        defByGroupId[def.groupId] = def;
4444                    }
4445                }
4446                else {
4447                    inverseBgByDefId[defId] = [];
4448                }
4449            }
4450        }
4451        for (let instanceId in eventStore.instances) {
4452            let instance = eventStore.instances[instanceId];
4453            let def = eventStore.defs[instance.defId];
4454            let ui = eventUis[def.defId];
4455            let origRange = instance.range;
4456            let normalRange = (!def.allDay && nextDayThreshold) ?
4457                computeVisibleDayRange(origRange, nextDayThreshold) :
4458                origRange;
4459            let slicedRange = intersectRanges(normalRange, framingRange);
4460            if (slicedRange) {
4461                if (ui.display === 'inverse-background') {
4462                    if (def.groupId) {
4463                        inverseBgByGroupId[def.groupId].push(slicedRange);
4464                    }
4465                    else {
4466                        inverseBgByDefId[instance.defId].push(slicedRange);
4467                    }
4468                }
4469                else if (ui.display !== 'none') {
4470                    (ui.display === 'background' ? bgRanges : fgRanges).push({
4471                        def,
4472                        ui,
4473                        instance,
4474                        range: slicedRange,
4475                        isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(),
4476                        isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf(),
4477                    });
4478                }
4479            }
4480        }
4481        for (let groupId in inverseBgByGroupId) { // BY GROUP
4482            let ranges = inverseBgByGroupId[groupId];
4483            let invertedRanges = invertRanges(ranges, framingRange);
4484            for (let invertedRange of invertedRanges) {
4485                let def = defByGroupId[groupId];
4486                let ui = eventUis[def.defId];
4487                bgRanges.push({
4488                    def,
4489                    ui,
4490                    instance: null,
4491                    range: invertedRange,
4492                    isStart: false,
4493                    isEnd: false,
4494                });
4495            }
4496        }
4497        for (let defId in inverseBgByDefId) {
4498            let ranges = inverseBgByDefId[defId];
4499            let invertedRanges = invertRanges(ranges, framingRange);
4500            for (let invertedRange of invertedRanges) {
4501                bgRanges.push({
4502                    def: eventStore.defs[defId],
4503                    ui: eventUis[defId],
4504                    instance: null,
4505                    range: invertedRange,
4506                    isStart: false,
4507                    isEnd: false,
4508                });
4509            }
4510        }
4511        return { bg: bgRanges, fg: fgRanges };
4512    }
4513    function hasBgRendering(def) {
4514        return def.ui.display === 'background' || def.ui.display === 'inverse-background';
4515    }
4516    function setElSeg(el, seg) {
4517        el.fcSeg = seg;
4518    }
4519    function getElSeg(el) {
4520        return el.fcSeg ||
4521            el.parentNode.fcSeg || // for the harness
4522            null;
4523    }
4524    // event ui computation
4525    function compileEventUis(eventDefs, eventUiBases) {
4526        return mapHash(eventDefs, (eventDef) => compileEventUi(eventDef, eventUiBases));
4527    }
4528    function compileEventUi(eventDef, eventUiBases) {
4529        let uis = [];
4530        if (eventUiBases['']) {
4531            uis.push(eventUiBases['']);
4532        }
4533        if (eventUiBases[eventDef.defId]) {
4534            uis.push(eventUiBases[eventDef.defId]);
4535        }
4536        uis.push(eventDef.ui);
4537        return combineEventUis(uis);
4538    }
4539    function sortEventSegs(segs, eventOrderSpecs) {
4540        let objs = segs.map(buildSegCompareObj);
4541        objs.sort((obj0, obj1) => compareByFieldSpecs(obj0, obj1, eventOrderSpecs));
4542        return objs.map((c) => c._seg);
4543    }
4544    // returns a object with all primitive props that can be compared
4545    function buildSegCompareObj(seg) {
4546        let { eventRange } = seg;
4547        let eventDef = eventRange.def;
4548        let range = eventRange.instance ? eventRange.instance.range : eventRange.range;
4549        let start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events
4550        let end = range.end ? range.end.valueOf() : 0; // "
4551        return Object.assign(Object.assign(Object.assign({}, eventDef.extendedProps), eventDef), { id: eventDef.publicId, start,
4552            end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg });
4553    }
4554    function computeSegDraggable(seg, context) {
4555        let { pluginHooks } = context;
4556        let transformers = pluginHooks.isDraggableTransformers;
4557        let { def, ui } = seg.eventRange;
4558        let val = ui.startEditable;
4559        for (let transformer of transformers) {
4560            val = transformer(val, def, ui, context);
4561        }
4562        return val;
4563    }
4564    function computeSegStartResizable(seg, context) {
4565        return seg.isStart && seg.eventRange.ui.durationEditable && context.options.eventResizableFromStart;
4566    }
4567    function computeSegEndResizable(seg, context) {
4568        return seg.isEnd && seg.eventRange.ui.durationEditable;
4569    }
4570    function buildSegTimeText(seg, timeFormat, context, defaultDisplayEventTime, // defaults to true
4571    defaultDisplayEventEnd, // defaults to true
4572    startOverride, endOverride) {
4573        let { dateEnv, options } = context;
4574        let { displayEventTime, displayEventEnd } = options;
4575        let eventDef = seg.eventRange.def;
4576        let eventInstance = seg.eventRange.instance;
4577        if (displayEventTime == null) {
4578            displayEventTime = defaultDisplayEventTime !== false;
4579        }
4580        if (displayEventEnd == null) {
4581            displayEventEnd = defaultDisplayEventEnd !== false;
4582        }
4583        let wholeEventStart = eventInstance.range.start;
4584        let wholeEventEnd = eventInstance.range.end;
4585        let segStart = startOverride || seg.start || seg.eventRange.range.start;
4586        let segEnd = endOverride || seg.end || seg.eventRange.range.end;
4587        let isStartDay = startOfDay(wholeEventStart).valueOf() === startOfDay(segStart).valueOf();
4588        let isEndDay = startOfDay(addMs(wholeEventEnd, -1)).valueOf() === startOfDay(addMs(segEnd, -1)).valueOf();
4589        if (displayEventTime && !eventDef.allDay && (isStartDay || isEndDay)) {
4590            segStart = isStartDay ? wholeEventStart : segStart;
4591            segEnd = isEndDay ? wholeEventEnd : segEnd;
4592            if (displayEventEnd && eventDef.hasEnd) {
4593                return dateEnv.formatRange(segStart, segEnd, timeFormat, {
4594                    forcedStartTzo: startOverride ? null : eventInstance.forcedStartTzo,
4595                    forcedEndTzo: endOverride ? null : eventInstance.forcedEndTzo,
4596                });
4597            }
4598            return dateEnv.format(segStart, timeFormat, {
4599                forcedTzo: startOverride ? null : eventInstance.forcedStartTzo, // nooooo, same
4600            });
4601        }
4602        return '';
4603    }
4604    function getSegMeta(seg, todayRange, nowDate) {
4605        let segRange = seg.eventRange.range;
4606        return {
4607            isPast: segRange.end < (nowDate || todayRange.start),
4608            isFuture: segRange.start >= (nowDate || todayRange.end),
4609            isToday: todayRange && rangeContainsMarker(todayRange, segRange.start),
4610        };
4611    }
4612    function getEventClassNames(props) {
4613        let classNames = ['fc-event'];
4614        if (props.isMirror) {
4615            classNames.push('fc-event-mirror');
4616        }
4617        if (props.isDraggable) {
4618            classNames.push('fc-event-draggable');
4619        }
4620        if (props.isStartResizable || props.isEndResizable) {
4621            classNames.push('fc-event-resizable');
4622        }
4623        if (props.isDragging) {
4624            classNames.push('fc-event-dragging');
4625        }
4626        if (props.isResizing) {
4627            classNames.push('fc-event-resizing');
4628        }
4629        if (props.isSelected) {
4630            classNames.push('fc-event-selected');
4631        }
4632        if (props.isStart) {
4633            classNames.push('fc-event-start');
4634        }
4635        if (props.isEnd) {
4636            classNames.push('fc-event-end');
4637        }
4638        if (props.isPast) {
4639            classNames.push('fc-event-past');
4640        }
4641        if (props.isToday) {
4642            classNames.push('fc-event-today');
4643        }
4644        if (props.isFuture) {
4645            classNames.push('fc-event-future');
4646        }
4647        return classNames;
4648    }
4649    function buildEventRangeKey(eventRange) {
4650        return eventRange.instance
4651            ? eventRange.instance.instanceId
4652            : `${eventRange.def.defId}:${eventRange.range.start.toISOString()}`;
4653        // inverse-background events don't have specific instances. TODO: better solution
4654    }
4655    function getSegAnchorAttrs(seg, context) {
4656        let { def, instance } = seg.eventRange;
4657        let { url } = def;
4658        if (url) {
4659            return { href: url };
4660        }
4661        let { emitter, options } = context;
4662        let { eventInteractive } = options;
4663        if (eventInteractive == null) {
4664            eventInteractive = def.interactive;
4665            if (eventInteractive == null) {
4666                eventInteractive = Boolean(emitter.hasHandlers('eventClick'));
4667            }
4668        }
4669        // mock what happens in EventClicking
4670        if (eventInteractive) {
4671            // only attach keyboard-related handlers because click handler is already done in EventClicking
4672            return createAriaKeyboardAttrs((ev) => {
4673                emitter.trigger('eventClick', {
4674                    el: ev.target,
4675                    event: new EventImpl(context, def, instance),
4676                    jsEvent: ev,
4677                    view: context.viewApi,
4678                });
4679            });
4680        }
4681        return {};
4682    }
4683
4684    const STANDARD_PROPS = {
4685        start: identity,
4686        end: identity,
4687        allDay: Boolean,
4688    };
4689    function parseDateSpan(raw, dateEnv, defaultDuration) {
4690        let span = parseOpenDateSpan(raw, dateEnv);
4691        let { range } = span;
4692        if (!range.start) {
4693            return null;
4694        }
4695        if (!range.end) {
4696            if (defaultDuration == null) {
4697                return null;
4698            }
4699            range.end = dateEnv.add(range.start, defaultDuration);
4700        }
4701        return span;
4702    }
4703    /*
4704    TODO: somehow combine with parseRange?
4705    Will return null if the start/end props were present but parsed invali
vendor: 4,475 bytes, lines 4705-4818
4705dly.
4706    */
4707    function parseOpenDateSpan(raw, dateEnv) {
4708        let { refined: standardProps, extra } = refineProps(raw, STANDARD_PROPS);
4709        let startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null;
4710        let endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null;
4711        let { allDay } = standardProps;
4712        if (allDay == null) {
4713            allDay = (startMeta && startMeta.isTimeUnspecified) &&
4714                (!endMeta || endMeta.isTimeUnspecified);
4715        }
4716        return Object.assign({ range: {
4717                start: startMeta ? startMeta.marker : null,
4718                end: endMeta ? endMeta.marker : null,
4719            }, allDay }, extra);
4720    }
4721    function isDateSpansEqual(span0, span1) {
4722        return rangesEqual(span0.range, span1.range) &&
4723            span0.allDay === span1.allDay &&
4724            isSpanPropsEqual(span0, span1);
4725    }
4726    // the NON-DATE-RELATED props
4727    function isSpanPropsEqual(span0, span1) {
4728        for (let propName in span1) {
4729            if (propName !== 'range' && propName !== 'allDay') {
4730                if (span0[propName] !== span1[propName]) {
4731                    return false;
4732                }
4733            }
4734        }
4735        // are there any props that span0 has that span1 DOESN'T have?
4736        // both have range/allDay, so no need to special-case.
4737        for (let propName in span0) {
4738            if (!(propName in span1)) {
4739                return false;
4740            }
4741        }
4742        return true;
4743    }
4744    function buildDateSpanApi(span, dateEnv) {
4745        return Object.assign(Object.assign({}, buildRangeApi(span.range, dateEnv, span.allDay)), { allDay: span.allDay });
4746    }
4747    function buildRangeApiWithTimeZone(range, dateEnv, omitTime) {
4748        return Object.assign(Object.assign({}, buildRangeApi(range, dateEnv, omitTime)), { timeZone: dateEnv.timeZone });
4749    }
4750    function buildRangeApi(range, dateEnv, omitTime) {
4751        return {
4752            start: dateEnv.toDate(range.start),
4753            end: dateEnv.toDate(range.end),
4754            startStr: dateEnv.formatIso(range.start, { omitTime }),
4755            endStr: dateEnv.formatIso(range.end, { omitTime }),
4756        };
4757    }
4758    function fabricateEventRange(dateSpan, eventUiBases, context) {
4759        let res = refineEventDef({ editable: false }, context);
4760        let def = parseEventDef(res.refined, res.extra, '', // sourceId
4761        dateSpan.allDay, true, // hasEnd
4762        context);
4763        return {
4764            def,
4765            ui: compileEventUi(def, eventUiBases),
4766            instance: createEventInstance(def.defId, dateSpan.range),
4767            range: dateSpan.range,
4768            isStart: true,
4769            isEnd: true,
4770        };
4771    }
4772
4773    /*
4774    given a function that resolves a result asynchronously.
4775    the function can either call passed-in success and failure callbacks,
4776    or it can return a promise.
4777    if you need to pass additional params to func, bind them first.
4778    */
4779    function unpromisify(func, normalizedSuccessCallback, normalizedFailureCallback) {
4780        // guard against success/failure callbacks being called more than once
4781        // and guard against a promise AND callback being used together.
4782        let isResolved = false;
4783        let wrappedSuccess = function (res) {
4784            if (!isResolved) {
4785                isResolved = true;
4786                normalizedSuccessCallback(res);
4787            }
4788        };
4789        let wrappedFailure = function (error) {
4790            if (!isResolved) {
4791                isResolved = true;
4792                normalizedFailureCallback(error);
4793            }
4794        };
4795        let res = func(wrappedSuccess, wrappedFailure);
4796        if (res && typeof res.then === 'function') {
4797            res.then(wrappedSuccess, wrappedFailure);
4798        }
4799    }
4800
4801    let eventSourceDef$1 = {
4802        parseMeta(refined) {
4803            if (typeof refined.events === 'function') {
4804                return refined.events;
4805            }
4806            return null;
4807        },
4808        fetch(arg, successCallback, errorCallback) {
4809            const { dateEnv } = arg.context;
4810            const func = arg.eventSource.meta;
4811            unpromisify(func.bind(null, buildRangeApiWithTimeZone(arg.range, dateEnv)), (rawEvents) => successCallback({ rawEvents }), errorCallback);
4812        },
4813    };
4814    const funcEventSourcePlugin = createPlugin({
4815        name: 'func-event-source',
4816        eventSourceDefs: [eventSourceDef$1],
4817    });
4818
vendor: 2,688 bytes, lines 4819-4894
4819    class JsonRequestError extends Error {
4820        constructor(message, response) {
4821            super(message);
4822            this.response = response;
4823        }
4824    }
4825    function requestJson(method, url, params) {
4826        method = method.toUpperCase();
4827        const fetchOptions = {
4828            method,
4829        };
4830        if (method === 'GET') {
4831            url += (url.indexOf('?') === -1 ? '?' : '&') +
4832                new URLSearchParams(params);
4833        }
4834        else {
4835            fetchOptions.body = new URLSearchParams(params);
4836            fetchOptions.headers = {
4837                'Content-Type': 'application/x-www-form-urlencoded',
4838            };
4839        }
4840        return fetch(url, fetchOptions).then((fetchRes) => {
4841            if (fetchRes.ok) {
4842                return fetchRes.json().then((parsedResponse) => {
4843                    return [parsedResponse, fetchRes];
4844                }, () => {
4845                    throw new JsonRequestError('Failure parsing JSON', fetchRes);
4846                });
4847            }
4848            else {
4849                throw new JsonRequestError('Request failed', fetchRes);
4850            }
4851        });
4852    }
4853
4854    const JSON_FEED_EVENT_SOURCE_REFINERS = {
4855        method: String,
4856        extraParams: identity,
4857        startParam: String,
4858        endParam: String,
4859        timeZoneParam: String,
4860    };
4861
4862    let eventSourceDef = {
4863        parseMeta(refined) {
4864            if (refined.url && (refined.format === 'json' || !refined.format)) {
4865                return {
4866                    url: refined.url,
4867                    format: 'json',
4868                    method: (refined.method || 'GET').toUpperCase(),
4869                    extraParams: refined.extraParams,
4870                    startParam: refined.startParam,
4871                    endParam: refined.endParam,
4872                    timeZoneParam: refined.timeZoneParam,
4873                };
4874            }
4875            return null;
4876        },
4877        fetch(arg, successCallback, errorCallback) {
4878            const { meta } = arg.eventSource;
4879            const requestParams = buildRequestParams(meta, arg.range, arg.context);
4880            requestJson(meta.method, meta.url, requestParams).then(([rawEvents, response]) => {
4881                successCallback({ rawEvents, response });
4882            }, errorCallback);
4883        },
4884    };
4885    const jsonFeedEventSourcePlugin = createPlugin({
4886        name: 'json-event-source',
4887        eventSourceRefiners: JSON_FEED_EVENT_SOURCE_REFINERS,
4888        eventSourceDefs: [eventSourceDef],
4889    });
4890    function buildRequestParams(meta, range, context) {
4891        let { dateEnv, options } = context;
4892        let startParam;
4893        let endParam;
4894        let timeZoneParam;
vendor: 12,932 bytes, lines 4895-5241
4895        let customRequestParams;
4896        let params = {};
4897        startParam = meta.startParam;
4898        if (startParam == null) {
4899            startParam = options.startParam;
4900        }
4901        endParam = meta.endParam;
4902        if (endParam == null) {
4903            endParam = options.endParam;
4904        }
4905        timeZoneParam = meta.timeZoneParam;
4906        if (timeZoneParam == null) {
4907            timeZoneParam = options.timeZoneParam;
4908        }
4909        // retrieve any outbound GET/POST data from the options
4910        if (typeof meta.extraParams === 'function') {
4911            // supplied as a function that returns a key/value object
4912            customRequestParams = meta.extraParams();
4913        }
4914        else {
4915            // probably supplied as a straight key/value object
4916            customRequestParams = meta.extraParams || {};
4917        }
4918        Object.assign(params, customRequestParams);
4919        params[startParam] = dateEnv.formatIso(range.start);
4920        params[endParam] = dateEnv.formatIso(range.end);
4921        if (dateEnv.timeZone !== 'local') {
4922            params[timeZoneParam] = dateEnv.timeZone;
4923        }
4924        return params;
4925    }
4926
4927    const SIMPLE_RECURRING_REFINERS = {
4928        daysOfWeek: identity,
4929        startTime: createDuration,
4930        endTime: createDuration,
4931        duration: createDuration,
4932        startRecur: identity,
4933        endRecur: identity,
4934    };
4935
4936    let recurring = {
4937        parse(refined, dateEnv) {
4938            if (refined.daysOfWeek || refined.startTime || refined.endTime || refined.startRecur || refined.endRecur) {
4939                let recurringData = {
4940                    daysOfWeek: refined.daysOfWeek || null,
4941                    startTime: refined.startTime || null,
4942                    endTime: refined.endTime || null,
4943                    startRecur: refined.startRecur ? dateEnv.createMarker(refined.startRecur) : null,
4944                    endRecur: refined.endRecur ? dateEnv.createMarker(refined.endRecur) : null,
4945                };
4946                let duration;
4947                if (refined.duration) {
4948                    duration = refined.duration;
4949                }
4950                if (!duration && refined.startTime && refined.endTime) {
4951                    duration = subtractDurations(refined.endTime, refined.startTime);
4952                }
4953                return {
4954                    allDayGuess: Boolean(!refined.startTime && !refined.endTime),
4955                    duration,
4956                    typeData: recurringData, // doesn't need endTime anymore but oh well
4957                };
4958            }
4959            return null;
4960        },
4961        expand(typeData, framingRange, dateEnv) {
4962            let clippedFramingRange = intersectRanges(framingRange, { start: typeData.startRecur, end: typeData.endRecur });
4963            if (clippedFramingRange) {
4964                return expandRanges(typeData.daysOfWeek, typeData.startTime, clippedFramingRange, dateEnv);
4965            }
4966            return [];
4967        },
4968    };
4969    const simpleRecurringEventsPlugin = createPlugin({
4970        name: 'simple-recurring-event',
4971        recurringTypes: [recurring],
4972        eventRefiners: SIMPLE_RECURRING_REFINERS,
4973    });
4974    function expandRanges(daysOfWeek, startTime, framingRange, dateEnv) {
4975        let dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null;
4976        let dayMarker = startOfDay(framingRange.start);
4977        let endMarker = framingRange.end;
4978        let instanceStarts = [];
4979        while (dayMarker < endMarker) {
4980            let instanceStart;
4981            // if everyday, or this particular day-of-week
4982            if (!dowHash || dowHash[dayMarker.getUTCDay()]) {
4983                if (startTime) {
4984                    instanceStart = dateEnv.add(dayMarker, startTime);
4985                }
4986                else {
4987                    instanceStart = dayMarker;
4988                }
4989                instanceStarts.push(instanceStart);
4990            }
4991            dayMarker = addDays(dayMarker, 1);
4992        }
4993        return instanceStarts;
4994    }
4995
4996    const changeHandlerPlugin = createPlugin({
4997        name: 'change-handler',
4998        optionChangeHandlers: {
4999            events(events, context) {
5000                handleEventSources([events], context);
5001            },
5002            eventSources: handleEventSources,
5003        },
5004    });
5005    /*
5006    BUG: if `event` was supplied, all previously-given `eventSources` will be wiped out
5007    */
5008    function handleEventSources(inputs, context) {
5009        let unfoundSources = hashValuesToArray(context.getCurrentData().eventSources);
5010        let newInputs = [];
5011        for (let input of inputs) {
5012            let inputFound = false;
5013            for (let i = 0; i < unfoundSources.length; i += 1) {
5014                if (unfoundSources[i]._raw === input) {
5015                    unfoundSources.splice(i, 1); // delete
5016                    inputFound = true;
5017                    break;
5018                }
5019            }
5020            if (!inputFound) {
5021                newInputs.push(input);
5022            }
5023        }
5024        for (let unfoundSource of unfoundSources) {
5025            context.dispatch({
5026                type: 'REMOVE_EVENT_SOURCE',
5027                sourceId: unfoundSource.sourceId,
5028            });
5029        }
5030        for (let newInput of newInputs) {
5031            context.calendarApi.addEventSource(newInput);
5032        }
5033    }
5034
5035    function handleDateProfile(dateProfile, context) {
5036        context.emitter.trigger('datesSet', Object.assign(Object.assign({}, buildRangeApiWithTimeZone(dateProfile.activeRange, context.dateEnv)), { view: context.viewApi }));
5037    }
5038
5039    function handleEventStore(eventStore, context) {
5040        let { emitter } = context;
5041        if (emitter.hasHandlers('eventsSet')) {
5042            emitter.trigger('eventsSet', buildEventApis(eventStore, context));
5043        }
5044    }
5045
5046    /*
5047    this array is exposed on the root namespace so that UMD plugins can add to it.
5048    see the rollup-bundles script.
5049    */
5050    const globalPlugins = [
5051        arrayEventSourcePlugin,
5052        funcEventSourcePlugin,
5053        jsonFeedEventSourcePlugin,
5054        simpleRecurringEventsPlugin,
5055        changeHandlerPlugin,
5056        createPlugin({
5057            name: 'misc',
5058            isLoadingFuncs: [
5059                (state) => computeEventSourcesLoading(state.eventSources),
5060            ],
5061            propSetHandlers: {
5062                dateProfile: handleDateProfile,
5063                eventStore: handleEventStore,
5064            },
5065        }),
5066    ];
5067
5068    let canVGrowWithinCell;
5069    function getCanVGrowWithinCell() {
5070        if (canVGrowWithinCell == null) {
5071            canVGrowWithinCell = computeCanVGrowWithinCell();
5072        }
5073        return canVGrowWithinCell;
5074    }
5075    function computeCanVGrowWithinCell() {
5076        // for SSR, because this function is call immediately at top-level
5077        // TODO: just make this logic execute top-level, immediately, instead of doing lazily
5078        if (typeof document === 'undefined') {
5079            return true;
5080        }
5081        let el = document.createElement('div');
5082        el.style.position = 'absolute';
5083        el.style.top = '0px';
5084        el.style.left = '0px';
5085        el.innerHTML = '<table><tr><td><div></div></td></tr></table>';
5086        el.querySelector('table').style.height = '100px';
5087        el.querySelector('div').style.height = '100%';
5088        document.body.appendChild(el);
5089        let div = el.querySelector('div');
5090        let possible = div.offsetHeight > 0;
5091        document.body.removeChild(el);
5092        return possible;
5093    }
5094
5095    class CalendarRoot extends BaseComponent {
5096        constructor() {
5097            super(...arguments);
5098            this.state = {
5099                forPrint: false,
5100            };
5101            this.handleBeforePrint = () => {
5102                this.setState({ forPrint: true });
5103            };
5104            this.handleAfterPrint = () => {
5105                this.setState({ forPrint: false });
5106            };
5107        }
5108        render() {
5109            let { props } = this;
5110            let { options } = props;
5111            let { forPrint } = this.state;
5112            let isHeightAuto = forPrint || options.height === 'auto' || options.contentHeight === 'auto';
5113            let height = (!isHeightAuto && options.height != null) ? options.height : '';
5114            let classNames = [
5115                'fc',
5116                forPrint ? 'fc-media-print' : 'fc-media-screen',
5117                `fc-direction-${options.direction}`,
5118                props.theme.getClass('root'),
5119            ];
5120            if (!getCanVGrowWithinCell()) {
5121                classNames.push('fc-liquid-hack');
5122            }
5123            return props.children(classNames, height, isHeightAuto, forPrint);
5124        }
5125        componentDidMount() {
5126            let { emitter } = this.props;
5127            emitter.on('_beforeprint', this.handleBeforePrint);
5128            emitter.on('_afterprint', this.handleAfterPrint);
5129        }
5130        componentWillUnmount() {
5131            let { emitter } = this.props;
5132            emitter.off('_beforeprint', this.handleBeforePrint);
5133            emitter.off('_afterprint', this.handleAfterPrint);
5134        }
5135    }
5136
5137    class Interaction {
5138        constructor(settings) {
5139            this.component = settings.component;
5140            this.isHitComboAllowed = settings.isHitComboAllowed || null;
5141        }
5142        destroy() {
5143        }
5144    }
5145    function parseInteractionSettings(component, input) {
5146        return {
5147            component,
5148            el: input.el,
5149            useEventCenter: input.useEventCenter != null ? input.useEventCenter : true,
5150            isHitComboAllowed: input.isHitComboAllowed || null,
5151        };
5152    }
5153    function interactionSettingsToStore(settings) {
5154        return {
5155            [settings.component.uid]: settings,
5156        };
5157    }
5158    // global state
5159    const interactionSettingsStore = {};
5160
5161    class CalendarImpl {
5162        getCurrentData() {
5163            return this.currentDataManager.getCurrentData();
5164        }
5165        dispatch(action) {
5166            this.currentDataManager.dispatch(action);
5167        }
5168        get view() { return this.getCurrentData().viewApi; }
5169        batchRendering(callback) {
5170            callback();
5171        }
5172        updateSize() {
5173            this.trigger('_resize', true);
5174        }
5175        // Options
5176        // -----------------------------------------------------------------------------------------------------------------
5177        setOption(name, val) {
5178            this.dispatch({
5179                type: 'SET_OPTION',
5180                optionName: name,
5181                rawOptionValue: val,
5182            });
5183        }
5184        getOption(name) {
5185            return this.currentDataManager.currentCalendarOptionsInput[name];
5186        }
5187        getAvailableLocaleCodes() {
5188            return Object.keys(this.getCurrentData().availableRawLocales);
5189        }
5190        // Trigger
5191        // -----------------------------------------------------------------------------------------------------------------
5192        on(handlerName, handler) {
5193            let { currentDataManager } = this;
5194            if (currentDataManager.currentCalendarOptionsRefiners[handlerName]) {
5195                currentDataManager.emitter.on(handlerName, handler);
5196            }
5197            else {
5198                console.warn(`Unknown listener name '${handlerName}'`);
5199            }
5200        }
5201        off(handlerName, handler) {
5202            this.currentDataManager.emitter.off(handlerName, handler);
5203        }
5204        // not meant for public use
5205        trigger(handlerName, ...args) {
5206            this.currentDataManager.emitter.trigger(handlerName, ...args);
5207        }
5208        // View
5209        // -----------------------------------------------------------------------------------------------------------------
5210        changeView(viewType, dateOrRange) {
5211            this.batchRendering(() => {
5212                this.unselect();
5213                if (dateOrRange) {
5214                    if (dateOrRange.start && dateOrRange.end) { // a range
5215                        this.dispatch({
5216                            type: 'CHANGE_VIEW_TYPE',
5217                            viewType,
5218                        });
5219                        this.dispatch({
5220                            type: 'SET_OPTION',
5221                            optionName: 'visibleRange',
5222                            rawOptionValue: dateOrRange,
5223                        });
5224                    }
5225                    else {
5226                        let { dateEnv } = this.getCurrentData();
5227                        this.dispatch({
5228                            type: 'CHANGE_VIEW_TYPE',
5229                            viewType,
5230                            dateMarker: dateEnv.createMarker(dateOrRange),
5231                        });
5232                    }
5233                }
5234                else {
5235                    this.dispatch({
5236                        type: 'CHANGE_VIEW_TYPE',
5237                        viewType,
5238                    });
5239                }
5240            });
5241        }
vendor: 21,600 bytes, lines 5242-5773
5242        // Forces navigation to a view for the given date.
5243        // `viewType` can be a specific view name or a generic one like "week" or "day".
5244        // needs to change
5245        zoomTo(dateMarker, viewType) {
5246            let state = this.getCurrentData();
5247            let spec;
5248            viewType = viewType || 'day'; // day is default zoom
5249            spec = state.viewSpecs[viewType] || this.getUnitViewSpec(viewType);
5250            this.unselect();
5251            if (spec) {
5252                this.dispatch({
5253                    type: 'CHANGE_VIEW_TYPE',
5254                    viewType: spec.type,
5255                    dateMarker,
5256                });
5257            }
5258            else {
5259                this.dispatch({
5260                    type: 'CHANGE_DATE',
5261                    dateMarker,
5262                });
5263            }
5264        }
5265        // Given a duration singular unit, like "week" or "day", finds a matching view spec.
5266        // Preference is given to views that have corresponding buttons.
5267        getUnitViewSpec(unit) {
5268            let { viewSpecs, toolbarConfig } = this.getCurrentData();
5269            let viewTypes = [].concat(toolbarConfig.header ? toolbarConfig.header.viewsWithButtons : [], toolbarConfig.footer ? toolbarConfig.footer.viewsWithButtons : []);
5270            let i;
5271            let spec;
5272            for (let viewType in viewSpecs) {
5273                viewTypes.push(viewType);
5274            }
5275            for (i = 0; i < viewTypes.length; i += 1) {
5276                spec = viewSpecs[viewTypes[i]];
5277                if (spec) {
5278                    if (spec.singleUnit === unit) {
5279                        return spec;
5280                    }
5281                }
5282            }
5283            return null;
5284        }
5285        // Current Date
5286        // -----------------------------------------------------------------------------------------------------------------
5287        prev() {
5288            this.unselect();
5289            this.dispatch({ type: 'PREV' });
5290        }
5291        next() {
5292            this.unselect();
5293            this.dispatch({ type: 'NEXT' });
5294        }
5295        prevYear() {
5296            let state = this.getCurrentData();
5297            this.unselect();
5298            this.dispatch({
5299                type: 'CHANGE_DATE',
5300                dateMarker: state.dateEnv.addYears(state.currentDate, -1),
5301            });
5302        }
5303        nextYear() {
5304            let state = this.getCurrentData();
5305            this.unselect();
5306            this.dispatch({
5307                type: 'CHANGE_DATE',
5308                dateMarker: state.dateEnv.addYears(state.currentDate, 1),
5309            });
5310        }
5311        today() {
5312            let state = this.getCurrentData();
5313            this.unselect();
5314            this.dispatch({
5315                type: 'CHANGE_DATE',
5316                dateMarker: getNow(state.calendarOptions.now, state.dateEnv),
5317            });
5318        }
5319        gotoDate(zonedDateInput) {
5320            let state = this.getCurrentData();
5321            this.unselect();
5322            this.dispatch({
5323                type: 'CHANGE_DATE',
5324                dateMarker: state.dateEnv.createMarker(zonedDateInput),
5325            });
5326        }
5327        incrementDate(deltaInput) {
5328            let state = this.getCurrentData();
5329            let delta = createDuration(deltaInput);
5330            if (delta) { // else, warn about invalid input?
5331                this.unselect();
5332                this.dispatch({
5333                    type: 'CHANGE_DATE',
5334                    dateMarker: state.dateEnv.add(state.currentDate, delta),
5335                });
5336            }
5337        }
5338        getDate() {
5339            let state = this.getCurrentData();
5340            return state.dateEnv.toDate(state.currentDate);
5341        }
5342        // Date Formatting Utils
5343        // -----------------------------------------------------------------------------------------------------------------
5344        formatDate(d, formatter) {
5345            let { dateEnv } = this.getCurrentData();
5346            return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter));
5347        }
5348        // `settings` is for formatter AND isEndExclusive
5349        formatRange(d0, d1, settings) {
5350            let { dateEnv } = this.getCurrentData();
5351            return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings), settings);
5352        }
5353        formatIso(d, omitTime) {
5354            let { dateEnv } = this.getCurrentData();
5355            return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime });
5356        }
5357        // Date Selection / Event Selection / DayClick
5358        // -----------------------------------------------------------------------------------------------------------------
5359        select(dateOrObj, endDate) {
5360            let selectionInput;
5361            if (endDate == null) {
5362                if (dateOrObj.start != null) {
5363                    selectionInput = dateOrObj;
5364                }
5365                else {
5366                    selectionInput = {
5367                        start: dateOrObj,
5368                        end: null,
5369                    };
5370                }
5371            }
5372            else {
5373                selectionInput = {
5374                    start: dateOrObj,
5375                    end: endDate,
5376                };
5377            }
5378            let state = this.getCurrentData();
5379            let selection = parseDateSpan(selectionInput, state.dateEnv, createDuration({ days: 1 }));
5380            if (selection) { // throw parse error otherwise?
5381                this.dispatch({ type: 'SELECT_DATES', selection });
5382                triggerDateSelect(selection, null, state);
5383            }
5384        }
5385        unselect(pev) {
5386            let state = this.getCurrentData();
5387            if (state.dateSelection) {
5388                this.dispatch({ type: 'UNSELECT_DATES' });
5389                triggerDateUnselect(pev, state);
5390            }
5391        }
5392        // Public Events API
5393        // -----------------------------------------------------------------------------------------------------------------
5394        addEvent(eventInput, sourceInput) {
5395            if (eventInput instanceof EventImpl) {
5396                let def = eventInput._def;
5397                let instance = eventInput._instance;
5398                let currentData = this.getCurrentData();
5399                // not already present? don't want to add an old snapshot
5400                if (!currentData.eventStore.defs[def.defId]) {
5401                    this.dispatch({
5402                        type: 'ADD_EVENTS',
5403                        eventStore: eventTupleToStore({ def, instance }), // TODO: better util for two args?
5404                    });
5405                    this.triggerEventAdd(eventInput);
5406                }
5407                return eventInput;
5408            }
5409            let state = this.getCurrentData();
5410            let eventSource;
5411            if (sourceInput instanceof EventSourceImpl) {
5412                eventSource = sourceInput.internalEventSource;
5413            }
5414            else if (typeof sourceInput === 'boolean') {
5415                if (sourceInput) { // true. part of the first event source
5416                    [eventSource] = hashValuesToArray(state.eventSources);
5417                }
5418            }
5419            else if (sourceInput != null) { // an ID. accepts a number too
5420                let sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function
5421                if (!sourceApi) {
5422                    console.warn(`Could not find an event source with ID "${sourceInput}"`); // TODO: test
5423                    return null;
5424                }
5425                eventSource = sourceApi.internalEventSource;
5426            }
5427            let tuple = parseEvent(eventInput, eventSource, state, false);
5428            if (tuple) {
5429                let newEventApi = new EventImpl(state, tuple.def, tuple.def.recurringDef ? null : tuple.instance);
5430                this.dispatch({
5431                    type: 'ADD_EVENTS',
5432                    eventStore: eventTupleToStore(tuple),
5433                });
5434                this.triggerEventAdd(newEventApi);
5435                return newEventApi;
5436            }
5437            return null;
5438        }
5439        triggerEventAdd(eventApi) {
5440            let { emitter } = this.getCurrentData();
5441            emitter.trigger('eventAdd', {
5442                event: eventApi,
5443                relatedEvents: [],
5444                revert: () => {
5445                    this.dispatch({
5446                        type: 'REMOVE_EVENTS',
5447                        eventStore: eventApiToStore(eventApi),
5448                    });
5449                },
5450            });
5451        }
5452        // TODO: optimize
5453        getEventById(id) {
5454            let state = this.getCurrentData();
5455            let { defs, instances } = state.eventStore;
5456            id = String(id);
5457            for (let defId in defs) {
5458                let def = defs[defId];
5459                if (def.publicId === id) {
5460                    if (def.recurringDef) {
5461                        return new EventImpl(state, def, null);
5462                    }
5463                    for (let instanceId in instances) {
5464                        let instance = instances[instanceId];
5465                        if (instance.defId === def.defId) {
5466                            return new EventImpl(state, def, instance);
5467                        }
5468                    }
5469                }
5470            }
5471            return null;
5472        }
5473        getEvents() {
5474            let currentData = this.getCurrentData();
5475            return buildEventApis(currentData.eventStore, currentData);
5476        }
5477        removeAllEvents() {
5478            this.dispatch({ type: 'REMOVE_ALL_EVENTS' });
5479        }
5480        // Public Event Sources API
5481        // -----------------------------------------------------------------------------------------------------------------
5482        getEventSources() {
5483            let state = this.getCurrentData();
5484            let sourceHash = state.eventSources;
5485            let sourceApis = [];
5486            for (let internalId in sourceHash) {
5487                sourceApis.push(new EventSourceImpl(state, sourceHash[internalId]));
5488            }
5489            return sourceApis;
5490        }
5491        getEventSourceById(id) {
5492            let state = this.getCurrentData();
5493            let sourceHash = state.eventSources;
5494            id = String(id);
5495            for (let sourceId in sourceHash) {
5496                if (sourceHash[sourceId].publicId === id) {
5497                    return new EventSourceImpl(state, sourceHash[sourceId]);
5498                }
5499            }
5500            return null;
5501        }
5502        addEventSource(sourceInput) {
5503            let state = this.getCurrentData();
5504            if (sourceInput instanceof EventSourceImpl) {
5505                // not already present? don't want to add an old snapshot
5506                if (!state.eventSources[sourceInput.internalEventSource.sourceId]) {
5507                    this.dispatch({
5508                        type: 'ADD_EVENT_SOURCES',
5509                        sources: [sourceInput.internalEventSource],
5510                    });
5511                }
5512                return sourceInput;
5513            }
5514            let eventSource = parseEventSource(sourceInput, state);
5515            if (eventSource) { // TODO: error otherwise?
5516                this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] });
5517                return new EventSourceImpl(state, eventSource);
5518            }
5519            return null;
5520        }
5521        removeAllEventSources() {
5522            this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' });
5523        }
5524        refetchEvents() {
5525            this.dispatch({ type: 'FETCH_EVENT_SOURCES', isRefetch: true });
5526        }
5527        // Scroll
5528        // -----------------------------------------------------------------------------------------------------------------
5529        scrollToTime(timeInput) {
5530            let time = createDuration(timeInput);
5531            if (time) {
5532                this.trigger('_scrollRequest', { time });
5533            }
5534        }
5535    }
5536
5537    function pointInsideRect(point, rect) {
5538        return point.left >= rect.left &&
5539            point.left < rect.right &&
5540            point.top >= rect.top &&
5541            point.top < rect.bottom;
5542    }
5543    // Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false
5544    function intersectRects(rect1, rect2) {
5545        let res = {
5546            left: Math.max(rect1.left, rect2.left),
5547            right: Math.min(rect1.right, rect2.right),
5548            top: Math.max(rect1.top, rect2.top),
5549            bottom: Math.min(rect1.bottom, rect2.bottom),
5550        };
5551        if (res.left < res.right && res.top < res.bottom) {
5552            return res;
5553        }
5554        return false;
5555    }
5556    function translateRect(rect, deltaX, deltaY) {
5557        return {
5558            left: rect.left + deltaX,
5559            right: rect.right + deltaX,
5560            top: rect.top + deltaY,
5561            bottom: rect.bottom + deltaY,
5562        };
5563    }
5564    // Returns a new point that will have been moved to reside within the given rectangle
5565    function constrainPoint(point, rect) {
5566        return {
5567            left: Math.min(Math.max(point.left, rect.left), rect.right),
5568            top: Math.min(Math.max(point.top, rect.top), rect.bottom),
5569        };
5570    }
5571    // Returns a point that is the center of the given rectangle
5572    function getRectCenter(rect) {
5573        return {
5574            left: (rect.left + rect.right) / 2,
5575            top: (rect.top + rect.bottom) / 2,
5576        };
5577    }
5578    // Subtracts point2's coordinates from point1's coordinates, returning a delta
5579    function diffPoints(point1, point2) {
5580        return {
5581            left: point1.left - point2.left,
5582            top: point1.top - point2.top,
5583        };
5584    }
5585
5586    const EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere
5587    class Splitter {
5588        constructor() {
5589            this.getKeysForEventDefs = memoize(this._getKeysForEventDefs);
5590            this.splitDateSelection = memoize(this._splitDateSpan);
5591            this.splitEventStore = memoize(this._splitEventStore);
5592            this.splitIndividualUi = memoize(this._splitIndividualUi);
5593            this.splitEventDrag = memoize(this._splitInteraction);
5594            this.splitEventResize = memoize(this._splitInteraction);
5595            this.eventUiBuilders = {}; // TODO: typescript protection
5596        }
5597        splitProps(props) {
5598            let keyInfos = this.getKeyInfo(props);
5599            let defKeys = this.getKeysForEventDefs(props.eventStore);
5600            let dateSelections = this.splitDateSelection(props.dateSelection);
5601            let individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases*
5602            let eventStores = this.splitEventStore(props.eventStore, defKeys);
5603            let eventDrags = this.splitEventDrag(props.eventDrag);
5604            let eventResizes = this.splitEventResize(props.eventResize);
5605            let splitProps = {};
5606            this.eventUiBuilders = mapHash(keyInfos, (info, key) => this.eventUiBuilders[key] || memoize(buildEventUiForKey));
5607            for (let key in keyInfos) {
5608                let keyInfo = keyInfos[key];
5609                let eventStore = eventStores[key] || EMPTY_EVENT_STORE;
5610                let buildEventUi = this.eventUiBuilders[key];
5611                splitProps[key] = {
5612                    businessHours: keyInfo.businessHours || props.businessHours,
5613                    dateSelection: dateSelections[key] || null,
5614                    eventStore,
5615                    eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]),
5616                    eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '',
5617                    eventDrag: eventDrags[key] || null,
5618                    eventResize: eventResizes[key] || null,
5619                };
5620            }
5621            return splitProps;
5622        }
5623        _splitDateSpan(dateSpan) {
5624            let dateSpans = {};
5625            if (dateSpan) {
5626                let keys = this.getKeysForDateSpan(dateSpan);
5627                for (let key of keys) {
5628                    dateSpans[key] = dateSpan;
5629                }
5630            }
5631            return dateSpans;
5632        }
5633        _getKeysForEventDefs(eventStore) {
5634            return mapHash(eventStore.defs, (eventDef) => this.getKeysForEventDef(eventDef));
5635        }
5636        _splitEventStore(eventStore, defKeys) {
5637            let { defs, instances } = eventStore;
5638            let splitStores = {};
5639            for (let defId in defs) {
5640                for (let key of defKeys[defId]) {
5641                    if (!splitStores[key]) {
5642                        splitStores[key] = createEmptyEventStore();
5643                    }
5644                    splitStores[key].defs[defId] = defs[defId];
5645                }
5646            }
5647            for (let instanceId in instances) {
5648                let instance = instances[instanceId];
5649                for (let key of defKeys[instance.defId]) {
5650                    if (splitStores[key]) { // must have already been created
5651                        splitStores[key].instances[instanceId] = instance;
5652                    }
5653                }
5654            }
5655            return splitStores;
5656        }
5657        _splitIndividualUi(eventUiBases, defKeys) {
5658            let splitHashes = {};
5659            for (let defId in eventUiBases) {
5660                if (defId) { // not the '' key
5661                    for (let key of defKeys[defId]) {
5662                        if (!splitHashes[key]) {
5663                            splitHashes[key] = {};
5664                        }
5665                        splitHashes[key][defId] = eventUiBases[defId];
5666                    }
5667                }
5668            }
5669            return splitHashes;
5670        }
5671        _splitInteraction(interaction) {
5672            let splitStates = {};
5673            if (interaction) {
5674                let affectedStores = this._splitEventStore(interaction.affectedEvents, this._getKeysForEventDefs(interaction.affectedEvents));
5675                // can't rely on defKeys because event data is mutated
5676                let mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents);
5677                let mutatedStores = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId);
5678                let populate = (key) => {
5679                    if (!splitStates[key]) {
5680                        splitStates[key] = {
5681                            affectedEvents: affectedStores[key] || EMPTY_EVENT_STORE,
5682                            mutatedEvents: mutatedStores[key] || EMPTY_EVENT_STORE,
5683                            isEvent: interaction.isEvent,
5684                        };
5685                    }
5686                };
5687                for (let key in affectedStores) {
5688                    populate(key);
5689                }
5690                for (let key in mutatedStores) {
5691                    populate(key);
5692                }
5693            }
5694            return splitStates;
5695        }
5696    }
5697    function buildEventUiForKey(allUi, eventUiForKey, individualUi) {
5698        let baseParts = [];
5699        if (allUi) {
5700            baseParts.push(allUi);
5701        }
5702        if (eventUiForKey) {
5703            baseParts.push(eventUiForKey);
5704        }
5705        let stuff = {
5706            '': combineEventUis(baseParts),
5707        };
5708        if (individualUi) {
5709            Object.assign(stuff, individualUi);
5710        }
5711        return stuff;
5712    }
5713
5714    function getDateMeta(date, todayRange, nowDate, dateProfile) {
5715        return {
5716            dow: date.getUTCDay(),
5717            isDisabled: Boolean(dateProfile && !rangeContainsMarker(dateProfile.activeRange, date)),
5718            isOther: Boolean(dateProfile && !rangeContainsMarker(dateProfile.currentRange, date)),
5719            isToday: Boolean(todayRange && rangeContainsMarker(todayRange, date)),
5720            isPast: Boolean(nowDate ? (date < nowDate) : todayRange ? (date < todayRange.start) : false),
5721            isFuture: Boolean(nowDate ? (date > nowDate) : todayRange ? (date >= todayRange.end) : false),
5722        };
5723    }
5724    function getDayClassNames(meta, theme) {
5725        let classNames = [
5726            'fc-day',
5727            `fc-day-${DAY_IDS[meta.dow]}`,
5728        ];
5729        if (meta.isDisabled) {
5730            classNames.push('fc-day-disabled');
5731        }
5732        else {
5733            if (meta.isToday) {
5734                classNames.push('fc-day-today');
5735                classNames.push(theme.getClass('today'));
5736            }
5737            if (meta.isPast) {
5738                classNames.push('fc-day-past');
5739            }
5740            if (meta.isFuture) {
5741                classNames.push('fc-day-future');
5742            }
5743            if (meta.isOther) {
5744                classNames.push('fc-day-other');
5745            }
5746        }
5747        return classNames;
5748    }
5749    function getSlotClassNames(meta, theme) {
5750        let classNames = [
5751            'fc-slot',
5752            `fc-slot-${DAY_IDS[meta.dow]}`,
5753        ];
5754        if (meta.isDisabled) {
5755            classNames.push('fc-slot-disabled');
5756        }
5757        else {
5758            if (meta.isToday) {
5759                classNames.push('fc-slot-today');
5760                classNames.push(theme.getClass('today'));
5761            }
5762            if (meta.isPast) {
5763                classNames.push('fc-slot-past');
5764            }
5765            if (meta.isFuture) {
5766                classNames.push('fc-slot-future');
5767            }
5768        }
5769        return classNames;
5770    }
5771
5772    const DAY_FORMAT = createFormatter({ year: 'numeric', month: 'long', day: 'numeric' });
5773    const WEEK_FORMAT = createFormatter({ week: 'long' });
vendor: 7,271 bytes, lines 5774-5954
5774    function buildNavLinkAttrs(context, dateMarker, viewType = 'day', isTabbable = true) {
5775        const { dateEnv, options, calendarApi } = context;
5776        let dateStr = dateEnv.format(dateMarker, viewType === 'week' ? WEEK_FORMAT : DAY_FORMAT);
5777        if (options.navLinks) {
5778            let zonedDate = dateEnv.toDate(dateMarker);
5779            const handleInteraction = (ev) => {
5780                let customAction = viewType === 'day' ? options.navLinkDayClick :
5781                    viewType === 'week' ? options.navLinkWeekClick : null;
5782                if (typeof customAction === 'function') {
5783                    customAction.call(calendarApi, dateEnv.toDate(dateMarker), ev);
5784                }
5785                else {
5786                    if (typeof customAction === 'string') {
5787                        viewType = customAction;
5788                    }
5789                    calendarApi.zoomTo(dateMarker, viewType);
5790                }
5791            };
5792            return Object.assign({ title: formatWithOrdinals(options.navLinkHint, [dateStr, zonedDate], dateStr), 'data-navlink': '' }, (isTabbable
5793                ? createAriaClickAttrs(handleInteraction)
5794                : { onClick: handleInteraction }));
5795        }
5796        return { 'aria-label': dateStr };
5797    }
5798
5799    let _isRtlScrollbarOnLeft = null;
5800    function getIsRtlScrollbarOnLeft() {
5801        if (_isRtlScrollbarOnLeft === null) {
5802            _isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft();
5803        }
5804        return _isRtlScrollbarOnLeft;
5805    }
5806    function computeIsRtlScrollbarOnLeft() {
5807        let outerEl = document.createElement('div');
5808        applyStyle(outerEl, {
5809            position: 'absolute',
5810            top: -1000,
5811            left: 0,
5812            border: 0,
5813            padding: 0,
5814            overflow: 'scroll',
5815            direction: 'rtl',
5816        });
5817        outerEl.innerHTML = '<div></div>';
5818        document.body.appendChild(outerEl);
5819        let innerEl = outerEl.firstChild;
5820        let res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left;
5821        removeElement(outerEl);
5822        return res;
5823    }
5824
5825    let _scrollbarWidths;
5826    function getScrollbarWidths() {
5827        if (!_scrollbarWidths) {
5828            _scrollbarWidths = computeScrollbarWidths();
5829        }
5830        return _scrollbarWidths;
5831    }
5832    function computeScrollbarWidths() {
5833        let el = document.createElement('div');
5834        el.style.overflow = 'scroll';
5835        el.style.position = 'absolute';
5836        el.style.top = '-9999px';
5837        el.style.left = '-9999px';
5838        document.body.appendChild(el);
5839        let res = computeScrollbarWidthsForEl(el);
5840        document.body.removeChild(el);
5841        return res;
5842    }
5843    // WARNING: will include border
5844    function computeScrollbarWidthsForEl(el) {
5845        return {
5846            x: el.offsetHeight - el.clientHeight,
5847            y: el.offsetWidth - el.clientWidth,
5848        };
5849    }
5850
5851    function computeEdges(el, getPadding = false) {
5852        let computedStyle = window.getComputedStyle(el);
5853        let borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0;
5854        let borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0;
5855        let borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0;
5856        let borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
5857        let badScrollbarWidths = computeScrollbarWidthsForEl(el); // includes border!
5858        let scrollbarLeftRight = badScrollbarWidths.y - borderLeft - borderRight;
5859        let scrollbarBottom = badScrollbarWidths.x - borderTop - borderBottom;
5860        let res = {
5861            borderLeft,
5862            borderRight,
5863            borderTop,
5864            borderBottom,
5865            scrollbarBottom,
5866            scrollbarLeft: 0,
5867            scrollbarRight: 0,
5868        };
5869        if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side?
5870            res.scrollbarLeft = scrollbarLeftRight;
5871        }
5872        else {
5873            res.scrollbarRight = scrollbarLeftRight;
5874        }
5875        if (getPadding) {
5876            res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0;
5877            res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0;
5878            res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0;
5879            res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0;
5880        }
5881        return res;
5882    }
5883    function computeInnerRect(el, goWithinPadding = false, doFromWindowViewport) {
5884        let outerRect = doFromWindowViewport ? el.getBoundingClientRect() : computeRect(el);
5885        let edges = computeEdges(el, goWithinPadding);
5886        let res = {
5887            left: outerRect.left + edges.borderLeft + edges.scrollbarLeft,
5888            right: outerRect.right - edges.borderRight - edges.scrollbarRight,
5889            top: outerRect.top + edges.borderTop,
5890            bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom,
5891        };
5892        if (goWithinPadding) {
5893            res.left += edges.paddingLeft;
5894            res.right -= edges.paddingRight;
5895            res.top += edges.paddingTop;
5896            res.bottom -= edges.paddingBottom;
5897        }
5898        return res;
5899    }
5900    function computeRect(el) {
5901        let rect = el.getBoundingClientRect();
5902        return {
5903            left: rect.left + window.pageXOffset,
5904            top: rect.top + window.pageYOffset,
5905            right: rect.right + window.pageXOffset,
5906            bottom: rect.bottom + window.pageYOffset,
5907        };
5908    }
5909    function computeClippedClientRect(el) {
5910        let clippingParents = getClippingParents(el);
5911        let rect = el.getBoundingClientRect();
5912        for (let clippingParent of clippingParents) {
5913            let intersection = intersectRects(rect, clippingParent.getBoundingClientRect());
5914            if (intersection) {
5915                rect = intersection;
5916            }
5917            else {
5918                return null;
5919            }
5920        }
5921        return rect;
5922    }
5923    // does not return window
5924    function getClippingParents(el) {
5925        let parents = [];
5926        while (el instanceof HTMLElement) { // will stop when gets to document or null
5927            let computedStyle = window.getComputedStyle(el);
5928            if (computedStyle.position === 'fixed') {
5929                break;
5930            }
5931            if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) {
5932                parents.push(el);
5933            }
5934            el = el.parentNode;
5935        }
5936        return parents;
5937    }
5938
5939    /*
5940    Records offset information for a set of elements, relative to an origin element.
5941    Can record the left/right OR the top/bottom OR both.
5942    Provides methods for querying the cache by position.
5943    */
5944    class PositionCache {
5945        constructor(originEl, els, isHorizontal, isVertical) {
5946            this.els = els;
5947            let originClientRect = this.originClientRect = originEl.getBoundingClientRect(); // relative to viewport top-left
5948            if (isHorizontal) {
5949                this.buildElHorizontals(originClientRect.left);
5950            }
5951            if (isVertical) {
5952                this.buildElVerticals(originClientRect.top);
5953            }
5954        }
vendor: 15,444 bytes, lines 5955-6351
5955        // Populates the left/right internal coordinate arrays
5956        buildElHorizontals(originClientLeft) {
5957            let lefts = [];
5958            let rights = [];
5959            for (let el of this.els) {
5960                let rect = el.getBoundingClientRect();
5961                lefts.push(rect.left - originClientLeft);
5962                rights.push(rect.right - originClientLeft);
5963            }
5964            this.lefts = lefts;
5965            this.rights = rights;
5966        }
5967        // Populates the top/bottom internal coordinate arrays
5968        buildElVerticals(originClientTop) {
5969            let tops = [];
5970            let bottoms = [];
5971            for (let el of this.els) {
5972                let rect = el.getBoundingClientRect();
5973                tops.push(rect.top - originClientTop);
5974                bottoms.push(rect.bottom - originClientTop);
5975            }
5976            this.tops = tops;
5977            this.bottoms = bottoms;
5978        }
5979        // Given a left offset (from document left), returns the index of the el that it horizontally intersects.
5980        // If no intersection is made, returns undefined.
5981        leftToIndex(leftPosition) {
5982            let { lefts, rights } = this;
5983            let len = lefts.length;
5984            let i;
5985            for (i = 0; i < len; i += 1) {
5986                if (leftPosition >= lefts[i] && leftPosition < rights[i]) {
5987                    return i;
5988                }
5989            }
5990            return undefined; // TODO: better
5991        }
5992        // Given a top offset (from document top), returns the index of the el that it vertically intersects.
5993        // If no intersection is made, returns undefined.
5994        topToIndex(topPosition) {
5995            let { tops, bottoms } = this;
5996            let len = tops.length;
5997            let i;
5998            for (i = 0; i < len; i += 1) {
5999                if (topPosition >= tops[i] && topPosition < bottoms[i]) {
6000                    return i;
6001                }
6002            }
6003            return undefined; // TODO: better
6004        }
6005        // Gets the width of the element at the given index
6006        getWidth(leftIndex) {
6007            return this.rights[leftIndex] - this.lefts[leftIndex];
6008        }
6009        // Gets the height of the element at the given index
6010        getHeight(topIndex) {
6011            return this.bottoms[topIndex] - this.tops[topIndex];
6012        }
6013    }
6014
6015    /* eslint max-classes-per-file: "off" */
6016    /*
6017    An object for getting/setting scroll-related information for an element.
6018    Internally, this is done very differently for window versus DOM element,
6019    so this object serves as a common interface.
6020    */
6021    class ScrollController {
6022        getMaxScrollTop() {
6023            return this.getScrollHeight() - this.getClientHeight();
6024        }
6025        getMaxScrollLeft() {
6026            return this.getScrollWidth() - this.getClientWidth();
6027        }
6028        canScrollVertically() {
6029            return this.getMaxScrollTop() > 0;
6030        }
6031        canScrollHorizontally() {
6032            return this.getMaxScrollLeft() > 0;
6033        }
6034        canScrollUp() {
6035            return this.getScrollTop() > 0;
6036        }
6037        canScrollDown() {
6038            return this.getScrollTop() < this.getMaxScrollTop();
6039        }
6040        canScrollLeft() {
6041            return this.getScrollLeft() > 0;
6042        }
6043        canScrollRight() {
6044            return this.getScrollLeft() < this.getMaxScrollLeft();
6045        }
6046    }
6047    class ElementScrollController extends ScrollController {
6048        constructor(el) {
6049            super();
6050            this.el = el;
6051        }
6052        getScrollTop() {
6053            return this.el.scrollTop;
6054        }
6055        getScrollLeft() {
6056            return this.el.scrollLeft;
6057        }
6058        setScrollTop(top) {
6059            this.el.scrollTop = top;
6060        }
6061        setScrollLeft(left) {
6062            this.el.scrollLeft = left;
6063        }
6064        getScrollWidth() {
6065            return this.el.scrollWidth;
6066        }
6067        getScrollHeight() {
6068            return this.el.scrollHeight;
6069        }
6070        getClientHeight() {
6071            return this.el.clientHeight;
6072        }
6073        getClientWidth() {
6074            return this.el.clientWidth;
6075        }
6076    }
6077    class WindowScrollController extends ScrollController {
6078        getScrollTop() {
6079            return window.pageYOffset;
6080        }
6081        getScrollLeft() {
6082            return window.pageXOffset;
6083        }
6084        setScrollTop(n) {
6085            window.scroll(window.pageXOffset, n);
6086        }
6087        setScrollLeft(n) {
6088            window.scroll(n, window.pageYOffset);
6089        }
6090        getScrollWidth() {
6091            return document.documentElement.scrollWidth;
6092        }
6093        getScrollHeight() {
6094            return document.documentElement.scrollHeight;
6095        }
6096        getClientHeight() {
6097            return document.documentElement.clientHeight;
6098        }
6099        getClientWidth() {
6100            return document.documentElement.clientWidth;
6101        }
6102    }
6103
6104    /*
6105    an INTERACTABLE date component
6106
6107    PURPOSES:
6108    - hook up to fg, fill, and mirror renderers
6109    - interface for dragging and hits
6110    */
6111    class DateComponent extends BaseComponent {
6112        constructor() {
6113            super(...arguments);
6114            this.uid = guid();
6115        }
6116        // Hit System
6117        // -----------------------------------------------------------------------------------------------------------------
6118        prepareHits() {
6119        }
6120        queryHit(positionLeft, positionTop, elWidth, elHeight) {
6121            return null; // this should be abstract
6122        }
6123        // Pointer Interaction Utils
6124        // -----------------------------------------------------------------------------------------------------------------
6125        isValidSegDownEl(el) {
6126            return !this.props.eventDrag && // HACK
6127                !this.props.eventResize && // HACK
6128                !elementClosest(el, '.fc-event-mirror');
6129        }
6130        isValidDateDownEl(el) {
6131            return !elementClosest(el, '.fc-event:not(.fc-bg-event)') &&
6132                !elementClosest(el, '.fc-more-link') && // a "more.." link
6133                !elementClosest(el, 'a[data-navlink]') && // a clickable nav link
6134                !elementClosest(el, '.fc-popover'); // hack
6135        }
6136    }
6137
6138    class NamedTimeZoneImpl {
6139        constructor(timeZoneName) {
6140            this.timeZoneName = timeZoneName;
6141        }
6142    }
6143
6144    class SegHierarchy {
6145        constructor() {
6146            // settings
6147            this.strictOrder = false;
6148            this.allowReslicing = false;
6149            this.maxCoord = -1; // -1 means no max
6150            this.maxStackCnt = -1; // -1 means no max
6151            this.levelCoords = []; // ordered
6152            this.entriesByLevel = []; // parallel with levelCoords
6153            this.stackCnts = {}; // TODO: use better technique!?
6154        }
6155        addSegs(inputs) {
6156            let hiddenEntries = [];
6157            for (let input of inputs) {
6158                this.insertEntry(input, hiddenEntries);
6159            }
6160            return hiddenEntries;
6161        }
6162        insertEntry(entry, hiddenEntries) {
6163            let insertion = this.findInsertion(entry);
6164            if (this.isInsertionValid(insertion, entry)) {
6165                this.insertEntryAt(entry, insertion);
6166                return 1;
6167            }
6168            return this.handleInvalidInsertion(insertion, entry, hiddenEntries);
6169        }
6170        isInsertionValid(insertion, entry) {
6171            return (this.maxCoord === -1 || insertion.levelCoord + entry.thickness <= this.maxCoord) &&
6172                (this.maxStackCnt === -1 || insertion.stackCnt < this.maxStackCnt);
6173        }
6174        // returns number of new entries inserted
6175        handleInvalidInsertion(insertion, entry, hiddenEntries) {
6176            if (this.allowReslicing && insertion.touchingEntry) {
6177                return this.splitEntry(entry, insertion.touchingEntry, hiddenEntries);
6178            }
6179            hiddenEntries.push(entry);
6180            return 0;
6181        }
6182        splitEntry(entry, barrier, hiddenEntries) {
6183            let partCnt = 0;
6184            let splitHiddenEntries = [];
6185            let entrySpan = entry.span;
6186            let barrierSpan = barrier.span;
6187            if (entrySpan.start < barrierSpan.start) {
6188                partCnt += this.insertEntry({
6189                    index: entry.index,
6190                    thickness: entry.thickness,
6191                    span: { start: entrySpan.start, end: barrierSpan.start },
6192                }, splitHiddenEntries);
6193            }
6194            if (entrySpan.end > barrierSpan.end) {
6195                partCnt += this.insertEntry({
6196                    index: entry.index,
6197                    thickness: entry.thickness,
6198                    span: { start: barrierSpan.end, end: entrySpan.end },
6199                }, splitHiddenEntries);
6200            }
6201            if (partCnt) {
6202                hiddenEntries.push({
6203                    index: entry.index,
6204                    thickness: entry.thickness,
6205                    span: intersectSpans(barrierSpan, entrySpan), // guaranteed to intersect
6206                }, ...splitHiddenEntries);
6207                return partCnt;
6208            }
6209            hiddenEntries.push(entry);
6210            return 0;
6211        }
6212        insertEntryAt(entry, insertion) {
6213            let { entriesByLevel, levelCoords } = this;
6214            if (insertion.lateral === -1) {
6215                // create a new level
6216                insertAt(levelCoords, insertion.level, insertion.levelCoord);
6217                insertAt(entriesByLevel, insertion.level, [entry]);
6218            }
6219            else {
6220                // insert into existing level
6221                insertAt(entriesByLevel[insertion.level], insertion.lateral, entry);
6222            }
6223            this.stackCnts[buildEntryKey(entry)] = insertion.stackCnt;
6224        }
6225        findInsertion(newEntry) {
6226            let { levelCoords, entriesByLevel, strictOrder, stackCnts } = this;
6227            let levelCnt = levelCoords.length;
6228            let candidateCoord = 0;
6229            let touchingLevel = -1;
6230            let touchingLateral = -1;
6231            let touchingEntry = null;
6232            let stackCnt = 0;
6233            for (let trackingLevel = 0; trackingLevel < levelCnt; trackingLevel += 1) {
6234                let trackingCoord = levelCoords[trackingLevel];
6235                // if the current level is past the placed entry, we have found a good empty space and can stop.
6236                // if strictOrder, keep finding more lateral intersections.
6237                if (!strictOrder && trackingCoord >= candidateCoord + newEntry.thickness) {
6238                    break;
6239                }
6240                let trackingEntries = entriesByLevel[trackingLevel];
6241                let trackingEntry;
6242                let searchRes = binarySearch(trackingEntries, newEntry.span.start, getEntrySpanEnd); // find first entry after newEntry's end
6243                let lateralIndex = searchRes[0] + searchRes[1]; // if exact match (which doesn't collide), go to next one
6244                while ( // loop through entries that horizontally intersect
6245                (trackingEntry = trackingEntries[lateralIndex]) && // but not past the whole entry list
6246                    trackingEntry.span.start < newEntry.span.end // and not entirely past newEntry
6247                ) {
6248                    let trackingEntryBottom = trackingCoord + trackingEntry.thickness;
6249                    // intersects into the top of the candidate?
6250                    if (trackingEntryBottom > candidateCoord) {
6251                        candidateCoord = trackingEntryBottom;
6252                        touchingEntry = trackingEntry;
6253                        touchingLevel = trackingLevel;
6254                        touchingLateral = lateralIndex;
6255                    }
6256                    // butts up against top of candidate? (will happen if just intersected as well)
6257                    if (trackingEntryBottom === candidateCoord) {
6258                        // accumulate the highest possible stackCnt of the trackingEntries that butt up
6259                        stackCnt = Math.max(stackCnt, stackCnts[buildEntryKey(trackingEntry)] + 1);
6260                    }
6261                    lateralIndex += 1;
6262                }
6263            }
6264            // the destination level will be after touchingEntry's level. find it
6265            let destLevel = 0;
6266            if (touchingEntry) {
6267                destLevel = touchingLevel + 1;
6268                while (destLevel < levelCnt && levelCoords[destLevel] < candidateCoord) {
6269                    destLevel += 1;
6270                }
6271            }
6272            // if adding to an existing level, find where to insert
6273            let destLateral = -1;
6274            if (destLevel < levelCnt && levelCoords[destLevel] === candidateCoord) {
6275                destLateral = binarySearch(entriesByLevel[destLevel], newEntry.span.end, getEntrySpanEnd)[0];
6276            }
6277            return {
6278                touchingLevel,
6279                touchingLateral,
6280                touchingEntry,
6281                stackCnt,
6282                levelCoord: candidateCoord,
6283                level: destLevel,
6284                lateral: destLateral,
6285            };
6286        }
6287        // sorted by levelCoord (lowest to highest)
6288        toRects() {
6289            let { entriesByLevel, levelCoords } = this;
6290            let levelCnt = entriesByLevel.length;
6291            let rects = [];
6292            for (let level = 0; level < levelCnt; level += 1) {
6293                let entries = entriesByLevel[level];
6294                let levelCoord = levelCoords[level];
6295                for (let entry of entries) {
6296                    rects.push(Object.assign(Object.assign({}, entry), { levelCoord }));
6297                }
6298            }
6299            return rects;
6300        }
6301    }
6302    function getEntrySpanEnd(entry) {
6303        return entry.span.end;
6304    }
6305    function buildEntryKey(entry) {
6306        return entry.index + ':' + entry.span.start;
6307    }
6308    // returns groups with entries sorted by input order
6309    function groupIntersectingEntries(entries) {
6310        let merges = [];
6311        for (let entry of entries) {
6312            let filteredMerges = [];
6313            let hungryMerge = {
6314                span: entry.span,
6315                entries: [entry],
6316            };
6317            for (let merge of merges) {
6318                if (intersectSpans(merge.span, hungryMerge.span)) {
6319                    hungryMerge = {
6320                        entries: merge.entries.concat(hungryMerge.entries),
6321                        span: joinSpans(merge.span, hungryMerge.span),
6322                    };
6323                }
6324                else {
6325                    filteredMerges.push(merge);
6326                }
6327            }
6328            filteredMerges.push(hungryMerge);
6329            merges = filteredMerges;
6330        }
6331        return merges;
6332    }
6333    function joinSpans(span0, span1) {
6334        return {
6335            start: Math.min(span0.start, span1.start),
6336            end: Math.max(span0.end, span1.end),
6337        };
6338    }
6339    function intersectSpans(span0, span1) {
6340        let start = Math.max(span0.start, span1.start);
6341        let end = Math.min(span0.end, span1.end);
6342        if (start < end) {
6343            return { start, end };
6344        }
6345        return null;
6346    }
6347    // general util
6348    // ---------------------------------------------------------------------------------------------------------------------
6349    function insertAt(arr, index, item) {
6350        arr.splice(index, 0, item);
6351    }
vendor: 10,429 bytes, lines 6352-6578
6352    function binarySearch(a, searchVal, getItemVal) {
6353        let startIndex = 0;
6354        let endIndex = a.length; // exclusive
6355        if (!endIndex || searchVal < getItemVal(a[startIndex])) { // no items OR before first item
6356            return [0, 0];
6357        }
6358        if (searchVal > getItemVal(a[endIndex - 1])) { // after last item
6359            return [endIndex, 0];
6360        }
6361        while (startIndex < endIndex) {
6362            let middleIndex = Math.floor(startIndex + (endIndex - startIndex) / 2);
6363            let middleVal = getItemVal(a[middleIndex]);
6364            if (searchVal < middleVal) {
6365                endIndex = middleIndex;
6366            }
6367            else if (searchVal > middleVal) {
6368                startIndex = middleIndex + 1;
6369            }
6370            else { // equal!
6371                return [middleIndex, 1];
6372            }
6373        }
6374        return [startIndex, 0];
6375    }
6376
6377    /*
6378    An abstraction for a dragging interaction originating on an event.
6379    Does higher-level things than PointerDragger, such as possibly:
6380    - a "mirror" that moves with the pointer
6381    - a minimum number of pixels or other criteria for a true drag to begin
6382
6383    subclasses must emit:
6384    - pointerdown
6385    - dragstart
6386    - dragmove
6387    - pointerup
6388    - dragend
6389    */
6390    class ElementDragging {
6391        constructor(el, selector) {
6392            this.emitter = new Emitter();
6393        }
6394        destroy() {
6395        }
6396        setMirrorIsVisible(bool) {
6397            // optional if subclass doesn't want to support a mirror
6398        }
6399        setMirrorNeedsRevert(bool) {
6400            // optional if subclass doesn't want to support a mirror
6401        }
6402        setAutoScrollEnabled(bool) {
6403            // optional
6404        }
6405    }
6406
6407    // TODO: get rid of this in favor of options system,
6408    // tho it's really easy to access this globally rather than pass thru options.
6409    const config = {};
6410
6411    /*
6412    Information about what will happen when an external element is dragged-and-dropped
6413    onto a calendar. Contains information for creating an event.
6414    */
6415    const DRAG_META_REFINERS = {
6416        startTime: createDuration,
6417        duration: createDuration,
6418        create: Boolean,
6419        sourceId: String,
6420    };
6421    function parseDragMeta(raw) {
6422        let { refined, extra } = refineProps(raw, DRAG_META_REFINERS);
6423        return {
6424            startTime: refined.startTime || null,
6425            duration: refined.duration || null,
6426            create: refined.create != null ? refined.create : true,
6427            sourceId: refined.sourceId,
6428            leftoverProps: extra,
6429        };
6430    }
6431
6432    // Computes a default column header formatting string if `colFormat` is not explicitly defined
6433    function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
6434        // if more than one week row, or if there are a lot of columns with not much space,
6435        // put just the day numbers will be in each cell
6436        if (!datesRepDistinctDays || dayCnt > 10) {
6437            return createFormatter({ weekday: 'short' }); // "Sat"
6438        }
6439        if (dayCnt > 1) {
6440            return createFormatter({ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }); // "Sat 11/12"
6441        }
6442        return createFormatter({ weekday: 'long' }); // "Saturday"
6443    }
6444
6445    const CLASS_NAME = 'fc-col-header-cell'; // do the cushion too? no
6446    function renderInner$1(renderProps) {
6447        return renderProps.text;
6448    }
6449
6450    // BAD name for this class now. used in the Header
6451    class TableDateCell extends BaseComponent {
6452        render() {
6453            let { dateEnv, options, theme, viewApi } = this.context;
6454            let { props } = this;
6455            let { date, dateProfile } = props;
6456            let dayMeta = getDateMeta(date, props.todayRange, null, dateProfile);
6457            let classNames = [CLASS_NAME].concat(getDayClassNames(dayMeta, theme));
6458            let text = dateEnv.format(date, props.dayHeaderFormat);
6459            // if colCnt is 1, we are already in a day-view and don't need a navlink
6460            let navLinkAttrs = (!dayMeta.isDisabled && props.colCnt > 1)
6461                ? buildNavLinkAttrs(this.context, date)
6462                : {};
6463            let renderProps = Object.assign(Object.assign(Object.assign({ date: dateEnv.toDate(date), view: viewApi }, props.extraRenderProps), { text }), dayMeta);
6464            return (h(ContentContainer, { elTag: "th", elClasses: classNames, elAttrs: Object.assign({ role: 'columnheader', colSpan: props.colSpan, 'data-date': !dayMeta.isDisabled ? formatDayString(date) : undefined }, props.extraDataAttrs), renderProps: renderProps, generatorName: "dayHeaderContent", generator: options.dayHeaderContent || renderInner$1, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContainer) => (h("div", { className: "fc-scrollgrid-sync-inner" }, !dayMeta.isDisabled && (h(InnerContainer, { elTag: "a", elAttrs: navLinkAttrs, elClasses: [
6465                    'fc-col-header-cell-cushion',
6466                    props.isSticky && 'fc-sticky',
6467                ] }))))));
6468        }
6469    }
6470
6471    const WEEKDAY_FORMAT = createFormatter({ weekday: 'long' });
6472    class TableDowCell extends BaseComponent {
6473        render() {
6474            let { props } = this;
6475            let { dateEnv, theme, viewApi, options } = this.context;
6476            let date = addDays(new Date(259200000), props.dow); // start with Sun, 04 Jan 1970 00:00:00 GMT
6477            let dateMeta = {
6478                dow: props.dow,
6479                isDisabled: false,
6480                isFuture: false,
6481                isPast: false,
6482                isToday: false,
6483                isOther: false,
6484            };
6485            let text = dateEnv.format(date, props.dayHeaderFormat);
6486            let renderProps = Object.assign(Object.assign(Object.assign(Object.assign({ // TODO: make this public?
6487                date }, dateMeta), { view: viewApi }), props.extraRenderProps), { text });
6488            return (h(ContentContainer, { elTag: "th", elClasses: [
6489                    CLASS_NAME,
6490                    ...getDayClassNames(dateMeta, theme),
6491                    ...(props.extraClassNames || []),
6492                ], elAttrs: Object.assign({ role: 'columnheader', colSpan: props.colSpan }, props.extraDataAttrs), renderProps: renderProps, generatorName: "dayHeaderContent", generator: options.dayHeaderContent || renderInner$1, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => (h("div", { className: "fc-scrollgrid-sync-inner" },
6493                h(InnerContent, { elTag: "a", elClasses: [
6494                        'fc-col-header-cell-cushion',
6495                        props.isSticky && 'fc-sticky',
6496                    ], elAttrs: {
6497                        'aria-label': dateEnv.format(date, WEEKDAY_FORMAT),
6498                    } })))));
6499        }
6500    }
6501
6502    class NowTimer extends d {
6503        constructor(props, context) {
6504            super(props, context);
6505            this.initialNowDate = getNow(context.options.now, context.dateEnv);
6506            this.initialNowQueriedMs = new Date().valueOf();
6507            this.state = this.computeTiming().currentState;
6508        }
6509        render() {
6510            let { props, state } = this;
6511            return props.children(state.nowDate, state.todayRange);
6512        }
6513        componentDidMount() {
6514            this.setTimeout();
6515        }
6516        componentDidUpdate(prevProps) {
6517            if (prevProps.unit !== this.props.unit) {
6518                this.clearTimeout();
6519                this.setTimeout();
6520            }
6521        }
6522        componentWillUnmount() {
6523            this.clearTimeout();
6524        }
6525        computeTiming() {
6526            let { props, context } = this;
6527            let unroundedNow = addMs(this.initialNowDate, new Date().valueOf() - this.initialNowQueriedMs);
6528            let currentUnitStart = context.dateEnv.startOf(unroundedNow, props.unit);
6529            let nextUnitStart = context.dateEnv.add(currentUnitStart, createDuration(1, props.unit));
6530            let waitMs = nextUnitStart.valueOf() - unroundedNow.valueOf();
6531            // there is a max setTimeout ms value (https://stackoverflow.com/a/3468650/96342)
6532            // ensure no longer than a day
6533            waitMs = Math.min(1000 * 60 * 60 * 24, waitMs);
6534            return {
6535                currentState: { nowDate: currentUnitStart, todayRange: buildDayRange(currentUnitStart) },
6536                nextState: { nowDate: nextUnitStart, todayRange: buildDayRange(nextUnitStart) },
6537                waitMs,
6538            };
6539        }
6540        setTimeout() {
6541            let { nextState, waitMs } = this.computeTiming();
6542            this.timeoutId = setTimeout(() => {
6543                this.setState(nextState, () => {
6544                    this.setTimeout();
6545                });
6546            }, waitMs);
6547        }
6548        clearTimeout() {
6549            if (this.timeoutId) {
6550                clearTimeout(this.timeoutId);
6551            }
6552        }
6553    }
6554    NowTimer.contextType = ViewContextType;
6555    function buildDayRange(date) {
6556        let start = startOfDay(date);
6557        let end = addDays(start, 1);
6558        return { start, end };
6559    }
6560
6561    class DayHeader extends BaseComponent {
6562        constructor() {
6563            super(...arguments);
6564            this.createDayHeaderFormatter = memoize(createDayHeaderFormatter);
6565        }
6566        render() {
6567            let { context } = this;
6568            let { dates, dateProfile, datesRepDistinctDays, renderIntro } = this.props;
6569            let dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dates.length);
6570            return (h(NowTimer, { unit: "day" }, (nowDate, todayRange) => (h("tr", { role: "row" },
6571                renderIntro && renderIntro('day'),
6572                dates.map((date) => (datesRepDistinctDays ? (h(TableDateCell, { key: date.toISOString(), date: date, dateProfile: dateProfile, todayRange: todayRange, colCnt: dates.length, dayHeaderFormat: dayHeaderFormat })) : (h(TableDowCell, { key: date.getUTCDay(), dow: date.getUTCDay(), dayHeaderFormat: dayHeaderFormat }))))))));
6573        }
6574    }
6575    function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) {
6576        return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt);
6577    }
6578
vendor: 16,258 bytes, lines 6579-6918
6579    class DaySeriesModel {
6580        constructor(range, dateProfileGenerator) {
6581            let date = range.start;
6582            let { end } = range;
6583            let indices = [];
6584            let dates = [];
6585            let dayIndex = -1;
6586            while (date < end) { // loop each day from start to end
6587                if (dateProfileGenerator.isHiddenDay(date)) {
6588                    indices.push(dayIndex + 0.5); // mark that it's between indices
6589                }
6590                else {
6591                    dayIndex += 1;
6592                    indices.push(dayIndex);
6593                    dates.push(date);
6594                }
6595                date = addDays(date, 1);
6596            }
6597            this.dates = dates;
6598            this.indices = indices;
6599            this.cnt = dates.length;
6600        }
6601        sliceRange(range) {
6602            let firstIndex = this.getDateDayIndex(range.start); // inclusive first index
6603            let lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index
6604            let clippedFirstIndex = Math.max(0, firstIndex);
6605            let clippedLastIndex = Math.min(this.cnt - 1, lastIndex);
6606            // deal with in-between indices
6607            clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell
6608            clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell
6609            if (clippedFirstIndex <= clippedLastIndex) {
6610                return {
6611                    firstIndex: clippedFirstIndex,
6612                    lastIndex: clippedLastIndex,
6613                    isStart: firstIndex === clippedFirstIndex,
6614                    isEnd: lastIndex === clippedLastIndex,
6615                };
6616            }
6617            return null;
6618        }
6619        // Given a date, returns its chronolocial cell-index from the first cell of the grid.
6620        // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.
6621        // If before the first offset, returns a negative number.
6622        // If after the last offset, returns an offset past the last cell offset.
6623        // Only works for *start* dates of cells. Will not work for exclusive end dates for cells.
6624        getDateDayIndex(date) {
6625            let { indices } = this;
6626            let dayOffset = Math.floor(diffDays(this.dates[0], date));
6627            if (dayOffset < 0) {
6628                return indices[0] - 1;
6629            }
6630            if (dayOffset >= indices.length) {
6631                return indices[indices.length - 1] + 1;
6632            }
6633            return indices[dayOffset];
6634        }
6635    }
6636
6637    class DayTableModel {
6638        constructor(daySeries, breakOnWeeks) {
6639            let { dates } = daySeries;
6640            let daysPerRow;
6641            let firstDay;
6642            let rowCnt;
6643            if (breakOnWeeks) {
6644                // count columns until the day-of-week repeats
6645                firstDay = dates[0].getUTCDay();
6646                for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow += 1) {
6647                    if (dates[daysPerRow].getUTCDay() === firstDay) {
6648                        break;
6649                    }
6650                }
6651                rowCnt = Math.ceil(dates.length / daysPerRow);
6652            }
6653            else {
6654                rowCnt = 1;
6655                daysPerRow = dates.length;
6656            }
6657            this.rowCnt = rowCnt;
6658            this.colCnt = daysPerRow;
6659            this.daySeries = daySeries;
6660            this.cells = this.buildCells();
6661            this.headerDates = this.buildHeaderDates();
6662        }
6663        buildCells() {
6664            let rows = [];
6665            for (let row = 0; row < this.rowCnt; row += 1) {
6666                let cells = [];
6667                for (let col = 0; col < this.colCnt; col += 1) {
6668                    cells.push(this.buildCell(row, col));
6669                }
6670                rows.push(cells);
6671            }
6672            return rows;
6673        }
6674        buildCell(row, col) {
6675            let date = this.daySeries.dates[row * this.colCnt + col];
6676            return {
6677                key: date.toISOString(),
6678                date,
6679            };
6680        }
6681        buildHeaderDates() {
6682            let dates = [];
6683            for (let col = 0; col < this.colCnt; col += 1) {
6684                dates.push(this.cells[0][col].date);
6685            }
6686            return dates;
6687        }
6688        sliceRange(range) {
6689            let { colCnt } = this;
6690            let seriesSeg = this.daySeries.sliceRange(range);
6691            let segs = [];
6692            if (seriesSeg) {
6693                let { firstIndex, lastIndex } = seriesSeg;
6694                let index = firstIndex;
6695                while (index <= lastIndex) {
6696                    let row = Math.floor(index / colCnt);
6697                    let nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1);
6698                    segs.push({
6699                        row,
6700                        firstCol: index % colCnt,
6701                        lastCol: (nextIndex - 1) % colCnt,
6702                        isStart: seriesSeg.isStart && index === firstIndex,
6703                        isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex,
6704                    });
6705                    index = nextIndex;
6706                }
6707            }
6708            return segs;
6709        }
6710    }
6711
6712    class Slicer {
6713        constructor() {
6714            this.sliceBusinessHours = memoize(this._sliceBusinessHours);
6715            this.sliceDateSelection = memoize(this._sliceDateSpan);
6716            this.sliceEventStore = memoize(this._sliceEventStore);
6717            this.sliceEventDrag = memoize(this._sliceInteraction);
6718            this.sliceEventResize = memoize(this._sliceInteraction);
6719            this.forceDayIfListItem = false; // hack
6720        }
6721        sliceProps(props, dateProfile, nextDayThreshold, context, ...extraArgs) {
6722            let { eventUiBases } = props;
6723            let eventSegs = this.sliceEventStore(props.eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs);
6724            return {
6725                dateSelectionSegs: this.sliceDateSelection(props.dateSelection, eventUiBases, context, ...extraArgs),
6726                businessHourSegs: this.sliceBusinessHours(props.businessHours, dateProfile, nextDayThreshold, context, ...extraArgs),
6727                fgEventSegs: eventSegs.fg,
6728                bgEventSegs: eventSegs.bg,
6729                eventDrag: this.sliceEventDrag(props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs),
6730                eventResize: this.sliceEventResize(props.eventResize, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs),
6731                eventSelection: props.eventSelection,
6732            }; // TODO: give interactionSegs?
6733        }
6734        sliceNowDate(// does not memoize
6735        date, context, ...extraArgs) {
6736            return this._sliceDateSpan({ range: { start: date, end: addMs(date, 1) }, allDay: false }, // add 1 ms, protect against null range
6737            {}, context, ...extraArgs);
6738        }
6739        _sliceBusinessHours(businessHours, dateProfile, nextDayThreshold, context, ...extraArgs) {
6740            if (!businessHours) {
6741                return [];
6742            }
6743            return this._sliceEventStore(expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), context), {}, dateProfile, nextDayThreshold, ...extraArgs).bg;
6744        }
6745        _sliceEventStore(eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs) {
6746            if (eventStore) {
6747                let rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
6748                return {
6749                    bg: this.sliceEventRanges(rangeRes.bg, extraArgs),
6750                    fg: this.sliceEventRanges(rangeRes.fg, extraArgs),
6751                };
6752            }
6753            return { bg: [], fg: [] };
6754        }
6755        _sliceInteraction(interaction, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs) {
6756            if (!interaction) {
6757                return null;
6758            }
6759            let rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
6760            return {
6761                segs: this.sliceEventRanges(rangeRes.fg, extraArgs),
6762                affectedInstances: interaction.affectedEvents.instances,
6763                isEvent: interaction.isEvent,
6764            };
6765        }
6766        _sliceDateSpan(dateSpan, eventUiBases, context, ...extraArgs) {
6767            if (!dateSpan) {
6768                return [];
6769            }
6770            let eventRange = fabricateEventRange(dateSpan, eventUiBases, context);
6771            let segs = this.sliceRange(dateSpan.range, ...extraArgs);
6772            for (let seg of segs) {
6773                seg.eventRange = eventRange;
6774            }
6775            return segs;
6776        }
6777        /*
6778        "complete" seg means it has component and eventRange
6779        */
6780        sliceEventRanges(eventRanges, extraArgs) {
6781            let segs = [];
6782            for (let eventRange of eventRanges) {
6783                segs.push(...this.sliceEventRange(eventRange, extraArgs));
6784            }
6785            return segs;
6786        }
6787        /*
6788        "complete" seg means it has component and eventRange
6789        */
6790        sliceEventRange(eventRange, extraArgs) {
6791            let dateRange = eventRange.range;
6792            // hack to make multi-day events that are being force-displayed as list-items to take up only one day
6793            if (this.forceDayIfListItem && eventRange.ui.display === 'list-item') {
6794                dateRange = {
6795                    start: dateRange.start,
6796                    end: addDays(dateRange.start, 1),
6797                };
6798            }
6799            let segs = this.sliceRange(dateRange, ...extraArgs);
6800            for (let seg of segs) {
6801                seg.eventRange = eventRange;
6802                seg.isStart = eventRange.isStart && seg.isStart;
6803                seg.isEnd = eventRange.isEnd && seg.isEnd;
6804            }
6805            return segs;
6806        }
6807    }
6808    /*
6809    for incorporating slotMinTime/slotMaxTime if appropriate
6810    TODO: should be part of DateProfile!
6811    TimelineDateProfile already does this btw
6812    */
6813    function computeActiveRange(dateProfile, isComponentAllDay) {
6814        let range = dateProfile.activeRange;
6815        if (isComponentAllDay) {
6816            return range;
6817        }
6818        return {
6819            start: addMs(range.start, dateProfile.slotMinTime.milliseconds),
6820            end: addMs(range.end, dateProfile.slotMaxTime.milliseconds - 864e5), // 864e5 = ms in a day
6821        };
6822    }
6823
6824    // high-level segmenting-aware tester functions
6825    // ------------------------------------------------------------------------------------------------------------------------
6826    function isInteractionValid(interaction, dateProfile, context) {
6827        let { instances } = interaction.mutatedEvents;
6828        for (let instanceId in instances) {
6829            if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) {
6830                return false;
6831            }
6832        }
6833        return isNewPropsValid({ eventDrag: interaction }, context); // HACK: the eventDrag props is used for ALL interactions
6834    }
6835    function isDateSelectionValid(dateSelection, dateProfile, context) {
6836        if (!rangeContainsRange(dateProfile.validRange, dateSelection.range)) {
6837            return false;
6838        }
6839        return isNewPropsValid({ dateSelection }, context);
6840    }
6841    function isNewPropsValid(newProps, context) {
6842        let calendarState = context.getCurrentData();
6843        let props = Object.assign({ businessHours: calendarState.businessHours, dateSelection: '', eventStore: calendarState.eventStore, eventUiBases: calendarState.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps);
6844        return (context.pluginHooks.isPropsValid || isPropsValid)(props, context);
6845    }
6846    function isPropsValid(state, context, dateSpanMeta = {}, filterConfig) {
6847        if (state.eventDrag && !isInteractionPropsValid(state, context, dateSpanMeta, filterConfig)) {
6848            return false;
6849        }
6850        if (state.dateSelection && !isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig)) {
6851            return false;
6852        }
6853        return true;
6854    }
6855    // Moving Event Validation
6856    // ------------------------------------------------------------------------------------------------------------------------
6857    function isInteractionPropsValid(state, context, dateSpanMeta, filterConfig) {
6858        let currentState = context.getCurrentData();
6859        let interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions
6860        let subjectEventStore = interaction.mutatedEvents;
6861        let subjectDefs = subjectEventStore.defs;
6862        let subjectInstances = subjectEventStore.instances;
6863        let subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ?
6864            state.eventUiBases :
6865            { '': currentState.selectionConfig });
6866        if (filterConfig) {
6867            subjectConfigs = mapHash(subjectConfigs, filterConfig);
6868        }
6869        // exclude the subject events. TODO: exclude defs too?
6870        let otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances);
6871        let otherDefs = otherEventStore.defs;
6872        let otherInstances = otherEventStore.instances;
6873        let otherConfigs = compileEventUis(otherDefs, state.eventUiBases);
6874        for (let subjectInstanceId in subjectInstances) {
6875            let subjectInstance = subjectInstances[subjectInstanceId];
6876            let subjectRange = subjectInstance.range;
6877            let subjectConfig = subjectConfigs[subjectInstance.defId];
6878            let subjectDef = subjectDefs[subjectInstance.defId];
6879            // constraint
6880            if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, context)) {
6881                return false;
6882            }
6883            // overlap
6884            let { eventOverlap } = context.options;
6885            let eventOverlapFunc = typeof eventOverlap === 'function' ? eventOverlap : null;
6886            for (let otherInstanceId in otherInstances) {
6887                let otherInstance = otherInstances[otherInstanceId];
6888                // intersect! evaluate
6889                if (rangesIntersect(subjectRange, otherInstance.range)) {
6890                    let otherOverlap = otherConfigs[otherInstance.defId].overlap;
6891                    // consider the other event's overlap. only do this if the subject event is a "real" event
6892                    if (otherOverlap === false && interaction.isEvent) {
6893                        return false;
6894                    }
6895                    if (subjectConfig.overlap === false) {
6896                        return false;
6897                    }
6898                    if (eventOverlapFunc && !eventOverlapFunc(new EventImpl(context, otherDefs[otherInstance.defId], otherInstance), // still event
6899                    new EventImpl(context, subjectDef, subjectInstance))) {
6900                        return false;
6901                    }
6902                }
6903            }
6904            // allow (a function)
6905            let calendarEventStore = currentState.eventStore; // need global-to-calendar, not local to component (splittable)state
6906            for (let subjectAllow of subjectConfig.allows) {
6907                let subjectDateSpan = Object.assign(Object.assign({}, dateSpanMeta), { range: subjectInstance.range, allDay: subjectDef.allDay });
6908                let origDef = calendarEventStore.defs[subjectDef.defId];
6909                let origInstance = calendarEventStore.instances[subjectInstanceId];
6910                let eventApi;
6911                if (origDef) { // was previously in the calendar
6912                    eventApi = new EventImpl(context, origDef, origInstance);
6913                }
6914                else { // was an external event
6915                    eventApi = new EventImpl(context, subjectDef); // no instance, because had no dates
6916                }
6917                if (!subjectAllow(buildDateSpanApiWithContext(subjectDateSpan, context), eventApi)) {
6918                    return false;
vendor: 40,285 bytes, lines 6919-7734
6919                }
6920            }
6921        }
6922        return true;
6923    }
6924    // Date Selection Validation
6925    // ------------------------------------------------------------------------------------------------------------------------
6926    function isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig) {
6927        let relevantEventStore = state.eventStore;
6928        let relevantDefs = relevantEventStore.defs;
6929        let relevantInstances = relevantEventStore.instances;
6930        let selection = state.dateSelection;
6931        let selectionRange = selection.range;
6932        let { selectionConfig } = context.getCurrentData();
6933        if (filterConfig) {
6934            selectionConfig = filterConfig(selectionConfig);
6935        }
6936        // constraint
6937        if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, context)) {
6938            return false;
6939        }
6940        // overlap
6941        let { selectOverlap } = context.options;
6942        let selectOverlapFunc = typeof selectOverlap === 'function' ? selectOverlap : null;
6943        for (let relevantInstanceId in relevantInstances) {
6944            let relevantInstance = relevantInstances[relevantInstanceId];
6945            // intersect! evaluate
6946            if (rangesIntersect(selectionRange, relevantInstance.range)) {
6947                if (selectionConfig.overlap === false) {
6948                    return false;
6949                }
6950                if (selectOverlapFunc && !selectOverlapFunc(new EventImpl(context, relevantDefs[relevantInstance.defId], relevantInstance), null)) {
6951                    return false;
6952                }
6953            }
6954        }
6955        // allow (a function)
6956        for (let selectionAllow of selectionConfig.allows) {
6957            let fullDateSpan = Object.assign(Object.assign({}, dateSpanMeta), selection);
6958            if (!selectionAllow(buildDateSpanApiWithContext(fullDateSpan, context), null)) {
6959                return false;
6960            }
6961        }
6962        return true;
6963    }
6964    // Constraint Utils
6965    // ------------------------------------------------------------------------------------------------------------------------
6966    function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, context) {
6967        for (let constraint of constraints) {
6968            if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, context), subjectRange)) {
6969                return false;
6970            }
6971        }
6972        return true;
6973    }
6974    function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours
6975    otherEventStore, // for if constraint is an even group ID
6976    businessHoursUnexpanded, // for if constraint is 'businessHours'
6977    context) {
6978        if (constraint === 'businessHours') {
6979            return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, context));
6980        }
6981        if (typeof constraint === 'string') { // an group ID
6982            return eventStoreToRanges(filterEventStoreDefs(otherEventStore, (eventDef) => eventDef.groupId === constraint));
6983        }
6984        if (typeof constraint === 'object' && constraint) { // non-null object
6985            return eventStoreToRanges(expandRecurring(constraint, subjectRange, context));
6986        }
6987        return []; // if it's false
6988    }
6989    // TODO: move to event-store file?
6990    function eventStoreToRanges(eventStore) {
6991        let { instances } = eventStore;
6992        let ranges = [];
6993        for (let instanceId in instances) {
6994            ranges.push(instances[instanceId].range);
6995        }
6996        return ranges;
6997    }
6998    // TODO: move to geom file?
6999    function anyRangesContainRange(outerRanges, innerRange) {
7000        for (let outerRange of outerRanges) {
7001            if (rangeContainsRange(outerRange, innerRange)) {
7002                return true;
7003            }
7004        }
7005        return false;
7006    }
7007
7008    const VISIBLE_HIDDEN_RE = /^(visible|hidden)$/;
7009    class Scroller extends BaseComponent {
7010        constructor() {
7011            super(...arguments);
7012            this.handleEl = (el) => {
7013                this.el = el;
7014                setRef(this.props.elRef, el);
7015            };
7016        }
7017        render() {
7018            let { props } = this;
7019            let { liquid, liquidIsAbsolute } = props;
7020            let isAbsolute = liquid && liquidIsAbsolute;
7021            let className = ['fc-scroller'];
7022            if (liquid) {
7023                if (liquidIsAbsolute) {
7024                    className.push('fc-scroller-liquid-absolute');
7025                }
7026                else {
7027                    className.push('fc-scroller-liquid');
7028                }
7029            }
7030            return (h("div", { ref: this.handleEl, className: className.join(' '), style: {
7031                    overflowX: props.overflowX,
7032                    overflowY: props.overflowY,
7033                    left: (isAbsolute && -(props.overcomeLeft || 0)) || '',
7034                    right: (isAbsolute && -(props.overcomeRight || 0)) || '',
7035                    bottom: (isAbsolute && -(props.overcomeBottom || 0)) || '',
7036                    marginLeft: (!isAbsolute && -(props.overcomeLeft || 0)) || '',
7037                    marginRight: (!isAbsolute && -(props.overcomeRight || 0)) || '',
7038                    marginBottom: (!isAbsolute && -(props.overcomeBottom || 0)) || '',
7039                    maxHeight: props.maxHeight || '',
7040                } }, props.children));
7041        }
7042        needsXScrolling() {
7043            if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {
7044                return false;
7045            }
7046            // testing scrollWidth>clientWidth is unreliable cross-browser when pixel heights aren't integers.
7047            // much more reliable to see if children are taller than the scroller, even tho doesn't account for
7048            // inner-child margins and absolute positioning
7049            let { el } = this;
7050            let realClientWidth = this.el.getBoundingClientRect().width - this.getYScrollbarWidth();
7051            let { children } = el;
7052            for (let i = 0; i < children.length; i += 1) {
7053                let childEl = children[i];
7054                if (childEl.getBoundingClientRect().width > realClientWidth) {
7055                    return true;
7056                }
7057            }
7058            return false;
7059        }
7060        needsYScrolling() {
7061            if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {
7062                return false;
7063            }
7064            // testing scrollHeight>clientHeight is unreliable cross-browser when pixel heights aren't integers.
7065            // much more reliable to see if children are taller than the scroller, even tho doesn't account for
7066            // inner-child margins and absolute positioning
7067            let { el } = this;
7068            let realClientHeight = this.el.getBoundingClientRect().height - this.getXScrollbarWidth();
7069            let { children } = el;
7070            for (let i = 0; i < children.length; i += 1) {
7071                let childEl = children[i];
7072                if (childEl.getBoundingClientRect().height > realClientHeight) {
7073                    return true;
7074                }
7075            }
7076            return false;
7077        }
7078        getXScrollbarWidth() {
7079            if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {
7080                return 0;
7081            }
7082            return this.el.offsetHeight - this.el.clientHeight; // only works because we guarantee no borders. TODO: add to CSS with important?
7083        }
7084        getYScrollbarWidth() {
7085            if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {
7086                return 0;
7087            }
7088            return this.el.offsetWidth - this.el.clientWidth; // only works because we guarantee no borders. TODO: add to CSS with important?
7089        }
7090    }
7091
7092    /*
7093    TODO: somehow infer OtherArgs from masterCallback?
7094    TODO: infer RefType from masterCallback if provided
7095    */
7096    class RefMap {
7097        constructor(masterCallback) {
7098            this.masterCallback = masterCallback;
7099            this.currentMap = {};
7100            this.depths = {};
7101            this.callbackMap = {};
7102            this.handleValue = (val, key) => {
7103                let { depths, currentMap } = this;
7104                let removed = false;
7105                let added = false;
7106                if (val !== null) {
7107                    // for bug... ACTUALLY: can probably do away with this now that callers don't share numeric indices anymore
7108                    removed = (key in currentMap);
7109                    currentMap[key] = val;
7110                    depths[key] = (depths[key] || 0) + 1;
7111                    added = true;
7112                }
7113                else {
7114                    depths[key] -= 1;
7115                    if (!depths[key]) {
7116                        delete currentMap[key];
7117                        delete this.callbackMap[key];
7118                        removed = true;
7119                    }
7120                }
7121                if (this.masterCallback) {
7122                    if (removed) {
7123                        this.masterCallback(null, String(key));
7124                    }
7125                    if (added) {
7126                        this.masterCallback(val, String(key));
7127                    }
7128                }
7129            };
7130        }
7131        createRef(key) {
7132            let refCallback = this.callbackMap[key];
7133            if (!refCallback) {
7134                refCallback = this.callbackMap[key] = (val) => {
7135                    this.handleValue(val, String(key));
7136                };
7137            }
7138            return refCallback;
7139        }
7140        // TODO: check callers that don't care about order. should use getAll instead
7141        // NOTE: this method has become less valuable now that we are encouraged to map order by some other index
7142        // TODO: provide ONE array-export function, buildArray, which fails on non-numeric indexes. caller can manipulate and "collect"
7143        collect(startIndex, endIndex, step) {
7144            return collectFromHash(this.currentMap, startIndex, endIndex, step);
7145        }
7146        getAll() {
7147            return hashValuesToArray(this.currentMap);
7148        }
7149    }
7150
7151    function computeShrinkWidth(chunkEls) {
7152        let shrinkCells = findElements(chunkEls, '.fc-scrollgrid-shrink');
7153        let largestWidth = 0;
7154        for (let shrinkCell of shrinkCells) {
7155            largestWidth = Math.max(largestWidth, computeSmallestCellWidth(shrinkCell));
7156        }
7157        return Math.ceil(largestWidth); // <table> elements work best with integers. round up to ensure contents fits
7158    }
7159    function getSectionHasLiquidHeight(props, sectionConfig) {
7160        return props.liquid && sectionConfig.liquid; // does the section do liquid-height? (need to have whole scrollgrid liquid-height as well)
7161    }
7162    function getAllowYScrolling(props, sectionConfig) {
7163        return sectionConfig.maxHeight != null || // if its possible for the height to max out, we might need scrollbars
7164            getSectionHasLiquidHeight(props, sectionConfig); // if the section is liquid height, it might condense enough to require scrollbars
7165    }
7166    // TODO: ONLY use `arg`. force out internal function to use same API
7167    function renderChunkContent(sectionConfig, chunkConfig, arg, isHeader) {
7168        let { expandRows } = arg;
7169        let content = typeof chunkConfig.content === 'function' ?
7170            chunkConfig.content(arg) :
7171            h('table', {
7172                role: 'presentation',
7173                className: [
7174                    chunkConfig.tableClassName,
7175                    sectionConfig.syncRowHeights ? 'fc-scrollgrid-sync-table' : '',
7176                ].join(' '),
7177                style: {
7178                    minWidth: arg.tableMinWidth,
7179                    width: arg.clientWidth,
7180                    height: expandRows ? arg.clientHeight : '', // css `height` on a <table> serves as a min-height
7181                },
7182            }, arg.tableColGroupNode, h(isHeader ? 'thead' : 'tbody', {
7183                role: 'presentation',
7184            }, typeof chunkConfig.rowContent === 'function'
7185                ? chunkConfig.rowContent(arg)
7186                : chunkConfig.rowContent));
7187        return content;
7188    }
7189    function isColPropsEqual(cols0, cols1) {
7190        return isArraysEqual(cols0, cols1, isPropsEqual);
7191    }
7192    function renderMicroColGroup(cols, shrinkWidth) {
7193        let colNodes = [];
7194        /*
7195        for ColProps with spans, it would have been great to make a single <col span="">
7196        HOWEVER, Chrome was getting messing up distributing the width to <td>/<th> elements with colspans.
7197        SOLUTION: making individual <col> elements makes Chrome behave.
7198        */
7199        for (let colProps of cols) {
7200            let span = colProps.span || 1;
7201            for (let i = 0; i < span; i += 1) {
7202                colNodes.push(h("col", { style: {
7203                        width: colProps.width === 'shrink' ? sanitizeShrinkWidth(shrinkWidth) : (colProps.width || ''),
7204                        minWidth: colProps.minWidth || '',
7205                    } }));
7206            }
7207        }
7208        return h('colgroup', {}, ...colNodes);
7209    }
7210    function sanitizeShrinkWidth(shrinkWidth) {
7211        /* why 4? if we do 0, it will kill any border, which are needed for computeSmallestCellWidth
7212        4 accounts for 2 2-pixel borders. TODO: better solution? */
7213        return shrinkWidth == null ? 4 : shrinkWidth;
7214    }
7215    function hasShrinkWidth(cols) {
7216        for (let col of cols) {
7217            if (col.width === 'shrink') {
7218                return true;
7219            }
7220        }
7221        return false;
7222    }
7223    function getScrollGridClassNames(liquid, context) {
7224        let classNames = [
7225            'fc-scrollgrid',
7226            context.theme.getClass('table'),
7227        ];
7228        if (liquid) {
7229            classNames.push('fc-scrollgrid-liquid');
7230        }
7231        return classNames;
7232    }
7233    function getSectionClassNames(sectionConfig, wholeTableVGrow) {
7234        let classNames = [
7235            'fc-scrollgrid-section',
7236            `fc-scrollgrid-section-${sectionConfig.type}`,
7237            sectionConfig.className, // used?
7238        ];
7239        if (wholeTableVGrow && sectionConfig.liquid && sectionConfig.maxHeight == null) {
7240            classNames.push('fc-scrollgrid-section-liquid');
7241        }
7242        if (sectionConfig.isSticky) {
7243            classNames.push('fc-scrollgrid-section-sticky');
7244        }
7245        return classNames;
7246    }
7247    function renderScrollShim(arg) {
7248        return (h("div", { className: "fc-scrollgrid-sticky-shim", style: {
7249                width: arg.clientWidth,
7250                minWidth: arg.tableMinWidth,
7251            } }));
7252    }
7253    function getStickyHeaderDates(options) {
7254        let { stickyHeaderDates } = options;
7255        if (stickyHeaderDates == null || stickyHeaderDates === 'auto') {
7256            stickyHeaderDates = options.height === 'auto' || options.viewHeight === 'auto';
7257        }
7258        return stickyHeaderDates;
7259    }
7260    function getStickyFooterScrollbar(options) {
7261        let { stickyFooterScrollbar } = options;
7262        if (stickyFooterScrollbar == null || stickyFooterScrollbar === 'auto') {
7263            stickyFooterScrollbar = options.height === 'auto' || options.viewHeight === 'auto';
7264        }
7265        return stickyFooterScrollbar;
7266    }
7267
7268    class SimpleScrollGrid extends BaseComponent {
7269        constructor() {
7270            super(...arguments);
7271            this.processCols = memoize((a) => a, isColPropsEqual); // so we get same `cols` props every time
7272            // yucky to memoize VNodes, but much more efficient for consumers
7273            this.renderMicroColGroup = memoize(renderMicroColGroup);
7274            this.scrollerRefs = new RefMap();
7275            this.scrollerElRefs = new RefMap(this._handleScrollerEl.bind(this));
7276            this.state = {
7277                shrinkWidth: null,
7278                forceYScrollbars: false,
7279                scrollerClientWidths: {},
7280                scrollerClientHeights: {},
7281            };
7282            // TODO: can do a really simple print-view. dont need to join rows
7283            this.handleSizing = () => {
7284                this.safeSetState(Object.assign({ shrinkWidth: this.computeShrinkWidth() }, this.computeScrollerDims()));
7285            };
7286        }
7287        render() {
7288            let { props, state, context } = this;
7289            let sectionConfigs = props.sections || [];
7290            let cols = this.processCols(props.cols);
7291            let microColGroupNode = this.renderMicroColGroup(cols, state.shrinkWidth);
7292            let classNames = getScrollGridClassNames(props.liquid, context);
7293            if (props.collapsibleWidth) {
7294                classNames.push('fc-scrollgrid-collapsible');
7295            }
7296            // TODO: make DRY
7297            let configCnt = sectionConfigs.length;
7298            let configI = 0;
7299            let currentConfig;
7300            let headSectionNodes = [];
7301            let bodySectionNodes = [];
7302            let footSectionNodes = [];
7303            while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'header') {
7304                headSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));
7305                configI += 1;
7306            }
7307            while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'body') {
7308                bodySectionNodes.push(this.renderSection(currentConfig, microColGroupNode, false));
7309                configI += 1;
7310            }
7311            while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'footer') {
7312                footSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));
7313                configI += 1;
7314            }
7315            // firefox bug: when setting height on table and there is a thead or tfoot,
7316            // the necessary height:100% on the liquid-height body section forces the *whole* table to be taller. (bug #5524)
7317            // use getCanVGrowWithinCell as a way to detect table-stupid firefox.
7318            // if so, use a simpler dom structure, jam everything into a lone tbody.
7319            let isBuggy = !getCanVGrowWithinCell();
7320            const roleAttrs = { role: 'rowgroup' };
7321            return h('table', {
7322                role: 'grid',
7323                className: classNames.join(' '),
7324                style: { height: props.height },
7325            }, Boolean(!isBuggy && headSectionNodes.length) && h('thead', roleAttrs, ...headSectionNodes), Boolean(!isBuggy && bodySectionNodes.length) && h('tbody', roleAttrs, ...bodySectionNodes), Boolean(!isBuggy && footSectionNodes.length) && h('tfoot', roleAttrs, ...footSectionNodes), isBuggy && h('tbody', roleAttrs, ...headSectionNodes, ...bodySectionNodes, ...footSectionNodes));
7326        }
7327        renderSection(sectionConfig, microColGroupNode, isHeader) {
7328            if ('outerContent' in sectionConfig) {
7329                return (h(p, { key: sectionConfig.key }, sectionConfig.outerContent));
7330            }
7331            return (h("tr", { key: sectionConfig.key, role: "presentation", className: getSectionClassNames(sectionConfig, this.props.liquid).join(' ') }, this.renderChunkTd(sectionConfig, microColGroupNode, sectionConfig.chunk, isHeader)));
7332        }
7333        renderChunkTd(sectionConfig, microColGroupNode, chunkConfig, isHeader) {
7334            if ('outerContent' in chunkConfig) {
7335                return chunkConfig.outerContent;
7336            }
7337            let { props } = this;
7338            let { forceYScrollbars, scrollerClientWidths, scrollerClientHeights } = this.state;
7339            let needsYScrolling = getAllowYScrolling(props, sectionConfig); // TODO: do lazily. do in section config?
7340            let isLiquid = getSectionHasLiquidHeight(props, sectionConfig);
7341            // for `!props.liquid` - is WHOLE scrollgrid natural height?
7342            // TODO: do same thing in advanced scrollgrid? prolly not b/c always has horizontal scrollbars
7343            let overflowY = !props.liquid ? 'visible' :
7344                forceYScrollbars ? 'scroll' :
7345                    !needsYScrolling ? 'hidden' :
7346                        'auto';
7347            let sectionKey = sectionConfig.key;
7348            let content = renderChunkContent(sectionConfig, chunkConfig, {
7349                tableColGroupNode: microColGroupNode,
7350                tableMinWidth: '',
7351                clientWidth: (!props.collapsibleWidth && scrollerClientWidths[sectionKey] !== undefined) ? scrollerClientWidths[sectionKey] : null,
7352                clientHeight: scrollerClientHeights[sectionKey] !== undefined ? scrollerClientHeights[sectionKey] : null,
7353                expandRows: sectionConfig.expandRows,
7354                syncRowHeights: false,
7355                rowSyncHeights: [],
7356                reportRowHeightChange: () => { },
7357            }, isHeader);
7358            return h(isHeader ? 'th' : 'td', {
7359                ref: chunkConfig.elRef,
7360                role: 'presentation',
7361            }, h("div", { className: `fc-scroller-harness${isLiquid ? ' fc-scroller-harness-liquid' : ''}` },
7362                h(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
7363                    : true }, content)));
7364        }
7365        _handleScrollerEl(scrollerEl, key) {
7366            let section = getSectionByKey(this.props.sections, key);
7367            if (section) {
7368                setRef(section.chunk.scrollerElRef, scrollerEl);
7369            }
7370        }
7371        componentDidMount() {
7372            this.handleSizing();
7373            this.context.addResizeHandler(this.handleSizing);
7374        }
7375        componentDidUpdate() {
7376            // TODO: need better solution when state contains non-sizing things
7377            this.handleSizing();
7378        }
7379        componentWillUnmount() {
7380            this.context.removeResizeHandler(this.handleSizing);
7381        }
7382        computeShrinkWidth() {
7383            return hasShrinkWidth(this.props.cols)
7384                ? computeShrinkWidth(this.scrollerElRefs.getAll())
7385                : 0;
7386        }
7387        computeScrollerDims() {
7388            let scrollbarWidth = getScrollbarWidths();
7389            let { scrollerRefs, scrollerElRefs } = this;
7390            let forceYScrollbars = false;
7391            let scrollerClientWidths = {};
7392            let scrollerClientHeights = {};
7393            for (let sectionKey in scrollerRefs.currentMap) {
7394                let scroller = scrollerRefs.currentMap[sectionKey];
7395                if (scroller && scroller.needsYScrolling()) {
7396                    forceYScrollbars = true;
7397                    break;
7398                }
7399            }
7400            for (let section of this.props.sections) {
7401                let sectionKey = section.key;
7402                let scrollerEl = scrollerElRefs.currentMap[sectionKey];
7403                if (scrollerEl) {
7404                    let harnessEl = scrollerEl.parentNode; // TODO: weird way to get this. need harness b/c doesn't include table borders
7405                    scrollerClientWidths[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().width - (forceYScrollbars
7406                        ? scrollbarWidth.y // use global because scroller might not have scrollbars yet but will need them in future
7407                        : 0));
7408                    scrollerClientHeights[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().height);
7409                }
7410            }
7411            return { forceYScrollbars, scrollerClientWidths, scrollerClientHeights };
7412        }
7413    }
7414    SimpleScrollGrid.addStateEquality({
7415        scrollerClientWidths: isPropsEqual,
7416        scrollerClientHeights: isPropsEqual,
7417    });
7418    function getSectionByKey(sections, key) {
7419        for (let section of sections) {
7420            if (section.key === key) {
7421                return section;
7422            }
7423        }
7424        return null;
7425    }
7426
7427    class EventContainer extends BaseComponent {
7428        constructor() {
7429            super(...arguments);
7430            this.handleEl = (el) => {
7431                if (el) {
7432                    setElSeg(el, this.props.seg);
7433                }
7434                // TODO: when null, should unset to avoid memory leaks?
7435            };
7436        }
7437        render() {
7438            const { props, context } = this;
7439            const { options } = context;
7440            const { seg } = props;
7441            const { eventRange } = seg;
7442            const { ui } = eventRange;
7443            const renderProps = {
7444                event: new EventImpl(context, eventRange.def, eventRange.instance),
7445                view: context.viewApi,
7446                timeText: props.timeText,
7447                textColor: ui.textColor,
7448                backgroundColor: ui.backgroundColor,
7449                borderColor: ui.borderColor,
7450                isDraggable: !props.disableDragging && computeSegDraggable(seg, context),
7451                isStartResizable: !props.disableResizing && computeSegStartResizable(seg, context),
7452                isEndResizable: !props.disableResizing && computeSegEndResizable(seg),
7453                isMirror: Boolean(props.isDragging || props.isResizing || props.isDateSelecting),
7454                isStart: Boolean(seg.isStart),
7455                isEnd: Boolean(seg.isEnd),
7456                isPast: Boolean(props.isPast),
7457                isFuture: Boolean(props.isFuture),
7458                isToday: Boolean(props.isToday),
7459                isSelected: Boolean(props.isSelected),
7460                isDragging: Boolean(props.isDragging),
7461                isResizing: Boolean(props.isResizing),
7462            };
7463            return (h(ContentContainer, Object.assign({}, props /* contains children */, { elRef: this.handleEl, elClasses: [
7464                    ...getEventClassNames(renderProps),
7465                    ...seg.eventRange.ui.classNames,
7466                    ...(props.elClasses || []),
7467                ], renderProps: renderProps, generatorName: "eventContent", generator: options.eventContent || props.defaultGenerator, classNameGenerator: options.eventClassNames, didMount: options.eventDidMount, willUnmount: options.eventWillUnmount })));
7468        }
7469    }
7470
7471    // should not be a purecomponent
7472    class StandardEvent extends BaseComponent {
7473        render() {
7474            let { props, context } = this;
7475            let { options } = context;
7476            let { seg } = props;
7477            let { ui } = seg.eventRange;
7478            let timeFormat = options.eventTimeFormat || props.defaultTimeFormat;
7479            let timeText = buildSegTimeText(seg, timeFormat, context, props.defaultDisplayEventTime, props.defaultDisplayEventEnd);
7480            return (h(EventContainer, Object.assign({}, props /* includes elRef */, { elTag: "a", elStyle: {
7481                    borderColor: ui.borderColor,
7482                    backgroundColor: ui.backgroundColor,
7483                }, elAttrs: getSegAnchorAttrs(seg, context), defaultGenerator: renderInnerContent$1$1, timeText: timeText }), (InnerContent, eventContentArg) => (h(p, null,
7484                h(InnerContent, { elTag: "div", elClasses: ['fc-event-main'], elStyle: { color: eventContentArg.textColor } }),
7485                Boolean(eventContentArg.isStartResizable) && (h("div", { className: "fc-event-resizer fc-event-resizer-start" })),
7486                Boolean(eventContentArg.isEndResizable) && (h("div", { className: "fc-event-resizer fc-event-resizer-end" }))))));
7487        }
7488    }
7489    function renderInnerContent$1$1(innerProps) {
7490        return (h("div", { className: "fc-event-main-frame" },
7491            innerProps.timeText && (h("div", { className: "fc-event-time" }, innerProps.timeText)),
7492            h("div", { className: "fc-event-title-container" },
7493                h("div", { className: "fc-event-title fc-sticky" }, innerProps.event.title || h(p, null, "\u00A0")))));
7494    }
7495
7496    const NowIndicatorContainer = (props) => (h(ViewContextType.Consumer, null, (context) => {
7497        let { options } = context;
7498        let renderProps = {
7499            isAxis: props.isAxis,
7500            date: context.dateEnv.toDate(props.date),
7501            view: context.viewApi,
7502        };
7503        return (h(ContentContainer, Object.assign({}, props /* includes children */, { elTag: props.elTag || 'div', renderProps: renderProps, generatorName: "nowIndicatorContent", generator: options.nowIndicatorContent, classNameGenerator: options.nowIndicatorClassNames, didMount: options.nowIndicatorDidMount, willUnmount: options.nowIndicatorWillUnmount })));
7504    }));
7505
7506    const DAY_NUM_FORMAT = createFormatter({ day: 'numeric' });
7507    class DayCellContainer extends BaseComponent {
7508        constructor() {
7509            super(...arguments);
7510            this.refineRenderProps = memoizeObjArg(refineRenderProps);
7511        }
7512        render() {
7513            let { props, context } = this;
7514            let { options } = context;
7515            let renderProps = this.refineRenderProps({
7516                date: props.date,
7517                dateProfile: props.dateProfile,
7518                todayRange: props.todayRange,
7519                showDayNumber: props.showDayNumber,
7520                extraRenderProps: props.extraRenderProps,
7521                viewApi: context.viewApi,
7522                dateEnv: context.dateEnv,
7523            });
7524            return (h(ContentContainer, Object.assign({}, props /* includes children */, { elClasses: [
7525                    ...getDayClassNames(renderProps, context.theme),
7526                    ...(props.elClasses || []),
7527                ], elAttrs: Object.assign(Object.assign({}, props.elAttrs), (renderProps.isDisabled ? {} : { 'data-date': formatDayString(props.date) })), renderProps: renderProps, generatorName: "dayCellContent", generator: options.dayCellContent || props.defaultGenerator, classNameGenerator: 
7528                // don't use custom classNames if disabled
7529                renderProps.isDisabled ? undefined : options.dayCellClassNames, didMount: options.dayCellDidMount, willUnmount: options.dayCellWillUnmount })));
7530        }
7531    }
7532    function hasCustomDayCellContent(options) {
7533        return Boolean(options.dayCellContent || hasCustomRenderingHandler('dayCellContent', options));
7534    }
7535    function refineRenderProps(raw) {
7536        let { date, dateEnv } = raw;
7537        let dayMeta = getDateMeta(date, raw.todayRange, null, raw.dateProfile);
7538        return Object.assign(Object.assign(Object.assign({ date: dateEnv.toDate(date), view: raw.viewApi }, dayMeta), { dayNumberText: raw.showDayNumber ? dateEnv.format(date, DAY_NUM_FORMAT) : '' }), raw.extraRenderProps);
7539    }
7540
7541    class BgEvent extends BaseComponent {
7542        render() {
7543            let { props } = this;
7544            let { seg } = props;
7545            return (h(EventContainer, { elTag: "div", elClasses: ['fc-bg-event'], elStyle: { backgroundColor: seg.eventRange.ui.backgroundColor }, defaultGenerator: renderInnerContent$3, seg: seg, timeText: "", isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false, isPast: props.isPast, isFuture: props.isFuture, isToday: props.isToday, disableDragging: true, disableResizing: true }));
7546        }
7547    }
7548    function renderInnerContent$3(props) {
7549        let { title } = props.event;
7550        return title && (h("div", { className: "fc-event-title" }, props.event.title));
7551    }
7552    function renderFill(fillType) {
7553        return (h("div", { className: `fc-${fillType}` }));
7554    }
7555
7556    const WeekNumberContainer = (props) => (h(ViewContextType.Consumer, null, (context) => {
7557        let { dateEnv, options } = context;
7558        let { date } = props;
7559        let format = options.weekNumberFormat || props.defaultFormat;
7560        let num = dateEnv.computeWeekNumber(date); // TODO: somehow use for formatting as well?
7561        let text = dateEnv.format(date, format);
7562        let renderProps = { num, text, date };
7563        return (h(ContentContainer // why isn't WeekNumberContentArg being auto-detected?
7564        , Object.assign({}, props /* includes children */, { renderProps: renderProps, generatorName: "weekNumberContent", generator: options.weekNumberContent || renderInner, classNameGenerator: options.weekNumberClassNames, didMount: options.weekNumberDidMount, willUnmount: options.weekNumberWillUnmount })));
7565    }));
7566    function renderInner(innerProps) {
7567        return innerProps.text;
7568    }
7569
7570    const PADDING_FROM_VIEWPORT = 10;
7571    class Popover extends BaseComponent {
7572        constructor() {
7573            super(...arguments);
7574            this.state = {
7575                titleId: getUniqueDomId(),
7576            };
7577            this.handleRootEl = (el) => {
7578                this.rootEl = el;
7579                if (this.props.elRef) {
7580                    setRef(this.props.elRef, el);
7581                }
7582            };
7583            // Triggered when the user clicks *anywhere* in the document, for the autoHide feature
7584            this.handleDocumentMouseDown = (ev) => {
7585                // only hide the popover if the click happened outside the popover
7586                const target = getEventTargetViaRoot(ev);
7587                if (!this.rootEl.contains(target)) {
7588                    this.handleCloseClick();
7589                }
7590            };
7591            this.handleDocumentKeyDown = (ev) => {
7592                if (ev.key === 'Escape') {
7593                    this.handleCloseClick();
7594                }
7595            };
7596            this.handleCloseClick = () => {
7597                let { onClose } = this.props;
7598                if (onClose) {
7599                    onClose();
7600                }
7601            };
7602        }
7603        render() {
7604            let { theme, options } = this.context;
7605            let { props, state } = this;
7606            let classNames = [
7607                'fc-popover',
7608                theme.getClass('popover'),
7609            ].concat(props.extraClassNames || []);
7610            return j(h("div", Object.assign({}, props.extraAttrs, { id: props.id, className: classNames.join(' '), "aria-labelledby": state.titleId, ref: this.handleRootEl }),
7611                h("div", { className: 'fc-popover-header ' + theme.getClass('popoverHeader') },
7612                    h("span", { className: "fc-popover-title", id: state.titleId }, props.title),
7613                    h("span", { className: 'fc-popover-close ' + theme.getIconClass('close'), title: options.closeHint, onClick: this.handleCloseClick })),
7614                h("div", { className: 'fc-popover-body ' + theme.getClass('popoverContent') }, props.children)), props.parentEl);
7615        }
7616        componentDidMount() {
7617            document.addEventListener('mousedown', this.handleDocumentMouseDown);
7618            document.addEventListener('keydown', this.handleDocumentKeyDown);
7619            this.updateSize();
7620        }
7621        componentWillUnmount() {
7622            document.removeEventListener('mousedown', this.handleDocumentMouseDown);
7623            document.removeEventListener('keydown', this.handleDocumentKeyDown);
7624        }
7625        updateSize() {
7626            let { isRtl } = this.context;
7627            let { alignmentEl, alignGridTop } = this.props;
7628            let { rootEl } = this;
7629            let alignmentRect = computeClippedClientRect(alignmentEl);
7630            if (alignmentRect) {
7631                let popoverDims = rootEl.getBoundingClientRect();
7632                // position relative to viewport
7633                let popoverTop = alignGridTop
7634                    ? elementClosest(alignmentEl, '.fc-scrollgrid').getBoundingClientRect().top
7635                    : alignmentRect.top;
7636                let popoverLeft = isRtl ? alignmentRect.right - popoverDims.width : alignmentRect.left;
7637                // constrain
7638                popoverTop = Math.max(popoverTop, PADDING_FROM_VIEWPORT);
7639                popoverLeft = Math.min(popoverLeft, document.documentElement.clientWidth - PADDING_FROM_VIEWPORT - popoverDims.width);
7640                popoverLeft = Math.max(popoverLeft, PADDING_FROM_VIEWPORT);
7641                let origin = rootEl.offsetParent.getBoundingClientRect();
7642                applyStyle(rootEl, {
7643                    top: popoverTop - origin.top,
7644                    left: popoverLeft - origin.left,
7645                });
7646            }
7647        }
7648    }
7649
7650    class MorePopover extends DateComponent {
7651        constructor() {
7652            super(...arguments);
7653            this.handleRootEl = (rootEl) => {
7654                this.rootEl = rootEl;
7655                if (rootEl) {
7656                    this.context.registerInteractiveComponent(this, {
7657                        el: rootEl,
7658                        useEventCenter: false,
7659                    });
7660                }
7661                else {
7662                    this.context.unregisterInteractiveComponent(this);
7663                }
7664            };
7665        }
7666        render() {
7667            let { options, dateEnv } = this.context;
7668            let { props } = this;
7669            let { startDate, todayRange, dateProfile } = props;
7670            let title = dateEnv.format(startDate, options.dayPopoverFormat);
7671            return (h(DayCellContainer, { elRef: this.handleRootEl, date: startDate, dateProfile: dateProfile, todayRange: todayRange }, (InnerContent, renderProps, elAttrs) => (h(Popover, { elRef: elAttrs.ref, id: props.id, title: title, extraClassNames: ['fc-more-popover'].concat(elAttrs.className || []), extraAttrs: elAttrs /* TODO: make these time-based when not whole-day? */, parentEl: props.parentEl, alignmentEl: props.alignmentEl, alignGridTop: props.alignGridTop, onClose: props.onClose },
7672                hasCustomDayCellContent(options) && (h(InnerContent, { elTag: "div", elClasses: ['fc-more-popover-misc'] })),
7673                props.children))));
7674        }
7675        queryHit(positionLeft, positionTop, elWidth, elHeight) {
7676            let { rootEl, props } = this;
7677            if (positionLeft >= 0 && positionLeft < elWidth &&
7678                positionTop >= 0 && positionTop < elHeight) {
7679                return {
7680                    dateProfile: props.dateProfile,
7681                    dateSpan: Object.assign({ allDay: true, range: {
7682                            start: props.startDate,
7683                            end: props.endDate,
7684                        } }, props.extraDateSpan),
7685                    dayEl: rootEl,
7686                    rect: {
7687                        left: 0,
7688                        top: 0,
7689                        right: elWidth,
7690                        bottom: elHeight,
7691                    },
7692                    layer: 1, // important when comparing with hits from other components
7693                };
7694            }
7695            return null;
7696        }
7697    }
7698
7699    class MoreLinkContainer extends BaseComponent {
7700        constructor() {
7701            super(...arguments);
7702            this.linkElRef = y();
7703            this.state = {
7704                isPopoverOpen: false,
7705                popoverId: getUniqueDomId(),
7706            };
7707            this.handleClick = (ev) => {
7708                let { props, context } = this;
7709                let { moreLinkClick } = context.options;
7710                let date = computeRange(props).start;
7711                function buildPublicSeg(seg) {
7712                    let { def, instance, range } = seg.eventRange;
7713                    return {
7714                        event: new EventImpl(context, def, instance),
7715                        start: context.dateEnv.toDate(range.start),
7716                        end: context.dateEnv.toDate(range.end),
7717                        isStart: seg.isStart,
7718                        isEnd: seg.isEnd,
7719                    };
7720                }
7721                if (typeof moreLinkClick === 'function') {
7722                    moreLinkClick = moreLinkClick({
7723                        date,
7724                        allDay: Boolean(props.allDayDate),
7725                        allSegs: props.allSegs.map(buildPublicSeg),
7726                        hiddenSegs: props.hiddenSegs.map(buildPublicSeg),
7727                        jsEvent: ev,
7728                        view: context.viewApi,
7729                    });
7730                }
7731                if (!moreLinkClick || moreLinkClick === 'popover') {
7732                    this.setState({ isPopoverOpen: true });
7733                }
7734                else if (typeof moreLinkClick === 'string') { // a view n
7734ame
7735                    context.calendarApi.zoomTo(date, moreLinkClick);
7736                }
7737            };
7738            this.handlePopoverClose = () => {
7739                this.setState({ isPopoverOpen: false });
7740            };
7741        }
7742        render() {
7743            let { props, state } = this;
7744            return (h(ViewContextType.Consumer, null, (context) => {
7745                let { viewApi, options, calendarApi } = context;
7746                let { moreLinkText } = options;
7747                let { moreCnt } = props;
7748                let range = computeRange(props);
7749                let text = typeof moreLinkText === 'function' // TODO: eventually use formatWithOrdinals
7750                    ? moreLinkText.call(calendarApi, moreCnt)
7751                    : `+${moreCnt} ${moreLinkText}`;
7752                let hint = formatWithOrdinals(options.moreLinkHint, [moreCnt], text);
7753                let renderProps = {
7754                    num: moreCnt,
7755                    shortText: `+${moreCnt}`,
7756                    text,
7757                    view: viewApi,
7758                };
7759                return (h(p, null,
7760                    Boolean(props.moreCnt) && (h(ContentContainer, { elTag: props.elTag || 'a', elRef: this.linkElRef, elClasses: [
7761                            ...(props.elClasses || []),
7762                            'fc-more-link',
7763                        ], elAttrs: Object.assign(Object.assign(Object.assign({}, props.elAttrs), createAriaClickAttrs(this.handleClick)), { title: hint, 'aria-expanded': state.isPopoverOpen, 'aria-controls': state.isPopoverOpen ? state.popoverId : '' }), renderProps: renderProps, generatorName: "moreLinkContent", generator: options.moreLinkContent || props.defaultGenerator || renderMoreLinkInner$1, classNameGenerator: options.moreLinkClassNames, didMount: options.moreLinkDidMount, willUnmount: options.moreLinkWillUnmount }, props.children)),
7764                    state.isPopoverOpen && (h(MorePopover, { id: state.popoverId, startDate: range.start, endDate: range.end, dateProfile: props.dateProfile, todayRange: props.todayRange, extraDateSpan: props.extraDateSpan, parentEl: this.parentEl, alignmentEl: props.alignmentElRef ?
7765                            props.alignmentElRef.current :
7766                            this.linkElRef.current, alignGridTop: props.alignGridTop, onClose: this.handlePopoverClose }, props.popoverContent()))));
7767            }));
7768        }
7769        componentDidMount() {
7770            this.updateParentEl();
7771        }
7772        componentDidUpdate() {
7773            this.updateParentEl();
7774        }
7775        updateParentEl() {
7776            if (this.linkElRef.current) {
7777                this.parentEl = elementClosest(this.linkElRef.current, '.fc-view-harness');
7778            }
7779        }
7780    }
7781    function renderMoreLinkInner$1(props) {
7782        return props.text;
7783    }
7784    function computeRange(props) {
7785        if (props.allDayDate) {
7786            return {
7787                start: props.allDayDate,
7788                end: addDays(props.allDayDate, 1),
7789            };
7790        }
7791        let { hiddenSegs } = props;
7792        return {
7793            start: computeEarliestSegStart(hiddenSegs),
7794            end: computeLatestSegEnd(hiddenSegs),
7795        };
7796    }
7797    function computeEarliestSegStart(segs) {
7798        return segs.reduce(pickEarliestStart).eventRange.range.start;
7799    }
7800    function pickEarliestStart(seg0, seg1) {
7801        return seg0.eventRange.range.start < seg1.eventRange.range.start ? seg0 : seg1;
7802    }
7803    function computeLatestSegEnd(segs) {
7804        return segs.reduce(pickLatestEnd).eventRange.range.end;
7805    }
7806    function pickLatestEnd(seg0, seg1) {
7807        return seg0.eventRange.range.end > seg1.eventRange.range.end ? seg0 : seg1;
7808    }
7809
7810    class Store {
7811        constructor() {
7812            this.handlers = [];
7813        }
7814        set(value) {
7815            this.currentValue = value;
7816            for (let handler of this.handlers) {
7817                handler(value);
7818            }
7819        }
7820        subscribe(handler) {
7821            this.handlers.push(handler);
7822            if (this.currentValue !== undefined) {
7823                handler(this.currentValue);
7824            }
7825        }
7826    }
7827
7828    /*
7829    Subscribers will get a LIST of CustomRenderings
7830    */
7831    class CustomRenderingStore extends Store {
7832        constructor() {
7833            super(...arguments);
7834            this.map = new Map();
7835        }
7836        // for consistent order
7837        handle(customRendering) {
7838            const { map } = this;
7839            let updated = false;
7840            if (customRendering.isActive) {
7841                map.set(customRendering.id, customRendering);
7842                updated = true;
7843            }
7844            else if (map.has(customRendering.id)) {
7845                map.delete(customRendering.id);
7846                updated = true;
7847            }
7848            if (updated) {
7849                this.set(map);
7850            }
7851        }
7852    }
7853
7854    var internal = {
7855        __proto__: null,
7856        BASE_OPTION_DEFAULTS: BASE_OPTION_DEFAULTS,
7857        BaseComponent: BaseComponent,
7858        BgEvent: BgEvent,
7859        CalendarImpl: CalendarImpl,
7860        CalendarRoot: CalendarRoot,
7861        ContentContainer: ContentContainer,
7862        CustomRenderingStore: CustomRenderingStore,
7863        DateComponent: DateComponent,
7864        DateEnv: DateEnv,
7865        DateProfileGenerator: DateProfileGenerator,
7866        DayCellContainer: DayCellContainer,
7867        DayHeader: DayHeader,
7868        DaySeriesModel: DaySeriesModel,
7869        DayTableModel: DayTableModel,
7870        DelayedRunner: DelayedRunner,
7871        ElementDragging: ElementDragging,
7872        ElementScrollController: ElementScrollController,
7873        Emitter: Emitter,
7874        EventContainer: EventContainer,
7875        EventImpl: EventImpl,
7876        Interaction: Interaction,
7877        MoreLinkContainer: MoreLinkContainer,
7878        NamedTimeZoneImpl: NamedTimeZoneImpl,
7879        NowIndicatorContainer: NowIndicatorContainer,
7880        NowTimer: NowTimer,
7881        PositionCache: PositionCache,
7882        RefMap: RefMap,
7883        ScrollController: ScrollController,
7884        ScrollResponder: ScrollResponder,
7885        Scroller: Scroller,
7886        SegHierarchy: SegHierarchy,
7887        SimpleScrollGrid: SimpleScrollGrid,
7888        Slicer: Slicer,
7889        Splitter: Splitter,
7890        StandardEvent: StandardEvent,
7891        TableDateCell: TableDateCell,
7892        TableDowCell: TableDowCell,
7893        Theme: Theme,
7894        ViewContainer: ViewContainer$1,
7895        ViewContextType: ViewContextType,
7896        WeekNumberContainer: WeekNumberContainer,
7897        WindowScrollController: WindowScrollController,
7898        addDays: addDays,
7899        addDurations: addDurations,
7900        addMs: addMs,
7901        addWeeks: addWeeks,
7902        allowContextMenu: allowContextMenu,
7903        allowSelection: allowSelection,
7904        applyMutationToEventStore: applyMutationToEventStore,
7905        applyStyle: applyStyle,
7906        asCleanDays: asCleanDays,
7907        asRoughMinutes: asRoughMinutes,
7908        asRoughMs: asRoughMs,
7909        asRoughSeconds: asRoughSeconds,
7910        binarySearch: binarySearch,
7911        buildElAttrs: buildElAttrs,
7912        buildEntryKey: buildEntryKey,
7913        buildEventApis: buildEventApis,
7914        buildEventRangeKey: buildEventRangeKey,
7915        buildIsoString: buildIsoString,
7916        buildNavLinkAttrs: buildNavLinkAttrs,
7917        buildSegTimeText: buildSegTimeText,
7918        collectFromHash: collectFromHash,
7919        combineEventUis: combineEventUis,
7920        compareByFieldSpecs: compareByFieldSpecs,
7921        compareNumbers: compareNumbers,
7922        compareObjs: compareObjs,
7923        computeEarliestSegStart: computeEarliestSegStart,
7924        computeEdges: computeEdges,
7925        computeFallbackHeaderFormat: computeFallbackHeaderFormat,
7926        computeInnerRect: computeInnerRect,
7927        computeRect: computeRect,
7928        computeShrinkWidth: computeShrinkWidth,
7929        computeVisibleDayRange: computeVisibleDayRange,
7930        config: config,
7931        constrainPoint: constrainPoint,
7932        createDuration: createDuration,
7933        createEmptyEventStore: createEmptyEventStore,
7934        createEventInstance: createEventInstance,
7935        createEventUi: createEventUi,
7936        createFormatter: createFormatter,
7937        diffDates: diffDates,
7938        diffDayAndTime: diffDayAndTime,
7939        diffDays: diffDays,
7940        diffPoints: diffPoints,
7941        diffWeeks: diffWeeks,
7942        diffWholeDays: diffWholeDays,
7943        diffWholeWeeks: diffWholeWeeks,
7944        disableCursor: disableCursor,
7945        elementClosest: elementClosest,
7946        elementMatches: elementMatches,
7947        enableCursor: enableCursor,
7948        eventTupleToStore: eventTupleToStore,
7949        filterHash: filterHash,
7950        findDirectChildren: findDirectChildren,
7951        findElements: findElements,
7952        flexibleCompare: flexibleCompare,
7953        formatDayString: formatDayString,
7954        formatIsoTimeString: formatIsoTimeString,
7955        getAllowYScrolling: getAllowYScrolling,
7956        getCanVGrowWithinCell: getCanVGrowWithinCell,
7957        getClippingParents: getClippingParents,
7958        getDateMeta: getDateMeta,
7959        getDayClassNames: getDayClassNames,
7960        getDefaultEventEnd: getDefaultEventEnd,
7961        getElRoot: getElRoot,
7962        getElSeg: getElSeg,
7963        getEntrySpanEnd: getEntrySpanEnd,
7964        getEventTargetViaRoot: getEventTargetViaRoot,
7965        getIsRtlScrollbarOnLeft: getIsRtlScrollbarOnLeft,
7966        getRectCenter: getRectCenter,
7967        getRelevantEvents: getRelevantEvents,
7968        getScrollGridClassNames: getScrollGridClassNames,
7969        getScrollbarWidths: getScrollbarWidths,
7970        getSectionClassNames: getSectionClassNames,
7971        getSectionHasLiquidHeight: getSectionHasLiquidHeight,
7972        getSegAnchorAttrs: getSegAnchorAttrs,
7973        getSegMeta: getSegMeta,
7974        getSlotClassNames: getSlotClassNames,
7975        getStickyFooterScrollbar: getStickyFooterScrollbar,
7976        getStickyHeaderDates: getStickyHeaderDates,
7977        getUniqueDomId: getUniqueDomId,
7978        globalLocales: globalLocales,
7979        globalPlugins: globalPlugins,
7980        greatestDurationDenominator: greatestDurationDenominator,
7981        groupIntersectingEntries: groupIntersectingEntries,
7982        guid: guid,
7983        hasBgRendering: hasBgRendering,
7984        hasCustomDayCellContent: hasCustomDayCellContent,
7985        hasShrinkWidth: hasShrinkWidth,
7986        identity: identity,
7987        injectStyles: injectStyles,
7988        interactionSettingsStore: interactionSettingsStore,
7989        interactionSettingsToStore: interactionSettingsToStore,
7990        intersectRanges: intersectRanges,
7991        intersectRects: intersectRects,
7992        intersectSpans: intersectSpans,
7993        isArraysEqual: isArraysEqual,
7994        isColPropsEqual: isColPropsEqual,
7995        isDateSelectionValid: isDateSelectionValid,
7996        isDateSpansEqual: isDateSpansEqual,
7997        isInt: isInt,
7998        isInteractionValid: isInteractionValid,
7999        isMultiDayRange: isMultiDayRange,
8000        isPropsEqual: isPropsEqual,
8001        isPropsValid: isPropsValid,
8002        isValidDate: isValidDate,
8003        mapHash: mapHash,
8004        memoize: memoize,
8005        memoizeArraylike: memoizeArraylike,
8006        memoizeHashlike: memoizeHashlike,
8007        memoizeObjArg: memoizeObjArg,
8008        mergeEventStores: mergeEventStores,
8009        multiplyDuration: multiplyDuration,
8010        padStart: padStart,
8011        parseBusinessHours: parseBusinessHours,
8012        parseClassNames: parseClassNames,
8013        parseDragMeta: parseDragMeta,
8014        parseEventDef: parseEventDef,
8015        parseFieldSpecs: parseFieldSpecs,
8016        parseMarker: parse,
8017        pointInsideRect: pointInsideRect,
8018        preventContextMenu: preventContextMenu,
8019        preventDefault: preventDefault,
8020        preventSelection: preventSelection,
8021        rangeContainsMarker: rangeContainsMarker,
8022        rangeContainsRange: rangeContainsRange,
8023        rangesEqual: rangesEqual,
8024        rangesIntersect: rangesIntersect,
8025        refineEventDef: refineEventDef,
8026        refineProps: refineProps,
8027        removeElement: removeElement,
8028        removeExact: removeExact,
8029        renderChunkContent: renderChunkContent,
8030        renderFill: renderFill,
8031        renderMicroColGroup: renderMicroColGroup,
8032        renderScrollShim: renderScrollShim,
8033        requestJson: requestJson,
8034        sanitizeShrinkWidth: sanitizeShrinkWidth,
8035        setRef: setRef,
8036        sliceEventStore: sliceEventStore,
8037        sortEventSegs: sortEventSegs,
8038        startOfDay: startOfDay,
8039        translateRect: translateRect,
8040        triggerDateSelect: triggerDateSelect,
8041        unpromisify: unpromisify,
8042        whenTransitionDone: whenTransitionDone,
8043        wholeDivideDurations: wholeDivideDurations
8044    };
8045
8046    var css_248z$3 = ":root{--fc-small-font-size:.85em;--fc-page-bg-color:#fff;--fc-neutral-bg-color:hsla(0,0%,82%,.3);--fc-neutral-text-color:grey;--fc-border-color:#ddd;--fc-button-text-color:#fff;--fc-button-bg-color:#2c3e50;--fc-button-border-color:#2c3e50;--fc-button-hover-bg-color:#1e2b37;--fc-button-hover-border-color:#1a252f;--fc-button-active-bg-color:#1a252f;--fc-button-active-border-color:#151e27;--fc-event-bg-color:#3788d8;--fc-event-border-color:#3788d8;--fc-event-text-color:#fff;--fc-event-selected-overlay-color:rgba(0,0,0,.25);--fc-more-link-bg-color:#d0d0d0;--fc-more-link-text-color:inherit;--fc-event-resizer-thickness:8px;--fc-event-resizer-dot-total-width:8px;--fc-event-resizer-dot-border-width:1px;--fc-non-business-color:hsla(0,0%,84%,.3);--fc-bg-event-color:#8fdf82;--fc-bg-event-opacity:0.3;--fc-highlight-color:rgba(188,232,241,.3);--fc-today-bg-color:rgba(255,220,40,.15);--fc-now-indicator-color:red}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc-unselectable{-webkit-touch-callout:none;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-moz-user-select:none;user-select:none}.fc{display:flex;flex-direction:column;font-size:1em}.fc,.fc *,.fc :after,.fc :before{box-sizing:border-box}.fc table{border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{padding:0;vertical-align:top}.fc a[data-navlink]{cursor:pointer}.fc a[data-navlink]:hover{text-decoration:underline}.fc-direction-ltr{direction:ltr;text-align:left}.fc-direction-rtl{direction:rtl;text-align:right}.fc-theme-standard td,.fc-theme-standard th{border:1px solid var(--fc-border-color)}.fc-liquid-hack td,.fc-liquid-hack th{position:relative}@font-face{font-family:fcicons;font-style:normal;font-weight:400;src:url(\"data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBfAAAAC8AAAAYGNtYXAXVtKNAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5ZgYydxIAAAF4AAAFNGhlYWQUJ7cIAAAGrAAAADZoaGVhB20DzAAABuQAAAAkaG10eCIABhQAAAcIAAAALGxvY2ED4AU6AAAHNAAAABhtYXhwAA8AjAAAB0wAAAAgbmFtZXsr690AAAdsAAABhnBvc3QAAwAAAAAI9AAAACAAAwPAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpBgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6Qb//f//AAAAAAAg6QD//f//AAH/4xcEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAWIAjQKeAskAEwAAJSc3NjQnJiIHAQYUFwEWMjc2NCcCnuLiDQ0MJAz/AA0NAQAMJAwNDcni4gwjDQwM/wANIwz/AA0NDCMNAAAAAQFiAI0CngLJABMAACUBNjQnASYiBwYUHwEHBhQXFjI3AZ4BAA0N/wAMJAwNDeLiDQ0MJAyNAQAMIw0BAAwMDSMM4uINIwwNDQAAAAIA4gC3Ax4CngATACcAACUnNzY0JyY
8046iDwEGFB8BFjI3NjQnISc3NjQnJiIPAQYUHwEWMjc2NCcB87e3DQ0MIw3VDQ3VDSMMDQ0BK7e3DQ0MJAzVDQ3VDCQMDQ3zuLcMJAwNDdUNIwzWDAwNIwy4twwkDA0N1Q0jDNYMDA0jDAAAAgDiALcDHgKeABMAJwAAJTc2NC8BJiIHBhQfAQcGFBcWMjchNzY0LwEmIgcGFB8BBwYUFxYyNwJJ1Q0N1Q0jDA0Nt7cNDQwjDf7V1Q0N1QwkDA0Nt7cNDQwkDLfWDCMN1Q0NDCQMt7gMIw0MDNYMIw3VDQ0MJAy3uAwjDQwMAAADAFUAAAOrA1UAMwBoAHcAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMhMjY1NCYjISIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAAVYRGRkR/qoRGRkRA1UFBAUOCQkVDAsZDf2rDRkLDBUJCA4FBQUFBQUOCQgVDAsZDQJVDRkLDBUJCQ4FBAVVAgECBQMCBwQECAX9qwQJAwQHAwMFAQICAgIBBQMDBwQDCQQCVQUIBAQHAgMFAgEC/oAZEhEZGRESGQAAAAADAFUAAAOrA1UAMwBoAIkAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMzFRQWMzI2PQEzMjY1NCYrATU0JiMiBh0BIyIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAgBkSEhmAERkZEYAZEhIZgBEZGREDVQUEBQ4JCRUMCxkN/asNGQsMFQkIDgUFBQUFBQ4JCBUMCxkNAlUNGQsMFQkJDgUEBVUCAQIFAwIHBAQIBf2rBAkDBAcDAwUBAgICAgEFAwMHBAMJBAJVBQgEBAcCAwUCAQL+gIASGRkSgBkSERmAEhkZEoAZERIZAAABAOIAjQMeAskAIAAAExcHBhQXFjI/ARcWMjc2NC8BNzY0JyYiDwEnJiIHBhQX4uLiDQ0MJAzi4gwkDA0N4uINDQwkDOLiDCQMDQ0CjeLiDSMMDQ3h4Q0NDCMN4uIMIw0MDOLiDAwNIwwAAAABAAAAAQAAa5n0y18PPPUACwQAAAAAANivOVsAAAAA2K85WwAAAAADqwNVAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAAAAAOrAAEAAAAAAAAAAAAAAAAAAAALBAAAAAAAAAAAAAAAAgAAAAQAAWIEAAFiBAAA4gQAAOIEAABVBAAAVQQAAOIAAAAAAAoAFAAeAEQAagCqAOoBngJkApoAAQAAAAsAigADAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGZjaWNvbnMAZgBjAGkAYwBvAG4Ac1ZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGZjaWNvbnMAZgBjAGkAYwBvAG4Ac2ZjaWNvbnMAZgBjAGkAYwBvAG4Ac1JlZ3VsYXIAUgBlAGcAdQBsAGEAcmZjaWNvbnMAZgBjAGkAYwBvAG4Ac0ZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\") format(\"truetype\")}.fc-icon{speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font-family:fcicons!important;font-style:normal;font-variant:normal;font-weight:400;height:1em;line-height:1;text-align:center;text-transform:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:1em}.fc-icon-chevron-left:before{content:\"\\e900\"}.fc-icon-chevron-right:before{content:\"\\e901\"}.fc-icon-chevrons-left:before{content:\"\\e902\"}.fc-icon-chevrons-right:before{content:\"\\e903\"}.fc-icon-minus-square:before{content:\"\\e904\"}.fc-icon-plus-square:before{content:\"\\e905\"}.fc-icon-x:before{content:\"\\e906\"}.fc .fc-button{border-radius:0;font-family:inherit;font-size:inherit;line-height:inherit;margin:0;overflow:visible;text-transform:none}.fc .fc-button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.fc .fc-button{-webkit-appearance:button}.fc .fc-button:not(:disabled){cursor:pointer}.fc .fc-button::-moz-focus-inner{border-style:none;padding:0}.fc .fc-button{background-color:transparent;border:1px solid transparent;border-radius:.25em;display:inline-block;font-size:1em;font-weight:400;line-height:1.5;padding:.4em .65em;text-align:center;-webkit-user-select:none
vendor: 8,355 bytes, line 8046
8046;-moz-user-select:none;user-select:none;vertical-align:middle}.fc .fc-button:hover{text-decoration:none}.fc .fc-button:focus{box-shadow:0 0 0 .2rem rgba(44,62,80,.25);outline:0}.fc .fc-button:disabled{opacity:.65}.fc .fc-button-primary{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:hover{background-color:var(--fc-button-hover-bg-color);border-color:var(--fc-button-hover-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:disabled{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button-primary:not(:disabled).fc-button-active,.fc .fc-button-primary:not(:disabled):active{background-color:var(--fc-button-active-bg-color);border-color:var(--fc-button-active-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:not(:disabled).fc-button-active:focus,.fc .fc-button-primary:not(:disabled):active:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button .fc-icon{font-size:1.5em;vertical-align:middle}.fc .fc-button-group{display:inline-flex;position:relative;vertical-align:middle}.fc .fc-button-group>.fc-button{flex:1 1 auto;position:relative}.fc .fc-button-group>.fc-button.fc-button-active,.fc .fc-button-group>.fc-button:active,.fc .fc-button-group>.fc-button:focus,.fc .fc-button-group>.fc-button:hover{z-index:1}.fc-direction-ltr .fc-button-group>.fc-button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;margin-left:-1px}.fc-direction-ltr .fc-button-group>.fc-button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.fc-direction-rtl .fc-button-group>.fc-button:not(:first-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.fc-direction-rtl .fc-button-group>.fc-button:not(:last-child){border-bottom-left-radius:0;border-top-left-radius:0}.fc .fc-toolbar{align-items:center;display:flex;justify-content:space-between}.fc .fc-toolbar.fc-header-toolbar{margin-bottom:1.5em}.fc .fc-toolbar.fc-footer-toolbar{margin-top:1.5em}.fc .fc-toolbar-title{font-size:1.75em;margin:0}.fc-direction-ltr .fc-toolbar>*>:not(:first-child){margin-left:.75em}.fc-direction-rtl .fc-toolbar>*>:not(:first-child){margin-right:.75em}.fc-direction-rtl .fc-toolbar-ltr{flex-direction:row-reverse}.fc .fc-scroller{-webkit-overflow-scrolling:touch;position:relative}.fc .fc-scroller-liquid{height:100%}.fc .fc-scroller-liquid-absolute{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-scroller-harness{direction:ltr;overflow:hidden;position:relative}.fc .fc-scroller-harness-liquid{height:100%}.fc-direction-rtl .fc-scroller-harness>.fc-scroller{direction:rtl}.fc-theme-standard .fc-scrollgrid{border:1px solid var(--fc-border-color)}.fc .fc-scrollgrid,.fc .fc-scrollgrid table{table-layout:fixed;width:100%}.fc .fc-scrollgrid table{border-left-style:hidden;border-right-style:hidden;border-top-style:hidden}.fc .fc-scrollgrid{border-bottom-width:0;border-collapse:separate;border-right-width:0}.fc .fc-scrollgrid-liquid{height:100%}.fc .fc-scrollgrid-section,.fc .fc-scrollgrid-section table,.fc .fc-scrollgrid-section>td{height:1px}.fc .fc-scrollgrid-section-liquid>td{height:100%}.fc .fc-scrollgrid-section>*{border-left-width:0;border-top-width:0}.fc .fc-scrollgrid-section-footer>*,.fc .fc-scrollgrid-section-header>*{border-bottom-width:0}.fc .fc-scrollgrid-section-body table,.fc .fc-scrollgrid-section-footer table{border-bottom-style:hidden}.fc .fc-scrollgrid-section-sticky>*{background:var(--fc-page-bg-color);position:sticky;z-index:3}.fc .fc-scrollgrid-section-header.fc-scrollgrid-section-sticky>*{top:0}.fc .fc-scrollgrid-section-footer.fc-scrollgrid-section-sticky>*{bottom:0}.fc .fc-scrollgrid-sticky-shim{height:1px;margin-bottom:-1px}.fc-sticky{position:sticky}.fc .fc-view-harness{flex-grow:1;position:relative}.fc .fc-view-harness-active>.fc-view{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-col-header-cell-cushion{display:inline-block;padding:2px 4px}.fc .fc-bg-event,.fc .fc-highlight,.fc .fc-non-business{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-non-business{background:var(--fc-non-business-color)}.fc .fc-bg-event{background:var(--fc-bg-event-color);opacity:var(--fc-bg-event-opacity)}.fc .fc-bg-event .fc-event-title{font-size:var(--fc-small-font-size);font-style:italic;margin:.5em}.fc .fc-highlight{background:var(--fc-highlight-color)}.fc .fc-cell-shaded,.fc .fc-day-disabled{background:var(--fc-neutral-bg-color)}a.fc-event,a.fc-event:hover{text-decoration:none}.fc-event.fc-event-draggable,.fc-event[href]{cursor:pointer}.fc-event .fc-event-main{position:relative;z-index:2}.fc-event-dragging:not(.fc-event-selected){opacity:.75}.fc-event-dragging.fc-event-selected{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-event .fc-event-resizer{display:none;position:absolute;z-index:4}.fc-event-selected .fc-event-resizer,.fc-event:hover .fc-event-resizer{display:block}.fc-event-selected .fc-event-resizer{background:var(--fc-page-bg-color);border-color:inherit;border-radius:calc(var(--fc-event-resizer-dot-total-width)/2);border-style:solid;border-width:var(--fc-event-resizer-dot-border-width);height:var(--fc-event-resizer-dot-total-width);width:var(--fc-event-resizer-dot-total-width)}.fc-event-selected .fc-event-resizer:before{bottom:-20px;content:\"\";left:-20px;position:absolute;right:-20px;top:-20px}.fc-event-selected,.fc-event:focus{box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event-selected:before,.fc-event:focus:before{bottom:0;content:\"\";left:0;position:absolute;right:0;top:0;z-index:3}.fc-event-selected:after,.fc-event:focus:after{background:var(--fc-event-selected-overlay-color);bottom:-1px;content:\"\";left:-1px;position:absolute;right:-1px;top:-1px;z-index:1}.fc-h-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-h-event .fc-event-main{color:var(--fc-event-text-color)}.fc-h-event .fc-event-main-frame{display:flex}.fc-h-event .fc-event-time{max-width:100%;overflow:hidden}.fc-h-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-width:0}.fc-h-event .fc-event-title{display:inline-block;left:0;max-width:100%;overflow:hidden;right:0;vertical-align:top}.fc-h-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-start),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-end){border-bottom-left-radius:0;border-left-width:0;border-top-left-radius:0}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-end),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-start){border-bottom-right-radius:0;border-right-width:0;border-top-right-radius:0}.fc-h-event:not(.fc-event-selected) .fc-event-resizer{bottom:0;top:0;width:var(--fc-event-resizer-thickness)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end{cursor:w-resize;left:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start{cursor:e-resize;right:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-h-event.fc-event-selected .fc-event-resizer{margin-top:calc(var(--fc-event-resizer-dot-total-width)*-.5);top:50%}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-start,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-end{left:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-end,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-start{right:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc .fc-popover{box-shadow:0 2px 6px rgba(0,0,0,.15);position:absolute;z-index:9999}.fc .fc-popover-header{align-items:center;display:flex;flex-direction:row;justify-content:space-between;padding:3px 4px}.fc .fc-popover-title{margin:0 2px}.fc .fc-popover-close{cursor:pointer;font-size:1.1em;opacity:.65}.fc-theme-standard .fc-popover{background:var(--fc-page-bg-color);border:1px solid var(--fc-border-color)}.fc-theme-standard .fc-popover-header{background:var(--fc-neutral-bg-color)}";
vendor: 65,694 bytes, lines 8047-9433
8047    injectStyles(css_248z$3);
8048
8049    const MINIMAL_RAW_EN_LOCALE = {
8050        code: 'en',
8051        week: {
8052            dow: 0,
8053            doy: 4, // 4 days need to be within the year to be considered the first week
8054        },
8055        direction: 'ltr',
8056        buttonText: {
8057            prev: 'prev',
8058            next: 'next',
8059            prevYear: 'prev year',
8060            nextYear: 'next year',
8061            year: 'year',
8062            today: 'today',
8063            month: 'month',
8064            week: 'week',
8065            day: 'day',
8066            list: 'list',
8067        },
8068        weekText: 'W',
8069        weekTextLong: 'Week',
8070        closeHint: 'Close',
8071        timeHint: 'Time',
8072        eventHint: 'Event',
8073        allDayText: 'all-day',
8074        moreLinkText: 'more',
8075        noEventsText: 'No events to display',
8076    };
8077    const RAW_EN_LOCALE = Object.assign(Object.assign({}, MINIMAL_RAW_EN_LOCALE), { 
8078        // Includes things we don't want other locales to inherit,
8079        // things that derive from other translatable strings.
8080        buttonHints: {
8081            prev: 'Previous $0',
8082            next: 'Next $0',
8083            today(buttonText, unit) {
8084                return (unit === 'day')
8085                    ? 'Today'
8086                    : `This ${buttonText}`;
8087            },
8088        }, viewHint: '$0 view', navLinkHint: 'Go to $0', moreLinkHint(eventCnt) {
8089            return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;
8090        } });
8091    function organizeRawLocales(explicitRawLocales) {
8092        let defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en';
8093        let allRawLocales = globalLocales.concat(explicitRawLocales);
8094        let rawLocaleMap = {
8095            en: RAW_EN_LOCALE,
8096        };
8097        for (let rawLocale of allRawLocales) {
8098            rawLocaleMap[rawLocale.code] = rawLocale;
8099        }
8100        return {
8101            map: rawLocaleMap,
8102            defaultCode,
8103        };
8104    }
8105    function buildLocale(inputSingular, available) {
8106        if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) {
8107            return parseLocale(inputSingular.code, [inputSingular.code], inputSingular);
8108        }
8109        return queryLocale(inputSingular, available);
8110    }
8111    function queryLocale(codeArg, available) {
8112        let codes = [].concat(codeArg || []); // will convert to array
8113        let raw = queryRawLocale(codes, available) || RAW_EN_LOCALE;
8114        return parseLocale(codeArg, codes, raw);
8115    }
8116    function queryRawLocale(codes, available) {
8117        for (let i = 0; i < codes.length; i += 1) {
8118            let parts = codes[i].toLocaleLowerCase().split('-');
8119            for (let j = parts.length; j > 0; j -= 1) {
8120                let simpleId = parts.slice(0, j).join('-');
8121                if (available[simpleId]) {
8122                    return available[simpleId];
8123                }
8124            }
8125        }
8126        return null;
8127    }
8128    function parseLocale(codeArg, codes, raw) {
8129        let merged = mergeProps([MINIMAL_RAW_EN_LOCALE, raw], ['buttonText']);
8130        delete merged.code; // don't want this part of the options
8131        let { week } = merged;
8132        delete merged.week;
8133        return {
8134            codeArg,
8135            codes,
8136            week,
8137            simpleNumberFormat: new Intl.NumberFormat(codeArg),
8138            options: merged,
8139        };
8140    }
8141
8142    class StandardTheme extends Theme {
8143    }
8144    StandardTheme.prototype.classes = {
8145        root: 'fc-theme-standard',
8146        tableCellShaded: 'fc-cell-shaded',
8147        buttonGroup: 'fc-button-group',
8148        button: 'fc-button fc-button-primary',
8149        buttonActive: 'fc-button-active',
8150    };
8151    StandardTheme.prototype.baseIconClass = 'fc-icon';
8152    StandardTheme.prototype.iconClasses = {
8153        close: 'fc-icon-x',
8154        prev: 'fc-icon-chevron-left',
8155        next: 'fc-icon-chevron-right',
8156        prevYear: 'fc-icon-chevrons-left',
8157        nextYear: 'fc-icon-chevrons-right',
8158    };
8159    StandardTheme.prototype.rtlIconClasses = {
8160        prev: 'fc-icon-chevron-right',
8161        next: 'fc-icon-chevron-left',
8162        prevYear: 'fc-icon-chevrons-right',
8163        nextYear: 'fc-icon-chevrons-left',
8164    };
8165    StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; // TODO: make TS-friendly
8166    StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon';
8167    StandardTheme.prototype.iconOverridePrefix = 'fc-icon-';
8168
8169    function compileViewDefs(defaultConfigs, overrideConfigs) {
8170        let hash = {};
8171        let viewType;
8172        for (viewType in defaultConfigs) {
8173            ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
8174        }
8175        for (viewType in overrideConfigs) {
8176            ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
8177        }
8178        return hash;
8179    }
8180    function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
8181        if (hash[viewType]) {
8182            return hash[viewType];
8183        }
8184        let viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs);
8185        if (viewDef) {
8186            hash[viewType] = viewDef;
8187        }
8188        return viewDef;
8189    }
8190    function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
8191        let defaultConfig = defaultConfigs[viewType];
8192        let overrideConfig = overrideConfigs[viewType];
8193        let queryProp = (name) => ((defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] :
8194            ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null));
8195        let theComponent = queryProp('component');
8196        let superType = queryProp('superType');
8197        let superDef = null;
8198        if (superType) {
8199            if (superType === viewType) {
8200                throw new Error('Can\'t have a custom view type that references itself');
8201            }
8202            superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs);
8203        }
8204        if (!theComponent && superDef) {
8205            theComponent = superDef.component;
8206        }
8207        if (!theComponent) {
8208            return null; // don't throw a warning, might be settings for a single-unit view
8209        }
8210        return {
8211            type: viewType,
8212            component: theComponent,
8213            defaults: Object.assign(Object.assign({}, (superDef ? superDef.defaults : {})), (defaultConfig ? defaultConfig.rawOptions : {})),
8214            overrides: Object.assign(Object.assign({}, (superDef ? superDef.overrides : {})), (overrideConfig ? overrideConfig.rawOptions : {})),
8215        };
8216    }
8217
8218    function parseViewConfigs(inputs) {
8219        return mapHash(inputs, parseViewConfig);
8220    }
8221    function parseViewConfig(input) {
8222        let rawOptions = typeof input === 'function' ?
8223            { component: input } :
8224            input;
8225        let { component } = rawOptions;
8226        if (rawOptions.content) {
8227            component = createViewHookComponent(rawOptions);
8228            // TODO: remove content/classNames/didMount/etc from options?
8229        }
8230        return {
8231            superType: rawOptions.type,
8232            component: component,
8233            rawOptions, // includes type and component too :(
8234        };
8235    }
8236    function createViewHookComponent(options) {
8237        return (viewProps) => (h(ViewContextType.Consumer, null, (context) => (h(ContentContainer, { elTag: "div", elClasses: buildViewClassNames(context.viewSpec), renderProps: Object.assign(Object.assign({}, viewProps), { nextDayThreshold: context.options.nextDayThreshold }), generatorName: undefined, generator: options.content, classNameGenerator: options.classNames, didMount: options.didMount, willUnmount: options.willUnmount }))));
8238    }
8239
8240    function buildViewSpecs(defaultInputs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
8241        let defaultConfigs = parseViewConfigs(defaultInputs);
8242        let overrideConfigs = parseViewConfigs(optionOverrides.views);
8243        let viewDefs = compileViewDefs(defaultConfigs, overrideConfigs);
8244        return mapHash(viewDefs, (viewDef) => buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults));
8245    }
8246    function buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
8247        let durationInput = viewDef.overrides.duration ||
8248            viewDef.defaults.duration ||
8249            dynamicOptionOverrides.duration ||
8250            optionOverrides.duration;
8251        let duration = null;
8252        let durationUnit = '';
8253        let singleUnit = '';
8254        let singleUnitOverrides = {};
8255        if (durationInput) {
8256            duration = createDurationCached(durationInput);
8257            if (duration) { // valid?
8258                let denom = greatestDurationDenominator(duration);
8259                durationUnit = denom.unit;
8260                if (denom.value === 1) {
8261                    singleUnit = durationUnit;
8262                    singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].rawOptions : {};
8263                }
8264            }
8265        }
8266        let queryButtonText = (optionsSubset) => {
8267            let buttonTextMap = optionsSubset.buttonText || {};
8268            let buttonTextKey = viewDef.defaults.buttonTextKey;
8269            if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) {
8270                return buttonTextMap[buttonTextKey];
8271            }
8272            if (buttonTextMap[viewDef.type] != null) {
8273                return buttonTextMap[viewDef.type];
8274            }
8275            if (buttonTextMap[singleUnit] != null) {
8276                return buttonTextMap[singleUnit];
8277            }
8278            return null;
8279        };
8280        let queryButtonTitle = (optionsSubset) => {
8281            let buttonHints = optionsSubset.buttonHints || {};
8282            let buttonKey = viewDef.defaults.buttonTextKey; // use same key as text
8283            if (buttonKey != null && buttonHints[buttonKey] != null) {
8284                return buttonHints[buttonKey];
8285            }
8286            if (buttonHints[viewDef.type] != null) {
8287                return buttonHints[viewDef.type];
8288            }
8289            if (buttonHints[singleUnit] != null) {
8290                return buttonHints[singleUnit];
8291            }
8292            return null;
8293        };
8294        return {
8295            type: viewDef.type,
8296            component: viewDef.component,
8297            duration,
8298            durationUnit,
8299            singleUnit,
8300            optionDefaults: viewDef.defaults,
8301            optionOverrides: Object.assign(Object.assign({}, singleUnitOverrides), viewDef.overrides),
8302            buttonTextOverride: queryButtonText(dynamicOptionOverrides) ||
8303                queryButtonText(optionOverrides) || // constructor-specified buttonText lookup hash takes precedence
8304                viewDef.overrides.buttonText,
8305            buttonTextDefault: queryButtonText(localeDefaults) ||
8306                viewDef.defaults.buttonText ||
8307                queryButtonText(BASE_OPTION_DEFAULTS) ||
8308                viewDef.type,
8309            // not DRY
8310            buttonTitleOverride: queryButtonTitle(dynamicOptionOverrides) ||
8311                queryButtonTitle(optionOverrides) ||
8312                viewDef.overrides.buttonHint,
8313            buttonTitleDefault: queryButtonTitle(localeDefaults) ||
8314                viewDef.defaults.buttonHint ||
8315                queryButtonTitle(BASE_OPTION_DEFAULTS),
8316            // will eventually fall back to buttonText
8317        };
8318    }
8319    // hack to get memoization working
8320    let durationInputMap = {};
8321    function createDurationCached(durationInput) {
8322        let json = JSON.stringify(durationInput);
8323        let res = durationInputMap[json];
8324        if (res === undefined) {
8325            res = createDuration(durationInput);
8326            durationInputMap[json] = res;
8327        }
8328        return res;
8329    }
8330
8331    function reduceViewType(viewType, action) {
8332        switch (action.type) {
8333            case 'CHANGE_VIEW_TYPE':
8334                viewType = action.viewType;
8335        }
8336        return viewType;
8337    }
8338
8339    function reduceDynamicOptionOverrides(dynamicOptionOverrides, action) {
8340        switch (action.type) {
8341            case 'SET_OPTION':
8342                return Object.assign(Object.assign({}, dynamicOptionOverrides), { [action.optionName]: action.rawOptionValue });
8343            default:
8344                return dynamicOptionOverrides;
8345        }
8346    }
8347
8348    function reduceDateProfile(currentDateProfile, action, currentDate, dateProfileGenerator) {
8349        let dp;
8350        switch (action.type) {
8351            case 'CHANGE_VIEW_TYPE':
8352                return dateProfileGenerator.build(action.dateMarker || currentDate);
8353            case 'CHANGE_DATE':
8354                return dateProfileGenerator.build(action.dateMarker);
8355            case 'PREV':
8356                dp = dateProfileGenerator.buildPrev(currentDateProfile, currentDate);
8357                if (dp.isValid) {
8358                    return dp;
8359                }
8360                break;
8361            case 'NEXT':
8362                dp = dateProfileGenerator.buildNext(currentDateProfile, currentDate);
8363                if (dp.isValid) {
8364                    return dp;
8365                }
8366                break;
8367        }
8368        return currentDateProfile;
8369    }
8370
8371    function reduceDateSelection(currentSelection, action) {
8372        switch (action.type) {
8373            case 'UNSELECT_DATES':
8374                return null;
8375            case 'SELECT_DATES':
8376                return action.selection;
8377            default:
8378                return currentSelection;
8379        }
8380    }
8381
8382    function reduceSelectedEvent(currentInstanceId, action) {
8383        switch (action.type) {
8384            case 'UNSELECT_EVENT':
8385                return '';
8386            case 'SELECT_EVENT':
8387                return action.eventInstanceId;
8388            default:
8389                return currentInstanceId;
8390        }
8391    }
8392
8393    function reduceEventDrag(currentDrag, action) {
8394        let newDrag;
8395        switch (action.type) {
8396            case 'UNSET_EVENT_DRAG':
8397                return null;
8398            case 'SET_EVENT_DRAG':
8399                newDrag = action.state;
8400                return {
8401                    affectedEvents: newDrag.affectedEvents,
8402                    mutatedEvents: newDrag.mutatedEvents,
8403                    isEvent: newDrag.isEvent,
8404                };
8405            default:
8406                return currentDrag;
8407        }
8408    }
8409
8410    function reduceEventResize(currentResize, action) {
8411        let newResize;
8412        switch (action.type) {
8413            case 'UNSET_EVENT_RESIZE':
8414                return null;
8415            case 'SET_EVENT_RESIZE':
8416                newResize = action.state;
8417                return {
8418                    affectedEvents: newResize.affectedEvents,
8419                    mutatedEvents: newResize.mutatedEvents,
8420                    isEvent: newResize.isEvent,
8421                };
8422            default:
8423                return currentResize;
8424        }
8425    }
8426
8427    function parseToolbars(calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
8428        let header = calendarOptions.headerToolbar ? parseToolbar(calendarOptions.headerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
8429        let footer = calendarOptions.footerToolbar ? parseToolbar(calendarOptions.footerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
8430        return { header, footer };
8431    }
8432    function parseToolbar(sectionStrHash, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
8433        let sectionWidgets = {};
8434        let viewsWithButtons = [];
8435        let hasTitle = false;
8436        for (let sectionName in sectionStrHash) {
8437            let sectionStr = sectionStrHash[sectionName];
8438            let sectionRes = parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi);
8439            sectionWidgets[sectionName] = sectionRes.widgets;
8440            viewsWithButtons.push(...sectionRes.viewsWithButtons);
8441            hasTitle = hasTitle || sectionRes.hasTitle;
8442        }
8443        return { sectionWidgets, viewsWithButtons, hasTitle };
8444    }
8445    /*
8446    BAD: querying icons and text here. should be done at render time
8447    */
8448    function parseSection(sectionStr, calendarOptions, // defaults+overrides, then refined
8449    calendarOptionOverrides, // overrides only!, unrefined :(
8450    theme, viewSpecs, calendarApi) {
8451        let isRtl = calendarOptions.direction === 'rtl';
8452        let calendarCustomButtons = calendarOptions.customButtons || {};
8453        let calendarButtonTextOverrides = calendarOptionOverrides.buttonText || {};
8454        let calendarButtonText = calendarOptions.buttonText || {};
8455        let calendarButtonHintOverrides = calendarOptionOverrides.buttonHints || {};
8456        let calendarButtonHints = calendarOptions.buttonHints || {};
8457        let sectionSubstrs = sectionStr ? sectionStr.split(' ') : [];
8458        let viewsWithButtons = [];
8459        let hasTitle = false;
8460        let widgets = sectionSubstrs.map((buttonGroupStr) => (buttonGroupStr.split(',').map((buttonName) => {
8461            if (buttonName === 'title') {
8462                hasTitle = true;
8463                return { buttonName };
8464            }
8465            let customButtonProps;
8466            let viewSpec;
8467            let buttonClick;
8468            let buttonIcon; // only one of these will be set
8469            let buttonText; // "
8470            let buttonHint;
8471            // ^ for the title="" attribute, for accessibility
8472            if ((customButtonProps = calendarCustomButtons[buttonName])) {
8473                buttonClick = (ev) => {
8474                    if (customButtonProps.click) {
8475                        customButtonProps.click.call(ev.target, ev, ev.target); // TODO: use Calendar this context?
8476                    }
8477                };
8478                (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) ||
8479                    (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
8480                    (buttonText = customButtonProps.text);
8481                buttonHint = customButtonProps.hint || customButtonProps.text;
8482            }
8483            else if ((viewSpec = viewSpecs[buttonName])) {
8484                viewsWithButtons.push(buttonName);
8485                buttonClick = () => {
8486                    calendarApi.changeView(buttonName);
8487                };
8488                (buttonText = viewSpec.buttonTextOverride) ||
8489                    (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
8490                    (buttonText = viewSpec.buttonTextDefault);
8491                let textFallback = viewSpec.buttonTextOverride ||
8492                    viewSpec.buttonTextDefault;
8493                buttonHint = formatWithOrdinals(viewSpec.buttonTitleOverride ||
8494                    viewSpec.buttonTitleDefault ||
8495                    calendarOptions.viewHint, [textFallback, buttonName], // view-name = buttonName
8496                textFallback);
8497            }
8498            else if (calendarApi[buttonName]) { // a calendarApi method
8499                buttonClick = () => {
8500                    calendarApi[buttonName]();
8501                };
8502                (buttonText = calendarButtonTextOverrides[buttonName]) ||
8503                    (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
8504                    (buttonText = calendarButtonText[buttonName]); // everything else is considered default
8505                if (buttonName === 'prevYear' || buttonName === 'nextYear') {
8506                    let prevOrNext = buttonName === 'prevYear' ? 'prev' : 'next';
8507                    buttonHint = formatWithOrdinals(calendarButtonHintOverrides[prevOrNext] ||
8508                        calendarButtonHints[prevOrNext], [
8509                        calendarButtonText.year || 'year',
8510                        'year',
8511                    ], calendarButtonText[buttonName]);
8512                }
8513                else {
8514                    buttonHint = (navUnit) => formatWithOrdinals(calendarButtonHintOverrides[buttonName] ||
8515                        calendarButtonHints[buttonName], [
8516                        calendarButtonText[navUnit] || navUnit,
8517                        navUnit,
8518                    ], calendarButtonText[buttonName]);
8519                }
8520            }
8521            return { buttonName, buttonClick, buttonIcon, buttonText, buttonHint };
8522        })));
8523        return { widgets, viewsWithButtons, hasTitle };
8524    }
8525
8526    // always represents the current view. otherwise, it'd need to change value every time date changes
8527    class ViewImpl {
8528        constructor(type, getCurrentData, dateEnv) {
8529            this.type = type;
8530            this.getCurrentData = getCurrentData;
8531            this.dateEnv = dateEnv;
8532        }
8533        get calendar() {
8534            return this.getCurrentData().calendarApi;
8535        }
8536        get title() {
8537            return this.getCurrentData().viewTitle;
8538        }
8539        get activeStart() {
8540            return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.start);
8541        }
8542        get activeEnd() {
8543            return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.end);
8544        }
8545        get currentStart() {
8546            return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.start);
8547        }
8548        get currentEnd() {
8549            return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.end);
8550        }
8551        getOption(name) {
8552            return this.getCurrentData().options[name]; // are the view-specific options
8553        }
8554    }
8555
8556    class TaskRunner {
8557        constructor(runTaskOption, drainedOption) {
8558            this.runTaskOption = runTaskOption;
8559            this.drainedOption = drainedOption;
8560            this.queue = [];
8561            this.delayedRunner = new DelayedRunner(this.drain.bind(this));
8562        }
8563        request(task, delay) {
8564            this.queue.push(task);
8565            this.delayedRunner.request(delay);
8566        }
8567        pause(scope) {
8568            this.delayedRunner.pause(scope);
8569        }
8570        resume(scope, force) {
8571            this.delayedRunner.resume(scope, force);
8572        }
8573        drain() {
8574            let { queue } = this;
8575            while (queue.length) {
8576                let completedTasks = [];
8577                let task;
8578                while ((task = queue.shift())) {
8579                    this.runTask(task);
8580                    completedTasks.push(task);
8581                }
8582                this.drained(completedTasks);
8583            } // keep going, in case new tasks were added in the drained handler
8584        }
8585        runTask(task) {
8586            if (this.runTaskOption) {
8587                this.runTaskOption(task);
8588            }
8589        }
8590        drained(completedTasks) {
8591            if (this.drainedOption) {
8592                this.drainedOption(completedTasks);
8593            }
8594        }
8595    }
8596
8597    // Computes what the title at the top of the calendarApi should be for this view
8598    function buildTitle(dateProfile, viewOptions, dateEnv) {
8599        let range;
8600        // for views that span a large unit of time, show the proper interval, ignoring stray days before and after
8601        if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) {
8602            range = dateProfile.currentRange;
8603        }
8604        else { // for day units or smaller, use the actual day range
8605            range = dateProfile.activeRange;
8606        }
8607        return dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || buildTitleFormat(dateProfile)), {
8608            isEndExclusive: dateProfile.isRangeAllDay,
8609            defaultSeparator: viewOptions.titleRangeSeparator,
8610        });
8611    }
8612    // Generates the format string that should be used to generate the title for the current date range.
8613    // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
8614    function buildTitleFormat(dateProfile) {
8615        let { currentRangeUnit } = dateProfile;
8616        if (currentRangeUnit === 'year') {
8617            return { year: 'numeric' };
8618        }
8619        if (currentRangeUnit === 'month') {
8620            return { year: 'numeric', month: 'long' }; // like "September 2014"
8621        }
8622        let days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end);
8623        if (days !== null && days > 1) {
8624            // multi-day range. shorter, like "Sep 9 - 10 2014"
8625            return { year: 'numeric', month: 'short', day: 'numeric' };
8626        }
8627        // one day. longer, like "September 9 2014"
8628        return { year: 'numeric', month: 'long', day: 'numeric' };
8629    }
8630
8631    // in future refactor, do the redux-style function(state=initial) for initial-state
8632    // also, whatever is happening in constructor, have it happen in action queue too
8633    class CalendarDataManager {
8634        constructor(props) {
8635            this.computeOptionsData = memoize(this._computeOptionsData);
8636            this.computeCurrentViewData = memoize(this._computeCurrentViewData);
8637            this.organizeRawLocales = memoize(organizeRawLocales);
8638            this.buildLocale = memoize(buildLocale);
8639            this.buildPluginHooks = buildBuildPluginHooks();
8640            this.buildDateEnv = memoize(buildDateEnv$1);
8641            this.buildTheme = memoize(buildTheme);
8642            this.parseToolbars = memoize(parseToolbars);
8643            this.buildViewSpecs = memoize(buildViewSpecs);
8644            this.buildDateProfileGenerator = memoizeObjArg(buildDateProfileGenerator);
8645            this.buildViewApi = memoize(buildViewApi);
8646            this.buildViewUiProps = memoizeObjArg(buildViewUiProps);
8647            this.buildEventUiBySource = memoize(buildEventUiBySource, isPropsEqual);
8648            this.buildEventUiBases = memoize(buildEventUiBases);
8649            this.parseContextBusinessHours = memoizeObjArg(parseContextBusinessHours);
8650            this.buildTitle = memoize(buildTitle);
8651            this.emitter = new Emitter();
8652            this.actionRunner = new TaskRunner(this._handleAction.bind(this), this.updateData.bind(this));
8653            this.currentCalendarOptionsInput = {};
8654            this.currentCalendarOptionsRefined = {};
8655            this.currentViewOptionsInput = {};
8656            this.currentViewOptionsRefined = {};
8657            this.currentCalendarOptionsRefiners = {};
8658            this.getCurrentData = () => this.data;
8659            this.dispatch = (action) => {
8660                this.actionRunner.request(action); // protects against recursive calls to _handleAction
8661            };
8662            this.props = props;
8663            this.actionRunner.pause();
8664            let dynamicOptionOverrides = {};
8665            let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
8666            let currentViewType = optionsData.calendarOptions.initialView || optionsData.pluginHooks.initialView;
8667            let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
8668            // wire things up
8669            // TODO: not DRY
8670            props.calendarApi.currentDataManager = this;
8671            this.emitter.setThisContext(props.calendarApi);
8672            this.emitter.setOptions(currentViewData.options);
8673            let currentDate = getInitialDate(optionsData.calendarOptions, optionsData.dateEnv);
8674            let dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
8675            if (!rangeContainsMarker(dateProfile.activeRange, currentDate)) {
8676                currentDate = dateProfile.currentRange.start;
8677            }
8678            let calendarContext = {
8679                dateEnv: optionsData.dateEnv,
8680                options: optionsData.calendarOptions,
8681                pluginHooks: optionsData.pluginHooks,
8682                calendarApi: props.calendarApi,
8683                dispatch: this.dispatch,
8684                emitter: this.emitter,
8685                getCurrentData: this.getCurrentData,
8686            };
8687            // needs to be after setThisContext
8688            for (let callback of optionsData.pluginHooks.contextInit) {
8689                callback(calendarContext);
8690            }
8691            // NOT DRY
8692            let eventSources = initEventSources(optionsData.calendarOptions, dateProfile, calendarContext);
8693            let initialState = {
8694                dynamicOptionOverrides,
8695                currentViewType,
8696                currentDate,
8697                dateProfile,
8698                businessHours: this.parseContextBusinessHours(calendarContext),
8699                eventSources,
8700                eventUiBases: {},
8701                eventStore: createEmptyEventStore(),
8702                renderableEventStore: createEmptyEventStore(),
8703                dateSelection: null,
8704                eventSelection: '',
8705                eventDrag: null,
8706                eventResize: null,
8707                selectionConfig: this.buildViewUiProps(calendarContext).selectionConfig,
8708            };
8709            let contextAndState = Object.assign(Object.assign({}, calendarContext), initialState);
8710            for (let reducer of optionsData.pluginHooks.reducers) {
8711                Object.assign(initialState, reducer(null, null, contextAndState));
8712            }
8713            if (computeIsLoading(initialState, calendarContext)) {
8714                this.emitter.trigger('loading', true); // NOT DRY
8715            }
8716            this.state = initialState;
8717            this.updateData();
8718            this.actionRunner.resume();
8719        }
8720        resetOptions(optionOverrides, append) {
8721            let { props } = this;
8722            props.optionOverrides = append
8723                ? Object.assign(Object.assign({}, props.optionOverrides), optionOverrides) : optionOverrides;
8724            this.actionRunner.request({
8725                type: 'NOTHING',
8726            });
8727        }
8728        _handleAction(action) {
8729            let { props, state, emitter } = this;
8730            let dynamicOptionOverrides = reduceDynamicOptionOverrides(state.dynamicOptionOverrides, action);
8731            let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
8732            let currentViewType = reduceViewType(state.currentViewType, action);
8733            let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
8734            // wire things up
8735            // TODO: not DRY
8736            props.calendarApi.currentDataManager = this;
8737            emitter.setThisContext(props.calendarApi);
8738            emitter.setOptions(currentViewData.options);
8739            let calendarContext = {
8740                dateEnv: optionsData.dateEnv,
8741                options: optionsData.calendarOptions,
8742                pluginHooks: optionsData.pluginHooks,
8743                calendarApi: props.calendarApi,
8744                dispatch: this.dispatch,
8745                emitter,
8746                getCurrentData: this.getCurrentData,
8747            };
8748            let { currentDate, dateProfile } = state;
8749            if (this.data && this.data.dateProfileGenerator !== currentViewData.dateProfileGenerator) { // hack
8750                dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
8751            }
8752            currentDate = reduceCurrentDate(currentDate, action);
8753            dateProfile = reduceDateProfile(dateProfile, action, currentDate, currentViewData.dateProfileGenerator);
8754            if (action.type === 'PREV' || // TODO: move this logic into DateProfileGenerator
8755                action.type === 'NEXT' || // "
8756                !rangeContainsMarker(dateProfile.currentRange, currentDate)) {
8757                currentDate = dateProfile.currentRange.start;
8758            }
8759            let eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendarContext);
8760            let eventStore = reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendarContext);
8761            let isEventsLoading = computeEventSourcesLoading(eventSources); // BAD. also called in this func in computeIsLoading
8762            let renderableEventStore = (isEventsLoading && !currentViewData.options.progressiveEventRendering) ?
8763                (state.renderableEventStore || eventStore) : // try from previous state
8764                eventStore;
8765            let { eventUiSingleBase, selectionConfig } = this.buildViewUiProps(calendarContext); // will memoize obj
8766            let eventUiBySource = this.buildEventUiBySource(eventSources);
8767            let eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource);
8768            let newState = {
8769                dynamicOptionOverrides,
8770                currentViewType,
8771                currentDate,
8772                dateProfile,
8773                eventSources,
8774                eventStore,
8775                renderableEventStore,
8776                selectionConfig,
8777                eventUiBases,
8778                businessHours: this.parseContextBusinessHours(calendarContext),
8779                dateSelection: reduceDateSelection(state.dateSelection, action),
8780                eventSelection: reduceSelectedEvent(state.eventSelection, action),
8781                eventDrag: reduceEventDrag(state.eventDrag, action),
8782                eventResize: reduceEventResize(state.eventResize, action),
8783            };
8784            let contextAndState = Object.assign(Object.assign({}, calendarContext), newState);
8785            for (let reducer of optionsData.pluginHooks.reducers) {
8786                Object.assign(newState, reducer(state, action, contextAndState)); // give the OLD state, for old value
8787            }
8788            let wasLoading = computeIsLoading(state, calendarContext);
8789            let isLoading = computeIsLoading(newState, calendarContext);
8790            // TODO: use propSetHandlers in plugin system
8791            if (!wasLoading && isLoading) {
8792                emitter.trigger('loading', true);
8793            }
8794            else if (wasLoading && !isLoading) {
8795                emitter.trigger('loading', false);
8796            }
8797            this.state = newState;
8798            if (props.onAction) {
8799                props.onAction(action);
8800            }
8801        }
8802        updateData() {
8803            let { props, state } = this;
8804            let oldData = this.data;
8805            let optionsData = this.computeOptionsData(props.optionOverrides, state.dynamicOptionOverrides, props.calendarApi);
8806            let currentViewData = this.computeCurrentViewData(state.currentViewType, optionsData, props.optionOverrides, state.dynamicOptionOverrides);
8807            let data = this.data = Object.assign(Object.assign(Object.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);
8808            let changeHandlers = optionsData.pluginHooks.optionChangeHandlers;
8809            let oldCalendarOptions = oldData && oldData.calendarOptions;
8810            let newCalendarOptions = optionsData.calendarOptions;
8811            if (oldCalendarOptions && oldCalendarOptions !== newCalendarOptions) {
8812                if (oldCalendarOptions.timeZone !== newCalendarOptions.timeZone) {
8813                    // hack
8814                    state.eventSources = data.eventSources = reduceEventSourcesNewTimeZone(data.eventSources, state.dateProfile, data);
8815                    state.eventStore = data.eventStore = rezoneEventStoreDates(data.eventStore, oldData.dateEnv, data.dateEnv);
8816                }
8817                for (let optionName in changeHandlers) {
8818                    if (oldCalendarOptions[optionName] !== newCalendarOptions[optionName]) {
8819                        changeHandlers[optionName](newCalendarOptions[optionName], data);
8820                    }
8821                }
8822            }
8823            if (props.onData) {
8824                props.onData(data);
8825            }
8826        }
8827        _computeOptionsData(optionOverrides, dynamicOptionOverrides, calendarApi) {
8828            // TODO: blacklist options that are handled by optionChangeHandlers
8829            let { refinedOptions, pluginHooks, localeDefaults, availableLocaleData, extra, } = this.processRawCalendarOptions(optionOverrides, dynamicOptionOverrides);
8830            warnUnknownOptions(extra);
8831            let dateEnv = this.buildDateEnv(refinedOptions.timeZone, refinedOptions.locale, refinedOptions.weekNumberCalculation, refinedOptions.firstDay, refinedOptions.weekText, pluginHooks, availableLocaleData, refinedOptions.defaultRangeSeparator);
8832            let viewSpecs = this.buildViewSpecs(pluginHooks.views, optionOverrides, dynamicOptionOverrides, localeDefaults);
8833            let theme = this.buildTheme(refinedOptions, pluginHooks);
8834            let toolbarConfig = this.parseToolbars(refinedOptions, optionOverrides, theme, viewSpecs, calendarApi);
8835            return {
8836                calendarOptions: refinedOptions,
8837                pluginHooks,
8838                dateEnv,
8839                viewSpecs,
8840                theme,
8841                toolbarConfig,
8842                localeDefaults,
8843                availableRawLocales: availableLocaleData.map,
8844            };
8845        }
8846        // always called from behind a memoizer
8847        processRawCalendarOptions(optionOverrides, dynamicOptionOverrides) {
8848            let { locales, locale } = mergeRawOptions([
8849                BASE_OPTION_DEFAULTS,
8850                optionOverrides,
8851                dynamicOptionOverrides,
8852            ]);
8853            let availableLocaleData = this.organizeRawLocales(locales);
8854            let availableRawLocales = availableLocaleData.map;
8855            let localeDefaults = this.buildLocale(locale || availableLocaleData.defaultCode, availableRawLocales).options;
8856            let pluginHooks = this.buildPluginHooks(optionOverrides.plugins || [], globalPlugins);
8857            let refiners = this.currentCalendarOptionsRefiners = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, BASE_OPTION_REFINERS), CALENDAR_LISTENER_REFINERS), CALENDAR_OPTION_REFINERS), pluginHooks.listenerRefiners), pluginHooks.optionRefiners);
8858            let extra = {};
8859            let raw = mergeRawOptions([
8860                BASE_OPTION_DEFAULTS,
8861                localeDefaults,
8862                optionOverrides,
8863                dynamicOptionOverrides,
8864            ]);
8865            let refined = {};
8866            let currentRaw = this.currentCalendarOptionsInput;
8867            let currentRefined = this.currentCalendarOptionsRefined;
8868            let anyChanges = false;
8869            for (let optionName in raw) {
8870                if (optionName !== 'plugins') { // because plugins is special-cased
8871                    if (raw[optionName] === currentRaw[optionName] ||
8872                        (COMPLEX_OPTION_COMPARATORS[optionName] &&
8873                            (optionName in currentRaw) &&
8874                            COMPLEX_OPTION_COMPARATORS[optionName](currentRaw[optionName], raw[optionName]))) {
8875                        refined[optionName] = currentRefined[optionName];
8876                    }
8877                    else if (refiners[optionName]) {
8878                        refined[optionName] = refiners[optionName](raw[optionName]);
8879                        anyChanges = true;
8880                    }
8881                    else {
8882                        extra[optionName] = currentRaw[optionName];
8883                    }
8884                }
8885            }
8886            if (anyChanges) {
8887                this.currentCalendarOptionsInput = raw;
8888                this.currentCalendarOptionsRefined = refined;
8889            }
8890            return {
8891                rawOptions: this.currentCalendarOptionsInput,
8892                refinedOptions: this.currentCalendarOptionsRefined,
8893                pluginHooks,
8894                availableLocaleData,
8895                localeDefaults,
8896                extra,
8897            };
8898        }
8899        _computeCurrentViewData(viewType, optionsData, optionOverrides, dynamicOptionOverrides) {
8900            let viewSpec = optionsData.viewSpecs[viewType];
8901            if (!viewSpec) {
8902                throw new Error(`viewType "${viewType}" is not available. Please make sure you've loaded all neccessary plugins`);
8903            }
8904            let { refinedOptions, extra } = this.processRawViewOptions(viewSpec, optionsData.pluginHooks, optionsData.localeDefaults, optionOverrides, dynamicOptionOverrides);
8905            warnUnknownOptions(extra);
8906            let dateProfileGenerator = this.buildDateProfileGenerator({
8907                dateProfileGeneratorClass: viewSpec.optionDefaults.dateProfileGeneratorClass,
8908                duration: viewSpec.duration,
8909                durationUnit: viewSpec.durationUnit,
8910                usesMinMaxTime: viewSpec.optionDefaults.usesMinMaxTime,
8911                dateEnv: optionsData.dateEnv,
8912                calendarApi: this.props.calendarApi,
8913                slotMinTime: refinedOptions.slotMinTime,
8914                slotMaxTime: refinedOptions.slotMaxTime,
8915                showNonCurrentDates: refinedOptions.showNonCurrentDates,
8916                dayCount: refinedOptions.dayCount,
8917                dateAlignment: refinedOptions.dateAlignment,
8918                dateIncrement: refinedOptions.dateIncrement,
8919                hiddenDays: refinedOptions.hiddenDays,
8920                weekends: refinedOptions.weekends,
8921                nowInput: refinedOptions.now,
8922                validRangeInput: refinedOptions.validRange,
8923                visibleRangeInput: refinedOptions.visibleRange,
8924                monthMode: refinedOptions.monthMode,
8925                fixedWeekCount: refinedOptions.fixedWeekCount,
8926            });
8927            let viewApi = this.buildViewApi(viewType, this.getCurrentData, optionsData.dateEnv);
8928            return { viewSpec, options: refinedOptions, dateProfileGenerator, viewApi };
8929        }
8930        processRawViewOptions(viewSpec, pluginHooks, localeDefaults, optionOverrides, dynamicOptionOverrides) {
8931            let raw = mergeRawOptions([
8932                BASE_OPTION_DEFAULTS,
8933                viewSpec.optionDefaults,
8934                localeDefaults,
8935                optionOverrides,
8936                viewSpec.optionOverrides,
8937                dynamicOptionOverrides,
8938            ]);
8939            let refiners = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, BASE_OPTION_REFINERS), CALENDAR_LISTENER_REFINERS), CALENDAR_OPTION_REFINERS), VIEW_OPTION_REFINERS), pluginHooks.listenerRefiners), pluginHooks.optionRefiners);
8940            let refined = {};
8941            let currentRaw = this.currentViewOptionsInput;
8942            let currentRefined = this.currentViewOptionsRefined;
8943            let anyChanges = false;
8944            let extra = {};
8945            for (let optionName in raw) {
8946                if (raw[optionName] === currentRaw[optionName] ||
8947                    (COMPLEX_OPTION_COMPARATORS[optionName] &&
8948                        COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], currentRaw[optionName]))) {
8949                    refined[optionName] = currentRefined[optionName];
8950                }
8951                else {
8952                    if (raw[optionName] === this.currentCalendarOptionsInput[optionName] ||
8953                        (COMPLEX_OPTION_COMPARATORS[optionName] &&
8954                            COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], this.currentCalendarOptionsInput[optionName]))) {
8955                        if (optionName in this.currentCalendarOptionsRefined) { // might be an "extra" prop
8956                            refined[optionName] = this.currentCalendarOptionsRefined[optionName];
8957                        }
8958                    }
8959                    else if (refiners[optionName]) {
8960                        refined[optionName] = refiners[optionName](raw[optionName]);
8961                    }
8962                    else {
8963                        extra[optionName] = raw[optionName];
8964                    }
8965                    anyChanges = true;
8966                }
8967            }
8968            if (anyChanges) {
8969                this.currentViewOptionsInput = raw;
8970                this.currentViewOptionsRefined = refined;
8971            }
8972            return {
8973                rawOptions: this.currentViewOptionsInput,
8974                refinedOptions: this.currentViewOptionsRefined,
8975                extra,
8976            };
8977        }
8978    }
8979    function buildDateEnv$1(timeZone, explicitLocale, weekNumberCalculation, firstDay, weekText, pluginHooks, availableLocaleData, defaultSeparator) {
8980        let locale = buildLocale(explicitLocale || availableLocaleData.defaultCode, availableLocaleData.map);
8981        return new DateEnv({
8982            calendarSystem: 'gregory',
8983            timeZone,
8984            namedTimeZoneImpl: pluginHooks.namedTimeZonedImpl,
8985            locale,
8986            weekNumberCalculation,
8987            firstDay,
8988            weekText,
8989            cmdFormatter: pluginHooks.cmdFormatter,
8990            defaultSeparator,
8991        });
8992    }
8993    function buildTheme(options, pluginHooks) {
8994        let ThemeClass = pluginHooks.themeClasses[options.themeSystem] || StandardTheme;
8995        return new ThemeClass(options);
8996    }
8997    function buildDateProfileGenerator(props) {
8998        let DateProfileGeneratorClass = props.dateProfileGeneratorClass || DateProfileGenerator;
8999        return new DateProfileGeneratorClass(props);
9000    }
9001    function buildViewApi(type, getCurrentData, dateEnv) {
9002        return new ViewImpl(type, getCurrentData, dateEnv);
9003    }
9004    function buildEventUiBySource(eventSources) {
9005        return mapHash(eventSources, (eventSource) => eventSource.ui);
9006    }
9007    function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) {
9008        let eventUiBases = { '': eventUiSingleBase };
9009        for (let defId in eventDefs) {
9010            let def = eventDefs[defId];
9011            if (def.sourceId && eventUiBySource[def.sourceId]) {
9012                eventUiBases[defId] = eventUiBySource[def.sourceId];
9013            }
9014        }
9015        return eventUiBases;
9016    }
9017    function buildViewUiProps(calendarContext) {
9018        let { options } = calendarContext;
9019        return {
9020            eventUiSingleBase: createEventUi({
9021                display: options.eventDisplay,
9022                editable: options.editable,
9023                startEditable: options.eventStartEditable,
9024                durationEditable: options.eventDurationEditable,
9025                constraint: options.eventConstraint,
9026                overlap: typeof options.eventOverlap === 'boolean' ? options.eventOverlap : undefined,
9027                allow: options.eventAllow,
9028                backgroundColor: options.eventBackgroundColor,
9029                borderColor: options.eventBorderColor,
9030                textColor: options.eventTextColor,
9031                color: options.eventColor,
9032                // classNames: options.eventClassNames // render hook will handle this
9033            }, calendarContext),
9034            selectionConfig: createEventUi({
9035                constraint: options.selectConstraint,
9036                overlap: typeof options.selectOverlap === 'boolean' ? options.selectOverlap : undefined,
9037                allow: options.selectAllow,
9038            }, calendarContext),
9039        };
9040    }
9041    function computeIsLoading(state, context) {
9042        for (let isLoadingFunc of context.pluginHooks.isLoadingFuncs) {
9043            if (isLoadingFunc(state)) {
9044                return true;
9045            }
9046        }
9047        return false;
9048    }
9049    function parseContextBusinessHours(calendarContext) {
9050        return parseBusinessHours(calendarContext.options.businessHours, calendarContext);
9051    }
9052    function warnUnknownOptions(options, viewName) {
9053        for (let optionName in options) {
9054            console.warn(`Unknown option '${optionName}'` +
9055                (viewName ? ` for view '${viewName}'` : ''));
9056        }
9057    }
9058
9059    class ToolbarSection extends BaseComponent {
9060        render() {
9061            let children = this.props.widgetGroups.map((widgetGroup) => this.renderWidgetGroup(widgetGroup));
9062            return h('div', { className: 'fc-toolbar-chunk' }, ...children);
9063        }
9064        renderWidgetGroup(widgetGroup) {
9065            let { props } = this;
9066            let { theme } = this.context;
9067            let children = [];
9068            let isOnlyButtons = true;
9069            for (let widget of widgetGroup) {
9070                let { buttonName, buttonClick, buttonText, buttonIcon, buttonHint } = widget;
9071                if (buttonName === 'title') {
9072                    isOnlyButtons = false;
9073                    children.push(h("h2", { className: "fc-toolbar-title", id: props.titleId }, props.title));
9074                }
9075                else {
9076                    let isPressed = buttonName === props.activeButton;
9077                    let isDisabled = (!props.isTodayEnabled && buttonName === 'today') ||
9078                        (!props.isPrevEnabled && buttonName === 'prev') ||
9079                        (!props.isNextEnabled && buttonName === 'next');
9080                    let buttonClasses = [`fc-${buttonName}-button`, theme.getClass('button')];
9081                    if (isPressed) {
9082                        buttonClasses.push(theme.getClass('buttonActive'));
9083                    }
9084                    children.push(h("button", { type: "button", title: typeof buttonHint === 'function' ? buttonHint(props.navUnit) : buttonHint, disabled: isDisabled, "aria-pressed": isPressed, className: buttonClasses.join(' '), onClick: buttonClick }, buttonText || (buttonIcon ? h("span", { className: buttonIcon }) : '')));
9085                }
9086            }
9087            if (children.length > 1) {
9088                let groupClassName = (isOnlyButtons && theme.getClass('buttonGroup')) || '';
9089                return h('div', { className: groupClassName }, ...children);
9090            }
9091            return children[0];
9092        }
9093    }
9094
9095    class Toolbar extends BaseComponent {
9096        render() {
9097            let { model, extraClassName } = this.props;
9098            let forceLtr = false;
9099            let startContent;
9100            let endContent;
9101            let sectionWidgets = model.sectionWidgets;
9102            let centerContent = sectionWidgets.center;
9103            if (sectionWidgets.left) {
9104                forceLtr = true;
9105                startContent = sectionWidgets.left;
9106            }
9107            else {
9108                startContent = sectionWidgets.start;
9109            }
9110            if (sectionWidgets.right) {
9111                forceLtr = true;
9112                endContent = sectionWidgets.right;
9113            }
9114            else {
9115                endContent = sectionWidgets.end;
9116            }
9117            let classNames = [
9118                extraClassName || '',
9119                'fc-toolbar',
9120                forceLtr ? 'fc-toolbar-ltr' : '',
9121            ];
9122            return (h("div", { className: classNames.join(' ') },
9123                this.renderSection('start', startContent || []),
9124                this.renderSection('center', centerContent || []),
9125                this.renderSection('end', endContent || [])));
9126        }
9127        renderSection(key, widgetGroups) {
9128            let { props } = this;
9129            return (h(ToolbarSection, { key: key, widgetGroups: widgetGroups, title: props.title, navUnit: props.navUnit, activeButton: props.activeButton, isTodayEnabled: props.isTodayEnabled, isPrevEnabled: props.isPrevEnabled, isNextEnabled: props.isNextEnabled, titleId: props.titleId }));
9130        }
9131    }
9132
9133    // TODO: do function component?
9134    class ViewContainer extends BaseComponent {
9135        constructor() {
9136            super(...arguments);
9137            this.state = {
9138                availableWidth: null,
9139            };
9140            this.handleEl = (el) => {
9141                this.el = el;
9142                setRef(this.props.elRef, el);
9143                this.updateAvailableWidth();
9144            };
9145            this.handleResize = () => {
9146                this.updateAvailableWidth();
9147            };
9148        }
9149        render() {
9150            let { props, state } = this;
9151            let { aspectRatio } = props;
9152            let classNames = [
9153                'fc-view-harness',
9154                (aspectRatio || props.liquid || props.height)
9155                    ? 'fc-view-harness-active' // harness controls the height
9156                    : 'fc-view-harness-passive', // let the view do the height
9157            ];
9158            let height = '';
9159            let paddingBottom = '';
9160            if (aspectRatio) {
9161                if (state.availableWidth !== null) {
9162                    height = state.availableWidth / aspectRatio;
9163                }
9164                else {
9165                    // while waiting to know availableWidth, we can't set height to *zero*
9166                    // because will cause lots of unnecessary scrollbars within scrollgrid.
9167                    // BETTER: don't start rendering ANYTHING yet until we know container width
9168                    // NOTE: why not always use paddingBottom? Causes height oscillation (issue 5606)
9169                    paddingBottom = `${(1 / aspectRatio) * 100}%`;
9170                }
9171            }
9172            else {
9173                height = props.height || '';
9174            }
9175            return (h("div", { "aria-labelledby": props.labeledById, ref: this.handleEl, className: classNames.join(' '), style: { height, paddingBottom } }, props.children));
9176        }
9177        componentDidMount() {
9178            this.context.addResizeHandler(this.handleResize);
9179        }
9180        componentWillUnmount() {
9181            this.context.removeResizeHandler(this.handleResize);
9182        }
9183        updateAvailableWidth() {
9184            if (this.el && // needed. but why?
9185                this.props.aspectRatio // aspectRatio is the only height setting that needs availableWidth
9186            ) {
9187                this.setState({ availableWidth: this.el.offsetWidth });
9188            }
9189        }
9190    }
9191
9192    /*
9193    Detects when the user clicks on an event within a DateComponent
9194    */
9195    class EventClicking extends Interaction {
9196        constructor(settings) {
9197            super(settings);
9198            this.handleSegClick = (ev, segEl) => {
9199                let { component } = this;
9200                let { context } = component;
9201                let seg = getElSeg(segEl);
9202                if (seg && // might be the <div> surrounding the more link
9203                    component.isValidSegDownEl(ev.target)) {
9204                    // our way to simulate a link click for elements that can't be <a> tags
9205                    // grab before trigger fired in case trigger trashes DOM thru rerendering
9206                    let hasUrlContainer = elementClosest(ev.target, '.fc-event-forced-url');
9207                    let url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : '';
9208                    context.emitter.trigger('eventClick', {
9209                        el: segEl,
9210                        event: new EventImpl(component.context, seg.eventRange.def, seg.eventRange.instance),
9211                        jsEvent: ev,
9212                        view: context.viewApi,
9213                    });
9214                    if (url && !ev.defaultPrevented) {
9215                        window.location.href = url;
9216                    }
9217                }
9218            };
9219            this.destroy = listenBySelector(settings.el, 'click', '.fc-event', // on both fg and bg events
9220            this.handleSegClick);
9221        }
9222    }
9223
9224    /*
9225    Triggers events and adds/removes core classNames when the user's pointer
9226    enters/leaves event-elements of a component.
9227    */
9228    class EventHovering extends Interaction {
9229        constructor(settings) {
9230            super(settings);
9231            // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it
9232            this.handleEventElRemove = (el) => {
9233                if (el === this.currentSegEl) {
9234                    this.handleSegLeave(null, this.currentSegEl);
9235                }
9236            };
9237            this.handleSegEnter = (ev, segEl) => {
9238                if (getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper
9239                    this.currentSegEl = segEl;
9240                    this.triggerEvent('eventMouseEnter', ev, segEl);
9241                }
9242            };
9243            this.handleSegLeave = (ev, segEl) => {
9244                if (this.currentSegEl) {
9245                    this.currentSegEl = null;
9246                    this.triggerEvent('eventMouseLeave', ev, segEl);
9247                }
9248            };
9249            this.removeHoverListeners = listenToHoverBySelector(settings.el, '.fc-event', // on both fg and bg events
9250            this.handleSegEnter, this.handleSegLeave);
9251        }
9252        destroy() {
9253            this.removeHoverListeners();
9254        }
9255        triggerEvent(publicEvName, ev, segEl) {
9256            let { component } = this;
9257            let { context } = component;
9258            let seg = getElSeg(segEl);
9259            if (!ev || component.isValidSegDownEl(ev.target)) {
9260                context.emitter.trigger(publicEvName, {
9261                    el: segEl,
9262                    event: new EventImpl(context, seg.eventRange.def, seg.eventRange.instance),
9263                    jsEvent: ev,
9264                    view: context.viewApi,
9265                });
9266            }
9267        }
9268    }
9269
9270    class CalendarContent extends PureComponent {
9271        constructor() {
9272            super(...arguments);
9273            this.buildViewContext = memoize(buildViewContext);
9274            this.buildViewPropTransformers = memoize(buildViewPropTransformers);
9275            this.buildToolbarProps = memoize(buildToolbarProps);
9276            this.headerRef = y();
9277            this.footerRef = y();
9278            this.interactionsStore = {};
9279            // eslint-disable-next-line
9280            this.state = {
9281                viewLabelId: getUniqueDomId(),
9282            };
9283            // Component Registration
9284            // -----------------------------------------------------------------------------------------------------------------
9285            this.registerInteractiveComponent = (component, settingsInput) => {
9286                let settings = parseInteractionSettings(component, settingsInput);
9287                let DEFAULT_INTERACTIONS = [
9288                    EventClicking,
9289                    EventHovering,
9290                ];
9291                let interactionClasses = DEFAULT_INTERACTIONS.concat(this.props.pluginHooks.componentInteractions);
9292                let interactions = interactionClasses.map((TheInteractionClass) => new TheInteractionClass(settings));
9293                this.interactionsStore[component.uid] = interactions;
9294                interactionSettingsStore[component.uid] = settings;
9295            };
9296            this.unregisterInteractiveComponent = (component) => {
9297                let listeners = this.interactionsStore[component.uid];
9298                if (listeners) {
9299                    for (let listener of listeners) {
9300                        listener.destroy();
9301                    }
9302                    delete this.interactionsStore[component.uid];
9303                }
9304                delete interactionSettingsStore[component.uid];
9305            };
9306            // Resizing
9307            // -----------------------------------------------------------------------------------------------------------------
9308            this.resizeRunner = new DelayedRunner(() => {
9309                this.props.emitter.trigger('_resize', true); // should window resizes be considered "forced" ?
9310                this.props.emitter.trigger('windowResize', { view: this.props.viewApi });
9311            });
9312            this.handleWindowResize = (ev) => {
9313                let { options } = this.props;
9314                if (options.handleWindowResize &&
9315                    ev.target === window // avoid jqui events
9316                ) {
9317                    this.resizeRunner.request(options.windowResizeDelay);
9318                }
9319            };
9320        }
9321        /*
9322        renders INSIDE of an outer div
9323        */
9324        render() {
9325            let { props } = this;
9326            let { toolbarConfig, options } = props;
9327            let toolbarProps = this.buildToolbarProps(props.viewSpec, props.dateProfile, props.dateProfileGenerator, props.currentDate, getNow(props.options.now, props.dateEnv), // TODO: use NowTimer????
9328            props.viewTitle);
9329            let viewVGrow = false;
9330            let viewHeight = '';
9331            let viewAspectRatio;
9332            if (props.isHeightAuto || props.forPrint) {
9333                viewHeight = '';
9334            }
9335            else if (options.height != null) {
9336                viewVGrow = true;
9337            }
9338            else if (options.contentHeight != null) {
9339                viewHeight = options.contentHeight;
9340            }
9341            else {
9342                viewAspectRatio = Math.max(options.aspectRatio, 0.5); // prevent from getting too tall
9343            }
9344            let 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);
9345            let viewLabelId = (toolbarConfig.header && toolbarConfig.header.hasTitle)
9346                ? this.state.viewLabelId
9347                : '';
9348            return (h(ViewContextType.Provider, { value: viewContext },
9349                toolbarConfig.header && (h(Toolbar, Object.assign({ ref: this.headerRef, extraClassName: "fc-header-toolbar", model: toolbarConfig.header, titleId: viewLabelId }, toolbarProps))),
9350                h(ViewContainer, { liquid: viewVGrow, height: viewHeight, aspectRatio: viewAspectRatio, labeledById: viewLabelId },
9351                    this.renderView(props),
9352                    this.buildAppendContent()),
9353                toolbarConfig.footer && (h(Toolbar, Object.assign({ ref: this.footerRef, extraClassName: "fc-footer-toolbar", model: toolbarConfig.footer, titleId: "" }, toolbarProps)))));
9354        }
9355        componentDidMount() {
9356            let { props } = this;
9357            this.calendarInteractions = props.pluginHooks.calendarInteractions
9358                .map((CalendarInteractionClass) => new CalendarInteractionClass(props));
9359            window.addEventListener('resize', this.handleWindowResize);
9360            let { propSetHandlers } = props.pluginHooks;
9361            for (let propName in propSetHandlers) {
9362                propSetHandlers[propName](props[propName], props);
9363            }
9364        }
9365        componentDidUpdate(prevProps) {
9366            let { props } = this;
9367            let { propSetHandlers } = props.pluginHooks;
9368            for (let propName in propSetHandlers) {
9369                if (props[propName] !== prevProps[propName]) {
9370                    propSetHandlers[propName](props[propName], props);
9371                }
9372            }
9373        }
9374        componentWillUnmount() {
9375            window.removeEventListener('resize', this.handleWindowResize);
9376            this.resizeRunner.clear();
9377            for (let interaction of this.calendarInteractions) {
9378                interaction.destroy();
9379            }
9380            this.props.emitter.trigger('_unmount');
9381        }
9382        buildAppendContent() {
9383            let { props } = this;
9384            let children = props.pluginHooks.viewContainerAppends.map((buildAppendContent) => buildAppendContent(props));
9385            return h(p, {}, ...children);
9386        }
9387        renderView(props) {
9388            let { pluginHooks } = props;
9389            let { viewSpec } = props;
9390            let viewProps = {
9391                dateProfile: props.dateProfile,
9392                businessHours: props.businessHours,
9393                eventStore: props.renderableEventStore,
9394                eventUiBases: props.eventUiBases,
9395                dateSelection: props.dateSelection,
9396                eventSelection: props.eventSelection,
9397                eventDrag: props.eventDrag,
9398                eventResize: props.eventResize,
9399                isHeightAuto: props.isHeightAuto,
9400                forPrint: props.forPrint,
9401            };
9402            let transformers = this.buildViewPropTransformers(pluginHooks.viewPropsTransformers);
9403            for (let transformer of transformers) {
9404                Object.assign(viewProps, transformer.transform(viewProps, props));
9405            }
9406            let ViewComponent = viewSpec.component;
9407            return (h(ViewComponent, Object.assign({}, viewProps)));
9408        }
9409    }
9410    function buildToolbarProps(viewSpec, dateProfile, dateProfileGenerator, currentDate, now, title) {
9411        // don't force any date-profiles to valid date profiles (the `false`) so that we can tell if it's invalid
9412        let todayInfo = dateProfileGenerator.build(now, undefined, false); // TODO: need `undefined` or else INFINITE LOOP for some reason
9413        let prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate, false);
9414        let nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate, false);
9415        return {
9416            title,
9417            activeButton: viewSpec.type,
9418            navUnit: viewSpec.singleUnit,
9419            isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now),
9420            isPrevEnabled: prevInfo.isValid,
9421            isNextEnabled: nextInfo.isValid,
9422        };
9423    }
9424    // Plugin
9425    // -----------------------------------------------------------------------------------------------------------------
9426    function buildViewPropTransformers(theClasses) {
9427        return theClasses.map((TheClass) => new TheClass());
9428    }
9429
9430    class Calendar extends CalendarImpl {
9431        constructor(el, optionOverrides = {}) {
9432            super();
9433            this.isRendering = false;
9434            this.isRendered = false;
9435            this.currentClassNames = [];
9436            this.customContentRenderId = 0;
9437            this.handleAction = (action) => {
9438                // actions we know we want to render immediately
9439                switch (action.type) {
9440                    case 'SET_EVENT_DRAG':
9441                    case 'SET_EVENT_RESIZE':
9442                        this.renderRunner.tryDrain();
9443                }
9444            };
9445            this.handleData = (data) => {
9446                this.currentData = data;
9447                this.renderRunner.request(data.calendarOptions.rerenderDelay);
9448            };
9449            this.handleRenderRequest = () => {
9450                if (this.isRendering) {
9451                    this.isRendered = true;
9452                    let { currentData } = this;
9453                    flushSync(() => {
9454                        P$1(h(CalendarRoot, { options: currentData.calendarOptions, theme: currentData.theme, emitter: currentData.emitter }, (classNames, height, isHeightAuto, forPrint) => {
9455                            this.setClassNames(classNames);
9456                            this.setHeight(height);
9457                            return (h(RenderId.Provider, { value: this.customContentRenderId },
9458                                h(CalendarContent, Object.assign({ isHeightAuto: isHeightAuto, forPrint: forPrint }, currentData))));
9459                        }), this.el);
9460                    });
9461                }
9462                else if (this.isRendered) {
9463                    this.isRendered = false;
9464                    P$1(null, this.el);
9465                    this.setClassNames([]);
9466                    this.setHeight('');
9467                }
9468            };
9469            this.el = el;
9470            this.renderRunner = new DelayedRunner(this.handleRenderRequest);
9471            new CalendarDataManager({
9472                optionOverrides,
9473                calendarApi: this,
9474                onAction: this.handleAction,
9475                onData: this.handleData,
9476            });
9477        }
9478        render() {
9479            let wasRendering = this.isRendering;
9480            if (!wasRendering) {
9481                this.isRendering = true;
9482            }
9483            else {
9484                this.customContentRenderId += 1;
9485            }
9486            this.renderRunner.request();
9487            if (wasRendering) {
9488                this.updateSize();
9489            }
9490        }
9491        destroy() {
9492            if (this.isRendering) {
9493                this.isRendering = false;
9494                this.renderRunner.request();
9495            }
9496        }
9497        updateSize() {
9498            flushSync(() => {
9499                super.updateSize();
9500            });
9501        }
9502        batchRendering(func) {
9503            this.renderRunner.pause('batchRendering');
9504            func();
9505            this.renderRunner.resume('batchRendering');
9506        }
9507        pauseRendering() {
9508            this.renderRunner.pause('pauseRendering');
9509        }
9510        resumeRendering() {
9511            this.renderRunner.resume('pauseRendering', true);
9512        }
9513        resetOptions(optionOverrides, append) {
9514            this.currentDataManager.resetOptions(optionOverrides, append);
9515        }
9516        setClassNames(classNames) {
9517            if (!isArraysEqual(classNames, this.currentClassNames)) {
9518                let { classList } = this.el;
9519                for (let className of this.currentClassNames) {
9520                    classList.remove(className);
9521                }
9522                for (let className of classNames) {
9523                    classList.add(className);
9524                }
9525                this.currentClassNames = classNames;
9526            }
9527        }
9528        setHeight(height) {
9529            applyStyleProp(this.el, 'height', height);
9530        }
9531    }
9532
9533    function formatDate(dateInput, options = {}) {
9534        let dateEnv = buildDateEnv(options);
9535        let formatter = createFormatter(options);
9536        let dateMeta = dateEnv.createMarkerMeta(dateInput);
9537        if (!dateMeta) { // TODO: warning?
9538            return '';
9539        }
9540        return dateEnv.format(dateMeta.marker, formatter, {
9541            forcedTzo: dateMeta.forcedTzo,
9542        });
9543    }
9544    function formatRange(startInput, endInput, options) {
9545        let dateEnv = buildDateEnv(typeof options === 'object' && options ? options : {}); // pass in if non-null object
9546        let formatter = createFormatter(options);
9547        let startMeta = dateEnv.createMarkerMeta(startInput);
9548        let endMeta = dateEnv.createMarkerMeta(endInput);
9549        if (!startMeta || !endMeta) { // TODO: warning?
9550            return '';
9551        }
9552        return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, {
9553            forcedStartTzo: startMeta.forcedTzo,
9554            forcedEndTzo: endMeta.forcedTzo,
9555            isEndExclusive: options.isEndExclusive,
9556            defaultSeparator: BASE_OPTION_DEFAULTS.defaultRangeSeparator,
9557        });
9558    }
9559    // TODO: more DRY and optimized
9560    function buildDateEnv(settings) {
9561        let locale = buildLocale(settings.locale || 'en', organizeRawLocales([]).map); // TODO: don't hardcode 'en' everywhere
9562        return new DateEnv(Object.assign(Object.assign({ timeZone: BASE_OPTION_DEFAULTS.timeZone, calendarSystem: 'gregory' }, settings), { locale }));
9563    }
9564
9565    // HELPERS
9566    /*
9567    if nextDayThreshold is specified, slicing is done in an all-day fashion.
9568    you can get nextDayThreshold from context.nextDayThreshold
9569    */
9570    function sliceEvents(props, allDay) {
9571        return sliceEventStore(props.eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? props.nextDayThreshold : null).fg;
9572    }
9573
9574    const version = '6.0.0';
9575
9576    config.touchMouseIgnoreWait = 500;
9577    let ignoreMouseDepth = 0;
9578    let listenerCnt = 0;
9579    let isWindowTouchMoveCancelled = false;
vendor: 4,736 bytes, lines 9580-9667
9580    /*
9581    Uses a "pointer" abstraction, which monitors UI events for both mouse and touch.
9582    Tracks when the pointer "drags" on a certain element, meaning down+move+up.
9583
9584    Also, tracks if there was touch-scrolling.
9585    Also, can prevent touch-scrolling from happening.
9586    Also, can fire pointermove events when scrolling happens underneath, even when no real pointer movement.
9587
9588    emits:
9589    - pointerdown
9590    - pointermove
9591    - pointerup
9592    */
9593    class PointerDragging {
9594        constructor(containerEl) {
9595            this.subjectEl = null;
9596            // options that can be directly assigned by caller
9597            this.selector = ''; // will cause subjectEl in all emitted events to be this element
9598            this.handleSelector = '';
9599            this.shouldIgnoreMove = false;
9600            this.shouldWatchScroll = true; // for simulating pointermove on scroll
9601            // internal states
9602            this.isDragging = false;
9603            this.isTouchDragging = false;
9604            this.wasTouchScroll = false;
9605            // Mouse
9606            // ----------------------------------------------------------------------------------------------------
9607            this.handleMouseDown = (ev) => {
9608                if (!this.shouldIgnoreMouse() &&
9609                    isPrimaryMouseButton(ev) &&
9610                    this.tryStart(ev)) {
9611                    let pev = this.createEventFromMouse(ev, true);
9612                    this.emitter.trigger('pointerdown', pev);
9613                    this.initScrollWatch(pev);
9614                    if (!this.shouldIgnoreMove) {
9615                        document.addEventListener('mousemove', this.handleMouseMove);
9616                    }
9617                    document.addEventListener('mouseup', this.handleMouseUp);
9618                }
9619            };
9620            this.handleMouseMove = (ev) => {
9621                let pev = this.createEventFromMouse(ev);
9622                this.recordCoords(pev);
9623                this.emitter.trigger('pointermove', pev);
9624            };
9625            this.handleMouseUp = (ev) => {
9626                document.removeEventListener('mousemove', this.handleMouseMove);
9627                document.removeEventListener('mouseup', this.handleMouseUp);
9628                this.emitter.trigger('pointerup', this.createEventFromMouse(ev));
9629                this.cleanup(); // call last so that pointerup has access to props
9630            };
9631            // Touch
9632            // ----------------------------------------------------------------------------------------------------
9633            this.handleTouchStart = (ev) => {
9634                if (this.tryStart(ev)) {
9635                    this.isTouchDragging = true;
9636                    let pev = this.createEventFromTouch(ev, true);
9637                    this.emitter.trigger('pointerdown', pev);
9638                    this.initScrollWatch(pev);
9639                    // unlike mouse, need to attach to target, not document
9640                    // https://stackoverflow.com/a/45760014
9641                    let targetEl = ev.target;
9642                    if (!this.shouldIgnoreMove) {
9643                        targetEl.addEventListener('touchmove', this.handleTouchMove);
9644                    }
9645                    targetEl.addEventListener('touchend', this.handleTouchEnd);
9646                    targetEl.addEventListener('touchcancel', this.handleTouchEnd); // treat it as a touch end
9647                    // attach a handler to get called when ANY scroll action happens on the page.
9648                    // this was impossible to do with normal on/off because 'scroll' doesn't bubble.
9649                    // http://stackoverflow.com/a/32954565/96342
9650                    window.addEventListener('scroll', this.handleTouchScroll, true);
9651                }
9652            };
9653            this.handleTouchMove = (ev) => {
9654                let pev = this.createEventFromTouch(ev);
9655                this.recordCoords(pev);
9656                this.emitter.trigger('pointermove', pev);
9657            };
9658            this.handleTouchEnd = (ev) => {
9659                if (this.isDragging) { // done to guard against touchend followed by touchcancel
9660                    let targetEl = ev.target;
9661                    targetEl.removeEventListener('touchmove', this.handleTouchMove);
9662                    targetEl.removeEventListener('touchend', this.handleTouchEnd);
9663                    targetEl.removeEventListener('touchcancel', this.handleTouchEnd);
9664                    window.removeEventListener('scroll', this.handleTouchScroll, true); // useCaptured=true
9665                    this.emitter.trigger('pointerup', this.createEventFromTouch(ev));
9666                    this.cleanup(); // call last so that pointerup has access to props
9667                    this.isTouchDragging = false;
vendor: 16,810 bytes, lines 9668-10100
9668                    startIgnoringMouse();
9669                }
9670            };
9671            this.handleTouchScroll = () => {
9672                this.wasTouchScroll = true;
9673            };
9674            this.handleScroll = (ev) => {
9675                if (!this.shouldIgnoreMove) {
9676                    let pageX = (window.pageXOffset - this.prevScrollX) + this.prevPageX;
9677                    let pageY = (window.pageYOffset - this.prevScrollY) + this.prevPageY;
9678                    this.emitter.trigger('pointermove', {
9679                        origEvent: ev,
9680                        isTouch: this.isTouchDragging,
9681                        subjectEl: this.subjectEl,
9682                        pageX,
9683                        pageY,
9684                        deltaX: pageX - this.origPageX,
9685                        deltaY: pageY - this.origPageY,
9686                    });
9687                }
9688            };
9689            this.containerEl = containerEl;
9690            this.emitter = new Emitter();
9691            containerEl.addEventListener('mousedown', this.handleMouseDown);
9692            containerEl.addEventListener('touchstart', this.handleTouchStart, { passive: true });
9693            listenerCreated();
9694        }
9695        destroy() {
9696            this.containerEl.removeEventListener('mousedown', this.handleMouseDown);
9697            this.containerEl.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
9698            listenerDestroyed();
9699        }
9700        tryStart(ev) {
9701            let subjectEl = this.querySubjectEl(ev);
9702            let downEl = ev.target;
9703            if (subjectEl &&
9704                (!this.handleSelector || elementClosest(downEl, this.handleSelector))) {
9705                this.subjectEl = subjectEl;
9706                this.isDragging = true; // do this first so cancelTouchScroll will work
9707                this.wasTouchScroll = false;
9708                return true;
9709            }
9710            return false;
9711        }
9712        cleanup() {
9713            isWindowTouchMoveCancelled = false;
9714            this.isDragging = false;
9715            this.subjectEl = null;
9716            // keep wasTouchScroll around for later access
9717            this.destroyScrollWatch();
9718        }
9719        querySubjectEl(ev) {
9720            if (this.selector) {
9721                return elementClosest(ev.target, this.selector);
9722            }
9723            return this.containerEl;
9724        }
9725        shouldIgnoreMouse() {
9726            return ignoreMouseDepth || this.isTouchDragging;
9727        }
9728        // can be called by user of this class, to cancel touch-based scrolling for the current drag
9729        cancelTouchScroll() {
9730            if (this.isDragging) {
9731                isWindowTouchMoveCancelled = true;
9732            }
9733        }
9734        // Scrolling that simulates pointermoves
9735        // ----------------------------------------------------------------------------------------------------
9736        initScrollWatch(ev) {
9737            if (this.shouldWatchScroll) {
9738                this.recordCoords(ev);
9739                window.addEventListener('scroll', this.handleScroll, true); // useCapture=true
9740            }
9741        }
9742        recordCoords(ev) {
9743            if (this.shouldWatchScroll) {
9744                this.prevPageX = ev.pageX;
9745                this.prevPageY = ev.pageY;
9746                this.prevScrollX = window.pageXOffset;
9747                this.prevScrollY = window.pageYOffset;
9748            }
9749        }
9750        destroyScrollWatch() {
9751            if (this.shouldWatchScroll) {
9752                window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true
9753            }
9754        }
9755        // Event Normalization
9756        // ----------------------------------------------------------------------------------------------------
9757        createEventFromMouse(ev, isFirst) {
9758            let deltaX = 0;
9759            let deltaY = 0;
9760            // TODO: repeat code
9761            if (isFirst) {
9762                this.origPageX = ev.pageX;
9763                this.origPageY = ev.pageY;
9764            }
9765            else {
9766                deltaX = ev.pageX - this.origPageX;
9767                deltaY = ev.pageY - this.origPageY;
9768            }
9769            return {
9770                origEvent: ev,
9771                isTouch: false,
9772                subjectEl: this.subjectEl,
9773                pageX: ev.pageX,
9774                pageY: ev.pageY,
9775                deltaX,
9776                deltaY,
9777            };
9778        }
9779        createEventFromTouch(ev, isFirst) {
9780            let touches = ev.touches;
9781            let pageX;
9782            let pageY;
9783            let deltaX = 0;
9784            let deltaY = 0;
9785            // if touch coords available, prefer,
9786            // because FF would give bad ev.pageX ev.pageY
9787            if (touches && touches.length) {
9788                pageX = touches[0].pageX;
9789                pageY = touches[0].pageY;
9790            }
9791            else {
9792                pageX = ev.pageX;
9793                pageY = ev.pageY;
9794            }
9795            // TODO: repeat code
9796            if (isFirst) {
9797                this.origPageX = pageX;
9798                this.origPageY = pageY;
9799            }
9800            else {
9801                deltaX = pageX - this.origPageX;
9802                deltaY = pageY - this.origPageY;
9803            }
9804            return {
9805                origEvent: ev,
9806                isTouch: true,
9807                subjectEl: this.subjectEl,
9808                pageX,
9809                pageY,
9810                deltaX,
9811                deltaY,
9812            };
9813        }
9814    }
9815    // Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)
9816    function isPrimaryMouseButton(ev) {
9817        return ev.button === 0 && !ev.ctrlKey;
9818    }
9819    // Ignoring fake mouse events generated by touch
9820    // ----------------------------------------------------------------------------------------------------
9821    function startIgnoringMouse() {
9822        ignoreMouseDepth += 1;
9823        setTimeout(() => {
9824            ignoreMouseDepth -= 1;
9825        }, config.touchMouseIgnoreWait);
9826    }
9827    // We want to attach touchmove as early as possible for Safari
9828    // ----------------------------------------------------------------------------------------------------
9829    function listenerCreated() {
9830        listenerCnt += 1;
9831        if (listenerCnt === 1) {
9832            window.addEventListener('touchmove', onWindowTouchMove, { passive: false });
9833        }
9834    }
9835    function listenerDestroyed() {
9836        listenerCnt -= 1;
9837        if (!listenerCnt) {
9838            window.removeEventListener('touchmove', onWindowTouchMove, { passive: false });
9839        }
9840    }
9841    function onWindowTouchMove(ev) {
9842        if (isWindowTouchMoveCancelled) {
9843            ev.preventDefault();
9844        }
9845    }
9846
9847    /*
9848    An effect in which an element follows the movement of a pointer across the screen.
9849    The moving element is a clone of some other element.
9850    Must call start + handleMove + stop.
9851    */
9852    class ElementMirror {
9853        constructor() {
9854            this.isVisible = false; // must be explicitly enabled
9855            this.sourceEl = null;
9856            this.mirrorEl = null;
9857            this.sourceElRect = null; // screen coords relative to viewport
9858            // options that can be set directly by caller
9859            this.parentNode = document.body; // HIGHLY SUGGESTED to set this to sidestep ShadowDOM issues
9860            this.zIndex = 9999;
9861            this.revertDuration = 0;
9862        }
9863        start(sourceEl, pageX, pageY) {
9864            this.sourceEl = sourceEl;
9865            this.sourceElRect = this.sourceEl.getBoundingClientRect();
9866            this.origScreenX = pageX - window.pageXOffset;
9867            this.origScreenY = pageY - window.pageYOffset;
9868            this.deltaX = 0;
9869            this.deltaY = 0;
9870            this.updateElPosition();
9871        }
9872        handleMove(pageX, pageY) {
9873            this.deltaX = (pageX - window.pageXOffset) - this.origScreenX;
9874            this.deltaY = (pageY - window.pageYOffset) - this.origScreenY;
9875            this.updateElPosition();
9876        }
9877        // can be called before start
9878        setIsVisible(bool) {
9879            if (bool) {
9880                if (!this.isVisible) {
9881                    if (this.mirrorEl) {
9882                        this.mirrorEl.style.display = '';
9883                    }
9884                    this.isVisible = bool; // needs to happen before updateElPosition
9885                    this.updateElPosition(); // because was not updating the position while invisible
9886                }
9887            }
9888            else if (this.isVisible) {
9889                if (this.mirrorEl) {
9890                    this.mirrorEl.style.display = 'none';
9891                }
9892                this.isVisible = bool;
9893            }
9894        }
9895        // always async
9896        stop(needsRevertAnimation, callback) {
9897            let done = () => {
9898                this.cleanup();
9899                callback();
9900            };
9901            if (needsRevertAnimation &&
9902                this.mirrorEl &&
9903                this.isVisible &&
9904                this.revertDuration && // if 0, transition won't work
9905                (this.deltaX || this.deltaY) // if same coords, transition won't work
9906            ) {
9907                this.doRevertAnimation(done, this.revertDuration);
9908            }
9909            else {
9910                setTimeout(done, 0);
9911            }
9912        }
9913        doRevertAnimation(callback, revertDuration) {
9914            let mirrorEl = this.mirrorEl;
9915            let finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened
9916            mirrorEl.style.transition =
9917                'top ' + revertDuration + 'ms,' +
9918                    'left ' + revertDuration + 'ms';
9919            applyStyle(mirrorEl, {
9920                left: finalSourceElRect.left,
9921                top: finalSourceElRect.top,
9922            });
9923            whenTransitionDone(mirrorEl, () => {
9924                mirrorEl.style.transition = '';
9925                callback();
9926            });
9927        }
9928        cleanup() {
9929            if (this.mirrorEl) {
9930                removeElement(this.mirrorEl);
9931                this.mirrorEl = null;
9932            }
9933            this.sourceEl = null;
9934        }
9935        updateElPosition() {
9936            if (this.sourceEl && this.isVisible) {
9937                applyStyle(this.getMirrorEl(), {
9938                    left: this.sourceElRect.left + this.deltaX,
9939                    top: this.sourceElRect.top + this.deltaY,
9940                });
9941            }
9942        }
9943        getMirrorEl() {
9944            let sourceElRect = this.sourceElRect;
9945            let mirrorEl = this.mirrorEl;
9946            if (!mirrorEl) {
9947                mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true
9948                // we don't want long taps or any mouse interaction causing selection/menus.
9949                // would use preventSelection(), but that prevents selectstart, causing problems.
9950                mirrorEl.classList.add('fc-unselectable');
9951                mirrorEl.classList.add('fc-event-dragging');
9952                applyStyle(mirrorEl, {
9953                    position: 'fixed',
9954                    zIndex: this.zIndex,
9955                    visibility: '',
9956                    boxSizing: 'border-box',
9957                    width: sourceElRect.right - sourceElRect.left,
9958                    height: sourceElRect.bottom - sourceElRect.top,
9959                    right: 'auto',
9960                    bottom: 'auto',
9961                    margin: 0,
9962                });
9963                this.parentNode.appendChild(mirrorEl);
9964            }
9965            return mirrorEl;
9966        }
9967    }
9968
9969    /*
9970    Is a cache for a given element's scroll information (all the info that ScrollController stores)
9971    in addition the "client rectangle" of the element.. the area within the scrollbars.
9972
9973    The cache can be in one of two modes:
9974    - doesListening:false - ignores when the container is scrolled by someone else
9975    - doesListening:true - watch for scrolling and update the cache
9976    */
9977    class ScrollGeomCache extends ScrollController {
9978        constructor(scrollController, doesListening) {
9979            super();
9980            this.handleScroll = () => {
9981                this.scrollTop = this.scrollController.getScrollTop();
9982                this.scrollLeft = this.scrollController.getScrollLeft();
9983                this.handleScrollChange();
9984            };
9985            this.scrollController = scrollController;
9986            this.doesListening = doesListening;
9987            this.scrollTop = this.origScrollTop = scrollController.getScrollTop();
9988            this.scrollLeft = this.origScrollLeft = scrollController.getScrollLeft();
9989            this.scrollWidth = scrollController.getScrollWidth();
9990            this.scrollHeight = scrollController.getScrollHeight();
9991            this.clientWidth = scrollController.getClientWidth();
9992            this.clientHeight = scrollController.getClientHeight();
9993            this.clientRect = this.computeClientRect(); // do last in case it needs cached values
9994            if (this.doesListening) {
9995                this.getEventTarget().addEventListener('scroll', this.handleScroll);
9996            }
9997        }
9998        destroy() {
9999            if (this.doesListening) {
10000                this.getEventTarget().removeEventListener('scroll', this.handleScroll);
10001            }
10002        }
10003        getScrollTop() {
10004            return this.scrollTop;
10005        }
10006        getScrollLeft() {
10007            return this.scrollLeft;
10008        }
10009        setScrollTop(top) {
10010            this.scrollController.setScrollTop(top);
10011            if (!this.doesListening) {
10012                // we are not relying on the element to normalize out-of-bounds scroll values
10013                // so we need to sanitize ourselves
10014                this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0);
10015                this.handleScrollChange();
10016            }
10017        }
10018        setScrollLeft(top) {
10019            this.scrollController.setScrollLeft(top);
10020            if (!this.doesListening) {
10021                // we are not relying on the element to normalize out-of-bounds scroll values
10022                // so we need to sanitize ourselves
10023                this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0);
10024                this.handleScrollChange();
10025            }
10026        }
10027        getClientWidth() {
10028            return this.clientWidth;
10029        }
10030        getClientHeight() {
10031            return this.clientHeight;
10032        }
10033        getScrollWidth() {
10034            return this.scrollWidth;
10035        }
10036        getScrollHeight() {
10037            return this.scrollHeight;
10038        }
10039        handleScrollChange() {
10040        }
10041    }
10042
10043    class ElementScrollGeomCache extends ScrollGeomCache {
10044        constructor(el, doesListening) {
10045            super(new ElementScrollController(el), doesListening);
10046        }
10047        getEventTarget() {
10048            return this.scrollController.el;
10049        }
10050        computeClientRect() {
10051            return computeInnerRect(this.scrollController.el);
10052        }
10053    }
10054
10055    class WindowScrollGeomCache extends ScrollGeomCache {
10056        constructor(doesListening) {
10057            super(new WindowScrollController(), doesListening);
10058        }
10059        getEventTarget() {
10060            return window;
10061        }
10062        computeClientRect() {
10063            return {
10064                left: this.scrollLeft,
10065                right: this.scrollLeft + this.clientWidth,
10066                top: this.scrollTop,
10067                bottom: this.scrollTop + this.clientHeight,
10068            };
10069        }
10070        // the window is the only scroll object that changes it's rectangle relative
10071        // to the document's topleft as it scrolls
10072        handleScrollChange() {
10073            this.clientRect = this.computeClientRect();
10074        }
10075    }
10076
10077    // If available we are using native "performance" API instead of "Date"
10078    // Read more about it on MDN:
10079    // https://developer.mozilla.org/en-US/docs/Web/API/Performance
10080    const getTime = typeof performance === 'function' ? performance.now : Date.now;
10081    /*
10082    For a pointer interaction, automatically scrolls certain scroll containers when the pointer
10083    approaches the edge.
10084
10085    The caller must call start + handleMove + stop.
10086    */
10087    class AutoScroller {
10088        constructor() {
10089            // options that can be set by caller
10090            this.isEnabled = true;
10091            this.scrollQuery = [window, '.fc-scroller'];
10092            this.edgeThreshold = 50; // pixels
10093            this.maxVelocity = 300; // pixels per second
10094            // internal state
10095            this.pointerScreenX = null;
10096            this.pointerScreenY = null;
10097            this.isAnimating = false;
10098            this.scrollCaches = null;
10099            // protect against the initial pointerdown being too close to an edge and starting the scroll
10100            this.everMovedUp = false;
vendor: 6,695 bytes, lines 10101-10252
10101            this.everMovedDown = false;
10102            this.everMovedLeft = false;
10103            this.everMovedRight = false;
10104            this.animate = () => {
10105                if (this.isAnimating) { // wasn't cancelled between animation calls
10106                    let edge = this.computeBestEdge(this.pointerScreenX + window.pageXOffset, this.pointerScreenY + window.pageYOffset);
10107                    if (edge) {
10108                        let now = getTime();
10109                        this.handleSide(edge, (now - this.msSinceRequest) / 1000);
10110                        this.requestAnimation(now);
10111                    }
10112                    else {
10113                        this.isAnimating = false; // will stop animation
10114                    }
10115                }
10116            };
10117        }
10118        start(pageX, pageY, scrollStartEl) {
10119            if (this.isEnabled) {
10120                this.scrollCaches = this.buildCaches(scrollStartEl);
10121                this.pointerScreenX = null;
10122                this.pointerScreenY = null;
10123                this.everMovedUp = false;
10124                this.everMovedDown = false;
10125                this.everMovedLeft = false;
10126                this.everMovedRight = false;
10127                this.handleMove(pageX, pageY);
10128            }
10129        }
10130        handleMove(pageX, pageY) {
10131            if (this.isEnabled) {
10132                let pointerScreenX = pageX - window.pageXOffset;
10133                let pointerScreenY = pageY - window.pageYOffset;
10134                let yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY;
10135                let xDelta = this.pointerScreenX === null ? 0 : pointerScreenX - this.pointerScreenX;
10136                if (yDelta < 0) {
10137                    this.everMovedUp = true;
10138                }
10139                else if (yDelta > 0) {
10140                    this.everMovedDown = true;
10141                }
10142                if (xDelta < 0) {
10143                    this.everMovedLeft = true;
10144                }
10145                else if (xDelta > 0) {
10146                    this.everMovedRight = true;
10147                }
10148                this.pointerScreenX = pointerScreenX;
10149                this.pointerScreenY = pointerScreenY;
10150                if (!this.isAnimating) {
10151                    this.isAnimating = true;
10152                    this.requestAnimation(getTime());
10153                }
10154            }
10155        }
10156        stop() {
10157            if (this.isEnabled) {
10158                this.isAnimating = false; // will stop animation
10159                for (let scrollCache of this.scrollCaches) {
10160                    scrollCache.destroy();
10161                }
10162                this.scrollCaches = null;
10163            }
10164        }
10165        requestAnimation(now) {
10166            this.msSinceRequest = now;
10167            requestAnimationFrame(this.animate);
10168        }
10169        handleSide(edge, seconds) {
10170            let { scrollCache } = edge;
10171            let { edgeThreshold } = this;
10172            let invDistance = edgeThreshold - edge.distance;
10173            let velocity = // the closer to the edge, the faster we scroll
10174             ((invDistance * invDistance) / (edgeThreshold * edgeThreshold)) * // quadratic
10175                this.maxVelocity * seconds;
10176            let sign = 1;
10177            switch (edge.name) {
10178                case 'left':
10179                    sign = -1;
10180                // falls through
10181                case 'right':
10182                    scrollCache.setScrollLeft(scrollCache.getScrollLeft() + velocity * sign);
10183                    break;
10184                case 'top':
10185                    sign = -1;
10186                // falls through
10187                case 'bottom':
10188                    scrollCache.setScrollTop(scrollCache.getScrollTop() + velocity * sign);
10189                    break;
10190            }
10191        }
10192        // left/top are relative to document topleft
10193        computeBestEdge(left, top) {
10194            let { edgeThreshold } = this;
10195            let bestSide = null;
10196            let scrollCaches = this.scrollCaches || [];
10197            for (let scrollCache of scrollCaches) {
10198                let rect = scrollCache.clientRect;
10199                let leftDist = left - rect.left;
10200                let rightDist = rect.right - left;
10201                let topDist = top - rect.top;
10202                let bottomDist = rect.bottom - top;
10203                // completely within the rect?
10204                if (leftDist >= 0 && rightDist >= 0 && topDist >= 0 && bottomDist >= 0) {
10205                    if (topDist <= edgeThreshold && this.everMovedUp && scrollCache.canScrollUp() &&
10206                        (!bestSide || bestSide.distance > topDist)) {
10207                        bestSide = { scrollCache, name: 'top', distance: topDist };
10208                    }
10209                    if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() &&
10210                        (!bestSide || bestSide.distance > bottomDist)) {
10211                        bestSide = { scrollCache, name: 'bottom', distance: bottomDist };
10212                    }
10213                    if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() &&
10214                        (!bestSide || bestSide.distance > leftDist)) {
10215                        bestSide = { scrollCache, name: 'left', distance: leftDist };
10216                    }
10217                    if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() &&
10218                        (!bestSide || bestSide.distance > rightDist)) {
10219                        bestSide = { scrollCache, name: 'right', distance: rightDist };
10220                    }
10221                }
10222            }
10223            return bestSide;
10224        }
10225        buildCaches(scrollStartEl) {
10226            return this.queryScrollEls(scrollStartEl).map((el) => {
10227                if (el === window) {
10228                    return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls
10229                }
10230                return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls
10231            });
10232        }
10233        queryScrollEls(scrollStartEl) {
10234            let els = [];
10235            for (let query of this.scrollQuery) {
10236                if (typeof query === 'object') {
10237                    els.push(query);
10238                }
10239                else {
10240                    els.push(...Array.prototype.slice.call(getElRoot(scrollStartEl).querySelectorAll(query)));
10241                }
10242            }
10243            return els;
10244        }
10245    }
10246
10247    /*
10248    Monitors dragging on an element. Has a number of high-level features:
10249    - minimum distance required before dragging
10250    - minimum wait time ("delay") before dragging
10251    - a mirror element that follows the pointer
10252    */
vendor: 8,987 bytes, lines 10253-10448
10253    class FeaturefulElementDragging extends ElementDragging {
10254        constructor(containerEl, selector) {
10255            super(containerEl);
10256            this.containerEl = containerEl;
10257            // options that can be directly set by caller
10258            // the caller can also set the PointerDragging's options as well
10259            this.delay = null;
10260            this.minDistance = 0;
10261            this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag
10262            this.mirrorNeedsRevert = false;
10263            this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup
10264            this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation
10265            this.isDelayEnded = false;
10266            this.isDistanceSurpassed = false;
10267            this.delayTimeoutId = null;
10268            this.onPointerDown = (ev) => {
10269                if (!this.isDragging) { // so new drag doesn't happen while revert animation is going
10270                    this.isInteracting = true;
10271                    this.isDelayEnded = false;
10272                    this.isDistanceSurpassed = false;
10273                    preventSelection(document.body);
10274                    preventContextMenu(document.body);
10275                    // prevent links from being visited if there's an eventual drag.
10276                    // also prevents selection in older browsers (maybe?).
10277                    // not necessary for touch, besides, browser would complain about passiveness.
10278                    if (!ev.isTouch) {
10279                        ev.origEvent.preventDefault();
10280                    }
10281                    this.emitter.trigger('pointerdown', ev);
10282                    if (this.isInteracting && // not destroyed via pointerdown handler
10283                        !this.pointer.shouldIgnoreMove) {
10284                        // actions related to initiating dragstart+dragmove+dragend...
10285                        this.mirror.setIsVisible(false); // reset. caller must set-visible
10286                        this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down
10287                        this.startDelay(ev);
10288                        if (!this.minDistance) {
10289                            this.handleDistanceSurpassed(ev);
10290                        }
10291                    }
10292                }
10293            };
10294            this.onPointerMove = (ev) => {
10295                if (this.isInteracting) {
10296                    this.emitter.trigger('pointermove', ev);
10297                    if (!this.isDistanceSurpassed) {
10298                        let minDistance = this.minDistance;
10299                        let distanceSq; // current distance from the origin, squared
10300                        let { deltaX, deltaY } = ev;
10301                        distanceSq = deltaX * deltaX + deltaY * deltaY;
10302                        if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem
10303                            this.handleDistanceSurpassed(ev);
10304                        }
10305                    }
10306                    if (this.isDragging) {
10307                        // a real pointer move? (not one simulated by scrolling)
10308                        if (ev.origEvent.type !== 'scroll') {
10309                            this.mirror.handleMove(ev.pageX, ev.pageY);
10310                            this.autoScroller.handleMove(ev.pageX, ev.pageY);
10311                        }
10312                        this.emitter.trigger('dragmove', ev);
10313                    }
10314                }
10315            };
10316            this.onPointerUp = (ev) => {
10317                if (this.isInteracting) {
10318                    this.isInteracting = false;
10319                    allowSelection(document.body);
10320                    allowContextMenu(document.body);
10321                    this.emitter.trigger('pointerup', ev); // can potentially set mirrorNeedsRevert
10322                    if (this.isDragging) {
10323                        this.autoScroller.stop();
10324                        this.tryStopDrag(ev); // which will stop the mirror
10325                    }
10326                    if (this.delayTimeoutId) {
10327                        clearTimeout(this.delayTimeoutId);
10328                        this.delayTimeoutId = null;
10329                    }
10330                }
10331            };
10332            let pointer = this.pointer = new PointerDragging(containerEl);
10333            pointer.emitter.on('pointerdown', this.onPointerDown);
10334            pointer.emitter.on('pointermove', this.onPointerMove);
10335            pointer.emitter.on('pointerup', this.onPointerUp);
10336            if (selector) {
10337                pointer.selector = selector;
10338            }
10339            this.mirror = new ElementMirror();
10340            this.autoScroller = new AutoScroller();
10341        }
10342        destroy() {
10343            this.pointer.destroy();
10344            // HACK: simulate a pointer-up to end the current drag
10345            // TODO: fire 'dragend' directly and stop interaction. discourage use of pointerup event (b/c might not fire)
10346            this.onPointerUp({});
10347        }
10348        startDelay(ev) {
10349            if (typeof this.delay === 'number') {
10350                this.delayTimeoutId = setTimeout(() => {
10351                    this.delayTimeoutId = null;
10352                    this.handleDelayEnd(ev);
10353                }, this.delay); // not assignable to number!
10354            }
10355            else {
10356                this.handleDelayEnd(ev);
10357            }
10358        }
10359        handleDelayEnd(ev) {
10360            this.isDelayEnded = true;
10361            this.tryStartDrag(ev);
10362        }
10363        handleDistanceSurpassed(ev) {
10364            this.isDistanceSurpassed = true;
10365            this.tryStartDrag(ev);
10366        }
10367        tryStartDrag(ev) {
10368            if (this.isDelayEnded && this.isDistanceSurpassed) {
10369                if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) {
10370                    this.isDragging = true;
10371                    this.mirrorNeedsRevert = false;
10372                    this.autoScroller.start(ev.pageX, ev.pageY, this.containerEl);
10373                    this.emitter.trigger('dragstart', ev);
10374                    if (this.touchScrollAllowed === false) {
10375                        this.pointer.cancelTouchScroll();
10376                    }
10377                }
10378            }
10379        }
10380        tryStopDrag(ev) {
10381            // .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events
10382            // that come from the document to fire beforehand. much more convenient this way.
10383            this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev));
10384        }
10385        stopDrag(ev) {
10386            this.isDragging = false;
10387            this.emitter.trigger('dragend', ev);
10388        }
10389        // fill in the implementations...
10390        setIgnoreMove(bool) {
10391            this.pointer.shouldIgnoreMove = bool;
10392        }
10393        setMirrorIsVisible(bool) {
10394            this.mirror.setIsVisible(bool);
10395        }
10396        setMirrorNeedsRevert(bool) {
10397            this.mirrorNeedsRevert = bool;
10398        }
10399        setAutoScrollEnabled(bool) {
10400            this.autoScroller.isEnabled = bool;
10401        }
10402    }
10403
10404    /*
10405    When this class is instantiated, it records the offset of an element (relative to the document topleft),
10406    and continues to monitor scrolling, updating the cached coordinates if it needs to.
10407    Does not access the DOM after instantiation, so highly performant.
10408
10409    Also keeps track of all scrolling/overflow:hidden containers that are parents of the given element
10410    and an determine if a given point is inside the combined clipping rectangle.
10411    */
10412    class OffsetTracker {
10413        constructor(el) {
10414            this.origRect = computeRect(el);
10415            // will work fine for divs that have overflow:hidden
10416            this.scrollCaches = getClippingParents(el).map((scrollEl) => new ElementScrollGeomCache(scrollEl, true));
10417        }
10418        destroy() {
10419            for (let scrollCache of this.scrollCaches) {
10420                scrollCache.destroy();
10421            }
10422        }
10423        computeLeft() {
10424            let left = this.origRect.left;
10425            for (let scrollCache of this.scrollCaches) {
10426                left += scrollCache.origScrollLeft - scrollCache.getScrollLeft();
10427            }
10428            return left;
10429        }
10430        computeTop() {
10431            let top = this.origRect.top;
10432            for (let scrollCache of this.scrollCaches) {
10433                top += scrollCache.origScrollTop - scrollCache.getScrollTop();
10434            }
10435            return top;
10436        }
10437        isWithinClipping(pageX, pageY) {
10438            let point = { left: pageX, top: pageY };
10439            for (let scrollCache of this.scrollCaches) {
10440                if (!isIgnoredClipping(scrollCache.getEventTarget()) &&
10441                    !pointInsideRect(point, scrollCache.clientRect)) {
10442                    return false;
10443                }
10444            }
10445            return true;
10446        }
10447    }
10448    // certain clipping containers should never constrain interactions, like <html> and <body>
10449    // https://github.com/fullcalendar/fullcalendar/issues/3615
10450    function isIgnoredClipping(node) {
10451        let tagName = node.tagName;
10452        return tagName === 'HTML' || tagName === 'BODY';
10453    }
10454
10455    /*
10456    Tracks movement over multiple droppable areas (aka "hits")
10457    that exist in one or more DateComponents.
10458    Relies on an existing draggable.
10459
10460    emits:
10461    - pointerdown
10462    - dragstart
10463    - hitchange - fires initially, even if not over a hit
10464    - pointerup
10465    - (hitchange - again, to null, if ended over a hit)
10466    - dragend
10467    */
10468    class HitDragging {
10469        constructor(dragging, droppableStore) {
10470            // options that can be set by caller
10471            this.useSubjectCenter = false;
10472            this.requireInitial = true; // if doesn't start out on a hit, won't emit any events
10473            this.initialHit = null;
10474            this.movingHit = null;
10475            this.finalHit = null; // won't ever be populated if shouldIgnoreMove
10476            this.handlePointerDown = (ev) => {
10477                let { dragging } = this;
10478                this.initialHit = null;
10479                this.movingHit = null;
10480                this.finalHit = null;
10481                this.prepareHits();
10482                this.processFirstCoord(ev);
10483                if (this.initialHit || !this.requireInitial) {
10484                    dragging.setIgnoreMove(false);
vendor: 52,336 bytes, lines 10485-11548
10485                    // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :(
10486                    this.emitter.trigger('pointerdown', ev);
10487                }
10488                else {
10489                    dragging.setIgnoreMove(true);
10490                }
10491            };
10492            this.handleDragStart = (ev) => {
10493                this.emitter.trigger('dragstart', ev);
10494                this.handleMove(ev, true); // force = fire even if initially null
10495            };
10496            this.handleDragMove = (ev) => {
10497                this.emitter.trigger('dragmove', ev);
10498                this.handleMove(ev);
10499            };
10500            this.handlePointerUp = (ev) => {
10501                this.releaseHits();
10502                this.emitter.trigger('pointerup', ev);
10503            };
10504            this.handleDragEnd = (ev) => {
10505                if (this.movingHit) {
10506                    this.emitter.trigger('hitupdate', null, true, ev);
10507                }
10508                this.finalHit = this.movingHit;
10509                this.movingHit = null;
10510                this.emitter.trigger('dragend', ev);
10511            };
10512            this.droppableStore = droppableStore;
10513            dragging.emitter.on('pointerdown', this.handlePointerDown);
10514            dragging.emitter.on('dragstart', this.handleDragStart);
10515            dragging.emitter.on('dragmove', this.handleDragMove);
10516            dragging.emitter.on('pointerup', this.handlePointerUp);
10517            dragging.emitter.on('dragend', this.handleDragEnd);
10518            this.dragging = dragging;
10519            this.emitter = new Emitter();
10520        }
10521        // sets initialHit
10522        // sets coordAdjust
10523        processFirstCoord(ev) {
10524            let origPoint = { left: ev.pageX, top: ev.pageY };
10525            let adjustedPoint = origPoint;
10526            let subjectEl = ev.subjectEl;
10527            let subjectRect;
10528            if (subjectEl instanceof HTMLElement) { // i.e. not a Document/ShadowRoot
10529                subjectRect = computeRect(subjectEl);
10530                adjustedPoint = constrainPoint(adjustedPoint, subjectRect);
10531            }
10532            let initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top);
10533            if (initialHit) {
10534                if (this.useSubjectCenter && subjectRect) {
10535                    let slicedSubjectRect = intersectRects(subjectRect, initialHit.rect);
10536                    if (slicedSubjectRect) {
10537                        adjustedPoint = getRectCenter(slicedSubjectRect);
10538                    }
10539                }
10540                this.coordAdjust = diffPoints(adjustedPoint, origPoint);
10541            }
10542            else {
10543                this.coordAdjust = { left: 0, top: 0 };
10544            }
10545        }
10546        handleMove(ev, forceHandle) {
10547            let hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top);
10548            if (forceHandle || !isHitsEqual(this.movingHit, hit)) {
10549                this.movingHit = hit;
10550                this.emitter.trigger('hitupdate', hit, false, ev);
10551            }
10552        }
10553        prepareHits() {
10554            this.offsetTrackers = mapHash(this.droppableStore, (interactionSettings) => {
10555                interactionSettings.component.prepareHits();
10556                return new OffsetTracker(interactionSettings.el);
10557            });
10558        }
10559        releaseHits() {
10560            let { offsetTrackers } = this;
10561            for (let id in offsetTrackers) {
10562                offsetTrackers[id].destroy();
10563            }
10564            this.offsetTrackers = {};
10565        }
10566        queryHitForOffset(offsetLeft, offsetTop) {
10567            let { droppableStore, offsetTrackers } = this;
10568            let bestHit = null;
10569            for (let id in droppableStore) {
10570                let component = droppableStore[id].component;
10571                let offsetTracker = offsetTrackers[id];
10572                if (offsetTracker && // wasn't destroyed mid-drag
10573                    offsetTracker.isWithinClipping(offsetLeft, offsetTop)) {
10574                    let originLeft = offsetTracker.computeLeft();
10575                    let originTop = offsetTracker.computeTop();
10576                    let positionLeft = offsetLeft - originLeft;
10577                    let positionTop = offsetTop - originTop;
10578                    let { origRect } = offsetTracker;
10579                    let width = origRect.right - origRect.left;
10580                    let height = origRect.bottom - origRect.top;
10581                    if (
10582                    // must be within the element's bounds
10583                    positionLeft >= 0 && positionLeft < width &&
10584                        positionTop >= 0 && positionTop < height) {
10585                        let hit = component.queryHit(positionLeft, positionTop, width, height);
10586                        if (hit && (
10587                        // make sure the hit is within activeRange, meaning it's not a dead cell
10588                        rangeContainsRange(hit.dateProfile.activeRange, hit.dateSpan.range)) &&
10589                            (!bestHit || hit.layer > bestHit.layer)) {
10590                            hit.componentId = id;
10591                            hit.context = component.context;
10592                            // TODO: better way to re-orient rectangle
10593                            hit.rect.left += originLeft;
10594                            hit.rect.right += originLeft;
10595                            hit.rect.top += originTop;
10596                            hit.rect.bottom += originTop;
10597                            bestHit = hit;
10598                        }
10599                    }
10600                }
10601            }
10602            return bestHit;
10603        }
10604    }
10605    function isHitsEqual(hit0, hit1) {
10606        if (!hit0 && !hit1) {
10607            return true;
10608        }
10609        if (Boolean(hit0) !== Boolean(hit1)) {
10610            return false;
10611        }
10612        return isDateSpansEqual(hit0.dateSpan, hit1.dateSpan);
10613    }
10614
10615    function buildDatePointApiWithContext(dateSpan, context) {
10616        let props = {};
10617        for (let transform of context.pluginHooks.datePointTransforms) {
10618            Object.assign(props, transform(dateSpan, context));
10619        }
10620        Object.assign(props, buildDatePointApi(dateSpan, context.dateEnv));
10621        return props;
10622    }
10623    function buildDatePointApi(span, dateEnv) {
10624        return {
10625            date: dateEnv.toDate(span.range.start),
10626            dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }),
10627            allDay: span.allDay,
10628        };
10629    }
10630
10631    /*
10632    Monitors when the user clicks on a specific date/time of a component.
10633    A pointerdown+pointerup on the same "hit" constitutes a click.
10634    */
10635    class DateClicking extends Interaction {
10636        constructor(settings) {
10637            super(settings);
10638            this.handlePointerDown = (pev) => {
10639                let { dragging } = this;
10640                let downEl = pev.origEvent.target;
10641                // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired
10642                dragging.setIgnoreMove(!this.component.isValidDateDownEl(downEl));
10643            };
10644            // won't even fire if moving was ignored
10645            this.handleDragEnd = (ev) => {
10646                let { component } = this;
10647                let { pointer } = this.dragging;
10648                if (!pointer.wasTouchScroll) {
10649                    let { initialHit, finalHit } = this.hitDragging;
10650                    if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) {
10651                        let { context } = component;
10652                        let arg = Object.assign(Object.assign({}, buildDatePointApiWithContext(initialHit.dateSpan, context)), { dayEl: initialHit.dayEl, jsEvent: ev.origEvent, view: context.viewApi || context.calendarApi.view });
10653                        context.emitter.trigger('dateClick', arg);
10654                    }
10655                }
10656            };
10657            // we DO want to watch pointer moves because otherwise finalHit won't get populated
10658            this.dragging = new FeaturefulElementDragging(settings.el);
10659            this.dragging.autoScroller.isEnabled = false;
10660            let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
10661            hitDragging.emitter.on('pointerdown', this.handlePointerDown);
10662            hitDragging.emitter.on('dragend', this.handleDragEnd);
10663        }
10664        destroy() {
10665            this.dragging.destroy();
10666        }
10667    }
10668
10669    /*
10670    Tracks when the user selects a portion of time of a component,
10671    constituted by a drag over date cells, with a possible delay at the beginning of the drag.
10672    */
10673    class DateSelecting extends Interaction {
10674        constructor(settings) {
10675            super(settings);
10676            this.dragSelection = null;
10677            this.handlePointerDown = (ev) => {
10678                let { component, dragging } = this;
10679                let { options } = component.context;
10680                let canSelect = options.selectable &&
10681                    component.isValidDateDownEl(ev.origEvent.target);
10682                // don't bother to watch expensive moves if component won't do selection
10683                dragging.setIgnoreMove(!canSelect);
10684                // if touch, require user to hold down
10685                dragging.delay = ev.isTouch ? getComponentTouchDelay$1(component) : null;
10686            };
10687            this.handleDragStart = (ev) => {
10688                this.component.context.calendarApi.unselect(ev); // unselect previous selections
10689            };
10690            this.handleHitUpdate = (hit, isFinal) => {
10691                let { context } = this.component;
10692                let dragSelection = null;
10693                let isInvalid = false;
10694                if (hit) {
10695                    let initialHit = this.hitDragging.initialHit;
10696                    let disallowed = hit.componentId === initialHit.componentId
10697                        && this.isHitComboAllowed
10698                        && !this.isHitComboAllowed(initialHit, hit);
10699                    if (!disallowed) {
10700                        dragSelection = joinHitsIntoSelection(initialHit, hit, context.pluginHooks.dateSelectionTransformers);
10701                    }
10702                    if (!dragSelection || !isDateSelectionValid(dragSelection, hit.dateProfile, context)) {
10703                        isInvalid = true;
10704                        dragSelection = null;
10705                    }
10706                }
10707                if (dragSelection) {
10708                    context.dispatch({ type: 'SELECT_DATES', selection: dragSelection });
10709                }
10710                else if (!isFinal) { // only unselect if moved away while dragging
10711                    context.dispatch({ type: 'UNSELECT_DATES' });
10712                }
10713                if (!isInvalid) {
10714                    enableCursor();
10715                }
10716                else {
10717                    disableCursor();
10718                }
10719                if (!isFinal) {
10720                    this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging
10721                }
10722            };
10723            this.handlePointerUp = (pev) => {
10724                if (this.dragSelection) {
10725                    // selection is already rendered, so just need to report selection
10726                    triggerDateSelect(this.dragSelection, pev, this.component.context);
10727                    this.dragSelection = null;
10728                }
10729            };
10730            let { component } = settings;
10731            let { options } = component.context;
10732            let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
10733            dragging.touchScrollAllowed = false;
10734            dragging.minDistance = options.selectMinDistance || 0;
10735            dragging.autoScroller.isEnabled = options.dragScroll;
10736            let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
10737            hitDragging.emitter.on('pointerdown', this.handlePointerDown);
10738            hitDragging.emitter.on('dragstart', this.handleDragStart);
10739            hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
10740            hitDragging.emitter.on('pointerup', this.handlePointerUp);
10741        }
10742        destroy() {
10743            this.dragging.destroy();
10744        }
10745    }
10746    function getComponentTouchDelay$1(component) {
10747        let { options } = component.context;
10748        let delay = options.selectLongPressDelay;
10749        if (delay == null) {
10750            delay = options.longPressDelay;
10751        }
10752        return delay;
10753    }
10754    function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) {
10755        let dateSpan0 = hit0.dateSpan;
10756        let dateSpan1 = hit1.dateSpan;
10757        let ms = [
10758            dateSpan0.range.start,
10759            dateSpan0.range.end,
10760            dateSpan1.range.start,
10761            dateSpan1.range.end,
10762        ];
10763        ms.sort(compareNumbers);
10764        let props = {};
10765        for (let transformer of dateSelectionTransformers) {
10766            let res = transformer(hit0, hit1);
10767            if (res === false) {
10768                return null;
10769            }
10770            if (res) {
10771                Object.assign(props, res);
10772            }
10773        }
10774        props.range = { start: ms[0], end: ms[3] };
10775        props.allDay = dateSpan0.allDay;
10776        return props;
10777    }
10778
10779    class EventDragging extends Interaction {
10780        constructor(settings) {
10781            super(settings);
10782            // internal state
10783            this.subjectEl = null;
10784            this.subjectSeg = null; // the seg being selected/dragged
10785            this.isDragging = false;
10786            this.eventRange = null;
10787            this.relevantEvents = null; // the events being dragged
10788            this.receivingContext = null;
10789            this.validMutation = null;
10790            this.mutatedRelevantEvents = null;
10791            this.handlePointerDown = (ev) => {
10792                let origTarget = ev.origEvent.target;
10793                let { component, dragging } = this;
10794                let { mirror } = dragging;
10795                let { options } = component.context;
10796                let initialContext = component.context;
10797                this.subjectEl = ev.subjectEl;
10798                let subjectSeg = this.subjectSeg = getElSeg(ev.subjectEl);
10799                let eventRange = this.eventRange = subjectSeg.eventRange;
10800                let eventInstanceId = eventRange.instance.instanceId;
10801                this.relevantEvents = getRelevantEvents(initialContext.getCurrentData().eventStore, eventInstanceId);
10802                dragging.minDistance = ev.isTouch ? 0 : options.eventDragMinDistance;
10803                dragging.delay =
10804                    // only do a touch delay if touch and this event hasn't been selected yet
10805                    (ev.isTouch && eventInstanceId !== component.props.eventSelection) ?
10806                        getComponentTouchDelay(component) :
10807                        null;
10808                if (options.fixedMirrorParent) {
10809                    mirror.parentNode = options.fixedMirrorParent;
10810                }
10811                else {
10812                    mirror.parentNode = elementClosest(origTarget, '.fc');
10813                }
10814                mirror.revertDuration = options.dragRevertDuration;
10815                let isValid = component.isValidSegDownEl(origTarget) &&
10816                    !elementClosest(origTarget, '.fc-event-resizer'); // NOT on a resizer
10817                dragging.setIgnoreMove(!isValid);
10818                // disable dragging for elements that are resizable (ie, selectable)
10819                // but are not draggable
10820                this.isDragging = isValid &&
10821                    ev.subjectEl.classList.contains('fc-event-draggable');
10822            };
10823            this.handleDragStart = (ev) => {
10824                let initialContext = this.component.context;
10825                let eventRange = this.eventRange;
10826                let eventInstanceId = eventRange.instance.instanceId;
10827                if (ev.isTouch) {
10828                    // need to select a different event?
10829                    if (eventInstanceId !== this.component.props.eventSelection) {
10830                        initialContext.dispatch({ type: 'SELECT_EVENT', eventInstanceId });
10831                    }
10832                }
10833                else {
10834                    // if now using mouse, but was previous touch interaction, clear selected event
10835                    initialContext.dispatch({ type: 'UNSELECT_EVENT' });
10836                }
10837                if (this.isDragging) {
10838                    initialContext.calendarApi.unselect(ev); // unselect *date* selection
10839                    initialContext.emitter.trigger('eventDragStart', {
10840                        el: this.subjectEl,
10841                        event: new EventImpl(initialContext, eventRange.def, eventRange.instance),
10842                        jsEvent: ev.origEvent,
10843                        view: initialContext.viewApi,
10844                    });
10845                }
10846            };
10847            this.handleHitUpdate = (hit, isFinal) => {
10848                if (!this.isDragging) {
10849                    return;
10850                }
10851                let relevantEvents = this.relevantEvents;
10852                let initialHit = this.hitDragging.initialHit;
10853                let initialContext = this.component.context;
10854                // states based on new hit
10855                let receivingContext = null;
10856                let mutation = null;
10857                let mutatedRelevantEvents = null;
10858                let isInvalid = false;
10859                let interaction = {
10860                    affectedEvents: relevantEvents,
10861                    mutatedEvents: createEmptyEventStore(),
10862                    isEvent: true,
10863                };
10864                if (hit) {
10865                    receivingContext = hit.context;
10866                    let receivingOptions = receivingContext.options;
10867                    if (initialContext === receivingContext ||
10868                        (receivingOptions.editable && receivingOptions.droppable)) {
10869                        mutation = computeEventMutation(initialHit, hit, receivingContext.getCurrentData().pluginHooks.eventDragMutationMassagers);
10870                        if (mutation) {
10871                            mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, receivingContext.getCurrentData().eventUiBases, mutation, receivingContext);
10872                            interaction.mutatedEvents = mutatedRelevantEvents;
10873                            if (!isInteractionValid(interaction, hit.dateProfile, receivingContext)) {
10874                                isInvalid = true;
10875                                mutation = null;
10876                                mutatedRelevantEvents = null;
10877                                interaction.mutatedEvents = createEmptyEventStore();
10878                            }
10879                        }
10880                    }
10881                    else {
10882                        receivingContext = null;
10883                    }
10884                }
10885                this.displayDrag(receivingContext, interaction);
10886                if (!isInvalid) {
10887                    enableCursor();
10888                }
10889                else {
10890                    disableCursor();
10891                }
10892                if (!isFinal) {
10893                    if (initialContext === receivingContext && // TODO: write test for this
10894                        isHitsEqual(initialHit, hit)) {
10895                        mutation = null;
10896                    }
10897                    this.dragging.setMirrorNeedsRevert(!mutation);
10898                    // render the mirror if no already-rendered mirror
10899                    // TODO: wish we could somehow wait for dispatch to guarantee render
10900                    this.dragging.setMirrorIsVisible(!hit || !getElRoot(this.subjectEl).querySelector('.fc-event-mirror'));
10901                    // assign states based on new hit
10902                    this.receivingContext = receivingContext;
10903                    this.validMutation = mutation;
10904                    this.mutatedRelevantEvents = mutatedRelevantEvents;
10905                }
10906            };
10907            this.handlePointerUp = () => {
10908                if (!this.isDragging) {
10909                    this.cleanup(); // because handleDragEnd won't fire
10910                }
10911            };
10912            this.handleDragEnd = (ev) => {
10913                if (this.isDragging) {
10914                    let initialContext = this.component.context;
10915                    let initialView = initialContext.viewApi;
10916                    let { receivingContext, validMutation } = this;
10917                    let eventDef = this.eventRange.def;
10918                    let eventInstance = this.eventRange.instance;
10919                    let eventApi = new EventImpl(initialContext, eventDef, eventInstance);
10920                    let relevantEvents = this.relevantEvents;
10921                    let mutatedRelevantEvents = this.mutatedRelevantEvents;
10922                    let { finalHit } = this.hitDragging;
10923                    this.clearDrag(); // must happen after revert animation
10924                    initialContext.emitter.trigger('eventDragStop', {
10925                        el: this.subjectEl,
10926                        event: eventApi,
10927                        jsEvent: ev.origEvent,
10928                        view: initialView,
10929                    });
10930                    if (validMutation) {
10931                        // dropped within same calendar
10932                        if (receivingContext === initialContext) {
10933                            let updatedEventApi = new EventImpl(initialContext, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null);
10934                            initialContext.dispatch({
10935                                type: 'MERGE_EVENTS',
10936                                eventStore: mutatedRelevantEvents,
10937                            });
10938                            let eventChangeArg = {
10939                                oldEvent: eventApi,
10940                                event: updatedEventApi,
10941                                relatedEvents: buildEventApis(mutatedRelevantEvents, initialContext, eventInstance),
10942                                revert() {
10943                                    initialContext.dispatch({
10944                                        type: 'MERGE_EVENTS',
10945                                        eventStore: relevantEvents, // the pre-change data
10946                                    });
10947                                },
10948                            };
10949                            let transformed = {};
10950                            for (let transformer of initialContext.getCurrentData().pluginHooks.eventDropTransformers) {
10951                                Object.assign(transformed, transformer(validMutation, initialContext));
10952                            }
10953                            initialContext.emitter.trigger('eventDrop', Object.assign(Object.assign(Object.assign({}, eventChangeArg), transformed), { el: ev.subjectEl, delta: validMutation.datesDelta, jsEvent: ev.origEvent, view: initialView }));
10954                            initialContext.emitter.trigger('eventChange', eventChangeArg);
10955                            // dropped in different calendar
10956                        }
10957                        else if (receivingContext) {
10958                            let eventRemoveArg = {
10959                                event: eventApi,
10960                                relatedEvents: buildEventApis(relevantEvents, initialContext, eventInstance),
10961                                revert() {
10962                                    initialContext.dispatch({
10963                                        type: 'MERGE_EVENTS',
10964                                        eventStore: relevantEvents,
10965                                    });
10966                                },
10967                            };
10968                            initialContext.emitter.trigger('eventLeave', Object.assign(Object.assign({}, eventRemoveArg), { draggedEl: ev.subjectEl, view: initialView }));
10969                            initialContext.dispatch({
10970                                type: 'REMOVE_EVENTS',
10971                                eventStore: relevantEvents,
10972                            });
10973                            initialContext.emitter.trigger('eventRemove', eventRemoveArg);
10974                            let addedEventDef = mutatedRelevantEvents.defs[eventDef.defId];
10975                            let addedEventInstance = mutatedRelevantEvents.instances[eventInstance.instanceId];
10976                            let addedEventApi = new EventImpl(receivingContext, addedEventDef, addedEventInstance);
10977                            receivingContext.dispatch({
10978                                type: 'MERGE_EVENTS',
10979                                eventStore: mutatedRelevantEvents,
10980                            });
10981                            let eventAddArg = {
10982                                event: addedEventApi,
10983                                relatedEvents: buildEventApis(mutatedRelevantEvents, receivingContext, addedEventInstance),
10984                                revert() {
10985                                    receivingContext.dispatch({
10986                                        type: 'REMOVE_EVENTS',
10987                                        eventStore: mutatedRelevantEvents,
10988                                    });
10989                                },
10990                            };
10991                            receivingContext.emitter.trigger('eventAdd', eventAddArg);
10992                            if (ev.isTouch) {
10993                                receivingContext.dispatch({
10994                                    type: 'SELECT_EVENT',
10995                                    eventInstanceId: eventInstance.instanceId,
10996                                });
10997                            }
10998                            receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.context.viewApi }));
10999                            receivingContext.emitter.trigger('eventReceive', Object.assign(Object.assign({}, eventAddArg), { draggedEl: ev.subjectEl, view: finalHit.context.viewApi }));
11000                        }
11001                    }
11002                    else {
11003                        initialContext.emitter.trigger('_noEventDrop');
11004                    }
11005                }
11006                this.cleanup();
11007            };
11008            let { component } = this;
11009            let { options } = component.context;
11010            let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
11011            dragging.pointer.selector = EventDragging.SELECTOR;
11012            dragging.touchScrollAllowed = false;
11013            dragging.autoScroller.isEnabled = options.dragScroll;
11014            let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsStore);
11015            hitDragging.useSubjectCenter = settings.useEventCenter;
11016            hitDragging.emitter.on('pointerdown', this.handlePointerDown);
11017            hitDragging.emitter.on('dragstart', this.handleDragStart);
11018            hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
11019            hitDragging.emitter.on('pointerup', this.handlePointerUp);
11020            hitDragging.emitter.on('dragend', this.handleDragEnd);
11021        }
11022        destroy() {
11023            this.dragging.destroy();
11024        }
11025        // render a drag state on the next receivingCalendar
11026        displayDrag(nextContext, state) {
11027            let initialContext = this.component.context;
11028            let prevContext = this.receivingContext;
11029            // does the previous calendar need to be cleared?
11030            if (prevContext && prevContext !== nextContext) {
11031                // does the initial calendar need to be cleared?
11032                // if so, don't clear all the way. we still need to to hide the affectedEvents
11033                if (prevContext === initialContext) {
11034                    prevContext.dispatch({
11035                        type: 'SET_EVENT_DRAG',
11036                        state: {
11037                            affectedEvents: state.affectedEvents,
11038                            mutatedEvents: createEmptyEventStore(),
11039                            isEvent: true,
11040                        },
11041                    });
11042                    // completely clear the old calendar if it wasn't the initial
11043                }
11044                else {
11045                    prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
11046                }
11047            }
11048            if (nextContext) {
11049                nextContext.dispatch({ type: 'SET_EVENT_DRAG', state });
11050            }
11051        }
11052        clearDrag() {
11053            let initialCalendar = this.component.context;
11054            let { receivingContext } = this;
11055            if (receivingContext) {
11056                receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
11057            }
11058            // the initial calendar might have an dummy drag state from displayDrag
11059            if (initialCalendar !== receivingContext) {
11060                initialCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
11061            }
11062        }
11063        cleanup() {
11064            this.subjectSeg = null;
11065            this.isDragging = false;
11066            this.eventRange = null;
11067            this.relevantEvents = null;
11068            this.receivingContext = null;
11069            this.validMutation = null;
11070            this.mutatedRelevantEvents = null;
11071        }
11072    }
11073    // TODO: test this in IE11
11074    // QUESTION: why do we need it on the resizable???
11075    EventDragging.SELECTOR = '.fc-event-draggable, .fc-event-resizable';
11076    function computeEventMutation(hit0, hit1, massagers) {
11077        let dateSpan0 = hit0.dateSpan;
11078        let dateSpan1 = hit1.dateSpan;
11079        let date0 = dateSpan0.range.start;
11080        let date1 = dateSpan1.range.start;
11081        let standardProps = {};
11082        if (dateSpan0.allDay !== dateSpan1.allDay) {
11083            standardProps.allDay = dateSpan1.allDay;
11084            standardProps.hasEnd = hit1.context.options.allDayMaintainDuration;
11085            if (dateSpan1.allDay) {
11086                // means date1 is already start-of-day,
11087                // but date0 needs to be converted
11088                date0 = startOfDay(date0);
11089            }
11090        }
11091        let delta = diffDates(date0, date1, hit0.context.dateEnv, hit0.componentId === hit1.componentId ?
11092            hit0.largeUnit :
11093            null);
11094        if (delta.milliseconds) { // has hours/minutes/seconds
11095            standardProps.allDay = false;
11096        }
11097        let mutation = {
11098            datesDelta: delta,
11099            standardProps,
11100        };
11101        for (let massager of massagers) {
11102            massager(mutation, hit0, hit1);
11103        }
11104        return mutation;
11105    }
11106    function getComponentTouchDelay(component) {
11107        let { options } = component.context;
11108        let delay = options.eventLongPressDelay;
11109        if (delay == null) {
11110            delay = options.longPressDelay;
11111        }
11112        return delay;
11113    }
11114
11115    class EventResizing extends Interaction {
11116        constructor(settings) {
11117            super(settings);
11118            // internal state
11119            this.draggingSegEl = null;
11120            this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg?
11121            this.eventRange = null;
11122            this.relevantEvents = null;
11123            this.validMutation = null;
11124            this.mutatedRelevantEvents = null;
11125            this.handlePointerDown = (ev) => {
11126                let { component } = this;
11127                let segEl = this.querySegEl(ev);
11128                let seg = getElSeg(segEl);
11129                let eventRange = this.eventRange = seg.eventRange;
11130                this.dragging.minDistance = component.context.options.eventDragMinDistance;
11131                // if touch, need to be working with a selected event
11132                this.dragging.setIgnoreMove(!this.component.isValidSegDownEl(ev.origEvent.target) ||
11133                    (ev.isTouch && this.component.props.eventSelection !== eventRange.instance.instanceId));
11134            };
11135            this.handleDragStart = (ev) => {
11136                let { context } = this.component;
11137                let eventRange = this.eventRange;
11138                this.relevantEvents = getRelevantEvents(context.getCurrentData().eventStore, this.eventRange.instance.instanceId);
11139                let segEl = this.querySegEl(ev);
11140                this.draggingSegEl = segEl;
11141                this.draggingSeg = getElSeg(segEl);
11142                context.calendarApi.unselect();
11143                context.emitter.trigger('eventResizeStart', {
11144                    el: segEl,
11145                    event: new EventImpl(context, eventRange.def, eventRange.instance),
11146                    jsEvent: ev.origEvent,
11147                    view: context.viewApi,
11148                });
11149            };
11150            this.handleHitUpdate = (hit, isFinal, ev) => {
11151                let { context } = this.component;
11152                let relevantEvents = this.relevantEvents;
11153                let initialHit = this.hitDragging.initialHit;
11154                let eventInstance = this.eventRange.instance;
11155                let mutation = null;
11156                let mutatedRelevantEvents = null;
11157                let isInvalid = false;
11158                let interaction = {
11159                    affectedEvents: relevantEvents,
11160                    mutatedEvents: createEmptyEventStore(),
11161                    isEvent: true,
11162                };
11163                if (hit) {
11164                    let disallowed = hit.componentId === initialHit.componentId
11165                        && this.isHitComboAllowed
11166                        && !this.isHitComboAllowed(initialHit, hit);
11167                    if (!disallowed) {
11168                        mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-event-resizer-start'), eventInstance.range);
11169                    }
11170                }
11171                if (mutation) {
11172                    mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, context.getCurrentData().eventUiBases, mutation, context);
11173                    interaction.mutatedEvents = mutatedRelevantEvents;
11174                    if (!isInteractionValid(interaction, hit.dateProfile, context)) {
11175                        isInvalid = true;
11176                        mutation = null;
11177                        mutatedRelevantEvents = null;
11178                        interaction.mutatedEvents = null;
11179                    }
11180                }
11181                if (mutatedRelevantEvents) {
11182                    context.dispatch({
11183                        type: 'SET_EVENT_RESIZE',
11184                        state: interaction,
11185                    });
11186                }
11187                else {
11188                    context.dispatch({ type: 'UNSET_EVENT_RESIZE' });
11189                }
11190                if (!isInvalid) {
11191                    enableCursor();
11192                }
11193                else {
11194                    disableCursor();
11195                }
11196                if (!isFinal) {
11197                    if (mutation && isHitsEqual(initialHit, hit)) {
11198                        mutation = null;
11199                    }
11200                    this.validMutation = mutation;
11201                    this.mutatedRelevantEvents = mutatedRelevantEvents;
11202                }
11203            };
11204            this.handleDragEnd = (ev) => {
11205                let { context } = this.component;
11206                let eventDef = this.eventRange.def;
11207                let eventInstance = this.eventRange.instance;
11208                let eventApi = new EventImpl(context, eventDef, eventInstance);
11209                let relevantEvents = this.relevantEvents;
11210                let mutatedRelevantEvents = this.mutatedRelevantEvents;
11211                context.emitter.trigger('eventResizeStop', {
11212                    el: this.draggingSegEl,
11213                    event: eventApi,
11214                    jsEvent: ev.origEvent,
11215                    view: context.viewApi,
11216                });
11217                if (this.validMutation) {
11218                    let updatedEventApi = new EventImpl(context, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null);
11219                    context.dispatch({
11220                        type: 'MERGE_EVENTS',
11221                        eventStore: mutatedRelevantEvents,
11222                    });
11223                    let eventChangeArg = {
11224                        oldEvent: eventApi,
11225                        event: updatedEventApi,
11226                        relatedEvents: buildEventApis(mutatedRelevantEvents, context, eventInstance),
11227                        revert() {
11228                            context.dispatch({
11229                                type: 'MERGE_EVENTS',
11230                                eventStore: relevantEvents, // the pre-change events
11231                            });
11232                        },
11233                    };
11234                    context.emitter.trigger('eventResize', Object.assign(Object.assign({}, eventChangeArg), { el: this.draggingSegEl, startDelta: this.validMutation.startDelta || createDuration(0), endDelta: this.validMutation.endDelta || createDuration(0), jsEvent: ev.origEvent, view: context.viewApi }));
11235                    context.emitter.trigger('eventChange', eventChangeArg);
11236                }
11237                else {
11238                    context.emitter.trigger('_noEventResize');
11239                }
11240                // reset all internal state
11241                this.draggingSeg = null;
11242                this.relevantEvents = null;
11243                this.validMutation = null;
11244                // okay to keep eventInstance around. useful to set it in handlePointerDown
11245            };
11246            let { component } = settings;
11247            let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
11248            dragging.pointer.selector = '.fc-event-resizer';
11249            dragging.touchScrollAllowed = false;
11250            dragging.autoScroller.isEnabled = component.context.options.dragScroll;
11251            let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
11252            hitDragging.emitter.on('pointerdown', this.handlePointerDown);
11253            hitDragging.emitter.on('dragstart', this.handleDragStart);
11254            hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
11255            hitDragging.emitter.on('dragend', this.handleDragEnd);
11256        }
11257        destroy() {
11258            this.dragging.destroy();
11259        }
11260        querySegEl(ev) {
11261            return elementClosest(ev.subjectEl, '.fc-event');
11262        }
11263    }
11264    function computeMutation(hit0, hit1, isFromStart, instanceRange) {
11265        let dateEnv = hit0.context.dateEnv;
11266        let date0 = hit0.dateSpan.range.start;
11267        let date1 = hit1.dateSpan.range.start;
11268        let delta = diffDates(date0, date1, dateEnv, hit0.largeUnit);
11269        if (isFromStart) {
11270            if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) {
11271                return { startDelta: delta };
11272            }
11273        }
11274        else if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) {
11275            return { endDelta: delta };
11276        }
11277        return null;
11278    }
11279
11280    class UnselectAuto {
11281        constructor(context) {
11282            this.context = context;
11283            this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system
11284            this.matchesCancel = false;
11285            this.matchesEvent = false;
11286            this.onSelect = (selectInfo) => {
11287                if (selectInfo.jsEvent) {
11288                    this.isRecentPointerDateSelect = true;
11289                }
11290            };
11291            this.onDocumentPointerDown = (pev) => {
11292                let unselectCancel = this.context.options.unselectCancel;
11293                let downEl = getEventTargetViaRoot(pev.origEvent);
11294                this.matchesCancel = !!elementClosest(downEl, unselectCancel);
11295                this.matchesEvent = !!elementClosest(downEl, EventDragging.SELECTOR); // interaction started on an event?
11296            };
11297            this.onDocumentPointerUp = (pev) => {
11298                let { context } = this;
11299                let { documentPointer } = this;
11300                let calendarState = context.getCurrentData();
11301                // touch-scrolling should never unfocus any type of selection
11302                if (!documentPointer.wasTouchScroll) {
11303                    if (calendarState.dateSelection && // an existing date selection?
11304                        !this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp?
11305                    ) {
11306                        let unselectAuto = context.options.unselectAuto;
11307                        if (unselectAuto && (!unselectAuto || !this.matchesCancel)) {
11308                            context.calendarApi.unselect(pev);
11309                        }
11310                    }
11311                    if (calendarState.eventSelection && // an existing event selected?
11312                        !this.matchesEvent // interaction DIDN'T start on an event
11313                    ) {
11314                        context.dispatch({ type: 'UNSELECT_EVENT' });
11315                    }
11316                }
11317                this.isRecentPointerDateSelect = false;
11318            };
11319            let documentPointer = this.documentPointer = new PointerDragging(document);
11320            documentPointer.shouldIgnoreMove = true;
11321            documentPointer.shouldWatchScroll = false;
11322            documentPointer.emitter.on('pointerdown', this.onDocumentPointerDown);
11323            documentPointer.emitter.on('pointerup', this.onDocumentPointerUp);
11324            /*
11325            TODO: better way to know about whether there was a selection with the pointer
11326            */
11327            context.emitter.on('select', this.onSelect);
11328        }
11329        destroy() {
11330            this.context.emitter.off('select', this.onSelect);
11331            this.documentPointer.destroy();
11332        }
11333    }
11334
11335    const OPTION_REFINERS$2 = {
11336        fixedMirrorParent: identity,
11337    };
11338    const LISTENER_REFINERS = {
11339        dateClick: identity,
11340        eventDragStart: identity,
11341        eventDragStop: identity,
11342        eventDrop: identity,
11343        eventResizeStart: identity,
11344        eventResizeStop: identity,
11345        eventResize: identity,
11346        drop: identity,
11347        eventReceive: identity,
11348        eventLeave: identity,
11349    };
11350
11351    /*
11352    Given an already instantiated draggable object for one-or-more elements,
11353    Interprets any dragging as an attempt to drag an events that lives outside
11354    of a calendar onto a calendar.
11355    */
11356    class ExternalElementDragging {
11357        constructor(dragging, suppliedDragMeta) {
11358            this.receivingContext = null;
11359            this.droppableEvent = null; // will exist for all drags, even if create:false
11360            this.suppliedDragMeta = null;
11361            this.dragMeta = null;
11362            this.handleDragStart = (ev) => {
11363                this.dragMeta = this.buildDragMeta(ev.subjectEl);
11364            };
11365            this.handleHitUpdate = (hit, isFinal, ev) => {
11366                let { dragging } = this.hitDragging;
11367                let receivingContext = null;
11368                let droppableEvent = null;
11369                let isInvalid = false;
11370                let interaction = {
11371                    affectedEvents: createEmptyEventStore(),
11372                    mutatedEvents: createEmptyEventStore(),
11373                    isEvent: this.dragMeta.create,
11374                };
11375                if (hit) {
11376                    receivingContext = hit.context;
11377                    if (this.canDropElOnCalendar(ev.subjectEl, receivingContext)) {
11378                        droppableEvent = computeEventForDateSpan(hit.dateSpan, this.dragMeta, receivingContext);
11379                        interaction.mutatedEvents = eventTupleToStore(droppableEvent);
11380                        isInvalid = !isInteractionValid(interaction, hit.dateProfile, receivingContext);
11381                        if (isInvalid) {
11382                            interaction.mutatedEvents = createEmptyEventStore();
11383                            droppableEvent = null;
11384                        }
11385                    }
11386                }
11387                this.displayDrag(receivingContext, interaction);
11388                // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?)
11389                // TODO: wish we could somehow wait for dispatch to guarantee render
11390                dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-event-mirror'));
11391                if (!isInvalid) {
11392                    enableCursor();
11393                }
11394                else {
11395                    disableCursor();
11396                }
11397                if (!isFinal) {
11398                    dragging.setMirrorNeedsRevert(!droppableEvent);
11399                    this.receivingContext = receivingContext;
11400                    this.droppableEvent = droppableEvent;
11401                }
11402            };
11403            this.handleDragEnd = (pev) => {
11404                let { receivingContext, droppableEvent } = this;
11405                this.clearDrag();
11406                if (receivingContext && droppableEvent) {
11407                    let finalHit = this.hitDragging.finalHit;
11408                    let finalView = finalHit.context.viewApi;
11409                    let dragMeta = this.dragMeta;
11410                    receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView }));
11411                    if (dragMeta.create) {
11412                        let addingEvents = eventTupleToStore(droppableEvent);
11413                        receivingContext.dispatch({
11414                            type: 'MERGE_EVENTS',
11415                            eventStore: addingEvents,
11416                        });
11417                        if (pev.isTouch) {
11418                            receivingContext.dispatch({
11419                                type: 'SELECT_EVENT',
11420                                eventInstanceId: droppableEvent.instance.instanceId,
11421                            });
11422                        }
11423                        // signal that an external event landed
11424                        receivingContext.emitter.trigger('eventReceive', {
11425                            event: new EventImpl(receivingContext, droppableEvent.def, droppableEvent.instance),
11426                            relatedEvents: [],
11427                            revert() {
11428                                receivingContext.dispatch({
11429                                    type: 'REMOVE_EVENTS',
11430                                    eventStore: addingEvents,
11431                                });
11432                            },
11433                            draggedEl: pev.subjectEl,
11434                            view: finalView,
11435                        });
11436                    }
11437                }
11438                this.receivingContext = null;
11439                this.droppableEvent = null;
11440            };
11441            let hitDragging = this.hitDragging = new HitDragging(dragging, interactionSettingsStore);
11442            hitDragging.requireInitial = false; // will start outside of a component
11443            hitDragging.emitter.on('dragstart', this.handleDragStart);
11444            hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
11445            hitDragging.emitter.on('dragend', this.handleDragEnd);
11446            this.suppliedDragMeta = suppliedDragMeta;
11447        }
11448        buildDragMeta(subjectEl) {
11449            if (typeof this.suppliedDragMeta === 'object') {
11450                return parseDragMeta(this.suppliedDragMeta);
11451            }
11452            if (typeof this.suppliedDragMeta === 'function') {
11453                return parseDragMeta(this.suppliedDragMeta(subjectEl));
11454            }
11455            return getDragMetaFromEl(subjectEl);
11456        }
11457        displayDrag(nextContext, state) {
11458            let prevContext = this.receivingContext;
11459            if (prevContext && prevContext !== nextContext) {
11460                prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
11461            }
11462            if (nextContext) {
11463                nextContext.dispatch({ type: 'SET_EVENT_DRAG', state });
11464            }
11465        }
11466        clearDrag() {
11467            if (this.receivingContext) {
11468                this.receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
11469            }
11470        }
11471        canDropElOnCalendar(el, receivingContext) {
11472            let dropAccept = receivingContext.options.dropAccept;
11473            if (typeof dropAccept === 'function') {
11474                return dropAccept.call(receivingContext.calendarApi, el);
11475            }
11476            if (typeof dropAccept === 'string' && dropAccept) {
11477                return Boolean(elementMatches(el, dropAccept));
11478            }
11479            return true;
11480        }
11481    }
11482    // Utils for computing event store from the DragMeta
11483    // ----------------------------------------------------------------------------------------------------
11484    function computeEventForDateSpan(dateSpan, dragMeta, context) {
11485        let defProps = Object.assign({}, dragMeta.leftoverProps);
11486        for (let transform of context.pluginHooks.externalDefTransforms) {
11487            Object.assign(defProps, transform(dateSpan, dragMeta));
11488        }
11489        let { refined, extra } = refineEventDef(defProps, context);
11490        let def = parseEventDef(refined, extra, dragMeta.sourceId, dateSpan.allDay, context.options.forceEventDuration || Boolean(dragMeta.duration), // hasEnd
11491        context);
11492        let start = dateSpan.range.start;
11493        // only rely on time info if drop zone is all-day,
11494        // otherwise, we already know the time
11495        if (dateSpan.allDay && dragMeta.startTime) {
11496            start = context.dateEnv.add(start, dragMeta.startTime);
11497        }
11498        let end = dragMeta.duration ?
11499            context.dateEnv.add(start, dragMeta.duration) :
11500            getDefaultEventEnd(dateSpan.allDay, start, context);
11501        let instance = createEventInstance(def.defId, { start, end });
11502        return { def, instance };
11503    }
11504    // Utils for extracting data from element
11505    // ----------------------------------------------------------------------------------------------------
11506    function getDragMetaFromEl(el) {
11507        let str = getEmbeddedElData(el, 'event');
11508        let obj = str ?
11509            JSON.parse(str) :
11510            { create: false }; // if no embedded data, assume no event creation
11511        return parseDragMeta(obj);
11512    }
11513    config.dataAttrPrefix = '';
11514    function getEmbeddedElData(el, name) {
11515        let prefix = config.dataAttrPrefix;
11516        let prefixedName = (prefix ? prefix + '-' : '') + name;
11517        return el.getAttribute('data-' + prefixedName) || '';
11518    }
11519
11520    /*
11521    Makes an element (that is *external* to any calendar) draggable.
11522    Can pass in data that determines how an event will be created when dropped onto a calendar.
11523    Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system.
11524    */
11525    class ExternalDraggable {
11526        constructor(el, settings = {}) {
11527            this.handlePointerDown = (ev) => {
11528                let { dragging } = this;
11529                let { minDistance, longPressDelay } = this.settings;
11530                dragging.minDistance =
11531                    minDistance != null ?
11532                        minDistance :
11533                        (ev.isTouch ? 0 : BASE_OPTION_DEFAULTS.eventDragMinDistance);
11534                dragging.delay =
11535                    ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv
11536                        (longPressDelay != null ? longPressDelay : BASE_OPTION_DEFAULTS.longPressDelay) :
11537                        0;
11538            };
11539            this.handleDragStart = (ev) => {
11540                if (ev.isTouch &&
11541                    this.dragging.delay &&
11542                    ev.subjectEl.classList.contains('fc-event')) {
11543                    this.dragging.mirror.getMirrorEl().classList.add('fc-event-selected');
11544                }
11545            };
11546            this.settings = settings;
11547            let dragging = this.dragging = new FeaturefulElementDragging(el);
11548            dragging.touchScrollAllowed = false;
vendor: 6,340 bytes, lines 11549-11701
11549            if (settings.itemSelector != null) {
11550                dragging.pointer.selector = settings.itemSelector;
11551            }
11552            if (settings.appendTo != null) {
11553                dragging.mirror.parentNode = settings.appendTo; // TODO: write tests
11554            }
11555            dragging.emitter.on('pointerdown', this.handlePointerDown);
11556            dragging.emitter.on('dragstart', this.handleDragStart);
11557            new ExternalElementDragging(dragging, settings.eventData); // eslint-disable-line no-new
11558        }
11559        destroy() {
11560            this.dragging.destroy();
11561        }
11562    }
11563
11564    /*
11565    Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements.
11566    The third-party system is responsible for drawing the visuals effects of the drag.
11567    This class simply monitors for pointer movements and fires events.
11568    It also has the ability to hide the moving element (the "mirror") during the drag.
11569    */
11570    class InferredElementDragging extends ElementDragging {
11571        constructor(containerEl) {
11572            super(containerEl);
11573            this.shouldIgnoreMove = false;
11574            this.mirrorSelector = '';
11575            this.currentMirrorEl = null;
11576            this.handlePointerDown = (ev) => {
11577                this.emitter.trigger('pointerdown', ev);
11578                if (!this.shouldIgnoreMove) {
11579                    // fire dragstart right away. does not support delay or min-distance
11580                    this.emitter.trigger('dragstart', ev);
11581                }
11582            };
11583            this.handlePointerMove = (ev) => {
11584                if (!this.shouldIgnoreMove) {
11585                    this.emitter.trigger('dragmove', ev);
11586                }
11587            };
11588            this.handlePointerUp = (ev) => {
11589                this.emitter.trigger('pointerup', ev);
11590                if (!this.shouldIgnoreMove) {
11591                    // fire dragend right away. does not support a revert animation
11592                    this.emitter.trigger('dragend', ev);
11593                }
11594            };
11595            let pointer = this.pointer = new PointerDragging(containerEl);
11596            pointer.emitter.on('pointerdown', this.handlePointerDown);
11597            pointer.emitter.on('pointermove', this.handlePointerMove);
11598            pointer.emitter.on('pointerup', this.handlePointerUp);
11599        }
11600        destroy() {
11601            this.pointer.destroy();
11602        }
11603        setIgnoreMove(bool) {
11604            this.shouldIgnoreMove = bool;
11605        }
11606        setMirrorIsVisible(bool) {
11607            if (bool) {
11608                // restore a previously hidden element.
11609                // use the reference in case the selector class has already been removed.
11610                if (this.currentMirrorEl) {
11611                    this.currentMirrorEl.style.visibility = '';
11612                    this.currentMirrorEl = null;
11613                }
11614            }
11615            else {
11616                let mirrorEl = this.mirrorSelector
11617                    // TODO: somehow query FullCalendars WITHIN shadow-roots
11618                    ? document.querySelector(this.mirrorSelector)
11619                    : null;
11620                if (mirrorEl) {
11621                    this.currentMirrorEl = mirrorEl;
11622                    mirrorEl.style.visibility = 'hidden';
11623                }
11624            }
11625        }
11626    }
11627
11628    /*
11629    Bridges third-party drag-n-drop systems with FullCalendar.
11630    Must be instantiated and destroyed by caller.
11631    */
11632    class ThirdPartyDraggable {
11633        constructor(containerOrSettings, settings) {
11634            let containerEl = document;
11635            if (
11636            // wish we could just test instanceof EventTarget, but doesn't work in IE11
11637            containerOrSettings === document ||
11638                containerOrSettings instanceof Element) {
11639                containerEl = containerOrSettings;
11640                settings = settings || {};
11641            }
11642            else {
11643                settings = (containerOrSettings || {});
11644            }
11645            let dragging = this.dragging = new InferredElementDragging(containerEl);
11646            if (typeof settings.itemSelector === 'string') {
11647                dragging.pointer.selector = settings.itemSelector;
11648            }
11649            else if (containerEl === document) {
11650                dragging.pointer.selector = '[data-event]';
11651            }
11652            if (typeof settings.mirrorSelector === 'string') {
11653                dragging.mirrorSelector = settings.mirrorSelector;
11654            }
11655            new ExternalElementDragging(dragging, settings.eventData); // eslint-disable-line no-new
11656        }
11657        destroy() {
11658            this.dragging.destroy();
11659        }
11660    }
11661
11662    var index$3 = createPlugin({
11663        name: '@fullcalendar/interaction',
11664        componentInteractions: [DateClicking, DateSelecting, EventDragging, EventResizing],
11665        calendarInteractions: [UnselectAuto],
11666        elementDraggingImpl: FeaturefulElementDragging,
11667        optionRefiners: OPTION_REFINERS$2,
11668        listenerRefiners: LISTENER_REFINERS,
11669    });
11670
11671    /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.
11672    ----------------------------------------------------------------------------------------------------------------------*/
11673    // It is a manager for a Table subcomponent, which does most of the heavy lifting.
11674    // It is responsible for managing width/height.
11675    class TableView extends DateComponent {
11676        constructor() {
11677            super(...arguments);
11678            this.headerElRef = y();
11679        }
11680        renderSimpleLayout(headerRowContent, bodyContent) {
11681            let { props, context } = this;
11682            let sections = [];
11683            let stickyHeaderDates = getStickyHeaderDates(context.options);
11684            if (headerRowContent) {
11685                sections.push({
11686                    type: 'header',
11687                    key: 'header',
11688                    isSticky: stickyHeaderDates,
11689                    chunk: {
11690                        elRef: this.headerElRef,
11691                        tableClassName: 'fc-col-header',
11692                        rowContent: headerRowContent,
11693                    },
11694                });
11695            }
11696            sections.push({
11697                type: 'body',
11698                key: 'body',
11699                liquid: true,
11700                chunk: { content: bodyContent },
11701            });
vendor: 4,067 bytes, lines 11702-11813
11702            return (h(ViewContainer$1, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
11703                h(SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [] /* TODO: make optional? */, sections: sections })));
11704        }
11705        renderHScrollLayout(headerRowContent, bodyContent, colCnt, dayMinWidth) {
11706            let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
11707            if (!ScrollGrid) {
11708                throw new Error('No ScrollGrid implementation');
11709            }
11710            let { props, context } = this;
11711            let stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options);
11712            let stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options);
11713            let sections = [];
11714            if (headerRowContent) {
11715                sections.push({
11716                    type: 'header',
11717                    key: 'header',
11718                    isSticky: stickyHeaderDates,
11719                    chunks: [{
11720                            key: 'main',
11721                            elRef: this.headerElRef,
11722                            tableClassName: 'fc-col-header',
11723                            rowContent: headerRowContent,
11724                        }],
11725                });
11726            }
11727            sections.push({
11728                type: 'body',
11729                key: 'body',
11730                liquid: true,
11731                chunks: [{
11732                        key: 'main',
11733                        content: bodyContent,
11734                    }],
11735            });
11736            if (stickyFooterScrollbar) {
11737                sections.push({
11738                    type: 'footer',
11739                    key: 'footer',
11740                    isSticky: true,
11741                    chunks: [{
11742                            key: 'main',
11743                            content: renderScrollShim,
11744                        }],
11745                });
11746            }
11747            return (h(ViewContainer$1, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
11748                h(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }], sections: sections })));
11749        }
11750    }
11751
11752    function splitSegsByRow(segs, rowCnt) {
11753        let byRow = [];
11754        for (let i = 0; i < rowCnt; i += 1) {
11755            byRow[i] = [];
11756        }
11757        for (let seg of segs) {
11758            byRow[seg.row].push(seg);
11759        }
11760        return byRow;
11761    }
11762    function splitSegsByFirstCol(segs, colCnt) {
11763        let byCol = [];
11764        for (let i = 0; i < colCnt; i += 1) {
11765            byCol[i] = [];
11766        }
11767        for (let seg of segs) {
11768            byCol[seg.firstCol].push(seg);
11769        }
11770        return byCol;
11771    }
11772    function splitInteractionByRow(ui, rowCnt) {
11773        let byRow = [];
11774        if (!ui) {
11775            for (let i = 0; i < rowCnt; i += 1) {
11776                byRow[i] = null;
11777            }
11778        }
11779        else {
11780            for (let i = 0; i < rowCnt; i += 1) {
11781                byRow[i] = {
11782                    affectedInstances: ui.affectedInstances,
11783                    isEvent: ui.isEvent,
11784                    segs: [],
11785                };
11786            }
11787            for (let seg of ui.segs) {
11788                byRow[seg.row].segs.push(seg);
11789            }
11790        }
11791        return byRow;
11792    }
11793
11794    const DEFAULT_TABLE_EVENT_TIME_FORMAT = createFormatter({
11795        hour: 'numeric',
11796        minute: '2-digit',
11797        omitZeroMinute: true,
11798        meridiem: 'narrow',
11799    });
11800    function hasListItemDisplay(seg) {
11801        let { display } = seg.eventRange.ui;
11802        return display === 'list-item' || (display === 'auto' &&
11803            !seg.eventRange.def.allDay &&
11804            seg.firstCol === seg.lastCol && // can't be multi-day
11805            seg.isStart && // "
11806            seg.isEnd // "
11807        );
11808    }
11809
11810    class TableBlockEvent extends BaseComponent {
11811        render() {
11812            let { props } = this;
11813            return (h(StandardEvent, Object.assign({}
vendor: 8,375 bytes, lines 11813-11953
11813, props, { elClasses: ['fc-daygrid-event', 'fc-daygrid-block-event', 'fc-h-event'], defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: props.defaultDisplayEventEnd, disableResizing: !props.seg.eventRange.def.allDay })));
11814        }
11815    }
11816
11817    class TableListItemEvent extends BaseComponent {
11818        render() {
11819            let { props, context } = this;
11820            let { options } = context;
11821            let { seg } = props;
11822            let timeFormat = options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT;
11823            let timeText = buildSegTimeText(seg, timeFormat, context, true, props.defaultDisplayEventEnd);
11824            return (h(EventContainer, Object.assign({}, props, { elTag: "a", elClasses: ['fc-daygrid-event', 'fc-daygrid-dot-event'], elAttrs: getSegAnchorAttrs(props.seg, context), defaultGenerator: renderInnerContent$2, timeText: timeText, isResizing: false, isDateSelecting: false })));
11825        }
11826    }
11827    function renderInnerContent$2(renderProps) {
11828        return (h(p, null,
11829            h("div", { className: "fc-daygrid-event-dot", style: { borderColor: renderProps.borderColor || renderProps.backgroundColor } }),
11830            renderProps.timeText && (h("div", { className: "fc-event-time" }, renderProps.timeText)),
11831            h("div", { className: "fc-event-title" }, renderProps.event.title || h(p, null, "\u00A0"))));
11832    }
11833
11834    class TableCellMoreLink extends BaseComponent {
11835        constructor() {
11836            super(...arguments);
11837            this.compileSegs = memoize(compileSegs);
11838        }
11839        render() {
11840            let { props } = this;
11841            let { allSegs, invisibleSegs } = this.compileSegs(props.singlePlacements);
11842            return (h(MoreLinkContainer, { elClasses: ['fc-daygrid-more-link'], dateProfile: props.dateProfile, todayRange: props.todayRange, allDayDate: props.allDayDate, moreCnt: props.moreCnt, allSegs: allSegs, hiddenSegs: invisibleSegs, alignmentElRef: props.alignmentElRef, alignGridTop: props.alignGridTop, extraDateSpan: props.extraDateSpan, popoverContent: () => {
11843                    let isForcedInvisible = (props.eventDrag ? props.eventDrag.affectedInstances : null) ||
11844                        (props.eventResize ? props.eventResize.affectedInstances : null) ||
11845                        {};
11846                    return (h(p, null, allSegs.map((seg) => {
11847                        let instanceId = seg.eventRange.instance.instanceId;
11848                        return (h("div", { className: "fc-daygrid-event-harness", key: instanceId, style: {
11849                                visibility: isForcedInvisible[instanceId] ? 'hidden' : '',
11850                            } }, hasListItemDisplay(seg) ? (h(TableListItemEvent, Object.assign({ seg: seg, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, getSegMeta(seg, props.todayRange)))) : (h(TableBlockEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, getSegMeta(seg, props.todayRange))))));
11851                    })));
11852                } }));
11853        }
11854    }
11855    function compileSegs(singlePlacements) {
11856        let allSegs = [];
11857        let invisibleSegs = [];
11858        for (let placement of singlePlacements) {
11859            allSegs.push(placement.seg);
11860            if (!placement.isVisible) {
11861                invisibleSegs.push(placement.seg);
11862            }
11863        }
11864        return { allSegs, invisibleSegs };
11865    }
11866
11867    const DEFAULT_WEEK_NUM_FORMAT$1 = createFormatter({ week: 'narrow' });
11868    class TableCell extends DateComponent {
11869        constructor() {
11870            super(...arguments);
11871            this.rootElRef = y();
11872            this.state = {
11873                dayNumberId: getUniqueDomId(),
11874            };
11875            this.handleRootEl = (el) => {
11876                setRef(this.rootElRef, el);
11877                setRef(this.props.elRef, el);
11878            };
11879        }
11880        render() {
11881            let { context, props, state, rootElRef } = this;
11882            let { options } = context;
11883            let { date, dateProfile } = props;
11884            return (h(DayCellContainer, { elTag: "td", elRef: this.handleRootEl, elClasses: [
11885                    'fc-daygrid-day',
11886                    ...(props.extraClassNames || []),
11887                ], elAttrs: Object.assign(Object.assign(Object.assign({}, props.extraDataAttrs), (props.showDayNumber ? { 'aria-labelledby': state.dayNumberId } : {})), { role: 'gridcell' }), defaultGenerator: renderTopInner, date: date, dateProfile: dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, extraRenderProps: props.extraRenderProps }, (InnerContent, renderProps) => (h("div", { className: "fc-daygrid-day-frame fc-scrollgrid-sync-inner", ref: props.innerElRef },
11888                props.showWeekNumber && (h(WeekNumberContainer, { elTag: "a", elClasses: ['fc-daygrid-week-number'], elAttrs: buildNavLinkAttrs(context, date, 'week'), date: date, defaultFormat: DEFAULT_WEEK_NUM_FORMAT$1 })),
11889                Boolean(!renderProps.isDisabled &&
11890                    (props.showDayNumber || hasCustomDayCellContent(options) || props.forceDayTop)) && (h("div", { className: "fc-daygrid-day-top" },
11891                    h(InnerContent, { elTag: "a", elClasses: ['fc-daygrid-day-number'], elAttrs: Object.assign(Object.assign({}, buildNavLinkAttrs(context, date)), { id: state.dayNumberId }) }))),
11892                h("div", { className: "fc-daygrid-day-events", ref: props.fgContentElRef },
11893                    props.fgContent,
11894                    h("div", { className: "fc-daygrid-day-bottom", style: { marginTop: props.moreMarginTop } },
11895                        h(TableCellMoreLink, { allDayDate: date, singlePlacements: props.singlePlacements, moreCnt: props.moreCnt, alignmentElRef: rootElRef, alignGridTop: !props.showDayNumber, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange }))),
11896                h("div", { className: "fc-daygrid-day-bg" }, props.bgContent)))));
11897        }
11898    }
11899    function renderTopInner(props) {
11900        return props.dayNumberText || h(p, null, "\u00A0");
11901    }
11902
11903    function computeFgSegPlacement(segs, // assumed already sorted
11904    dayMaxEvents, dayMaxEventRows, strictOrder, eventInstanceHeights, maxContentHeight, cells) {
11905        let hierarchy = new DayGridSegHierarchy();
11906        hierarchy.allowReslicing = true;
11907        hierarchy.strictOrder = strictOrder;
11908        if (dayMaxEvents === true || dayMaxEventRows === true) {
11909            hierarchy.maxCoord = maxContentHeight;
11910            hierarchy.hiddenConsumes = true;
11911        }
11912        else if (typeof dayMaxEvents === 'number') {
11913            hierarchy.maxStackCnt = dayMaxEvents;
11914        }
11915        else if (typeof dayMaxEventRows === 'number') {
11916            hierarchy.maxStackCnt = dayMaxEventRows;
11917            hierarchy.hiddenConsumes = true;
11918        }
11919        // create segInputs only for segs with known heights
11920        let segInputs = [];
11921        let unknownHeightSegs = [];
11922        for (let i = 0; i < segs.length; i += 1) {
11923            let seg = segs[i];
11924            let { instanceId } = seg.eventRange.instance;
11925            let eventHeight = eventInstanceHeights[instanceId];
11926            if (eventHeight != null) {
11927                segInputs.push({
11928                    index: i,
11929                    thickness: eventHeight,
11930                    span: {
11931                        start: seg.firstCol,
11932                        end: seg.lastCol + 1,
11933                    },
11934                });
11935            }
11936            else {
11937                unknownHeightSegs.push(seg);
11938            }
11939        }
11940        let hiddenEntries = hierarchy.addSegs(segInputs);
11941        let segRects = hierarchy.toRects();
11942        let { singleColPlacements, multiColPlacements, leftoverMargins } = placeRects(segRects, segs, cells);
11943        let moreCnts = [];
11944        let moreMarginTops = [];
11945        // add segs with unknown heights
11946        for (let seg of unknownHeightSegs) {
11947            multiColPlacements[seg.firstCol].push({
11948                seg,
11949                isVisible: false,
11950                isAbsolute: true,
11951                absoluteTop: 0,
11952                marginTop: 0,
11953            });
vendor: 13,637 bytes, lines 11954-12215
11954            for (let col = seg.firstCol; col <= seg.lastCol; col += 1) {
11955                singleColPlacements[col].push({
11956                    seg: resliceSeg(seg, col, col + 1, cells),
11957                    isVisible: false,
11958                    isAbsolute: false,
11959                    absoluteTop: 0,
11960                    marginTop: 0,
11961                });
11962            }
11963        }
11964        // add the hidden entries
11965        for (let col = 0; col < cells.length; col += 1) {
11966            moreCnts.push(0);
11967        }
11968        for (let hiddenEntry of hiddenEntries) {
11969            let seg = segs[hiddenEntry.index];
11970            let hiddenSpan = hiddenEntry.span;
11971            multiColPlacements[hiddenSpan.start].push({
11972                seg: resliceSeg(seg, hiddenSpan.start, hiddenSpan.end, cells),
11973                isVisible: false,
11974                isAbsolute: true,
11975                absoluteTop: 0,
11976                marginTop: 0,
11977            });
11978            for (let col = hiddenSpan.start; col < hiddenSpan.end; col += 1) {
11979                moreCnts[col] += 1;
11980                singleColPlacements[col].push({
11981                    seg: resliceSeg(seg, col, col + 1, cells),
11982                    isVisible: false,
11983                    isAbsolute: false,
11984                    absoluteTop: 0,
11985                    marginTop: 0,
11986                });
11987            }
11988        }
11989        // deal with leftover margins
11990        for (let col = 0; col < cells.length; col += 1) {
11991            moreMarginTops.push(leftoverMargins[col]);
11992        }
11993        return { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops };
11994    }
11995    // rects ordered by top coord, then left
11996    function placeRects(allRects, segs, cells) {
11997        let rectsByEachCol = groupRectsByEachCol(allRects, cells.length);
11998        let singleColPlacements = [];
11999        let multiColPlacements = [];
12000        let leftoverMargins = [];
12001        for (let col = 0; col < cells.length; col += 1) {
12002            let rects = rectsByEachCol[col];
12003            // compute all static segs in singlePlacements
12004            let singlePlacements = [];
12005            let currentHeight = 0;
12006            let currentMarginTop = 0;
12007            for (let rect of rects) {
12008                let seg = segs[rect.index];
12009                singlePlacements.push({
12010                    seg: resliceSeg(seg, col, col + 1, cells),
12011                    isVisible: true,
12012                    isAbsolute: false,
12013                    absoluteTop: rect.levelCoord,
12014                    marginTop: rect.levelCoord - currentHeight,
12015                });
12016                currentHeight = rect.levelCoord + rect.thickness;
12017            }
12018            // compute mixed static/absolute segs in multiPlacements
12019            let multiPlacements = [];
12020            currentHeight = 0;
12021            currentMarginTop = 0;
12022            for (let rect of rects) {
12023                let seg = segs[rect.index];
12024                let isAbsolute = rect.span.end - rect.span.start > 1; // multi-column?
12025                let isFirstCol = rect.span.start === col;
12026                currentMarginTop += rect.levelCoord - currentHeight; // amount of space since bottom of previous seg
12027                currentHeight = rect.levelCoord + rect.thickness; // height will now be bottom of current seg
12028                if (isAbsolute) {
12029                    currentMarginTop += rect.thickness;
12030                    if (isFirstCol) {
12031                        multiPlacements.push({
12032                            seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
12033                            isVisible: true,
12034                            isAbsolute: true,
12035                            absoluteTop: rect.levelCoord,
12036                            marginTop: 0,
12037                        });
12038                    }
12039                }
12040                else if (isFirstCol) {
12041                    multiPlacements.push({
12042                        seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
12043                        isVisible: true,
12044                        isAbsolute: false,
12045                        absoluteTop: rect.levelCoord,
12046                        marginTop: currentMarginTop, // claim the margin
12047                    });
12048                    currentMarginTop = 0;
12049                }
12050            }
12051            singleColPlacements.push(singlePlacements);
12052            multiColPlacements.push(multiPlacements);
12053            leftoverMargins.push(currentMarginTop);
12054        }
12055        return { singleColPlacements, multiColPlacements, leftoverMargins };
12056    }
12057    function groupRectsByEachCol(rects, colCnt) {
12058        let rectsByEachCol = [];
12059        for (let col = 0; col < colCnt; col += 1) {
12060            rectsByEachCol.push([]);
12061        }
12062        for (let rect of rects) {
12063            for (let col = rect.span.start; col < rect.span.end; col += 1) {
12064                rectsByEachCol[col].push(rect);
12065            }
12066        }
12067        return rectsByEachCol;
12068    }
12069    function resliceSeg(seg, spanStart, spanEnd, cells) {
12070        if (seg.firstCol === spanStart && seg.lastCol === spanEnd - 1) {
12071            return seg;
12072        }
12073        let eventRange = seg.eventRange;
12074        let origRange = eventRange.range;
12075        let slicedRange = intersectRanges(origRange, {
12076            start: cells[spanStart].date,
12077            end: addDays(cells[spanEnd - 1].date, 1),
12078        });
12079        return Object.assign(Object.assign({}, seg), { firstCol: spanStart, lastCol: spanEnd - 1, eventRange: {
12080                def: eventRange.def,
12081                ui: Object.assign(Object.assign({}, eventRange.ui), { durationEditable: false }),
12082                instance: eventRange.instance,
12083                range: slicedRange,
12084            }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() });
12085    }
12086    class DayGridSegHierarchy extends SegHierarchy {
12087        constructor() {
12088            super(...arguments);
12089            // config
12090            this.hiddenConsumes = false;
12091            // allows us to keep hidden entries in the hierarchy so they take up space
12092            this.forceHidden = {};
12093        }
12094        addSegs(segInputs) {
12095            const hiddenSegs = super.addSegs(segInputs);
12096            const { entriesByLevel } = this;
12097            const excludeHidden = (entry) => !this.forceHidden[buildEntryKey(entry)];
12098            // remove the forced-hidden segs
12099            for (let level = 0; level < entriesByLevel.length; level += 1) {
12100                entriesByLevel[level] = entriesByLevel[level].filter(excludeHidden);
12101            }
12102            return hiddenSegs;
12103        }
12104        handleInvalidInsertion(insertion, entry, hiddenEntries) {
12105            const { entriesByLevel, forceHidden } = this;
12106            const { touchingEntry, touchingLevel, touchingLateral } = insertion;
12107            if (this.hiddenConsumes && touchingEntry) {
12108                const touchingEntryId = buildEntryKey(touchingEntry);
12109                // if not already hidden
12110                if (!forceHidden[touchingEntryId]) {
12111                    if (this.allowReslicing) {
12112                        const placeholderEntry = Object.assign(Object.assign({}, touchingEntry), { span: intersectSpans(touchingEntry.span, entry.span) });
12113                        const placeholderEntryId = buildEntryKey(placeholderEntry);
12114                        forceHidden[placeholderEntryId] = true;
12115                        entriesByLevel[touchingLevel][touchingLateral] = placeholderEntry; // replace touchingEntry with our placeholder
12116                        this.splitEntry(touchingEntry, entry, hiddenEntries); // split up the touchingEntry, reinsert it
12117                    }
12118                    else {
12119                        forceHidden[touchingEntryId] = true;
12120                        hiddenEntries.push(touchingEntry);
12121                    }
12122                }
12123            }
12124            return super.handleInvalidInsertion(insertion, entry, hiddenEntries);
12125        }
12126    }
12127
12128    class TableRow extends DateComponent {
12129        constructor() {
12130            super(...arguments);
12131            this.cellElRefs = new RefMap(); // the <td>
12132            this.frameElRefs = new RefMap(); // the fc-daygrid-day-frame
12133            this.fgElRefs = new RefMap(); // the fc-daygrid-day-events
12134            this.segHarnessRefs = new RefMap(); // indexed by "instanceId:firstCol"
12135            this.rootElRef = y();
12136            this.state = {
12137                framePositions: null,
12138                maxContentHeight: null,
12139                eventInstanceHeights: {},
12140            };
12141            this.handleResize = (isForced) => {
12142                if (isForced) {
12143                    this.updateSizing(true); // isExternal=true
12144                }
12145            };
12146        }
12147        render() {
12148            let { props, state, context } = this;
12149            let { options } = context;
12150            let colCnt = props.cells.length;
12151            let businessHoursByCol = splitSegsByFirstCol(props.businessHourSegs, colCnt);
12152            let bgEventSegsByCol = splitSegsByFirstCol(props.bgEventSegs, colCnt);
12153            let highlightSegsByCol = splitSegsByFirstCol(this.getHighlightSegs(), colCnt);
12154            let mirrorSegsByCol = splitSegsByFirstCol(this.getMirrorSegs(), colCnt);
12155            let { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops } = computeFgSegPlacement(sortEventSegs(props.fgEventSegs, options.eventOrder), props.dayMaxEvents, props.dayMaxEventRows, options.eventOrderStrict, state.eventInstanceHeights, state.maxContentHeight, props.cells);
12156            let isForcedInvisible = // TODO: messy way to compute this
12157             (props.eventDrag && props.eventDrag.affectedInstances) ||
12158                (props.eventResize && props.eventResize.affectedInstances) ||
12159                {};
12160            return (h("tr", { ref: this.rootElRef, role: "row" },
12161                props.renderIntro && props.renderIntro(),
12162                props.cells.map((cell, col) => {
12163                    let normalFgNodes = this.renderFgSegs(col, props.forPrint ? singleColPlacements[col] : multiColPlacements[col], props.todayRange, isForcedInvisible);
12164                    let mirrorFgNodes = this.renderFgSegs(col, buildMirrorPlacements(mirrorSegsByCol[col], multiColPlacements), props.todayRange, {}, Boolean(props.eventDrag), Boolean(props.eventResize), false);
12165                    return (h(TableCell, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), innerElRef: this.frameElRefs.createRef(cell.key) /* FF <td> problem, but okay to use for left/right. TODO: rename prop */, dateProfile: props.dateProfile, date: cell.date, showDayNumber: props.showDayNumbers, showWeekNumber: props.showWeekNumbers && col === 0, forceDayTop: props.showWeekNumbers /* even displaying weeknum for row, not necessarily day */, todayRange: props.todayRange, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, moreCnt: moreCnts[col], moreMarginTop: moreMarginTops[col], singlePlacements: singleColPlacements[col], fgContentElRef: this.fgElRefs.createRef(cell.key), fgContent: ( // Fragment scopes the keys
12166                        h(p, null,
12167                            h(p, null, normalFgNodes),
12168                            h(p, null, mirrorFgNodes))), bgContent: ( // Fragment scopes the keys
12169                        h(p, null,
12170                            this.renderFillSegs(highlightSegsByCol[col], 'highlight'),
12171                            this.renderFillSegs(businessHoursByCol[col], 'non-business'),
12172                            this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))) }));
12173                })));
12174        }
12175        componentDidMount() {
12176            this.updateSizing(true);
12177            this.context.addResizeHandler(this.handleResize);
12178        }
12179        componentDidUpdate(prevProps, prevState) {
12180            let currentProps = this.props;
12181            this.updateSizing(!isPropsEqual(prevProps, currentProps));
12182        }
12183        componentWillUnmount() {
12184            this.context.removeResizeHandler(this.handleResize);
12185        }
12186        getHighlightSegs() {
12187            let { props } = this;
12188            if (props.eventDrag && props.eventDrag.segs.length) { // messy check
12189                return props.eventDrag.segs;
12190            }
12191            if (props.eventResize && props.eventResize.segs.length) { // messy check
12192                return props.eventResize.segs;
12193            }
12194            return props.dateSelectionSegs;
12195        }
12196        getMirrorSegs() {
12197            let { props } = this;
12198            if (props.eventResize && props.eventResize.segs.length) { // messy check
12199                return props.eventResize.segs;
12200            }
12201            return [];
12202        }
12203        renderFgSegs(col, segPlacements, todayRange, isForcedInvisible, isDragging, isResizing, isDateSelecting) {
12204            let { context } = this;
12205            let { eventSelection } = this.props;
12206            let { framePositions } = this.state;
12207            let defaultDisplayEventEnd = this.props.cells.length === 1; // colCnt === 1
12208            let isMirror = isDragging || isResizing || isDateSelecting;
12209            let nodes = [];
12210            if (framePositions) {
12211                for (let placement of segPlacements) {
12212                    let { seg } = placement;
12213                    let { instanceId } = seg.eventRange.instance;
12214                    let key = instanceId + ':' + col;
12215                    let isVisible = placement.isVisible && !isForcedInvisible[instanceId];
vendor: 15,724 bytes, lines 12216-12487
12216                    let isAbsolute = placement.isAbsolute;
12217                    let left = '';
12218                    let right = '';
12219                    if (isAbsolute) {
12220                        if (context.isRtl) {
12221                            right = 0;
12222                            left = framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol];
12223                        }
12224                        else {
12225                            left = 0;
12226                            right = framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol];
12227                        }
12228                    }
12229                    /*
12230                    known bug: events that are force to be list-item but span multiple days still take up space in later columns
12231                    todo: in print view, for multi-day events, don't display title within non-start/end segs
12232                    */
12233                    nodes.push(h("div", { className: 'fc-daygrid-event-harness' + (isAbsolute ? ' fc-daygrid-event-harness-abs' : ''), key: key, ref: isMirror ? null : this.segHarnessRefs.createRef(key), style: {
12234                            visibility: isVisible ? '' : 'hidden',
12235                            marginTop: isAbsolute ? '' : placement.marginTop,
12236                            top: isAbsolute ? placement.absoluteTop : '',
12237                            left,
12238                            right,
12239                        } }, hasListItemDisplay(seg) ? (h(TableListItemEvent, Object.assign({ seg: seg, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getSegMeta(seg, todayRange)))) : (h(TableBlockEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getSegMeta(seg, todayRange))))));
12240                }
12241            }
12242            return nodes;
12243        }
12244        renderFillSegs(segs, fillType) {
12245            let { isRtl } = this.context;
12246            let { todayRange } = this.props;
12247            let { framePositions } = this.state;
12248            let nodes = [];
12249            if (framePositions) {
12250                for (let seg of segs) {
12251                    let leftRightCss = isRtl ? {
12252                        right: 0,
12253                        left: framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol],
12254                    } : {
12255                        left: 0,
12256                        right: framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol],
12257                    };
12258                    nodes.push(h("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-daygrid-bg-harness", style: leftRightCss }, fillType === 'bg-event' ?
12259                        h(BgEvent, Object.assign({ seg: seg }, getSegMeta(seg, todayRange))) :
12260                        renderFill(fillType)));
12261                }
12262            }
12263            return h(p, {}, ...nodes);
12264        }
12265        updateSizing(isExternalSizingChange) {
12266            let { props, frameElRefs } = this;
12267            if (!props.forPrint &&
12268                props.clientWidth !== null // positioning ready?
12269            ) {
12270                if (isExternalSizingChange) {
12271                    let frameEls = props.cells.map((cell) => frameElRefs.currentMap[cell.key]);
12272                    if (frameEls.length) {
12273                        let originEl = this.rootElRef.current;
12274                        this.setState({
12275                            framePositions: new PositionCache(originEl, frameEls, true, // isHorizontal
12276                            false),
12277                        });
12278                    }
12279                }
12280                const oldInstanceHeights = this.state.eventInstanceHeights;
12281                const newInstanceHeights = this.queryEventInstanceHeights();
12282                const limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
12283                this.safeSetState({
12284                    // HACK to prevent oscillations of events being shown/hidden from max-event-rows
12285                    // Essentially, once you compute an element's height, never null-out.
12286                    // TODO: always display all events, as visibility:hidden?
12287                    eventInstanceHeights: Object.assign(Object.assign({}, oldInstanceHeights), newInstanceHeights),
12288                    maxContentHeight: limitByContentHeight ? this.computeMaxContentHeight() : null,
12289                });
12290            }
12291        }
12292        queryEventInstanceHeights() {
12293            let segElMap = this.segHarnessRefs.currentMap;
12294            let eventInstanceHeights = {};
12295            // get the max height amongst instance segs
12296            for (let key in segElMap) {
12297                let height = Math.round(segElMap[key].getBoundingClientRect().height);
12298                let instanceId = key.split(':')[0]; // deconstruct how renderFgSegs makes the key
12299                eventInstanceHeights[instanceId] = Math.max(eventInstanceHeights[instanceId] || 0, height);
12300            }
12301            return eventInstanceHeights;
12302        }
12303        computeMaxContentHeight() {
12304            let firstKey = this.props.cells[0].key;
12305            let cellEl = this.cellElRefs.currentMap[firstKey];
12306            let fcContainerEl = this.fgElRefs.currentMap[firstKey];
12307            return cellEl.getBoundingClientRect().bottom - fcContainerEl.getBoundingClientRect().top;
12308        }
12309        getCellEls() {
12310            let elMap = this.cellElRefs.currentMap;
12311            return this.props.cells.map((cell) => elMap[cell.key]);
12312        }
12313    }
12314    TableRow.addStateEquality({
12315        eventInstanceHeights: isPropsEqual,
12316    });
12317    function buildMirrorPlacements(mirrorSegs, colPlacements) {
12318        if (!mirrorSegs.length) {
12319            return [];
12320        }
12321        let topsByInstanceId = buildAbsoluteTopHash(colPlacements); // TODO: cache this at first render?
12322        return mirrorSegs.map((seg) => ({
12323            seg,
12324            isVisible: true,
12325            isAbsolute: true,
12326            absoluteTop: topsByInstanceId[seg.eventRange.instance.instanceId],
12327            marginTop: 0,
12328        }));
12329    }
12330    function buildAbsoluteTopHash(colPlacements) {
12331        let topsByInstanceId = {};
12332        for (let placements of colPlacements) {
12333            for (let placement of placements) {
12334                topsByInstanceId[placement.seg.eventRange.instance.instanceId] = placement.absoluteTop;
12335            }
12336        }
12337        return topsByInstanceId;
12338    }
12339
12340    class Table extends DateComponent {
12341        constructor() {
12342            super(...arguments);
12343            this.splitBusinessHourSegs = memoize(splitSegsByRow);
12344            this.splitBgEventSegs = memoize(splitSegsByRow);
12345            this.splitFgEventSegs = memoize(splitSegsByRow);
12346            this.splitDateSelectionSegs = memoize(splitSegsByRow);
12347            this.splitEventDrag = memoize(splitInteractionByRow);
12348            this.splitEventResize = memoize(splitInteractionByRow);
12349            this.rowRefs = new RefMap();
12350            this.handleRootEl = (rootEl) => {
12351                this.rootEl = rootEl;
12352                if (rootEl) {
12353                    this.context.registerInteractiveComponent(this, {
12354                        el: rootEl,
12355                        isHitComboAllowed: this.props.isHitComboAllowed,
12356                    });
12357                }
12358                else {
12359                    this.context.unregisterInteractiveComponent(this);
12360                }
12361            };
12362        }
12363        render() {
12364            let { props } = this;
12365            let { dateProfile, dayMaxEventRows, dayMaxEvents, expandRows } = props;
12366            let rowCnt = props.cells.length;
12367            let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt);
12368            let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);
12369            let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt);
12370            let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt);
12371            let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt);
12372            let eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt);
12373            let limitViaBalanced = dayMaxEvents === true || dayMaxEventRows === true;
12374            // if rows can't expand to fill fixed height, can't do balanced-height event limit
12375            // TODO: best place to normalize these options?
12376            if (limitViaBalanced && !expandRows) {
12377                limitViaBalanced = false;
12378                dayMaxEventRows = null;
12379                dayMaxEvents = null;
12380            }
12381            let classNames = [
12382                'fc-daygrid-body',
12383                limitViaBalanced ? 'fc-daygrid-body-balanced' : 'fc-daygrid-body-unbalanced',
12384                expandRows ? '' : 'fc-daygrid-body-natural', // will height of one row depend on the others?
12385            ];
12386            return (h("div", { className: classNames.join(' '), ref: this.handleRootEl, style: {
12387                    // these props are important to give this wrapper correct dimensions for interactions
12388                    // TODO: if we set it here, can we avoid giving to inner tables?
12389                    width: props.clientWidth,
12390                    minWidth: props.tableMinWidth,
12391                } },
12392                h(NowTimer, { unit: "day" }, (nowDate, todayRange) => (h(p, null,
12393                    h("table", { role: "presentation", className: "fc-scrollgrid-sync-table", style: {
12394                            width: props.clientWidth,
12395                            minWidth: props.tableMinWidth,
12396                            height: expandRows ? props.clientHeight : '',
12397                        } },
12398                        props.colGroupNode,
12399                        h("tbody", { role: "presentation" }, props.cells.map((cells, row) => (h(TableRow, { ref: this.rowRefs.createRef(row), key: cells.length
12400                                ? cells[0].date.toISOString() /* best? or put key on cell? or use diff formatter? */
12401                                : row // in case there are no cells (like when resource view is loading)
12402                            , 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, forPrint: props.forPrint }))))))))));
12403        }
12404        // Hit System
12405        // ----------------------------------------------------------------------------------------------------
12406        prepareHits() {
12407            this.rowPositions = new PositionCache(this.rootEl, this.rowRefs.collect().map((rowObj) => rowObj.getCellEls()[0]), // first cell el in each row. TODO: not optimal
12408            false, true);
12409            this.colPositions = new PositionCache(this.rootEl, this.rowRefs.currentMap[0].getCellEls(), // cell els in first row
12410            true, // horizontal
12411            false);
12412        }
12413        queryHit(positionLeft, positionTop) {
12414            let { colPositions, rowPositions } = this;
12415            let col = colPositions.leftToIndex(positionLeft);
12416            let row = rowPositions.topToIndex(positionTop);
12417            if (row != null && col != null) {
12418                let cell = this.props.cells[row][col];
12419                return {
12420                    dateProfile: this.props.dateProfile,
12421                    dateSpan: Object.assign({ range: this.getCellRange(row, col), allDay: true }, cell.extraDateSpan),
12422                    dayEl: this.getCellEl(row, col),
12423                    rect: {
12424                        left: colPositions.lefts[col],
12425                        right: colPositions.rights[col],
12426                        top: rowPositions.tops[row],
12427                        bottom: rowPositions.bottoms[row],
12428                    },
12429                    layer: 0,
12430                };
12431            }
12432            return null;
12433        }
12434        getCellEl(row, col) {
12435            return this.rowRefs.currentMap[row].getCellEls()[col]; // TODO: not optimal
12436        }
12437        getCellRange(row, col) {
12438            let start = this.props.cells[row][col].date;
12439            let end = addDays(start, 1);
12440            return { start, end };
12441        }
12442    }
12443    function isSegAllDay(seg) {
12444        return seg.eventRange.def.allDay;
12445    }
12446
12447    class DayTableSlicer extends Slicer {
12448        constructor() {
12449            super(...arguments);
12450            this.forceDayIfListItem = true;
12451        }
12452        sliceRange(dateRange, dayTableModel) {
12453            return dayTableModel.sliceRange(dateRange);
12454        }
12455    }
12456
12457    class DayTable extends DateComponent {
12458        constructor() {
12459            super(...arguments);
12460            this.slicer = new DayTableSlicer();
12461            this.tableRef = y();
12462        }
12463        render() {
12464            let { props, context } = this;
12465            return (h(Table, Object.assign({ ref: this.tableRef }, this.slicer.sliceProps(props, props.dateProfile, props.nextDayThreshold, context, props.dayTableModel), { dateProfile: props.dateProfile, cells: props.dayTableModel.cells, colGroupNode: props.colGroupNode, tableMinWidth: props.tableMinWidth, renderRowIntro: props.renderRowIntro, dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, showWeekNumbers: props.showWeekNumbers, expandRows: props.expandRows, headerAlignElRef: props.headerAlignElRef, clientWidth: props.clientWidth, clientHeight: props.clientHeight, forPrint: props.forPrint })));
12466        }
12467    }
12468
12469    class DayTableView extends TableView {
12470        constructor() {
12471            super(...arguments);
12472            this.buildDayTableModel = memoize(buildDayTableModel);
12473            this.headerRef = y();
12474            this.tableRef = y();
12475        }
12476        render() {
12477            let { options, dateProfileGenerator } = this.context;
12478            let { props } = this;
12479            let dayTableModel = this.buildDayTableModel(props.dateProfile, dateProfileGenerator);
12480            let headerContent = options.dayHeaders && (h(DayHeader, { ref: this.headerRef, dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: dayTableModel.rowCnt === 1 }));
12481            let bodyContent = (contentArg) => (h(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 }));
12482            return options.dayMinWidth
12483                ? this.renderHScrollLayout(headerContent, bodyContent, dayTableModel.colCnt, options.dayMinWidth)
12484                : this.renderSimpleLayout(headerContent, bodyContent);
12485        }
12486    }
12487    function buildDayTableModel(dateProfile, dateProfileGenerator) {
12488        let daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
12489        return new DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
12490    }
12491
12492    class TableDateProfileGenerator extends DateProfileGenerator {
12493        // Computes the date range that will be rendered.
12494        buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
12495            let { dateEnv } = this.props;
12496            let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay);
12497            let start = renderRange.start;
12498            let end = renderRange.end;
12499            let endOfWeek;
12500            // year and month views should be aligned with weeks. this is already done for week
12501            if (/^(year|month)$/.test(currentRangeUnit)) {
12502                start = dateEnv.startOfWeek(start);
12503                // make end-of-week if not already
12504                endOfWeek = dateEnv.startOfWeek(end);
12505                if (endOfWeek.valueOf() !== end.valueOf()) {
12506                    end = addWeeks(endOfWeek, 1);
12507                }
12508            }
12509            // ensure 6 weeks
12510            if (this.props.monthMode &&
12511                this.props.fixedWeekCount) {
12512                let rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
12513                diffWeeks(start, end));
12514                end = addWeeks(end, 6 - rowCnt);
12515            }
12516            return { start, end };
12517        }
12518    }
12519
12520    var css_248z$2 = ":root{--fc-daygrid-event-dot-width:8px}.fc-daygrid-day-events:after,.fc-daygrid-day-events:before,.fc-daygri
12520d-day-frame:after,.fc-daygrid-day-frame:before,.fc-daygrid-event-harness:after,.fc-daygrid-event-harness:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-body{position:relative;z-index:1}.fc .fc-daygrid-day.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-daygrid-day-frame{min-height:100%;position:relative}.fc .fc-daygrid-day-top{display:flex;flex-direction:row-reverse}.fc .fc-day-other .fc-daygrid-day-top{opacity:.3}.fc .fc-daygrid-day-number{padding:4px;position:relative;z-index:4}.fc .fc-daygrid-day-events{margin-top:1px}.fc .fc-daygrid-body-balanced .fc-daygrid-day-events{left:0;position:absolute;right:0}.fc .fc-daygrid-body-unbalanced .fc-daygrid-day-events{min-height:2em;position:relative}.fc .fc-daygrid-body-natural .fc-daygrid-day-events{margin-bottom:1em}.fc .fc-daygrid-event-harness{position:relative}.fc .fc-daygrid-event-harness-abs{left:0;position:absolute;right:0;top:0}.fc .fc-daygrid-bg-harness{bottom:0;position:absolute;top:0}.fc .fc-daygrid-day-bg .fc-non-business{z-index:1}.fc .fc-daygrid-day-bg .fc-bg-event{z-index:2}.fc .fc-daygrid-day-bg .fc-highlight{z-index:3}.fc .fc-daygrid-event{margin-top:1px;z-index:6}.fc .fc-daygrid-event.fc-event-mirror{z-index:7}.fc .fc-daygrid-day-bottom{font-size:.85em;padding:2px 3px 0}.fc .fc-daygrid-day-bottom:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-more-link{cursor:pointer;position:relative;z-index:4}.fc .fc-daygrid-week-number{background-color:var(--fc-neutral-bg-color);color:var(--fc-neutral-text-color);min-width:1.5em;padding:2px;position:absolute;text-align:center;top:0;z-index:5}.fc .fc-more-popover .fc-popover-body{min-width:220px;padding:10px}.fc-direction-ltr .fc-daygrid-event.fc-event-start,.fc-direction-rtl .fc-daygrid-event.fc-event-end{margin-left:2px}.fc-direction-ltr .fc-daygrid-event.fc-event-end,.fc-direction-rtl .fc-daygrid-event.fc-event-start{margin-right:2px}.fc-direction-ltr .fc-daygrid-week-number{border-radius:0 0 3px 0;left:0}.fc-direction-rtl .fc-daygrid-week-number{border-radius:0 0 0 3px;right:0}
vendor: 59,969 bytes, lines 12520-13679
12520.fc-liquid-hack .fc-daygrid-day-frame{position:static}.fc-daygrid-event{border-radius:3px;font-size:var(--fc-small-font-size);position:relative;white-space:nowrap}.fc-daygrid-block-event .fc-event-time{font-weight:700}.fc-daygrid-block-event .fc-event-time,.fc-daygrid-block-event .fc-event-title{padding:1px}.fc-daygrid-dot-event{align-items:center;display:flex;padding:2px 0}.fc-daygrid-dot-event .fc-event-title{flex-grow:1;flex-shrink:1;font-weight:700;min-width:0;overflow:hidden}.fc-daygrid-dot-event.fc-event-mirror,.fc-daygrid-dot-event:hover{background:rgba(0,0,0,.1)}.fc-daygrid-dot-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-daygrid-event-dot{border:calc(var(--fc-daygrid-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-daygrid-event-dot-width)/2);box-sizing:content-box;height:0;margin:0 4px;width:0}.fc-direction-ltr .fc-daygrid-event .fc-event-time{margin-right:3px}.fc-direction-rtl .fc-daygrid-event .fc-event-time{margin-left:3px}";
12521    injectStyles(css_248z$2);
12522
12523    var index$2 = createPlugin({
12524        name: '@fullcalendar/daygrid',
12525        initialView: 'dayGridMonth',
12526        views: {
12527            dayGrid: {
12528                component: DayTableView,
12529                dateProfileGeneratorClass: TableDateProfileGenerator,
12530            },
12531            dayGridDay: {
12532                type: 'dayGrid',
12533                duration: { days: 1 },
12534            },
12535            dayGridWeek: {
12536                type: 'dayGrid',
12537                duration: { weeks: 1 },
12538            },
12539            dayGridMonth: {
12540                type: 'dayGrid',
12541                duration: { months: 1 },
12542                monthMode: true,
12543                fixedWeekCount: true,
12544            },
12545        },
12546    });
12547
12548    class AllDaySplitter extends Splitter {
12549        getKeyInfo() {
12550            return {
12551                allDay: {},
12552                timed: {},
12553            };
12554        }
12555        getKeysForDateSpan(dateSpan) {
12556            if (dateSpan.allDay) {
12557                return ['allDay'];
12558            }
12559            return ['timed'];
12560        }
12561        getKeysForEventDef(eventDef) {
12562            if (!eventDef.allDay) {
12563                return ['timed'];
12564            }
12565            if (hasBgRendering(eventDef)) {
12566                return ['timed', 'allDay'];
12567            }
12568            return ['allDay'];
12569        }
12570    }
12571
12572    const DEFAULT_SLAT_LABEL_FORMAT = createFormatter({
12573        hour: 'numeric',
12574        minute: '2-digit',
12575        omitZeroMinute: true,
12576        meridiem: 'short',
12577    });
12578    function TimeColsAxisCell(props) {
12579        let classNames = [
12580            'fc-timegrid-slot',
12581            'fc-timegrid-slot-label',
12582            props.isLabeled ? 'fc-scrollgrid-shrink' : 'fc-timegrid-slot-minor',
12583        ];
12584        return (h(ViewContextType.Consumer, null, (context) => {
12585            if (!props.isLabeled) {
12586                return (h("td", { className: classNames.join(' '), "data-time": props.isoTimeStr }));
12587            }
12588            let { dateEnv, options, viewApi } = context;
12589            let labelFormat = // TODO: fully pre-parse
12590             options.slotLabelFormat == null ? DEFAULT_SLAT_LABEL_FORMAT :
12591                Array.isArray(options.slotLabelFormat) ? createFormatter(options.slotLabelFormat[0]) :
12592                    createFormatter(options.slotLabelFormat);
12593            let renderProps = {
12594                level: 0,
12595                time: props.time,
12596                date: dateEnv.toDate(props.date),
12597                view: viewApi,
12598                text: dateEnv.format(props.date, labelFormat),
12599            };
12600            return (h(ContentContainer, { elTag: "td", elClasses: classNames, elAttrs: {
12601                    'data-time': props.isoTimeStr,
12602                }, renderProps: renderProps, generatorName: "slotLabelContent", generator: options.slotLabelContent || renderInnerContent$1, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (h("div", { className: "fc-timegrid-slot-label-frame fc-scrollgrid-shrink-frame" },
12603                h(InnerContent, { elTag: "div", elClasses: [
12604                        'fc-timegrid-slot-label-cushion',
12605                        'fc-scrollgrid-shrink-cushion',
12606                    ] })))));
12607        }));
12608    }
12609    function renderInnerContent$1(props) {
12610        return props.text;
12611    }
12612
12613    class TimeBodyAxis extends BaseComponent {
12614        render() {
12615            return this.props.slatMetas.map((slatMeta) => (h("tr", { key: slatMeta.key },
12616                h(TimeColsAxisCell, Object.assign({}, slatMeta)))));
12617        }
12618    }
12619
12620    const DEFAULT_WEEK_NUM_FORMAT = createFormatter({ week: 'short' });
12621    const AUTO_ALL_DAY_MAX_EVENT_ROWS = 5;
12622    class TimeColsView extends DateComponent {
12623        constructor() {
12624            super(...arguments);
12625            this.allDaySplitter = new AllDaySplitter(); // for use by subclasses
12626            this.headerElRef = y();
12627            this.rootElRef = y();
12628            this.scrollerElRef = y();
12629            this.state = {
12630                slatCoords: null,
12631            };
12632            this.handleScrollTopRequest = (scrollTop) => {
12633                let scrollerEl = this.scrollerElRef.current;
12634                if (scrollerEl) { // TODO: not sure how this could ever be null. weirdness with the reducer
12635                    scrollerEl.scrollTop = scrollTop;
12636                }
12637            };
12638            /* Header Render Methods
12639            ------------------------------------------------------------------------------------------------------------------*/
12640            this.renderHeadAxis = (rowKey, frameHeight = '') => {
12641                let { options } = this.context;
12642                let { dateProfile } = this.props;
12643                let range = dateProfile.renderRange;
12644                let dayCnt = diffDays(range.start, range.end);
12645                // only do in day views (to avoid doing in week views that dont need it)
12646                let navLinkAttrs = (dayCnt === 1)
12647                    ? buildNavLinkAttrs(this.context, range.start, 'week')
12648                    : {};
12649                if (options.weekNumbers && rowKey === 'day') {
12650                    return (h(WeekNumberContainer, { elTag: "th", elClasses: [
12651                            'fc-timegrid-axis',
12652                            'fc-scrollgrid-shrink',
12653                        ], elAttrs: {
12654                            'aria-hidden': true,
12655                        }, date: range.start, defaultFormat: DEFAULT_WEEK_NUM_FORMAT }, (InnerContent) => (h("div", { className: [
12656                            'fc-timegrid-axis-frame',
12657                            'fc-scrollgrid-shrink-frame',
12658                            'fc-timegrid-axis-frame-liquid',
12659                        ].join(' '), style: { height: frameHeight } },
12660                        h(InnerContent, { elTag: "a", elClasses: [
12661                                'fc-timegrid-axis-cushion',
12662                                'fc-scrollgrid-shrink-cushion',
12663                                'fc-scrollgrid-sync-inner',
12664                            ], elAttrs: navLinkAttrs })))));
12665                }
12666                return (h("th", { "aria-hidden": true, className: "fc-timegrid-axis" },
12667                    h("div", { className: "fc-timegrid-axis-frame", style: { height: frameHeight } })));
12668            };
12669            /* Table Component Render Methods
12670            ------------------------------------------------------------------------------------------------------------------*/
12671            // only a one-way height sync. we don't send the axis inner-content height to the DayGrid,
12672            // but DayGrid still needs to have classNames on inner elements in order to measure.
12673            this.renderTableRowAxis = (rowHeight) => {
12674                let { options, viewApi } = this.context;
12675                let renderProps = {
12676                    text: options.allDayText,
12677                    view: viewApi,
12678                };
12679                return (
12680                // TODO: make reusable hook. used in list view too
12681                h(ContentContainer, { elTag: "td", elClasses: [
12682                        'fc-timegrid-axis',
12683                        'fc-scrollgrid-shrink',
12684                    ], elAttrs: {
12685                        'aria-hidden': true,
12686                    }, renderProps: renderProps, generatorName: "allDayContent", generator: options.allDayContent || renderAllDayInner$1, classNameGenerator: options.allDayClassNames, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }, (InnerContent) => (h("div", { className: [
12687                        'fc-timegrid-axis-frame',
12688                        'fc-scrollgrid-shrink-frame',
12689                        rowHeight == null ? ' fc-timegrid-axis-frame-liquid' : '',
12690                    ].join(' '), style: { height: rowHeight } },
12691                    h(InnerContent, { elTag: "span", elClasses: [
12692                            'fc-timegrid-axis-cushion',
12693                            'fc-scrollgrid-shrink-cushion',
12694                            'fc-scrollgrid-sync-inner',
12695                        ] })))));
12696            };
12697            this.handleSlatCoords = (slatCoords) => {
12698                this.setState({ slatCoords });
12699            };
12700        }
12701        // rendering
12702        // ----------------------------------------------------------------------------------------------------
12703        renderSimpleLayout(headerRowContent, allDayContent, timeContent) {
12704            let { context, props } = this;
12705            let sections = [];
12706            let stickyHeaderDates = getStickyHeaderDates(context.options);
12707            if (headerRowContent) {
12708                sections.push({
12709                    type: 'header',
12710                    key: 'header',
12711                    isSticky: stickyHeaderDates,
12712                    chunk: {
12713                        elRef: this.headerElRef,
12714                        tableClassName: 'fc-col-header',
12715                        rowContent: headerRowContent,
12716                    },
12717                });
12718            }
12719            if (allDayContent) {
12720                sections.push({
12721                    type: 'body',
12722                    key: 'all-day',
12723                    chunk: { content: allDayContent },
12724                });
12725                sections.push({
12726                    type: 'body',
12727                    key: 'all-day-divider',
12728                    outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?
12729                    h("tr", { role: "presentation", className: "fc-scrollgrid-section" },
12730                        h("td", { className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),
12731                });
12732            }
12733            sections.push({
12734                type: 'body',
12735                key: 'body',
12736                liquid: true,
12737                expandRows: Boolean(context.options.expandRows),
12738                chunk: {
12739                    scrollerElRef: this.scrollerElRef,
12740                    content: timeContent,
12741                },
12742            });
12743            return (h(ViewContainer$1, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },
12744                h(SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [{ width: 'shrink' }], sections: sections })));
12745        }
12746        renderHScrollLayout(headerRowContent, allDayContent, timeContent, colCnt, dayMinWidth, slatMetas, slatCoords) {
12747            let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
12748            if (!ScrollGrid) {
12749                throw new Error('No ScrollGrid implementation');
12750            }
12751            let { context, props } = this;
12752            let stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options);
12753            let stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options);
12754            let sections = [];
12755            if (headerRowContent) {
12756                sections.push({
12757                    type: 'header',
12758                    key: 'header',
12759                    isSticky: stickyHeaderDates,
12760                    syncRowHeights: true,
12761                    chunks: [
12762                        {
12763                            key: 'axis',
12764                            rowContent: (arg) => (h("tr", { role: "presentation" }, this.renderHeadAxis('day', arg.rowSyncHeights[0]))),
12765                        },
12766                        {
12767                            key: 'cols',
12768                            elRef: this.headerElRef,
12769                            tableClassName: 'fc-col-header',
12770                            rowContent: headerRowContent,
12771                        },
12772                    ],
12773                });
12774            }
12775            if (allDayContent) {
12776                sections.push({
12777                    type: 'body',
12778                    key: 'all-day',
12779                    syncRowHeights: true,
12780                    chunks: [
12781                        {
12782                            key: 'axis',
12783                            rowContent: (contentArg) => (h("tr", { role: "presentation" }, this.renderTableRowAxis(contentArg.rowSyncHeights[0]))),
12784                        },
12785                        {
12786                            key: 'cols',
12787                            content: allDayContent,
12788                        },
12789                    ],
12790                });
12791                sections.push({
12792                    key: 'all-day-divider',
12793                    type: 'body',
12794                    outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?
12795                    h("tr", { role: "presentation", className: "fc-scrollgrid-section" },
12796                        h("td", { colSpan: 2, className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),
12797                });
12798            }
12799            let isNowIndicator = context.options.nowIndicator;
12800            sections.push({
12801                type: 'body',
12802                key: 'body',
12803                liquid: true,
12804                expandRows: Boolean(context.options.expandRows),
12805                chunks: [
12806                    {
12807                        key: 'axis',
12808                        content: (arg) => (
12809                        // TODO: make this now-indicator arrow more DRY with TimeColsContent
12810                        h("div", { className: "fc-timegrid-axis-chunk" },
12811                            h("table", { "aria-hidden": true, style: { height: arg.expandRows ? arg.clientHeight : '' } },
12812                                arg.tableColGroupNode,
12813                                h("tbody", null,
12814                                    h(TimeBodyAxis, { slatMetas: slatMetas }))),
12815                            h("div", { className: "fc-timegrid-now-indicator-container" },
12816                                h(NowTimer, { unit: isNowIndicator ? 'minute' : 'day' /* hacky */ }, (nowDate) => {
12817                                    let nowIndicatorTop = isNowIndicator &&
12818                                        slatCoords &&
12819                                        slatCoords.safeComputeTop(nowDate); // might return void
12820                                    if (typeof nowIndicatorTop === 'number') {
12821                                        return (h(NowIndicatorContainer, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: nowDate }));
12822                                    }
12823                                    return null;
12824                                })))),
12825                    },
12826                    {
12827                        key: 'cols',
12828                        scrollerElRef: this.scrollerElRef,
12829                        content: timeContent,
12830                    },
12831                ],
12832            });
12833            if (stickyFooterScrollbar) {
12834                sections.push({
12835                    key: 'footer',
12836                    type: 'footer',
12837                    isSticky: true,
12838                    chunks: [
12839                        {
12840                            key: 'axis',
12841                            content: renderScrollShim,
12842                        },
12843                        {
12844                            key: 'cols',
12845                            content: renderScrollShim,
12846                        },
12847                    ],
12848                });
12849            }
12850            return (h(ViewContainer$1, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },
12851                h(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: false, colGroups: [
12852                        { width: 'shrink', cols: [{ width: 'shrink' }] },
12853                        { cols: [{ span: colCnt, minWidth: dayMinWidth }] },
12854                    ], sections: sections })));
12855        }
12856        /* Dimensions
12857        ------------------------------------------------------------------------------------------------------------------*/
12858        getAllDayMaxEventProps() {
12859            let { dayMaxEvents, dayMaxEventRows } = this.context.options;
12860            if (dayMaxEvents === true || dayMaxEventRows === true) { // is auto?
12861                dayMaxEvents = undefined;
12862                dayMaxEventRows = AUTO_ALL_DAY_MAX_EVENT_ROWS; // make sure "auto" goes to a real number
12863            }
12864            return { dayMaxEvents, dayMaxEventRows };
12865        }
12866    }
12867    function renderAllDayInner$1(renderProps) {
12868        return renderProps.text;
12869    }
12870
12871    class TimeColsSlatsCoords {
12872        constructor(positions, dateProfile, slotDuration) {
12873            this.positions = positions;
12874            this.dateProfile = dateProfile;
12875            this.slotDuration = slotDuration;
12876        }
12877        safeComputeTop(date) {
12878            let { dateProfile } = this;
12879            if (rangeContainsMarker(dateProfile.currentRange, date)) {
12880                let startOfDayDate = startOfDay(date);
12881                let timeMs = date.valueOf() - startOfDayDate.valueOf();
12882                if (timeMs >= asRoughMs(dateProfile.slotMinTime) &&
12883                    timeMs < asRoughMs(dateProfile.slotMaxTime)) {
12884                    return this.computeTimeTop(createDuration(timeMs));
12885                }
12886            }
12887            return null;
12888        }
12889        // Computes the top coordinate, relative to the bounds of the grid, of the given date.
12890        // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.
12891        computeDateTop(when, startOfDayDate) {
12892            if (!startOfDayDate) {
12893                startOfDayDate = startOfDay(when);
12894            }
12895            return this.computeTimeTop(createDuration(when.valueOf() - startOfDayDate.valueOf()));
12896        }
12897        // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).
12898        // This is a makeshify way to compute the time-top. Assumes all slatMetas dates are uniform.
12899        // Eventually allow computation with arbirary slat dates.
12900        computeTimeTop(duration) {
12901            let { positions, dateProfile } = this;
12902            let len = positions.els.length;
12903            // floating-point value of # of slots covered
12904            let slatCoverage = (duration.milliseconds - asRoughMs(dateProfile.slotMinTime)) / asRoughMs(this.slotDuration);
12905            let slatIndex;
12906            let slatRemainder;
12907            // compute a floating-point number for how many slats should be progressed through.
12908            // from 0 to number of slats (inclusive)
12909            // constrained because slotMinTime/slotMaxTime might be customized.
12910            slatCoverage = Math.max(0, slatCoverage);
12911            slatCoverage = Math.min(len, slatCoverage);
12912            // an integer index of the furthest whole slat
12913            // from 0 to number slats (*exclusive*, so len-1)
12914            slatIndex = Math.floor(slatCoverage);
12915            slatIndex = Math.min(slatIndex, len - 1);
12916            // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.
12917            // could be 1.0 if slatCoverage is covering *all* the slots
12918            slatRemainder = slatCoverage - slatIndex;
12919            return positions.tops[slatIndex] +
12920                positions.getHeight(slatIndex) * slatRemainder;
12921        }
12922    }
12923
12924    class TimeColsSlatsBody extends BaseComponent {
12925        render() {
12926            let { props, context } = this;
12927            let { options } = context;
12928            let { slatElRefs } = props;
12929            return (h("tbody", null, props.slatMetas.map((slatMeta, i) => {
12930                let renderProps = {
12931                    time: slatMeta.time,
12932                    date: context.dateEnv.toDate(slatMeta.date),
12933                    view: context.viewApi,
12934                };
12935                return (h("tr", { key: slatMeta.key, ref: slatElRefs.createRef(slatMeta.key) },
12936                    props.axis && (h(TimeColsAxisCell, Object.assign({}, slatMeta))),
12937                    h(ContentContainer, { elTag: "td", elClasses: [
12938                            'fc-timegrid-slot',
12939                            'fc-timegrid-slot-lane',
12940                            !slatMeta.isLabeled && 'fc-timegrid-slot-minor',
12941                        ], elAttrs: {
12942                            'data-time': slatMeta.isoTimeStr,
12943                        }, renderProps: renderProps, generatorName: "slotLaneContent", generator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount })));
12944            })));
12945        }
12946    }
12947
12948    /*
12949    for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL.
12950    */
12951    class TimeColsSlats extends BaseComponent {
12952        constructor() {
12953            super(...arguments);
12954            this.rootElRef = y();
12955            this.slatElRefs = new RefMap();
12956        }
12957        render() {
12958            let { props, context } = this;
12959            return (h("div", { ref: this.rootElRef, className: "fc-timegrid-slots" },
12960                h("table", { "aria-hidden": true, className: context.theme.getClass('table'), style: {
12961                        minWidth: props.tableMinWidth,
12962                        width: props.clientWidth,
12963                        height: props.minHeight,
12964                    } },
12965                    props.tableColGroupNode /* relies on there only being a single <col> for the axis */,
12966                    h(TimeColsSlatsBody, { slatElRefs: this.slatElRefs, axis: props.axis, slatMetas: props.slatMetas }))));
12967        }
12968        componentDidMount() {
12969            this.updateSizing();
12970        }
12971        componentDidUpdate() {
12972            this.updateSizing();
12973        }
12974        componentWillUnmount() {
12975            if (this.props.onCoords) {
12976                this.props.onCoords(null);
12977            }
12978        }
12979        updateSizing() {
12980            let { context, props } = this;
12981            if (props.onCoords &&
12982                props.clientWidth !== null // means sizing has stabilized
12983            ) {
12984                let rootEl = this.rootElRef.current;
12985                if (rootEl.offsetHeight) { // not hidden by css
12986                    props.onCoords(new TimeColsSlatsCoords(new PositionCache(this.rootElRef.current, collectSlatEls(this.slatElRefs.currentMap, props.slatMetas), false, true), this.props.dateProfile, context.options.slotDuration));
12987                }
12988            }
12989        }
12990    }
12991    function collectSlatEls(elMap, slatMetas) {
12992        return slatMetas.map((slatMeta) => elMap[slatMeta.key]);
12993    }
12994
12995    function splitSegsByCol(segs, colCnt) {
12996        let segsByCol = [];
12997        let i;
12998        for (i = 0; i < colCnt; i += 1) {
12999            segsByCol.push([]);
13000        }
13001        if (segs) {
13002            for (i = 0; i < segs.length; i += 1) {
13003                segsByCol[segs[i].col].push(segs[i]);
13004            }
13005        }
13006        return segsByCol;
13007    }
13008    function splitInteractionByCol(ui, colCnt) {
13009        let byRow = [];
13010        if (!ui) {
13011            for (let i = 0; i < colCnt; i += 1) {
13012                byRow[i] = null;
13013            }
13014        }
13015        else {
13016            for (let i = 0; i < colCnt; i += 1) {
13017                byRow[i] = {
13018                    affectedInstances: ui.affectedInstances,
13019                    isEvent: ui.isEvent,
13020                    segs: [],
13021                };
13022            }
13023            for (let seg of ui.segs) {
13024                byRow[seg.col].segs.push(seg);
13025            }
13026        }
13027        return byRow;
13028    }
13029
13030    class TimeColMoreLink extends BaseComponent {
13031        render() {
13032            let { props } = this;
13033            return (h(MoreLinkContainer, { elClasses: ['fc-timegrid-more-link'], elStyle: {
13034                    top: props.top,
13035                    bottom: props.bottom,
13036                }, allDayDate: null, moreCnt: props.hiddenSegs.length, allSegs: props.hiddenSegs, hiddenSegs: props.hiddenSegs, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, todayRange: props.todayRange, popoverContent: () => renderPlainFgSegs(props.hiddenSegs, props), defaultGenerator: renderMoreLinkInner }, (InnerContent) => (h(InnerContent, { elTag: "div", elClasses: ['fc-timegrid-more-link-inner', 'fc-sticky'] }))));
13037        }
13038    }
13039    function renderMoreLinkInner(props) {
13040        return props.shortText;
13041    }
13042
13043    // segInputs assumed sorted
13044    function buildPositioning(segInputs, strictOrder, maxStackCnt) {
13045        let hierarchy = new SegHierarchy();
13046        if (strictOrder != null) {
13047            hierarchy.strictOrder = strictOrder;
13048        }
13049        if (maxStackCnt != null) {
13050            hierarchy.maxStackCnt = maxStackCnt;
13051        }
13052        let hiddenEntries = hierarchy.addSegs(segInputs);
13053        let hiddenGroups = groupIntersectingEntries(hiddenEntries);
13054        let web = buildWeb(hierarchy);
13055        web = stretchWeb(web, 1); // all levelCoords/thickness will have 0.0-1.0
13056        let segRects = webToRects(web);
13057        return { segRects, hiddenGroups };
13058    }
13059    function buildWeb(hierarchy) {
13060        const { entriesByLevel } = hierarchy;
13061        const buildNode = cacheable((level, lateral) => level + ':' + lateral, (level, lateral) => {
13062            let siblingRange = findNextLevelSegs(hierarchy, level, lateral);
13063            let nextLevelRes = buildNodes(siblingRange, buildNode);
13064            let entry = entriesByLevel[level][lateral];
13065            return [
13066                Object.assign(Object.assign({}, entry), { nextLevelNodes: nextLevelRes[0] }),
13067                entry.thickness + nextLevelRes[1], // the pressure builds
13068            ];
13069        });
13070        return buildNodes(entriesByLevel.length
13071            ? { level: 0, lateralStart: 0, lateralEnd: entriesByLevel[0].length }
13072            : null, buildNode)[0];
13073    }
13074    function buildNodes(siblingRange, buildNode) {
13075        if (!siblingRange) {
13076            return [[], 0];
13077        }
13078        let { level, lateralStart, lateralEnd } = siblingRange;
13079        let lateral = lateralStart;
13080        let pairs = [];
13081        while (lateral < lateralEnd) {
13082            pairs.push(buildNode(level, lateral));
13083            lateral += 1;
13084        }
13085        pairs.sort(cmpDescPressures);
13086        return [
13087            pairs.map(extractNode),
13088            pairs[0][1], // first item's pressure
13089        ];
13090    }
13091    function cmpDescPressures(a, b) {
13092        return b[1] - a[1];
13093    }
13094    function extractNode(a) {
13095        return a[0];
13096    }
13097    function findNextLevelSegs(hierarchy, subjectLevel, subjectLateral) {
13098        let { levelCoords, entriesByLevel } = hierarchy;
13099        let subjectEntry = entriesByLevel[subjectLevel][subjectLateral];
13100        let afterSubject = levelCoords[subjectLevel] + subjectEntry.thickness;
13101        let levelCnt = levelCoords.length;
13102        let level = subjectLevel;
13103        // skip past levels that are too high up
13104        for (; level < levelCnt && levelCoords[level] < afterSubject; level += 1)
13105            ; // do nothing
13106        for (; level < levelCnt; level += 1) {
13107            let entries = entriesByLevel[level];
13108            let entry;
13109            let searchIndex = binarySearch(entries, subjectEntry.span.start, getEntrySpanEnd);
13110            let lateralStart = searchIndex[0] + searchIndex[1]; // if exact match (which doesn't collide), go to next one
13111            let lateralEnd = lateralStart;
13112            while ( // loop through entries that horizontally intersect
13113            (entry = entries[lateralEnd]) && // but not past the whole seg list
13114                entry.span.start < subjectEntry.span.end) {
13115                lateralEnd += 1;
13116            }
13117            if (lateralStart < lateralEnd) {
13118                return { level, lateralStart, lateralEnd };
13119            }
13120        }
13121        return null;
13122    }
13123    function stretchWeb(topLevelNodes, totalThickness) {
13124        const stretchNode = cacheable((node, startCoord, prevThickness) => buildEntryKey(node), (node, startCoord, prevThickness) => {
13125            let { nextLevelNodes, thickness } = node;
13126            let allThickness = thickness + prevThickness;
13127            let thicknessFraction = thickness / allThickness;
13128            let endCoord;
13129            let newChildren = [];
13130            if (!nextLevelNodes.length) {
13131                endCoord = totalThickness;
13132            }
13133            else {
13134                for (let childNode of nextLevelNodes) {
13135                    if (endCoord === undefined) {
13136                        let res = stretchNode(childNode, startCoord, allThickness);
13137                        endCoord = res[0];
13138                        newChildren.push(res[1]);
13139                    }
13140                    else {
13141                        let res = stretchNode(childNode, endCoord, 0);
13142                        newChildren.push(res[1]);
13143                    }
13144                }
13145            }
13146            let newThickness = (endCoord - startCoord) * thicknessFraction;
13147            return [endCoord - newThickness, Object.assign(Object.assign({}, node), { thickness: newThickness, nextLevelNodes: newChildren })];
13148        });
13149        return topLevelNodes.map((node) => stretchNode(node, 0, 0)[1]);
13150    }
13151    // not sorted in any particular order
13152    function webToRects(topLevelNodes) {
13153        let rects = [];
13154        const processNode = cacheable((node, levelCoord, stackDepth) => buildEntryKey(node), (node, levelCoord, stackDepth) => {
13155            let rect = Object.assign(Object.assign({}, node), { levelCoord,
13156                stackDepth, stackForward: 0 });
13157            rects.push(rect);
13158            return (rect.stackForward = processNodes(node.nextLevelNodes, levelCoord + node.thickness, stackDepth + 1) + 1);
13159        });
13160        function processNodes(nodes, levelCoord, stackDepth) {
13161            let stackForward = 0;
13162            for (let node of nodes) {
13163                stackForward = Math.max(processNode(node, levelCoord, stackDepth), stackForward);
13164            }
13165            return stackForward;
13166        }
13167        processNodes(topLevelNodes, 0, 0);
13168        return rects; // TODO: sort rects by levelCoord to be consistent with toRects?
13169    }
13170    // TODO: move to general util
13171    function cacheable(keyFunc, workFunc) {
13172        const cache = {};
13173        return (...args) => {
13174            let key = keyFunc(...args);
13175            return (key in cache)
13176                ? cache[key]
13177                : (cache[key] = workFunc(...args));
13178        };
13179    }
13180
13181    function computeSegVCoords(segs, colDate, slatCoords = null, eventMinHeight = 0) {
13182        let vcoords = [];
13183        if (slatCoords) {
13184            for (let i = 0; i < segs.length; i += 1) {
13185                let seg = segs[i];
13186                let spanStart = slatCoords.computeDateTop(seg.start, colDate);
13187                let spanEnd = Math.max(spanStart + (eventMinHeight || 0), // :(
13188                slatCoords.computeDateTop(seg.end, colDate));
13189                vcoords.push({
13190                    start: Math.round(spanStart),
13191                    end: Math.round(spanEnd), //
13192                });
13193            }
13194        }
13195        return vcoords;
13196    }
13197    function computeFgSegPlacements(segs, segVCoords, // might not have for every seg
13198    eventOrderStrict, eventMaxStack) {
13199        let segInputs = [];
13200        let dumbSegs = []; // segs without coords
13201        for (let i = 0; i < segs.length; i += 1) {
13202            let vcoords = segVCoords[i];
13203            if (vcoords) {
13204                segInputs.push({
13205                    index: i,
13206                    thickness: 1,
13207                    span: vcoords,
13208                });
13209            }
13210            else {
13211                dumbSegs.push(segs[i]);
13212            }
13213        }
13214        let { segRects, hiddenGroups } = buildPositioning(segInputs, eventOrderStrict, eventMaxStack);
13215        let segPlacements = [];
13216        for (let segRect of segRects) {
13217            segPlacements.push({
13218                seg: segs[segRect.index],
13219                rect: segRect,
13220            });
13221        }
13222        for (let dumbSeg of dumbSegs) {
13223            segPlacements.push({ seg: dumbSeg, rect: null });
13224        }
13225        return { segPlacements, hiddenGroups };
13226    }
13227
13228    const DEFAULT_TIME_FORMAT$1 = createFormatter({
13229        hour: 'numeric',
13230        minute: '2-digit',
13231        meridiem: false,
13232    });
13233    class TimeColEvent extends BaseComponent {
13234        render() {
13235            return (h(StandardEvent, Object.assign({}, this.props, { elClasses: [
13236                    'fc-timegrid-event',
13237                    'fc-v-event',
13238                    this.props.isShort && 'fc-timegrid-event-short',
13239                ], defaultTimeFormat: DEFAULT_TIME_FORMAT$1 })));
13240        }
13241    }
13242
13243    class TimeCol extends BaseComponent {
13244        constructor() {
13245            super(...arguments);
13246            this.sortEventSegs = memoize(sortEventSegs);
13247        }
13248        // TODO: memoize event-placement?
13249        render() {
13250            let { props, context } = this;
13251            let { options } = context;
13252            let isSelectMirror = options.selectMirror;
13253            let mirrorSegs = // yuck
13254             (props.eventDrag && props.eventDrag.segs) ||
13255                (props.eventResize && props.eventResize.segs) ||
13256                (isSelectMirror && props.dateSelectionSegs) ||
13257                [];
13258            let interactionAffectedInstances = // TODO: messy way to compute this
13259             (props.eventDrag && props.eventDrag.affectedInstances) ||
13260                (props.eventResize && props.eventResize.affectedInstances) ||
13261                {};
13262            let sortedFgSegs = this.sortEventSegs(props.fgEventSegs, options.eventOrder);
13263            return (h(DayCellContainer, { elTag: "td", elRef: props.elRef, elClasses: [
13264                    'fc-timegrid-col',
13265                    ...(props.extraClassNames || []),
13266                ], elAttrs: Object.assign({ role: 'gridcell' }, props.extraDataAttrs), date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, extraRenderProps: props.extraRenderProps }, (InnerContent) => (h("div", { className: "fc-timegrid-col-frame" },
13267                h("div", { className: "fc-timegrid-col-bg" },
13268                    this.renderFillSegs(props.businessHourSegs, 'non-business'),
13269                    this.renderFillSegs(props.bgEventSegs, 'bg-event'),
13270                    this.renderFillSegs(props.dateSelectionSegs, 'highlight')),
13271                h("div", { className: "fc-timegrid-col-events" }, this.renderFgSegs(sortedFgSegs, interactionAffectedInstances, false, false, false)),
13272                h("div", { className: "fc-timegrid-col-events" }, this.renderFgSegs(mirrorSegs, {}, Boolean(props.eventDrag), Boolean(props.eventResize), Boolean(isSelectMirror))),
13273                h("div", { className: "fc-timegrid-now-indicator-container" }, this.renderNowIndicator(props.nowIndicatorSegs)),
13274                hasCustomDayCellContent(options) && (h(InnerContent, { elTag: "div", elClasses: ['fc-timegrid-col-misc'] }))))));
13275        }
13276        renderFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting) {
13277            let { props } = this;
13278            if (props.forPrint) {
13279                return renderPlainFgSegs(sortedFgSegs, props);
13280            }
13281            return this.renderPositionedFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting);
13282        }
13283        renderPositionedFgSegs(segs, // if not mirror, needs to be sorted
13284        segIsInvisible, isDragging, isResizing, isDateSelecting) {
13285            let { eventMaxStack, eventShortHeight, eventOrderStrict, eventMinHeight } = this.context.options;
13286            let { date, slatCoords, eventSelection, todayRange, nowDate } = this.props;
13287            let isMirror = isDragging || isResizing || isDateSelecting;
13288            let segVCoords = computeSegVCoords(segs, date, slatCoords, eventMinHeight);
13289            let { segPlacements, hiddenGroups } = computeFgSegPlacements(segs, segVCoords, eventOrderStrict, eventMaxStack);
13290            return (h(p, null,
13291                this.renderHiddenGroups(hiddenGroups, segs),
13292                segPlacements.map((segPlacement) => {
13293                    let { seg, rect } = segPlacement;
13294                    let instanceId = seg.eventRange.instance.instanceId;
13295                    let isVisible = isMirror || Boolean(!segIsInvisible[instanceId] && rect);
13296                    let vStyle = computeSegVStyle(rect && rect.span);
13297                    let hStyle = (!isMirror && rect) ? this.computeSegHStyle(rect) : { left: 0, right: 0 };
13298                    let isInset = Boolean(rect) && rect.stackForward > 0;
13299                    let isShort = Boolean(rect) && (rect.span.end - rect.span.start) < eventShortHeight; // look at other places for this problem
13300                    return (h("div", { className: 'fc-timegrid-event-harness' +
13301                            (isInset ? ' fc-timegrid-event-harness-inset' : ''), key: instanceId, style: Object.assign(Object.assign({ visibility: isVisible ? '' : 'hidden' }, vStyle), hStyle) },
13302                        h(TimeColEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, isShort: isShort }, getSegMeta(seg, todayRange, nowDate)))));
13303                })));
13304        }
13305        // will already have eventMinHeight applied because segInputs already had it
13306        renderHiddenGroups(hiddenGroups, segs) {
13307            let { extraDateSpan, dateProfile, todayRange, nowDate, eventSelection, eventDrag, eventResize } = this.props;
13308            return (h(p, null, hiddenGroups.map((hiddenGroup) => {
13309                let positionCss = computeSegVStyle(hiddenGroup.span);
13310                let hiddenSegs = compileSegsFromEntries(hiddenGroup.entries, segs);
13311                return (h(TimeColMoreLink, { key: buildIsoString(computeEarliestSegStart(hiddenSegs)), hiddenSegs: hiddenSegs, top: positionCss.top, bottom: positionCss.bottom, extraDateSpan: extraDateSpan, dateProfile: dateProfile, todayRange: todayRange, nowDate: nowDate, eventSelection: eventSelection, eventDrag: eventDrag, eventResize: eventResize }));
13312            })));
13313        }
13314        renderFillSegs(segs, fillType) {
13315            let { props, context } = this;
13316            let segVCoords = computeSegVCoords(segs, props.date, props.slatCoords, context.options.eventMinHeight); // don't assume all populated
13317            let children = segVCoords.map((vcoords, i) => {
13318                let seg = segs[i];
13319                return (h("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-timegrid-bg-harness", style: computeSegVStyle(vcoords) }, fillType === 'bg-event' ?
13320                    h(BgEvent, Object.assign({ seg: seg }, getSegMeta(seg, props.todayRange, props.nowDate))) :
13321                    renderFill(fillType)));
13322            });
13323            return h(p, null, children);
13324        }
13325        renderNowIndicator(segs) {
13326            let { slatCoords, date } = this.props;
13327            if (!slatCoords) {
13328                return null;
13329            }
13330            return segs.map((seg, i) => (h(NowIndicatorContainer
13331            // key doesn't matter. will only ever be one
13332            , { 
13333                // key doesn't matter. will only ever be one
13334                key: i, elClasses: ['fc-timegrid-now-indicator-line'], elStyle: {
13335                    top: slatCoords.computeDateTop(seg.start, date),
13336                }, isAxis: false, date: date })));
13337        }
13338        computeSegHStyle(segHCoords) {
13339            let { isRtl, options } = this.context;
13340            let shouldOverlap = options.slotEventOverlap;
13341            let nearCoord = segHCoords.levelCoord; // the left side if LTR. the right side if RTL. floating-point
13342            let farCoord = segHCoords.levelCoord + segHCoords.thickness; // the right side if LTR. the left side if RTL. floating-point
13343            let left; // amount of space from left edge, a fraction of the total width
13344            let right; // amount of space from right edge, a fraction of the total width
13345            if (shouldOverlap) {
13346                // double the width, but don't go beyond the maximum forward coordinate (1.0)
13347                farCoord = Math.min(1, nearCoord + (farCoord - nearCoord) * 2);
13348            }
13349            if (isRtl) {
13350                left = 1 - farCoord;
13351                right = nearCoord;
13352            }
13353            else {
13354                left = nearCoord;
13355                right = 1 - farCoord;
13356            }
13357            let props = {
13358                zIndex: segHCoords.stackDepth + 1,
13359                left: left * 100 + '%',
13360                right: right * 100 + '%',
13361            };
13362            if (shouldOverlap && !segHCoords.stackForward) {
13363                // add padding to the edge so that forward stacked events don't cover the resizer's icon
13364                props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
13365            }
13366            return props;
13367        }
13368    }
13369    function renderPlainFgSegs(sortedFgSegs, { todayRange, nowDate, eventSelection, eventDrag, eventResize }) {
13370        let hiddenInstances = (eventDrag ? eventDrag.affectedInstances : null) ||
13371            (eventResize ? eventResize.affectedInstances : null) ||
13372            {};
13373        return (h(p, null, sortedFgSegs.map((seg) => {
13374            let instanceId = seg.eventRange.instance.instanceId;
13375            return (h("div", { key: instanceId, style: { visibility: hiddenInstances[instanceId] ? 'hidden' : '' } },
13376                h(TimeColEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === eventSelection, isShort: false }, getSegMeta(seg, todayRange, nowDate)))));
13377        })));
13378    }
13379    function computeSegVStyle(segVCoords) {
13380        if (!segVCoords) {
13381            return { top: '', bottom: '' };
13382        }
13383        return {
13384            top: segVCoords.start,
13385            bottom: -segVCoords.end,
13386        };
13387    }
13388    function compileSegsFromEntries(segEntries, allSegs) {
13389        return segEntries.map((segEntry) => allSegs[segEntry.index]);
13390    }
13391
13392    class TimeColsContent extends BaseComponent {
13393        constructor() {
13394            super(...arguments);
13395            this.splitFgEventSegs = memoize(splitSegsByCol);
13396            this.splitBgEventSegs = memoize(splitSegsByCol);
13397            this.splitBusinessHourSegs = memoize(splitSegsByCol);
13398            this.splitNowIndicatorSegs = memoize(splitSegsByCol);
13399            this.splitDateSelectionSegs = memoize(splitSegsByCol);
13400            this.splitEventDrag = memoize(splitInteractionByCol);
13401            this.splitEventResize = memoize(splitInteractionByCol);
13402            this.rootElRef = y();
13403            this.cellElRefs = new RefMap();
13404        }
13405        render() {
13406            let { props, context } = this;
13407            let nowIndicatorTop = context.options.nowIndicator &&
13408                props.slatCoords &&
13409                props.slatCoords.safeComputeTop(props.nowDate); // might return void
13410            let colCnt = props.cells.length;
13411            let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, colCnt);
13412            let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, colCnt);
13413            let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, colCnt);
13414            let nowIndicatorSegsByRow = this.splitNowIndicatorSegs(props.nowIndicatorSegs, colCnt);
13415            let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, colCnt);
13416            let eventDragByRow = this.splitEventDrag(props.eventDrag, colCnt);
13417            let eventResizeByRow = this.splitEventResize(props.eventResize, colCnt);
13418            return (h("div", { className: "fc-timegrid-cols", ref: this.rootElRef },
13419                h("table", { role: "presentation", style: {
13420                        minWidth: props.tableMinWidth,
13421                        width: props.clientWidth,
13422                    } },
13423                    props.tableColGroupNode,
13424                    h("tbody", { role: "presentation" },
13425                        h("tr", { role: "row" },
13426                            props.axis && (h("td", { "aria-hidden": true, className: "fc-timegrid-col fc-timegrid-axis" },
13427                                h("div", { className: "fc-timegrid-col-frame" },
13428                                    h("div", { className: "fc-timegrid-now-indicator-container" }, typeof nowIndicatorTop === 'number' && (h(NowIndicatorContainer, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: props.nowDate })))))),
13429                            props.cells.map((cell, i) => (h(TimeCol, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), dateProfile: props.dateProfile, date: cell.date, nowDate: props.nowDate, todayRange: props.todayRange, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, fgEventSegs: fgEventSegsByRow[i], bgEventSegs: bgEventSegsByRow[i], businessHourSegs: businessHourSegsByRow[i], nowIndicatorSegs: nowIndicatorSegsByRow[i], dateSelectionSegs: dateSelectionSegsByRow[i], eventDrag: eventDragByRow[i], eventResize: eventResizeByRow[i], slatCoords: props.slatCoords, eventSelection: props.eventSelection, forPrint: props.forPrint }))))))));
13430        }
13431        componentDidMount() {
13432            this.updateCoords();
13433        }
13434        componentDidUpdate() {
13435            this.updateCoords();
13436        }
13437        updateCoords() {
13438            let { props } = this;
13439            if (props.onColCoords &&
13440                props.clientWidth !== null // means sizing has stabilized
13441            ) {
13442                props.onColCoords(new PositionCache(this.rootElRef.current, collectCellEls(this.cellElRefs.currentMap, props.cells), true, // horizontal
13443                false));
13444            }
13445        }
13446    }
13447    function collectCellEls(elMap, cells) {
13448        return cells.map((cell) => elMap[cell.key]);
13449    }
13450
13451    /* A component that renders one or more columns of vertical time slots
13452    ----------------------------------------------------------------------------------------------------------------------*/
13453    class TimeCols extends DateComponent {
13454        constructor() {
13455            super(...arguments);
13456            this.processSlotOptions = memoize(processSlotOptions);
13457            this.state = {
13458                slatCoords: null,
13459            };
13460            this.handleRootEl = (el) => {
13461                if (el) {
13462                    this.context.registerInteractiveComponent(this, {
13463                        el,
13464                        isHitComboAllowed: this.props.isHitComboAllowed,
13465                    });
13466                }
13467                else {
13468                    this.context.unregisterInteractiveComponent(this);
13469                }
13470            };
13471            this.handleScrollRequest = (request) => {
13472                let { onScrollTopRequest } = this.props;
13473                let { slatCoords } = this.state;
13474                if (onScrollTopRequest && slatCoords) {
13475                    if (request.time) {
13476                        let top = slatCoords.computeTimeTop(request.time);
13477                        top = Math.ceil(top); // zoom can give weird floating-point values. rather scroll a little bit further
13478                        if (top) {
13479                            top += 1; // to overcome top border that slots beyond the first have. looks better
13480                        }
13481                        onScrollTopRequest(top);
13482                    }
13483                    return true;
13484                }
13485                return false;
13486            };
13487            this.handleColCoords = (colCoords) => {
13488                this.colCoords = colCoords;
13489            };
13490            this.handleSlatCoords = (slatCoords) => {
13491                this.setState({ slatCoords });
13492                if (this.props.onSlatCoords) {
13493                    this.props.onSlatCoords(slatCoords);
13494                }
13495            };
13496        }
13497        render() {
13498            let { props, state } = this;
13499            return (h("div", { className: "fc-timegrid-body", ref: this.handleRootEl, style: {
13500                    // these props are important to give this wrapper correct dimensions for interactions
13501                    // TODO: if we set it here, can we avoid giving to inner tables?
13502                    width: props.clientWidth,
13503                    minWidth: props.tableMinWidth,
13504                } },
13505                h(TimeColsSlats, { axis: props.axis, dateProfile: props.dateProfile, slatMetas: props.slatMetas, clientWidth: props.clientWidth, minHeight: props.expandRows ? props.clientHeight : '', tableMinWidth: props.tableMinWidth, tableColGroupNode: props.axis ? props.tableColGroupNode : null /* axis depends on the colgroup's shrinking */, onCoords: this.handleSlatCoords }),
13506                h(TimeColsContent, { cells: props.cells, axis: props.axis, dateProfile: props.dateProfile, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange, nowDate: props.nowDate, nowIndicatorSegs: props.nowIndicatorSegs, clientWidth: props.clientWidth, tableMinWidth: props.tableMinWidth, tableColGroupNode: props.tableColGroupNode, slatCoords: state.slatCoords, onColCoords: this.handleColCoords, forPrint: props.forPrint })));
13507        }
13508        componentDidMount() {
13509            this.scrollResponder = this.context.createScrollResponder(this.handleScrollRequest);
13510        }
13511        componentDidUpdate(prevProps) {
13512            this.scrollResponder.update(prevProps.dateProfile !== this.props.dateProfile);
13513        }
13514        componentWillUnmount() {
13515            this.scrollResponder.detach();
13516        }
13517        queryHit(positionLeft, positionTop) {
13518            let { dateEnv, options } = this.context;
13519            let { colCoords } = this;
13520            let { dateProfile } = this.props;
13521            let { slatCoords } = this.state;
13522            let { snapDuration, snapsPerSlot } = this.processSlotOptions(this.props.slotDuration, options.snapDuration);
13523            let colIndex = colCoords.leftToIndex(positionLeft);
13524            let slatIndex = slatCoords.positions.topToIndex(positionTop);
13525            if (colIndex != null && slatIndex != null) {
13526                let cell = this.props.cells[colIndex];
13527                let slatTop = slatCoords.positions.tops[slatIndex];
13528                let slatHeight = slatCoords.positions.getHeight(slatIndex);
13529                let partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1
13530                let localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat
13531                let snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
13532                let dayDate = this.props.cells[colIndex].date;
13533                let time = addDurations(dateProfile.slotMinTime, multiplyDuration(snapDuration, snapIndex));
13534                let start = dateEnv.add(dayDate, time);
13535                let end = dateEnv.add(start, snapDuration);
13536                return {
13537                    dateProfile,
13538                    dateSpan: Object.assign({ range: { start, end }, allDay: false }, cell.extraDateSpan),
13539                    dayEl: colCoords.els[colIndex],
13540                    rect: {
13541                        left: colCoords.lefts[colIndex],
13542                        right: colCoords.rights[colIndex],
13543                        top: slatTop,
13544                        bottom: slatTop + slatHeight,
13545                    },
13546                    layer: 0,
13547                };
13548            }
13549            return null;
13550        }
13551    }
13552    function processSlotOptions(slotDuration, snapDurationOverride) {
13553        let snapDuration = snapDurationOverride || slotDuration;
13554        let snapsPerSlot = wholeDivideDurations(slotDuration, snapDuration);
13555        if (snapsPerSlot === null) {
13556            snapDuration = slotDuration;
13557            snapsPerSlot = 1;
13558            // TODO: say warning?
13559        }
13560        return { snapDuration, snapsPerSlot };
13561    }
13562
13563    class DayTimeColsSlicer extends Slicer {
13564        sliceRange(range, dayRanges) {
13565            let segs = [];
13566            for (let col = 0; col < dayRanges.length; col += 1) {
13567                let segRange = intersectRanges(range, dayRanges[col]);
13568                if (segRange) {
13569                    segs.push({
13570                        start: segRange.start,
13571                        end: segRange.end,
13572                        isStart: segRange.start.valueOf() === range.start.valueOf(),
13573                        isEnd: segRange.end.valueOf() === range.end.valueOf(),
13574                        col,
13575                    });
13576                }
13577            }
13578            return segs;
13579        }
13580    }
13581
13582    class DayTimeCols extends DateComponent {
13583        constructor() {
13584            super(...arguments);
13585            this.buildDayRanges = memoize(buildDayRanges);
13586            this.slicer = new DayTimeColsSlicer();
13587            this.timeColsRef = y();
13588        }
13589        render() {
13590            let { props, context } = this;
13591            let { dateProfile, dayTableModel } = props;
13592            let isNowIndicator = context.options.nowIndicator;
13593            let dayRanges = this.buildDayRanges(dayTableModel, dateProfile, context.dateEnv);
13594            // give it the first row of cells
13595            // TODO: would move this further down hierarchy, but sliceNowDate needs it
13596            return (h(NowTimer, { unit: isNowIndicator ? 'minute' : 'day' }, (nowDate, todayRange) => (h(TimeCols, Object.assign({ ref: this.timeColsRef }, this.slicer.sliceProps(props, dateProfile, null, context, dayRanges), { forPrint: props.forPrint, axis: props.axis, dateProfile: dateProfile, slatMetas: props.slatMetas, slotDuration: props.slotDuration, cells: dayTableModel.cells[0], tableColGroupNode: props.tableColGroupNode, tableMinWidth: props.tableMinWidth, clientWidth: props.clientWidth, clientHeight: props.clientHeight, expandRows: props.expandRows, nowDate: nowDate, nowIndicatorSegs: isNowIndicator && this.slicer.sliceNowDate(nowDate, context, dayRanges), todayRange: todayRange, onScrollTopRequest: props.onScrollTopRequest, onSlatCoords: props.onSlatCoords })))));
13597        }
13598    }
13599    function buildDayRanges(dayTableModel, dateProfile, dateEnv) {
13600        let ranges = [];
13601        for (let date of dayTableModel.headerDates) {
13602            ranges.push({
13603                start: dateEnv.add(date, dateProfile.slotMinTime),
13604                end: dateEnv.add(date, dateProfile.slotMaxTime),
13605            });
13606        }
13607        return ranges;
13608    }
13609
13610    // potential nice values for the slot-duration and interval-duration
13611    // from largest to smallest
13612    const STOCK_SUB_DURATIONS = [
13613        { hours: 1 },
13614        { minutes: 30 },
13615        { minutes: 15 },
13616        { seconds: 30 },
13617        { seconds: 15 },
13618    ];
13619    function buildSlatMetas(slotMinTime, slotMaxTime, explicitLabelInterval, slotDuration, dateEnv) {
13620        let dayStart = new Date(0);
13621        let slatTime = slotMinTime;
13622        let slatIterator = createDuration(0);
13623        let labelInterval = explicitLabelInterval || computeLabelInterval(slotDuration);
13624        let metas = [];
13625        while (asRoughMs(slatTime) < asRoughMs(slotMaxTime)) {
13626            let date = dateEnv.add(dayStart, slatTime);
13627            let isLabeled = wholeDivideDurations(slatIterator, labelInterval) !== null;
13628            metas.push({
13629                date,
13630                time: slatTime,
13631                key: date.toISOString(),
13632                isoTimeStr: formatIsoTimeString(date),
13633                isLabeled,
13634            });
13635            slatTime = addDurations(slatTime, slotDuration);
13636            slatIterator = addDurations(slatIterator, slotDuration);
13637        }
13638        return metas;
13639    }
13640    // Computes an automatic value for slotLabelInterval
13641    function computeLabelInterval(slotDuration) {
13642        let i;
13643        let labelInterval;
13644        let slotsPerLabel;
13645        // find the smallest stock label interval that results in more than one slots-per-label
13646        for (i = STOCK_SUB_DURATIONS.length - 1; i >= 0; i -= 1) {
13647            labelInterval = createDuration(STOCK_SUB_DURATIONS[i]);
13648            slotsPerLabel = wholeDivideDurations(labelInterval, slotDuration);
13649            if (slotsPerLabel !== null && slotsPerLabel > 1) {
13650                return labelInterval;
13651            }
13652        }
13653        return slotDuration; // fall back
13654    }
13655
13656    class DayTimeColsView extends TimeColsView {
13657        constructor() {
13658            super(...arguments);
13659            this.buildTimeColsModel = memoize(buildTimeColsModel);
13660            this.buildSlatMetas = memoize(buildSlatMetas);
13661        }
13662        render() {
13663            let { options, dateEnv, dateProfileGenerator } = this.context;
13664            let { props } = this;
13665            let { dateProfile } = props;
13666            let dayTableModel = this.buildTimeColsModel(dateProfile, dateProfileGenerator);
13667            let splitProps = this.allDaySplitter.splitProps(props);
13668            let slatMetas = this.buildSlatMetas(dateProfile.slotMinTime, dateProfile.slotMaxTime, options.slotLabelInterval, options.slotDuration, dateEnv);
13669            let { dayMinWidth } = options;
13670            let hasAttachedAxis = !dayMinWidth;
13671            let hasDetachedAxis = dayMinWidth;
13672            let headerContent = options.dayHeaders && (h(DayHeader, { dates: dayTableModel.headerDates, dateProfile: dateProfile, datesRepDistinctDays: true, renderIntro: hasAttachedAxis ? this.renderHeadAxis : null }));
13673            let allDayContent = (options.allDaySlot !== false) && ((contentArg) => (h(DayTable, Object.assign({}, splitProps.allDay, { dateProfile: dateProfile, dayTableModel: dayTableModel, nextDayThreshold: options.nextDayThreshold, tableMinWidth: contentArg.tableMinWidth, colGroupNode: contentArg.tableColGroupNode, renderRowIntro: hasAttachedAxis ? this.renderTableRowAxis : null, showWeekNumbers: false, expandRows: false, headerAlignElRef: this.headerElRef, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, forPrint: props.forPrint }, this.getAllDayMaxEventProps()))));
13674            let timeGridContent = (contentArg) => (h(DayTimeCols, Object.assign({}, splitProps.timed, { dayTableModel: dayTableModel, dateProfile: dateProfile, axis: hasAttachedAxis, slotDuration: options.slotDuration, slatMetas: slatMetas, forPrint: props.forPrint, tableColGroupNode: contentArg.tableColGroupNode, tableMinWidth: contentArg.tableMinWidth, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, onSlatCoords: this.handleSlatCoords, expandRows: contentArg.expandRows, onScrollTopRequest: this.handleScrollTopRequest })));
13675            return hasDetachedAxis
13676                ? this.renderHScrollLayout(headerContent, allDayContent, timeGridContent, dayTableModel.colCnt, dayMinWidth, slatMetas, this.state.slatCoords)
13677                : this.renderSimpleLayout(headerContent, allDayContent, timeGridContent);
13678        }
13679    }
13680    function buildTimeColsModel(dateProfile, dateProfileGenerator) {
13681        let daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
13682        return new DayTableModel(daySeries, false);
13683    }
13684
13685    const OPTION_REFINERS$1 = {
13686        allDaySlot: Boolean,
13687    };
13688
13689    var css_248z$1 = ".fc-v-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-v-event .fc-event-main{color:var(--fc-event-text-color);height:100%}.fc-v-event .fc-event-main-frame{display:flex;flex-direction:column;height:100%}.fc-v-event .fc-event-time{flex-grow:0;flex-shrink:0;max-height:100%;overflow:hidden}.fc-v-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-height:0}.fc-v-event .fc-event-title{bottom:0;max-height:100%;overflow:hidden;top:0}.fc-v-event:not(.fc-event-start){border-top-left-radius:0;border-top-right-radius:0;border-top-width:0}.fc-v-event:not(.fc-event-end){border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-width:0}.fc-v-event.fc-event-selected:before{left:-10px;right:-10px}.fc-v-event .fc-event-resizer-start{cursor:n-resize}.fc-v-event .fc-event-resizer-end{cursor:s-resize}.fc-v-event:not(.fc-event-selected) .fc-event-resizer{height:var(--fc-event-resizer-thickness);left:0;right:0}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-start{top:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer{left:50%;margin-left:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-start{top:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc .fc-timegrid .fc-daygrid-body{z-index:2}.fc .fc-timegrid-divider{padding:0 0 2px}.fc .fc-timegrid-body{min-height:100%;position:relative;z-index:1}.fc .fc-timegrid-axis-chunk{position:relative}.fc .fc-timegrid-axis-chunk>table,.fc .fc-timegrid-slots{position:relative;z-index:1}.fc .fc-timegrid-slot{border-bottom:0;height:1.5em}.fc .fc-timegrid-slot:empty:before{content:\"\\00a0\"}.fc .fc-timegrid-slot-minor{border-top-style:dotted}.fc .fc-timegrid-slot-label-cushion{display:inline-block;white-space:nowrap}.fc .fc-timegrid-slot-label{vertical-align:middle}.fc .fc-timegrid-axis-cushion,.fc .fc-timegrid-slot-label-cushion{padding:0 4px}.fc .fc-timegrid-axis-frame-liquid{height:100%}.fc .fc-timegrid-axis-frame{align-items:center;display:flex;justify-content:flex-end;overflow:hidden}.fc .fc-timegrid-axis-cushion{flex-shrink:0;max-width:60px}.fc-direction-ltr .fc-timegrid-slot-label-frame{text-align:right}.fc-direction-rtl .fc-timegrid-slot-label-frame{text-align:left}.fc-liquid-hack .fc-timegrid-axis-frame-liquid{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-timegrid-col-frame{min-height:100%;position:relative}.fc-media-screen.fc-liquid-hack .fc-timegrid-col-frame{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols{bottom:0;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols>table{height:100%}.fc-media-screen .fc-timegrid-col-bg,.fc-media-screen .fc-timegrid-col-events,.fc-media-screen .fc-timegrid-now-indicator-container{left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col-bg{z-index:2}.fc .fc-timegrid-col-bg .fc-non-business{z-index:1}.fc .fc-timegrid-col-bg .fc-bg-event{z-index:2}.fc .fc-timegrid-col-bg .fc-highlight{z-index:3}.fc .fc-timegrid-bg-harness{left:0;position:absolute;right:0}.fc .fc-timegrid-col-events{z-index:3}.fc .fc-timegrid-now-indicator-container{bottom:0;overflow:hidden}.fc-direction-ltr .fc-timegrid-col-events{margin:0 2.5% 0 2px}.fc-direction-rtl .fc-timegrid-col-events{margin:0 2px 0 2.5%}.fc-timegrid-event-harness{position:absolute}.fc-timegrid-event-harness>.fc-timegrid-event{bottom:0;left:0;position:absolute;right:0;top:0}.fc-timegrid-event-harness-inset .fc-timegrid-event,.fc-timegrid-event.fc-event-mirror,.fc-timegrid-more-link{box-shadow:0 0 0 1px var(--fc-page-bg-color)}.fc-timegrid-event,.fc-timegrid-more-link{border-radius:3px;font-size:var(--fc-small-font-size)}.fc-timegrid-event{margin-bottom:1px}.fc-timegrid-event .fc-event-main{padding:1px 1px 0}.fc-timegrid-event .fc-event-time{font-size:var(--fc-small-font-size);margin-bottom:1px;white-space:nowrap}.fc-timegrid-event-short .fc-event-main-frame{flex-direction:row;overflow:hidden}.fc-timegrid-event-short .fc-event-time:after{content:\"\\00a0-\\00a0\"}.fc-timegrid-event-short .fc-event-title{font-size:var(--fc-small-font-size)}.fc-timegrid-more-link{background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;margin-bottom:1px;position:absolute;z-index:9999}.fc-timegrid-more-link-inner{padding:3px 2px;top:0}.fc-direction-ltr .fc-timegrid-more-link{right:0}.fc-direction-rtl .fc-timegrid-more-link{left:0}.fc .fc-timegrid-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;border-width:1px 0 0;left:0;position:absolute;right:0;z-index:4}.fc .fc-timegrid-now-indicator-arrow{border-color:var(--fc-now-indicator-color);border-style:solid;margin-top:-5px;position:absolute;z-index:4}.fc-direction-ltr .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 0 5px 6px;left:0}.fc-direction-rtl .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 6px 5px 0;right:0}";
13690    injectStyles(css_248z$1);
13691
13692    var index$1 = createPlugin({
13693        name: '@fullcalendar/timegrid',
13694        initialView: 'timeGridWeek',
13695        optionRefiners: OPTION_REFINERS$1,
13696        views: {
13697            timeGrid: {
13698                component: DayTimeColsView,
13699                usesMinMaxTime: true,
13700                allDaySlot: true,
13701                slotDuration: '00:30:00',
13702                slotEventOverlap: true, // a bad name. confused with overlap/constraint system
13703            },
13704            timeGridDay: {
13705                type: 'timeGrid',
13706                duration: { days: 1 },
13707            },
13708            timeGridWeek: {
13709                type: 'timeGrid',
13710                duration: { weeks: 1 },
13711            },
13712        },
13713    });
13714
13715    class ListViewHeaderRow extends BaseComponent {
13716        constructor() {
13717            super(...arguments);
13718            this.state = {
13719                textId: getUniqueDomId(),
13720            };
13721        }
13722        render() {
13723            let { theme, dateEnv, options, viewApi } = this.context;
13724            let { cellId, dayDate, todayRange } = this.props;
13725            let { textId } = this.state;
vendor: 17,170 bytes, lines 13726-14041
13726            let dayMeta = getDateMeta(dayDate, todayRange);
13727            // will ever be falsy?
13728            let text = options.listDayFormat ? dateEnv.format(dayDate, options.listDayFormat) : '';
13729            // will ever be falsy? also, BAD NAME "alt"
13730            let sideText = options.listDaySideFormat ? dateEnv.format(dayDate, options.listDaySideFormat) : '';
13731            let renderProps = Object.assign({ date: dateEnv.toDate(dayDate), view: viewApi, textId,
13732                text,
13733                sideText, navLinkAttrs: buildNavLinkAttrs(this.context, dayDate), sideNavLinkAttrs: buildNavLinkAttrs(this.context, dayDate, 'day', false) }, dayMeta);
13734            // TODO: make a reusable HOC for dayHeader (used in daygrid/timegrid too)
13735            return (h(ContentContainer, { elTag: "tr", elClasses: [
13736                    'fc-list-day',
13737                    ...getDayClassNames(dayMeta, theme),
13738                ], elAttrs: {
13739                    'data-date': formatDayString(dayDate),
13740                }, renderProps: renderProps, generatorName: "dayHeaderContent", generator: options.dayHeaderContent || renderInnerContent, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => ( // TODO: force-hide top border based on :first-child
13741            h("th", { scope: "colgroup", colSpan: 3, id: cellId, "aria-labelledby": textId },
13742                h(InnerContent, { elTag: "div", elClasses: [
13743                        'fc-list-day-cushion',
13744                        theme.getClass('tableCellShaded'),
13745                    ] })))));
13746        }
13747    }
13748    function renderInnerContent(props) {
13749        return (h(p, null,
13750            props.text && (h("a", Object.assign({ id: props.textId, className: "fc-list-day-text" }, props.navLinkAttrs), props.text)),
13751            props.sideText && ( /* not keyboard tabbable */h("a", Object.assign({ "aria-hidden": true, className: "fc-list-day-side-text" }, props.sideNavLinkAttrs), props.sideText))));
13752    }
13753
13754    const DEFAULT_TIME_FORMAT = createFormatter({
13755        hour: 'numeric',
13756        minute: '2-digit',
13757        meridiem: 'short',
13758    });
13759    class ListViewEventRow extends BaseComponent {
13760        render() {
13761            let { props, context } = this;
13762            let { options } = context;
13763            let { seg, timeHeaderId, eventHeaderId, dateHeaderId } = props;
13764            let timeFormat = options.eventTimeFormat || DEFAULT_TIME_FORMAT;
13765            return (h(EventContainer, Object.assign({}, props, { elTag: "tr", elClasses: [
13766                    'fc-list-event',
13767                    seg.eventRange.def.url && 'fc-event-forced-url',
13768                ], defaultGenerator: () => renderEventInnerContent(seg, context) /* weird */, seg: seg, timeText: "", disableDragging: true, disableResizing: true }), (InnerContent, eventContentArg) => (h(p, null,
13769                buildTimeContent(seg, timeFormat, context, timeHeaderId, dateHeaderId),
13770                h("td", { "aria-hidden": true, className: "fc-list-event-graphic" },
13771                    h("span", { className: "fc-list-event-dot", style: {
13772                            borderColor: eventContentArg.borderColor || eventContentArg.backgroundColor,
13773                        } })),
13774                h(InnerContent, { elTag: "td", elClasses: ['fc-list-event-title'], elAttrs: { headers: `${eventHeaderId} ${dateHeaderId}` } })))));
13775        }
13776    }
13777    function renderEventInnerContent(seg, context) {
13778        let interactiveAttrs = getSegAnchorAttrs(seg, context);
13779        return (h("a", Object.assign({}, interactiveAttrs), seg.eventRange.def.title));
13780    }
13781    function buildTimeContent(seg, timeFormat, context, timeHeaderId, dateHeaderId) {
13782        let { options } = context;
13783        if (options.displayEventTime !== false) {
13784            let eventDef = seg.eventRange.def;
13785            let eventInstance = seg.eventRange.instance;
13786            let doAllDay = false;
13787            let timeText;
13788            if (eventDef.allDay) {
13789                doAllDay = true;
13790            }
13791            else if (isMultiDayRange(seg.eventRange.range)) { // TODO: use (!isStart || !isEnd) instead?
13792                if (seg.isStart) {
13793                    timeText = buildSegTimeText(seg, timeFormat, context, null, null, eventInstance.range.start, seg.end);
13794                }
13795                else if (seg.isEnd) {
13796                    timeText = buildSegTimeText(seg, timeFormat, context, null, null, seg.start, eventInstance.range.end);
13797                }
13798                else {
13799                    doAllDay = true;
13800                }
13801            }
13802            else {
13803                timeText = buildSegTimeText(seg, timeFormat, context);
13804            }
13805            if (doAllDay) {
13806                let renderProps = {
13807                    text: context.options.allDayText,
13808                    view: context.viewApi,
13809                };
13810                return (h(ContentContainer, { elTag: "td", elClasses: ['fc-list-event-time'], elAttrs: {
13811                        headers: `${timeHeaderId} ${dateHeaderId}`,
13812                    }, renderProps: renderProps, generatorName: "allDayContent", generator: options.allDayContent || renderAllDayInner, classNameGenerator: options.allDayClassNames, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }));
13813            }
13814            return (h("td", { className: "fc-list-event-time" }, timeText));
13815        }
13816        return null;
13817    }
13818    function renderAllDayInner(renderProps) {
13819        return renderProps.text;
13820    }
13821
13822    /*
13823    Responsible for the scroller, and forwarding event-related actions into the "grid".
13824    */
13825    class ListView extends DateComponent {
13826        constructor() {
13827            super(...arguments);
13828            this.computeDateVars = memoize(computeDateVars);
13829            this.eventStoreToSegs = memoize(this._eventStoreToSegs);
13830            this.state = {
13831                timeHeaderId: getUniqueDomId(),
13832                eventHeaderId: getUniqueDomId(),
13833                dateHeaderIdRoot: getUniqueDomId(),
13834            };
13835            this.setRootEl = (rootEl) => {
13836                if (rootEl) {
13837                    this.context.registerInteractiveComponent(this, {
13838                        el: rootEl,
13839                    });
13840                }
13841                else {
13842                    this.context.unregisterInteractiveComponent(this);
13843                }
13844            };
13845        }
13846        render() {
13847            let { props, context } = this;
13848            let { dayDates, dayRanges } = this.computeDateVars(props.dateProfile);
13849            let eventSegs = this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges);
13850            return (h(ViewContainer$1, { elRef: this.setRootEl, elClasses: [
13851                    'fc-list',
13852                    context.theme.getClass('table'),
13853                    context.options.stickyHeaderDates !== false ?
13854                        'fc-list-sticky' :
13855                        '',
13856                ], viewSpec: context.viewSpec },
13857                h(Scroller, { liquid: !props.isHeightAuto, overflowX: props.isHeightAuto ? 'visible' : 'hidden', overflowY: props.isHeightAuto ? 'visible' : 'auto' }, eventSegs.length > 0 ?
13858                    this.renderSegList(eventSegs, dayDates) :
13859                    this.renderEmptyMessage())));
13860        }
13861        renderEmptyMessage() {
13862            let { options, viewApi } = this.context;
13863            let renderProps = {
13864                text: options.noEventsText,
13865                view: viewApi,
13866            };
13867            return (h(ContentContainer, { elTag: "div", elClasses: ['fc-list-empty'], renderProps: renderProps, generatorName: "noEventsContent", generator: options.noEventsContent || renderNoEventsInner, classNameGenerator: options.noEventsClassNames, didMount: options.noEventsDidMount, willUnmount: options.noEventsWillUnmount }, (InnerContent) => (h(InnerContent, { elTag: "div", elClasses: ['fc-list-empty-cushion'] }))));
13868        }
13869        renderSegList(allSegs, dayDates) {
13870            let { theme, options } = this.context;
13871            let { timeHeaderId, eventHeaderId, dateHeaderIdRoot } = this.state;
13872            let segsByDay = groupSegsByDay(allSegs); // sparse array
13873            return (h(NowTimer, { unit: "day" }, (nowDate, todayRange) => {
13874                let innerNodes = [];
13875                for (let dayIndex = 0; dayIndex < segsByDay.length; dayIndex += 1) {
13876                    let daySegs = segsByDay[dayIndex];
13877                    if (daySegs) { // sparse array, so might be undefined
13878                        let dayStr = formatDayString(dayDates[dayIndex]);
13879                        let dateHeaderId = dateHeaderIdRoot + '-' + dayStr;
13880                        // append a day header
13881                        innerNodes.push(h(ListViewHeaderRow, { key: dayStr, cellId: dateHeaderId, dayDate: dayDates[dayIndex], todayRange: todayRange }));
13882                        daySegs = sortEventSegs(daySegs, options.eventOrder);
13883                        for (let seg of daySegs) {
13884                            innerNodes.push(h(ListViewEventRow, Object.assign({ key: dayStr + ':' + seg.eventRange.instance.instanceId /* are multiple segs for an instanceId */, seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false, timeHeaderId: timeHeaderId, eventHeaderId: eventHeaderId, dateHeaderId: dateHeaderId }, getSegMeta(seg, todayRange, nowDate))));
13885                        }
13886                    }
13887                }
13888                return (h("table", { className: 'fc-list-table ' + theme.getClass('table') },
13889                    h("thead", null,
13890                        h("tr", null,
13891                            h("th", { scope: "col", id: timeHeaderId }, options.timeHint),
13892                            h("th", { scope: "col", "aria-hidden": true }),
13893                            h("th", { scope: "col", id: eventHeaderId }, options.eventHint))),
13894                    h("tbody", null, innerNodes)));
13895            }));
13896        }
13897        _eventStoreToSegs(eventStore, eventUiBases, dayRanges) {
13898            return this.eventRangesToSegs(sliceEventStore(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.context.options.nextDayThreshold).fg, dayRanges);
13899        }
13900        eventRangesToSegs(eventRanges, dayRanges) {
13901            let segs = [];
13902            for (let eventRange of eventRanges) {
13903                segs.push(...this.eventRangeToSegs(eventRange, dayRanges));
13904            }
13905            return segs;
13906        }
13907        eventRangeToSegs(eventRange, dayRanges) {
13908            let { dateEnv } = this.context;
13909            let { nextDayThreshold } = this.context.options;
13910            let range = eventRange.range;
13911            let allDay = eventRange.def.allDay;
13912            let dayIndex;
13913            let segRange;
13914            let seg;
13915            let segs = [];
13916            for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex += 1) {
13917                segRange = intersectRanges(range, dayRanges[dayIndex]);
13918                if (segRange) {
13919                    seg = {
13920                        component: this,
13921                        eventRange,
13922                        start: segRange.start,
13923                        end: segRange.end,
13924                        isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(),
13925                        isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(),
13926                        dayIndex,
13927                    };
13928                    segs.push(seg);
13929                    // detect when range won't go fully into the next day,
13930                    // and mutate the latest seg to the be the end.
13931                    if (!seg.isEnd && !allDay &&
13932                        dayIndex + 1 < dayRanges.length &&
13933                        range.end <
13934                            dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) {
13935                        seg.end = range.end;
13936                        seg.isEnd = true;
13937                        break;
13938                    }
13939                }
13940            }
13941            return segs;
13942        }
13943    }
13944    function renderNoEventsInner(renderProps) {
13945        return renderProps.text;
13946    }
13947    function computeDateVars(dateProfile) {
13948        let dayStart = startOfDay(dateProfile.renderRange.start);
13949        let viewEnd = dateProfile.renderRange.end;
13950        let dayDates = [];
13951        let dayRanges = [];
13952        while (dayStart < viewEnd) {
13953            dayDates.push(dayStart);
13954            dayRanges.push({
13955                start: dayStart,
13956                end: addDays(dayStart, 1),
13957            });
13958            dayStart = addDays(dayStart, 1);
13959        }
13960        return { dayDates, dayRanges };
13961    }
13962    // Returns a sparse array of arrays, segs grouped by their dayIndex
13963    function groupSegsByDay(segs) {
13964        let segsByDay = []; // sparse array
13965        let i;
13966        let seg;
13967        for (i = 0; i < segs.length; i += 1) {
13968            seg = segs[i];
13969            (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = []))
13970                .push(seg);
13971        }
13972        return segsByDay;
13973    }
13974
13975    const OPTION_REFINERS = {
13976        listDayFormat: createFalsableFormatter,
13977        listDaySideFormat: createFalsableFormatter,
13978        noEventsClassNames: identity,
13979        noEventsContent: identity,
13980        noEventsDidMount: identity,
13981        noEventsWillUnmount: identity,
13982        // noEventsText is defined in base options
13983    };
13984    function createFalsableFormatter(input) {
13985        return input === false ? null : createFormatter(input);
13986    }
13987
13988    var css_248z = ":root{--fc-list-event-dot-width:10px;--fc-list-event-hover-bg-color:#f5f5f5}.fc-theme-standard .fc-list{border:1px solid var(--fc-border-color)}.fc .fc-list-empty{align-items:center;background-color:var(--fc-neutral-bg-color);display:flex;height:100%;justify-content:center}.fc .fc-list-empty-cushion{margin:5em 0}.fc .fc-list-table{border-style:hidden;width:100%}.fc .fc-list-table tr>*{border-left:0;border-right:0}.fc .fc-list-sticky .fc-list-day>*{background:var(--fc-page-bg-color);position:sticky;top:0}.fc .fc-list-table thead{left:-10000px;position:absolute}.fc .fc-list-table tbody>tr:first-child th{border-top:0}.fc .fc-list-table th{padding:0}.fc .fc-list-day-cushion,.fc .fc-list-table td{padding:8px 14px}.fc .fc-list-day-cushion:after{clear:both;content:\"\";display:table}.fc-theme-standard .fc-list-day-cushion{background-color:var(--fc-neutral-bg-color)}.fc-direction-ltr .fc-list-day-text,.fc-direction-rtl .fc-list-day-side-text{float:left}.fc-direction-ltr .fc-list-day-side-text,.fc-direction-rtl .fc-list-day-text{float:right}.fc-direction-ltr .fc-list-table .fc-list-event-graphic{padding-right:0}.fc-direction-rtl .fc-list-table .fc-list-event-graphic{padding-left:0}.fc .fc-list-event.fc-event-forced-url{cursor:pointer}.fc .fc-list-event:hover td{background-color:var(--fc-list-event-hover-bg-color)}.fc .fc-list-event-graphic,.fc .fc-list-event-time{white-space:nowrap;width:1px}.fc .fc-list-event-dot{border:calc(var(--fc-list-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-list-event-dot-width)/2);box-sizing:content-box;display:inline-block;height:0;width:0}.fc .fc-list-event-title a{color:inherit;text-decoration:none}.fc .fc-list-event.fc-event-forced-url:hover a{text-decoration:underline}";
13989    injectStyles(css_248z);
13990
13991    var index = createPlugin({
13992        name: '@fullcalendar/list',
13993        optionRefiners: OPTION_REFINERS,
13994        views: {
13995            list: {
13996                component: ListView,
13997                buttonTextKey: 'list',
13998                listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' }, // like "January 1, 2016"
13999            },
14000            listDay: {
14001                type: 'list',
14002                duration: { days: 1 },
14003                listDayFormat: { weekday: 'long' }, // day-of-week is all we need. full date is probably in headerToolbar
14004            },
14005            listWeek: {
14006                type: 'list',
14007                duration: { weeks: 1 },
14008                listDayFormat: { weekday: 'long' },
14009                listDaySideFormat: { month: 'long', day: 'numeric', year: 'numeric' },
14010            },
14011            listMonth: {
14012                type: 'list',
14013                duration: { month: 1 },
14014                listDaySideFormat: { weekday: 'long' }, // day-of-week is nice-to-have
14015            },
14016            listYear: {
14017                type: 'list',
14018                duration: { year: 1 },
14019                listDaySideFormat: { weekday: 'long' }, // day-of-week is nice-to-have
14020            },
14021        },
14022    });
14023
14024    globalPlugins.push(index$3, index$2, index$1, index);
14025
14026    exports.Calendar = Calendar;
14027    exports.Draggable = ExternalDraggable;
14028    exports.Internal = internal;
14029    exports.JsonRequestError = JsonRequestError;
14030    exports.ThirdPartyDraggable = ThirdPartyDraggable;
14031    exports.createPlugin = createPlugin;
14032    exports.formatDate = formatDate;
14033    exports.formatRange = formatRange;
14034    exports.sliceEvents = sliceEvents;
14035    exports.version = version;
14036
14037    Object.defineProperty(exports, '__esModule', { value: true });
14038
14039    return exports;
14040
14041})({});

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.