PageSourceSearch

https://kamiensk.pl/js/fullcalendar-6.1.17/dist/index.global.js

js kamiensk.pl collected 2026-10-02 21:43:41 UTC 697,230 bytes, 14,775 lines download raw bytes

vendor: 20,805 bytes, lines 1-82
1/*!
2FullCalendar Standard Bundle v6.1.17
3Docs & License: https://fullcalendar.io/docs/initialize-globals
4(c) 2024 Adam Shaw
5*/
6var FullCalendar = (function (exports) {
7    'use strict';
8
9    var n,l$1,u$1,i$1,t,r$1,o,f$1,e$1,c$1={},s=[],a$1=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function h(n,l){for(var u in l)n[u]=l[u];return n}function v$1(n){var l=n.parentNode;l&&l.removeChild(n);}function y(l,u,i){var t,r,o,f={};for(o in u)"key"==o?t=u[o]:"ref"==o?r=u[o]:f[o]=u[o];if(arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),"function"==typeof l&&null!=l.defaultProps)for(o in l.defaultProps)void 0===f[o]&&(f[o]=l.defaultProps[o]);return p(l,f,t,r,null)}function p(n,i,t,r,o){var f={type:n,props:i,key:t,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++u$1:o};return null==o&&null!=l$1.vnode&&l$1.vnode(f),f}function d(){return {current:null}}function _(n){return n.children}function k$1(n,l,u,i,t){var r;for(r in u)"children"===r||"key"===r||r in l||g$2(n,r,null,u[r],i);for(r in l)t&&"function"!=typeof l[r]||"children"===r||"key"===r||"value"===r||"checked"===r||u[r]===l[r]||g$2(n,r,l[r],u[r],i);}function b$1(n,l,u){"-"===l[0]?n.setProperty(l,null==u?"":u):n[l]=null==u?"":"number"!=typeof u||a$1.test(l)?u:u+"px";}function g$2(n,l,u,i,t){var r;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||b$1(n.style,l,"");if(u)for(l in u)i&&u[l]===i[l]||b$1(n.style,l,u[l]);}else if("o"===l[0]&&"n"===l[1])r=l!==(l=l.replace(/Capture$/,"")),l=l.toLowerCase()in n?l.toLowerCase().slice(2):l.slice(2),n.l||(n.l={}),n.l[l+r]=u,u?i||n.addEventListener(l,r?w$2:m$1,r):n.removeEventListener(l,r?w$2:m$1,r);else if("dangerouslySetInnerHTML"!==l){if(t)l=l.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("width"!==l&&"height"!==l&&"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 m$1(n){t=!0;try{return this.l[n.type+!1](l$1.event?l$1.event(n):n)}finally{t=!1;}}function w$2(n){t=!0;try{return this.l[n.type+!0](l$1.event?l$1.event(n):n)}finally{t=!1;}}function x$1(n,l){this.props=n,this.context=l;}function A(n,l){if(null==l)return n.__?A(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?A(n):null}function P$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 P$1(n)}}function C$1(n){t?setTimeout(n):f$1(n);}function T$1(n){(!n.__d&&(n.__d=!0)&&r$1.push(n)&&!$$1.__r++||o!==l$1.debounceRendering)&&((o=l$1.debounceRendering)||C$1)($$1);}function $$1(){var n,l,u,i,t,o,f,e;for(r$1.sort(function(n,l){return n.__v.__b-l.__v.__b});n=r$1.shift();)n.__d&&(l=r$1.length,i=void 0,t=void 0,f=(o=(u=n).__v).__e,(e=u.__P)&&(i=[],(t=h({},o)).__v=o.__v+1,M(e,o,t,u.__n,void 0!==e.ownerSVGElement,null!=o.__h?[f]:null,i,null==f?A(o):f,o.__h),N(i,o),o.__e!=f&&P$1(o)),r$1.length>l&&r$1.sort(function(n,l){return n.__v.__b-l.__v.__b}));$$1.__r=0;}function H$1(n,l,u,i,t,r,o,f,e,a){var h,v,y,d,k,b,g,m=i&&i.__k||s,w=m.length;for(u.__k=[],h=0;h<l.length;h++)if(null!=(d=u.__k[h]=null==(d=l[h])||"boolean"==typeof d?null:"string"==typeof d||"number"==typeof d||"bigint"==typeof d?p(null,d,null,null,d):Array.isArray(d)?p(_,{children:d},null,null,null):d.__b>0?p(d.type,d.props,d.key,d.ref?d.ref:null,d.__v):d)){if(d.__=u,d.__b=u.__b+1,null===(y=m[h])||y&&d.key==y.key&&d.type===y.type)m[h]=void 0;else for(v=0;v<w;v++){if((y=m[v])&&d.key==y.key&&d.type===y.type){m[v]=void 0;break}y=null;}M(n,d,y=y||c$1,t,r,o,f,e,a),k=d.__e,(v=d.ref)&&y.ref!=v&&(g||(g=[]),y.ref&&g.push(y.ref,null,d),g.push(v,d.__c||k,d)),null!=k?(null==b&&(b=k),"function"==typeof d.type&&d.__k===y.__k?d.__d=e=I$1(d,e,n):e=z$1(n,d,y,m,k,e),"function"==typeof u.type&&(u.__d=e)):e&&y.__e==e&&e.parentNode!=n&&(e=A(y));}for(u.__e=b,h=w;h--;)null!=m[h]&&("function"==typeof u.type&&null!=m[h].__e&&m[h].__e==u.__d&&(u.__d=L$1(i).nextSibling),q(m[h],m[h]));if(g)for(h=0;h<g.length;h++)S(g[h],g[++h],g[++h]);}function I$1(n,l,u){for(var i,t=n.__k,r=0;t&&r<t.length;r++)(i=t[r])&&(i.__=n,l="function"==typeof i.type?I$1(i,l,u):z$1(u,i,i,t,i.__e,l));return l}function j$2(n,l){return l=l||[],null==n||"boolean"==typeof n||(Array.isArray(n)?n.some(function(n){j$2(n,l);}):l.push(n)),l}function z$1(n,l,u,i,t,r){var o,f,e;if(void 0!==l.__d)o=l.__d,l.__d=void 0;else if(null==u||t!=r||null==t.parentNode)n:if(null==r||r.parentNode!==n)n.appendChild(t),o=null;else {for(f=r,e=0;(f=f.nextSibling)&&e<i.length;e+=1)if(f==t)break n;n.insertBefore(t,r),o=r;}return void 0!==o?o:t.nextSibling}function L$1(n){var l,u,i;if(null==n.type||"string"==typeof n.type)return n.__e;if(n.__k)for(l=n.__k.length-1;l>=0;l--)if((u=n.__k[l])&&(i=L$1(u)))return i;return null}function M(n,u,i,t,r,o,f,e,c){var s,a,v,y,p,d,k,b,g,m,w,A,P,C,T,$=u.type;if(void 0!==u.constructor)return null;null!=i.__h&&(c=i.__h,e=u.__e=i.__e,u.__h=null,o=[e]),(s=l$1.__b)&&s(u);try{n:if("function"==typeof $){if(b=u.props,g=(s=$.contextType)&&t[s.__c],m=s?g?g.props.value:s.__:t,i.__c?k=(a=u.__c=i.__c).__=a.__E:("prototype"in $&&$.prototype.render?u.__c=a=new $(b,m):(u.__c=a=new x$1(b,m),a.constructor=$,a.render=B$1),g&&g.sub(a),a.props=b,a.state||(a.state={}),a.context=m,a.__n=t,v=a.__d=!0,a.__h=[],a._sb=[]),null==a.__s&&(a.__s=a.state),null!=$.getDerivedStateFromProps&&(a.__s==a.state&&(a.__s=h({},a.__s)),h(a.__s,$.getDerivedStateFromProps(b,a.__s))),y=a.props,p=a.state,a.__v=u,v)null==$.getDerivedStateFromProps&&null!=a.componentWillMount&&a.componentWillMount(),null!=a.componentDidMount&&a.__h.push(a.componentDidMount);else {if(null==$.getDerivedStateFromProps&&b!==y&&null!=a.componentWillReceiveProps&&a.componentWillReceiveProps(b,m),!a.__e&&null!=a.shouldComponentUpdate&&!1===a.shouldComponentUpdate(b,a.__s,m)||u.__v===i.__v){for(u.__v!==i.__v&&(a.props=b,a.state=a.__s,a.__d=!1),u.__e=i.__e,u.__k=i.__k,u.__k.forEach(function(n){n&&(n.__=u);}),w=0;w<a._sb.length;w++)a.__h.push(a._sb[w]);a._sb=[],a.__h.length&&f.push(a);break n}null!=a.componentWillUpdate&&a.componentWillUpdate(b,a.__s,m),null!=a.componentDidUpdate&&a.__h.push(function(){a.componentDidUpdate(y,p,d);});}if(a.context=m,a.props=b,a.__P=n,A=l$1.__r,P=0,"prototype"in $&&$.prototype.render){for(a.state=a.__s,a.__d=!1,A&&A(u),s=a.render(a.props,a.state,a.context),C=0;C<a._sb.length;C++)a.__h.push(a._sb[C]);a._sb=[];}else do{a.__d=!1,A&&A(u),s=a.render(a.props,a.state,a.context),a.state=a.__s;}while(a.__d&&++P<25);a.state=a.__s,null!=a.getChildContext&&(t=h(h({},t),a.getChildContext())),v||null==a.getSnapshotBeforeUpdate||(d=a.getSnapshotBeforeUpdate(y,p)),T=null!=s&&s.type===_&&null==s.key?s.props.children:s,H$1(n,Array.isArray(T)?T:[T],u,i,t,r,o,f,e,c),a.base=u.__e,u.__h=null,a.__h.length&&f.push(a),k&&(a.__E=a.__=null),a.__e=!1;}else null==o&&u.__v===i.__v?(u.__k=i.__k,u.__e=i.__e):u.__e=O(i.__e,u,i,t,r,o,f,c);(s=l$1.diffed)&&s(u);}catch(n){u.__v=null,(c||null!=o)&&(u.__e=e,u.__h=!!c,o[o.indexOf(e)]=null),l$1.__e(n,u,i);}}function N(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 O(l,u,i,t,r,o,f,e){var s,a,h,y=i.props,p=u.props,d=u.type,_=0;if("svg"===d&&(r=!0),null!=o)for(;_<o.length;_++)if((s=o[_])&&"setAttribute"in s==!!d&&(d?s.localName===d:3===s.nodeType)){l=s,o[_]=null;break}if(null==l){if(null===d)return document.createTextNode(p);l=r?document.createElementNS("http://www.w3.org/2000/svg",d):document.createElement(d,p.is&&p),o=null,e=!1;}if(null===d)y===p||e&&l.data===p||(l.data=p);else {if(o=o&&n.call(l.childNodes),a=(y=i.props||c$1).dangerouslySetInnerHTML,h=p.dangerouslySetInnerHTML,!e){if(null!=o)for(y={},_=0;_<l.attributes.length;_++)y[l.attributes[_].name]=l.attributes[_].value;(h||a)&&(h&&(a&&h.__html==a.__html||h.__html===l.innerHTML)||(l.innerHTML=h&&h.__html||""));}if(k$1(l,p,y,r,e),h)u.__k=[];else if(_=u.props.children,H$1(l,Array.isArray(_)?_:[_],u,i,t,r&&"foreignObject"!==d,o,f,o?o[0]:i.__k&&A(i,0),e),null!=o)for(_=o.length;_--;)null!=o[_]&&v$1(o[_]);e||("value"in p&&void 0!==(_=p.value)&&(_!==l.value||"progress"===d&&!_||"option"===d&&_!==y.value)&&g$2(l,"value",_,y.value,!1),"checked"in p&&void 0!==(_=p.checked)&&_!==l.checked&&g$2(l,"checked",_,y.checked,!1));}return l}function S(n,u,i){try{"function"==typeof n?n(u):n.current=u;}catch(n){l$1.__e(n,i);}}function q(n,u,i){var t,r;if(l$1.unmount&&l$1.unmount(n),(t=n.ref)&&(t.current&&t.current!==n.__e||S(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(r=0;r<t.length;r++)t[r]&&q(t[r],u,i||"function"!=typeof n.type);i||null==n.__e||v$1(n.__e),n.__=n.__e=n.__d=void 0;}function B$1(n,l,u){return this.constructor(n,u)}function D$1(u,i,t){var r,o,f;l$1.__&&l$1.__(u,i),o=(r="function"==typeof t)?null:t&&t.__k||i.__k,f=[],M(i,u=(!r&&t||i).__k=y(_,null,[u]),o||c$1,c$1,void 0!==i.ownerSVGElement,!r&&t?[t]:o?null:i.firstChild?n.call(i.childNodes):null,f,!r&&t?t:o?o.__e:i.firstChild,r),N(f,u);}function E(n,l){D$1(n,l,E);}function F$1(l,u,i){var t,r,o,f=h({},l.props);for(o in u)"key"==o?t=u[o]:"ref"==o?r=u[o]:f[o]=u[o];return arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),p(l.type,f,t||l.key,r||l.ref,null)}function G$1(n,l){var u={__c:l="__cC"+e$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(function(n){n.__e=!0,T$1(n);});},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=s.slice,l$1={__e:function(n,l,u,i){for(var t,r,o;l=l.__;)if((t=l.__c)&&!t.__)try{if((r=t.constructor)&&null!=r.getDerivedStateFromError&&(t.setState(r.getDerivedStateFromError(n)),o=t.__d),null!=t.componentDidCatch&&(t.componentDidCatch(n,i||{}),o=t.__d),o)return t.__E=t}catch(l){n=l;}throw n}},u$1=0,i$1=function(n){return null!=n&&void 0===n.constructor},t=!1,x$1.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=h({},this.state),"function"==typeof n&&(n=n(h({},u),this.props)),n&&h(u,n),null!=n&&this.__v&&(l&&this._sb.push(l),T$1(this));},x$1.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),T$1(this));},x$1.prototype.render=_,r$1=[],f$1="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,$$1.__r=0,e$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 x$1).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 x$1).__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&&y(_,null,n.fallback);return i&&(i.__h=null),[y(_,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(){D$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);}}),D$1(y(P,{context:e.context},n.__v),e.l)):e.l&&e.componentWillUnmount();}function j(n,e){var r=y($,{__v:n,i:e});return r.containerInfo=e,r}(V.prototype=new x$1).__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=j$2(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)};x$1.prototype.isReactComponent={},["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach(function(t){Object.defineProperty(x$1.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=j$2(e.children).forEach(function(n){n.props.selected=-1!=u.value.indexOf(n.props.value);})),"select"==t&&null!=u.defaultValue&&(u.value=j$2(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    const styleTexts = [];
16    const styleEls = new Map();
17    function injectStyles(styleText) {
18        styleTexts.push(styleText);
19        styleEls.forEach((styleEl) => {
20            appendStylesTo(styleEl, styleText);
21        });
22    }
23    function ensureElHasStyles(el) {
24        if (el.isConnected && // sometimes true if SSR system simulates DOM
25            el.getRootNode // sometimes undefined if SSR system simulates DOM
26        ) {
27            registerStylesRoot(el.getRootNode());
28        }
29    }
30    function registerStylesRoot(rootNode) {
31        let styleEl = styleEls.get(rootNode);
32        if (!styleEl || !styleEl.isConnected) {
33            styleEl = rootNode.querySelector('style[data-fullcalendar]');
34            if (!styleEl) {
35                styleEl = document.createElement('style');
36                styleEl.setAttribute('data-fullcalendar', '');
37                const nonce = getNonceValue();
38                if (nonce) {
39                    styleEl.nonce = nonce;
40                }
41                const parentEl = rootNode === document ? document.head : rootNode;
42                const insertBefore = rootNode === document
43                    ? parentEl.querySelector('script,link[rel=stylesheet],link[as=style],style')
44                    : parentEl.firstChild;
45                parentEl.insertBefore(styleEl, insertBefore);
46            }
47            styleEls.set(rootNode, styleEl);
48            hydrateStylesRoot(styleEl);
49        }
50    }
51    function hydrateStylesRoot(styleEl) {
52        for (const styleText of styleTexts) {
53            appendStylesTo(styleEl, styleText);
54        }
55    }
56    function appendStylesTo(styleEl, styleText) {
57        const { sheet } = styleEl;
58        const ruleCnt = sheet.cssRules.length;
59        styleText.split('}').forEach((styleStr, i) => {
60            styleStr = styleStr.trim();
61            if (styleStr) {
62                sheet.insertRule(styleStr + '}', ruleCnt + i);
63            }
64        });
65    }
66    // nonce
67    // -------------------------------------------------------------------------------------------------
68    let queriedNonceValue;
69    function getNonceValue() {
70        if (queriedNonceValue === undefined) {
71            queriedNonceValue = queryNonceValue();
72        }
73        return queriedNonceValue;
74    }
75    /*
76    TODO: discourage meta tag and instead put nonce attribute on placeholder <style> tag
77    */
78    function queryNonceValue() {
79        const metaWithNonce = document.querySelector('meta[name="csp-nonce"]');
80        if (metaWithNonce && metaWithNonce.hasAttribute('content')) {
81            return metaWithNonce.getAttribute('content');
82        }
83        const elWithNonce = document.querySelector('script[nonce]');
84        if (elWithNonce) {
85            return elWithNonce.nonce || '';
86        }
87        return '';
88    }
89    // main
90    // -------------------------------------------------------------------------------------------------
91    if (typeof document !== 'undefined') {
92        registerStylesRoot(document);
93    }
94
95    var css_248z$4 = ":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{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/wAMJAwNDeLiDQ0MJAyNAQAMIw0BAAwMDSMM4uINIwwNDQAAAAIA4gC3Ax4CngATACcAACUnNzY0JyYiDwEGFB8BFjI3NjQnISc3NjQnJiIPAQYUHwEWMjc2NCcB87e3DQ0MIw3VDQ3VDSMMDQ0BK7e3DQ0MJAzVDQ3VDCQMDQ3zuLcMJAwNDdUNIwzWDAwNIwy4twwkDA0N1Q0jDNYMDA0jDAAAAgDiALcDHgKeABMAJwAAJTc2NC8BJiIHBhQfAQcGFBcWMjchNzY0LwEmIgcGFB8BBwYUFxYyNwJJ1Q0N1Q0jDA0Nt7cNDQwjDf7V1Q0N1QwkDA0Nt7cNDQwkDLfWDCMN1Q0NDCQMt7gMIw0MDNYMIw3VDQ0MJAy3uAwjDQwMAAADAFUAAAOrA1UAMwBoAHcAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMhMjY1NCYjISIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAAVYRGRkR/qoRGRkRA1UFBAUOCQkVDAsZDf2rDRkLDBUJCA4FBQUFBQUOCQgVDAsZDQJVDRkLDBUJCQ4FBAVVAgECBQMCBwQECAX9qwQJAwQHAwMFAQICAgIBBQMDBwQDCQQCVQUIBAQHAgMFAgEC/oAZEhEZGRESGQAAAAADAFUAAAOrA1UAMwBoAIkAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMzFRQWMzI2PQEzMjY1NCYrATU0JiMiBh0BIyIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAgBkSEhmAERkZEYAZEhIZgBEZGREDVQUEBQ4JCRUMCxkN/asNGQsMFQkIDgUFBQUFBQ4JCBUMCxkNAlUNGQsMFQkJDgUEBVUCAQIFAwIHBAQIBf2rBAkDBAcDAwUBAgICAgEFAwMHBAMJBAJVBQgEBAcCAwUCAQL+gIASGRkSgBkSERmAEhkZEoAZERIZAAABAOIAjQMeAskAIAAAExcHBhQXFjI/ARcWMjc2NC8BNzY0JyY
95iDwEnJiIHBhQX4uLiDQ0MJAzi4gwkDA0N4uINDQwkDOLiDCQMDQ0CjeLiDSMMDQ3h4Q0NDCMN4uIMIw0MDOLiDAwNIwwAAAABAAAAAQAAa5n0y18PPPUACwQAAAAAANivOVsAAAAA2K85WwAAAAADqwNVAAAACAACAAAAAAAAAAEAAAPA/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{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;-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}
95.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)}";
96    injectStyles(css_248z$4);
97
98    class DelayedRunner {
99        constructor(drainedOption) {
100            this.drainedOption = drainedOption;
101            this.isRunning = false;
102            this.isDirty = false;
103            this.pauseDepths = {};
104            this.timeoutId = 0;
105        }
106        request(delay) {
107            this.isDirty = true;
108            if (!this.isPaused()) {
109                this.clearTimeout();
110                if (delay == null) {
111                    this.tryDrain();
112                }
113                else {
114                    this.timeoutId = setTimeout(// NOT OPTIMAL! TODO: look at debounce
115                    this.tryDrain.bind(this), delay);
116                }
117            }
118        }
119        pause(scope = '') {
120            let { pauseDepths } = this;
121            pauseDepths[scope] = (pauseDepths[scope] || 0) + 1;
122            this.clearTimeout();
123        }
124        resume(scope = '', force) {
125            let { pauseDepths } = this;
126            if (scope in pauseDepths) {
127                if (force) {
128                    delete pauseDepths[scope];
129                }
130                else {
131                    pauseDepths[scope] -= 1;
132                    let depth = pauseDepths[scope];
133                    if (depth <= 0) {
134                        delete pauseDepths[scope];
135                    }
136                }
137                this.tryDrain();
138            }
139        }
140        isPaused() {
141            return Object.keys(this.pauseDepths).length;
142        }
143        tryDrain() {
144            if (!this.isRunning && !this.isPaused()) {
145                this.isRunning = true;
146                while (this.isDirty) {
147                    this.isDirty = false;
148                    this.drained(); // might set isDirty to true again
149                }
150                this.isRunning = false;
151            }
152        }
153        clear() {
154            this.clearTimeout();
155            this.isDirty = false;
156            this.pauseDepths = {};
157        }
158        clearTimeout() {
159            if (this.timeoutId) {
160                clearTimeout(this.timeoutId);
161                this.timeoutId = 0;
162            }
163        }
164        drained() {
165            if (this.drainedOption) {
166                this.drainedOption();
167            }
168        }
169    }
170
171    function removeElement(el) {
172        if (el.parentNode) {
173            el.parentNode.removeChild(el);
174        }
175    }
176    // Querying
177    // ----------------------------------------------------------------------------------------------------------------
178    function elementClosest(el, selector) {
179        if (el.closest) {
180            return el.closest(selector);
181            // really bad fallback for IE
182            // from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
183        }
184        if (!document.documentElement.contains(el)) {
185            return null;
186        }
187        do {
188            if (elementMatches(el, selector)) {
189                return el;
190            }
191            el = (el.parentElement || el.parentNode);
192        } while (el !== null && el.nodeType === 1);
193        return null;
194    }
195    function elementMatches(el, selector) {
196        let method = el.matches || el.matchesSelector || el.msMatchesSelector;
197        return method.call(el, selector);
198    }
199    // accepts multiple subject els
200    // returns a real array. good for methods like forEach
201    // TODO: accept the document
202    function findElements(container, selector) {
203        let containers = container instanceof HTMLElement ? [container] : container;
204        let allMatches = [];
205        for (let i = 0; i < containers.length; i += 1) {
206            let matches = containers[i].querySelectorAll(selector);
207            for (let j = 0; j < matches.length; j += 1) {
208                allMatches.push(matches[j]);
209            }
210        }
211        return allMatches;
212    }
213    // accepts multiple subject els
214    // only queries direct child elements // TODO: rename to findDirectChildren!
215    function findDirectChildren(parent, selector) {
216        let parents = parent instanceof HTMLElement ? [parent] : parent;
217        let allMatches = [];
218        for (let i = 0; i < parents.length; i += 1) {
219            let childNodes = parents[i].children; // only ever elements
220            for (let j = 0; j < childNodes.length; j += 1) {
221                let childNode = childNodes[j];
222                if (!selector || elementMatches(childNode, selector)) {
223                    allMatches.push(childNode);
224                }
225            }
226        }
227        return allMatches;
228    }
229    // Style
230    // ----------------------------------------------------------------------------------------------------------------
231    const PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i;
232    function applyStyle(el, props) {
233        for (let propName in props) {
234            applyStyleProp(el, propName, props[propName]);
235        }
236    }
237    function applyStyleProp(el, name, val) {
238        if (val == null) {
239            el.style[name] = '';
240        }
241        else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) {
242            el.style[name] = `${val}px`;
243        }
244        else {
245            el.style[name] = val;
246        }
247    }
248    // Event Handling
249    // ----------------------------------------------------------------------------------------------------------------
250    // if intercepting bubbled events at the document/window/body level,
251    // and want to see originating element (the 'target'), use this util instead
252    // of `ev.target` because it goes within web-component boundaries.
253    function getEventTargetViaRoot(ev) {
254        var _a, _b;
255        return (_b = (_a = ev.composedPath) === null || _a === void 0 ? void 0 : _a.call(ev)[0]) !== null && _b !== void 0 ? _b : ev.target;
256    }
257    // Unique ID for DOM attribute
258    let guid$1 = 0;
259    function getUniqueDomId() {
260        guid$1 += 1;
261        return 'fc-dom-' + guid$1;
262    }
263
264    // Stops a mouse/touch event from doing it's native browser action
265    function preventDefault(ev) {
266        ev.preventDefault();
267    }
268    // Event Delegation
269    // ----------------------------------------------------------------------------------------------------------------
270    function buildDelegationHandler(selector, handler) {
271        return (ev) => {
vendor: 47,683 bytes, lines 272-1580
272            let matchedChild = elementClosest(ev.target, selector);
273            if (matchedChild) {
274                handler.call(matchedChild, ev, matchedChild);
275            }
276        };
277    }
278    function listenBySelector(container, eventType, selector, handler) {
279        let attachedHandler = buildDelegationHandler(selector, handler);
280        container.addEventListener(eventType, attachedHandler);
281        return () => {
282            container.removeEventListener(eventType, attachedHandler);
283        };
284    }
285    function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) {
286        let currentMatchedChild;
287        return listenBySelector(container, 'mouseover', selector, (mouseOverEv, matchedChild) => {
288            if (matchedChild !== currentMatchedChild) {
289                currentMatchedChild = matchedChild;
290                onMouseEnter(mouseOverEv, matchedChild);
291                let realOnMouseLeave = (mouseLeaveEv) => {
292                    currentMatchedChild = null;
293                    onMouseLeave(mouseLeaveEv, matchedChild);
294                    matchedChild.removeEventListener('mouseleave', realOnMouseLeave);
295                };
296                // listen to the next mouseleave, and then unattach
297                matchedChild.addEventListener('mouseleave', realOnMouseLeave);
298            }
299        });
300    }
301    // Animation
302    // ----------------------------------------------------------------------------------------------------------------
303    const transitionEventNames = [
304        'webkitTransitionEnd',
305        'otransitionend',
306        'oTransitionEnd',
307        'msTransitionEnd',
308        'transitionend',
309    ];
310    // triggered only when the next single subsequent transition finishes
311    function whenTransitionDone(el, callback) {
312        let realCallback = (ev) => {
313            callback(ev);
314            transitionEventNames.forEach((eventName) => {
315                el.removeEventListener(eventName, realCallback);
316            });
317        };
318        transitionEventNames.forEach((eventName) => {
319            el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes
320        });
321    }
322    // ARIA workarounds
323    // ----------------------------------------------------------------------------------------------------------------
324    function createAriaClickAttrs(handler) {
325        return Object.assign({ onClick: handler }, createAriaKeyboardAttrs(handler));
326    }
327    function createAriaKeyboardAttrs(handler) {
328        return {
329            tabIndex: 0,
330            onKeyDown(ev) {
331                if (ev.key === 'Enter' || ev.key === ' ') {
332                    handler(ev);
333                    ev.preventDefault(); // if space, don't scroll down page
334                }
335            },
336        };
337    }
338
339    let guidNumber = 0;
340    function guid() {
341        guidNumber += 1;
342        return String(guidNumber);
343    }
344    /* FullCalendar-specific DOM Utilities
345    ----------------------------------------------------------------------------------------------------------------------*/
346    // Make the mouse cursor express that an event is not allowed in the current area
347    function disableCursor() {
348        document.body.classList.add('fc-not-allowed');
349    }
350    // Returns the mouse cursor to its original look
351    function enableCursor() {
352        document.body.classList.remove('fc-not-allowed');
353    }
354    /* Selection
355    ----------------------------------------------------------------------------------------------------------------------*/
356    function preventSelection(el) {
357        el.style.userSelect = 'none';
358        el.style.webkitUserSelect = 'none';
359        el.addEventListener('selectstart', preventDefault);
360    }
361    function allowSelection(el) {
362        el.style.userSelect = '';
363        el.style.webkitUserSelect = '';
364        el.removeEventListener('selectstart', preventDefault);
365    }
366    /* Context Menu
367    ----------------------------------------------------------------------------------------------------------------------*/
368    function preventContextMenu(el) {
369        el.addEventListener('contextmenu', preventDefault);
370    }
371    function allowContextMenu(el) {
372        el.removeEventListener('contextmenu', preventDefault);
373    }
374    function parseFieldSpecs(input) {
375        let specs = [];
376        let tokens = [];
377        let i;
378        let token;
379        if (typeof input === 'string') {
380            tokens = input.split(/\s*,\s*/);
381        }
382        else if (typeof input === 'function') {
383            tokens = [input];
384        }
385        else if (Array.isArray(input)) {
386            tokens = input;
387        }
388        for (i = 0; i < tokens.length; i += 1) {
389            token = tokens[i];
390            if (typeof token === 'string') {
391                specs.push(token.charAt(0) === '-' ?
392                    { field: token.substring(1), order: -1 } :
393                    { field: token, order: 1 });
394            }
395            else if (typeof token === 'function') {
396                specs.push({ func: token });
397            }
398        }
399        return specs;
400    }
401    function compareByFieldSpecs(obj0, obj1, fieldSpecs) {
402        let i;
403        let cmp;
404        for (i = 0; i < fieldSpecs.length; i += 1) {
405            cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]);
406            if (cmp) {
407                return cmp;
408            }
409        }
410        return 0;
411    }
412    function compareByFieldSpec(obj0, obj1, fieldSpec) {
413        if (fieldSpec.func) {
414            return fieldSpec.func(obj0, obj1);
415        }
416        return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field])
417            * (fieldSpec.order || 1);
418    }
419    function flexibleCompare(a, b) {
420        if (!a && !b) {
421            return 0;
422        }
423        if (b == null) {
424            return -1;
425        }
426        if (a == null) {
427            return 1;
428        }
429        if (typeof a === 'string' || typeof b === 'string') {
430            return String(a).localeCompare(String(b));
431        }
432        return a - b;
433    }
434    /* String Utilities
435    ----------------------------------------------------------------------------------------------------------------------*/
436    function padStart(val, len) {
437        let s = String(val);
438        return '000'.substr(0, len - s.length) + s;
439    }
440    function formatWithOrdinals(formatter, args, fallbackText) {
441        if (typeof formatter === 'function') {
442            return formatter(...args);
443        }
444        if (typeof formatter === 'string') { // non-blank string
445            return args.reduce((str, arg, index) => (str.replace('$' + index, arg || '')), formatter);
446        }
447        return fallbackText;
448    }
449    /* Number Utilities
450    ----------------------------------------------------------------------------------------------------------------------*/
451    function compareNumbers(a, b) {
452        return a - b;
453    }
454    function isInt(n) {
455        return n % 1 === 0;
456    }
457    /* FC-specific DOM dimension stuff
458    ----------------------------------------------------------------------------------------------------------------------*/
459    function computeSmallestCellWidth(cellEl) {
460        let allWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-frame');
461        let contentWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-cushion');
462        if (!allWidthEl) {
463            throw new Error('needs fc-scrollgrid-shrink-frame className'); // TODO: use const
464        }
465        if (!contentWidthEl) {
466            throw new Error('needs fc-scrollgrid-shrink-cushion className');
467        }
468        return cellEl.getBoundingClientRect().width - allWidthEl.getBoundingClientRect().width + // the cell padding+border
469            contentWidthEl.getBoundingClientRect().width;
470    }
471
472    const INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];
473    const PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/;
474    // Parsing and Creation
475    function createDuration(input, unit) {
476        if (typeof input === 'string') {
477            return parseString(input);
478        }
479        if (typeof input === 'object' && input) { // non-null object
480            return parseObject(input);
481        }
482        if (typeof input === 'number') {
483            return parseObject({ [unit || 'milliseconds']: input });
484        }
485        return null;
486    }
487    function parseString(s) {
488        let m = PARSE_RE.exec(s);
489        if (m) {
490            let sign = m[1] ? -1 : 1;
491            return {
492                years: 0,
493                months: 0,
494                days: sign * (m[2] ? parseInt(m[2], 10) : 0),
495                milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours
496                    (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes
497                    (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds
498                    (m[6] ? parseInt(m[6], 10) : 0) // ms
499                ),
500            };
501        }
502        return null;
503    }
504    function parseObject(obj) {
505        let duration = {
506            years: obj.years || obj.year || 0,
507            months: obj.months || obj.month || 0,
508            days: obj.days || obj.day || 0,
509            milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours
510                (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes
511                (obj.seconds || obj.second || 0) * 1000 + // seconds
512                (obj.milliseconds || obj.millisecond || obj.ms || 0), // ms
513        };
514        let weeks = obj.weeks || obj.week;
515        if (weeks) {
516            duration.days += weeks * 7;
517            duration.specifiedWeeks = true;
518        }
519        return duration;
520    }
521    // Equality
522    function durationsEqual(d0, d1) {
523        return d0.years === d1.years &&
524            d0.months === d1.months &&
525            d0.days === d1.days &&
526            d0.milliseconds === d1.milliseconds;
527    }
528    function asCleanDays(dur) {
529        if (!dur.years && !dur.months && !dur.milliseconds) {
530            return dur.days;
531        }
532        return 0;
533    }
534    // Simple Math
535    function addDurations(d0, d1) {
536        return {
537            years: d0.years + d1.years,
538            months: d0.months + d1.months,
539            days: d0.days + d1.days,
540            milliseconds: d0.milliseconds + d1.milliseconds,
541        };
542    }
543    function subtractDurations(d1, d0) {
544        return {
545            years: d1.years - d0.years,
546            months: d1.months - d0.months,
547            days: d1.days - d0.days,
548            milliseconds: d1.milliseconds - d0.milliseconds,
549        };
550    }
551    function multiplyDuration(d, n) {
552        return {
553            years: d.years * n,
554            months: d.months * n,
555            days: d.days * n,
556            milliseconds: d.milliseconds * n,
557        };
558    }
559    // Conversions
560    // "Rough" because they are based on average-case Gregorian months/years
561    function asRoughYears(dur) {
562        return asRoughDays(dur) / 365;
563    }
564    function asRoughMonths(dur) {
565        return asRoughDays(dur) / 30;
566    }
567    function asRoughDays(dur) {
568        return asRoughMs(dur) / 864e5;
569    }
570    function asRoughMinutes(dur) {
571        return asRoughMs(dur) / (1000 * 60);
572    }
573    function asRoughSeconds(dur) {
574        return asRoughMs(dur) / 1000;
575    }
576    function asRoughMs(dur) {
577        return dur.years * (365 * 864e5) +
578            dur.months * (30 * 864e5) +
579            dur.days * 864e5 +
580            dur.milliseconds;
581    }
582    // Advanced Math
583    function wholeDivideDurations(numerator, denominator) {
584        let res = null;
585        for (let i = 0; i < INTERNAL_UNITS.length; i += 1) {
586            let unit = INTERNAL_UNITS[i];
587            if (denominator[unit]) {
588                let localRes = numerator[unit] / denominator[unit];
589                if (!isInt(localRes) || (res !== null && res !== localRes)) {
590                    return null;
591                }
592                res = localRes;
593            }
594            else if (numerator[unit]) {
595                // needs to divide by something but can't!
596                return null;
597            }
598        }
599        return res;
600    }
601    function greatestDurationDenominator(dur) {
602        let ms = dur.milliseconds;
603        if (ms) {
604            if (ms % 1000 !== 0) {
605                return { unit: 'millisecond', value: ms };
606            }
607            if (ms % (1000 * 60) !== 0) {
608                return { unit: 'second', value: ms / 1000 };
609            }
610            if (ms % (1000 * 60 * 60) !== 0) {
611                return { unit: 'minute', value: ms / (1000 * 60) };
612            }
613            if (ms) {
614                return { unit: 'hour', value: ms / (1000 * 60 * 60) };
615            }
616        }
617        if (dur.days) {
618            if (dur.specifiedWeeks && dur.days % 7 === 0) {
619                return { unit: 'week', value: dur.days / 7 };
620            }
621            return { unit: 'day', value: dur.days };
622        }
623        if (dur.months) {
624            return { unit: 'month', value: dur.months };
625        }
626        if (dur.years) {
627            return { unit: 'year', value: dur.years };
628        }
629        return { unit: 'millisecond', value: 0 };
630    }
631
632    // TODO: new util arrayify?
633    function removeExact(array, exactVal) {
634        let removeCnt = 0;
635        let i = 0;
636        while (i < array.length) {
637            if (array[i] === exactVal) {
638                array.splice(i, 1);
639                removeCnt += 1;
640            }
641            else {
642                i += 1;
643            }
644        }
645        return removeCnt;
646    }
647    function isArraysEqual(a0, a1, equalityFunc) {
648        if (a0 === a1) {
649            return true;
650        }
651        let len = a0.length;
652        let i;
653        if (len !== a1.length) { // not array? or not same length?
654            return false;
655        }
656        for (i = 0; i < len; i += 1) {
657            if (!(equalityFunc ? equalityFunc(a0[i], a1[i]) : a0[i] === a1[i])) {
658                return false;
659            }
660        }
661        return true;
662    }
663
664    const DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
665    // Adding
666    function addWeeks(m, n) {
667        let a = dateToUtcArray(m);
668        a[2] += n * 7;
669        return arrayToUtcDate(a);
670    }
671    function addDays(m, n) {
672        let a = dateToUtcArray(m);
673        a[2] += n;
674        return arrayToUtcDate(a);
675    }
676    function addMs(m, n) {
677        let a = dateToUtcArray(m);
678        a[6] += n;
679        return arrayToUtcDate(a);
680    }
681    // Diffing (all return floats)
682    // TODO: why not use ranges?
683    function diffWeeks(m0, m1) {
684        return diffDays(m0, m1) / 7;
685    }
686    function diffDays(m0, m1) {
687        return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24);
688    }
689    function diffHours(m0, m1) {
690        return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60);
691    }
692    function diffMinutes(m0, m1) {
693        return (m1.valueOf() - m0.valueOf()) / (1000 * 60);
694    }
695    function diffSeconds(m0, m1) {
696        return (m1.valueOf() - m0.valueOf()) / 1000;
697    }
698    function diffDayAndTime(m0, m1) {
699        let m0day = startOfDay(m0);
700        let m1day = startOfDay(m1);
701        return {
702            years: 0,
703            months: 0,
704            days: Math.round(diffDays(m0day, m1day)),
705            milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()),
706        };
707    }
708    // Diffing Whole Units
709    function diffWholeWeeks(m0, m1) {
710        let d = diffWholeDays(m0, m1);
711        if (d !== null && d % 7 === 0) {
712            return d / 7;
713        }
714        return null;
715    }
716    function diffWholeDays(m0, m1) {
717        if (timeAsMs(m0) === timeAsMs(m1)) {
718            return Math.round(diffDays(m0, m1));
719        }
720        return null;
721    }
722    // Start-Of
723    function startOfDay(m) {
724        return arrayToUtcDate([
725            m.getUTCFullYear(),
726            m.getUTCMonth(),
727            m.getUTCDate(),
728        ]);
729    }
730    function startOfHour(m) {
731        return arrayToUtcDate([
732            m.getUTCFullYear(),
733            m.getUTCMonth(),
734            m.getUTCDate(),
735            m.getUTCHours(),
736        ]);
737    }
738    function startOfMinute(m) {
739        return arrayToUtcDate([
740            m.getUTCFullYear(),
741            m.getUTCMonth(),
742            m.getUTCDate(),
743            m.getUTCHours(),
744            m.getUTCMinutes(),
745        ]);
746    }
747    function startOfSecond(m) {
748        return arrayToUtcDate([
749            m.getUTCFullYear(),
750            m.getUTCMonth(),
751            m.getUTCDate(),
752            m.getUTCHours(),
753            m.getUTCMinutes(),
754            m.getUTCSeconds(),
755        ]);
756    }
757    // Week Computation
758    function weekOfYear(marker, dow, doy) {
759        let y = marker.getUTCFullYear();
760        let w = weekOfGivenYear(marker, y, dow, doy);
761        if (w < 1) {
762            return weekOfGivenYear(marker, y - 1, dow, doy);
763        }
764        let nextW = weekOfGivenYear(marker, y + 1, dow, doy);
765        if (nextW >= 1) {
766            return Math.min(w, nextW);
767        }
768        return w;
769    }
770    function weekOfGivenYear(marker, year, dow, doy) {
771        let firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]);
772        let dayStart = startOfDay(marker);
773        let days = Math.round(diffDays(firstWeekStart, dayStart));
774        return Math.floor(days / 7) + 1; // zero-indexed
775    }
776    // start-of-first-week - start-of-year
777    function firstWeekOffset(year, dow, doy) {
778        // first-week day -- which january is always in the first week (4 for iso, 1 for other)
779        let fwd = 7 + dow - doy;
780        // first-week day local weekday -- which local weekday is fwd
781        let fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7;
782        return -fwdlw + fwd - 1;
783    }
784    // Array Conversion
785    function dateToLocalArray(date) {
786        return [
787            date.getFullYear(),
788            date.getMonth(),
789            date.getDate(),
790            date.getHours(),
791            date.getMinutes(),
792            date.getSeconds(),
793            date.getMilliseconds(),
794        ];
795    }
796    function arrayToLocalDate(a) {
797        return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month
798        a[3] || 0, a[4] || 0, a[5] || 0);
799    }
800    function dateToUtcArray(date) {
801        return [
802            date.getUTCFullYear(),
803            date.getUTCMonth(),
804            date.getUTCDate(),
805            date.getUTCHours(),
806            date.getUTCMinutes(),
807            date.getUTCSeconds(),
808            date.getUTCMilliseconds(),
809        ];
810    }
811    function arrayToUtcDate(a) {
812        // according to web standards (and Safari), a month index is required.
813        // massage if only given a year.
814        if (a.length === 1) {
815            a = a.concat([0]);
816        }
817        return new Date(Date.UTC(...a));
818    }
819    // Other Utils
820    function isValidDate(m) {
821        return !isNaN(m.valueOf());
822    }
823    function timeAsMs(m) {
824        return m.getUTCHours() * 1000 * 60 * 60 +
825            m.getUTCMinutes() * 1000 * 60 +
826            m.getUTCSeconds() * 1000 +
827            m.getUTCMilliseconds();
828    }
829
830    // timeZoneOffset is in minutes
831    function buildIsoString(marker, timeZoneOffset, stripZeroTime = false) {
832        let s = marker.toISOString();
833        s = s.replace('.000', '');
834        if (stripZeroTime) {
835            s = s.replace('T00:00:00Z', '');
836        }
837        if (s.length > 10) { // time part wasn't stripped, can add timezone info
838            if (timeZoneOffset == null) {
839                s = s.replace('Z', '');
840            }
841            else if (timeZoneOffset !== 0) {
842                s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true));
843            }
844            // otherwise, its UTC-0 and we want to keep the Z
845        }
846        return s;
847    }
848    // formats the date, but with no time part
849    // TODO: somehow merge with buildIsoString and stripZeroTime
850    // TODO: rename. omit "string"
851    function formatDayString(marker) {
852        return marker.toISOString().replace(/T.*$/, '');
853    }
854    function formatIsoMonthStr(marker) {
855        return marker.toISOString().match(/^\d{4}-\d{2}/)[0];
856    }
857    // TODO: use Date::toISOString and use everything after the T?
858    function formatIsoTimeString(marker) {
859        return padStart(marker.getUTCHours(), 2) + ':' +
860            padStart(marker.getUTCMinutes(), 2) + ':' +
861            padStart(marker.getUTCSeconds(), 2);
862    }
863    function formatTimeZoneOffset(minutes, doIso = false) {
864        let sign = minutes < 0 ? '-' : '+';
865        let abs = Math.abs(minutes);
866        let hours = Math.floor(abs / 60);
867        let mins = Math.round(abs % 60);
868        if (doIso) {
869            return `${sign + padStart(hours, 2)}:${padStart(mins, 2)}`;
870        }
871        return `GMT${sign}${hours}${mins ? `:${padStart(mins, 2)}` : ''}`;
872    }
873
874    function memoize(workerFunc, resEquality, teardownFunc) {
875        let currentArgs;
876        let currentRes;
877        return function (...newArgs) {
878            if (!currentArgs) {
879                currentRes = workerFunc.apply(this, newArgs);
880            }
881            else if (!isArraysEqual(currentArgs, newArgs)) {
882                if (teardownFunc) {
883                    teardownFunc(currentRes);
884                }
885                let res = workerFunc.apply(this, newArgs);
886                if (!resEquality || !resEquality(res, currentRes)) {
887                    currentRes = res;
888                }
889            }
890            currentArgs = newArgs;
891            return currentRes;
892        };
893    }
894    function memoizeObjArg(workerFunc, resEquality, teardownFunc) {
895        let currentArg;
896        let currentRes;
897        return (newArg) => {
898            if (!currentArg) {
899                currentRes = workerFunc.call(this, newArg);
900            }
901            else if (!isPropsEqual(currentArg, newArg)) {
902                if (teardownFunc) {
903                    teardownFunc(currentRes);
904                }
905                let res = workerFunc.call(this, newArg);
906                if (!resEquality || !resEquality(res, currentRes)) {
907                    currentRes = res;
908                }
909            }
910            currentArg = newArg;
911            return currentRes;
912        };
913    }
914    function memoizeArraylike(// used at all?
915    workerFunc, resEquality, teardownFunc) {
916        let currentArgSets = [];
917        let currentResults = [];
918        return (newArgSets) => {
919            let currentLen = currentArgSets.length;
920            let newLen = newArgSets.length;
921            let i = 0;
922            for (; i < currentLen; i += 1) {
923                if (!newArgSets[i]) { // one of the old sets no longer exists
924                    if (teardownFunc) {
925                        teardownFunc(currentResults[i]);
926                    }
927                }
928                else if (!isArraysEqual(currentArgSets[i], newArgSets[i])) {
929                    if (teardownFunc) {
930                        teardownFunc(currentResults[i]);
931                    }
932                    let res = workerFunc.apply(this, newArgSets[i]);
933                    if (!resEquality || !resEquality(res, currentResults[i])) {
934                        currentResults[i] = res;
935                    }
936                }
937            }
938            for (; i < newLen; i += 1) {
939                currentResults[i] = workerFunc.apply(this, newArgSets[i]);
940            }
941            currentArgSets = newArgSets;
942            currentResults.splice(newLen); // remove excess
943            return currentResults;
944        };
945    }
946    function memoizeHashlike(workerFunc, resEquality, teardownFunc) {
947        let currentArgHash = {};
948        let currentResHash = {};
949        return (newArgHash) => {
950            let newResHash = {};
951            for (let key in newArgHash) {
952                if (!currentResHash[key]) {
953                    newResHash[key] = workerFunc.apply(this, newArgHash[key]);
954                }
955                else if (!isArraysEqual(currentArgHash[key], newArgHash[key])) {
956                    if (teardownFunc) {
957                        teardownFunc(currentResHash[key]);
958                    }
959                    let res = workerFunc.apply(this, newArgHash[key]);
960                    newResHash[key] = (resEquality && resEquality(res, currentResHash[key]))
961                        ? currentResHash[key]
962                        : res;
963                }
964                else {
965                    newResHash[key] = currentResHash[key];
966                }
967            }
968            currentArgHash = newArgHash;
969            currentResHash = newResHash;
970            return newResHash;
971        };
972    }
973
974    const EXTENDED_SETTINGS_AND_SEVERITIES = {
975        week: 3,
976        separator: 9,
977        omitZeroMinute: 9,
978        meridiem: 9,
979        omitCommas: 9,
980    };
981    const STANDARD_DATE_PROP_SEVERITIES = {
982        timeZoneName: 7,
983        era: 6,
984        year: 5,
985        month: 4,
986        day: 2,
987        weekday: 2,
988        hour: 1,
989        minute: 1,
990        second: 1,
991    };
992    const MERIDIEM_RE = /\s*([ap])\.?m\.?/i; // eats up leading spaces too
993    const COMMA_RE = /,/g; // we need re for globalness
994    const MULTI_SPACE_RE = /\s+/g;
995    const LTR_RE = /\u200e/g; // control character
996    const UTC_RE = /UTC|GMT/;
997    class NativeFormatter {
998        constructor(formatSettings) {
999            let standardDateProps = {};
1000            let extendedSettings = {};
1001            let smallestUnitNum = 9; // the smallest unit in the formatter (9 is a sentinel, beyond max)
1002            for (let name in formatSettings) {
1003                if (name in EXTENDED_SETTINGS_AND_SEVERITIES) {
1004                    extendedSettings[name] = formatSettings[name];
1005                    const severity = EXTENDED_SETTINGS_AND_SEVERITIES[name];
1006                    if (severity < 9) {
1007                        smallestUnitNum = Math.min(EXTENDED_SETTINGS_AND_SEVERITIES[name], smallestUnitNum);
1008                    }
1009                }
1010                else {
1011                    standardDateProps[name] = formatSettings[name];
1012                    if (name in STANDARD_DATE_PROP_SEVERITIES) { // TODO: what about hour12? no severity
1013                        smallestUnitNum = Math.min(STANDARD_DATE_PROP_SEVERITIES[name], smallestUnitNum);
1014                    }
1015                }
1016            }
1017            this.standardDateProps = standardDateProps;
1018            this.extendedSettings = extendedSettings;
1019            this.smallestUnitNum = smallestUnitNum;
1020            this.buildFormattingFunc = memoize(buildFormattingFunc);
1021        }
1022        format(date, context) {
1023            return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date);
1024        }
1025        formatRange(start, end, context, betterDefaultSeparator) {
1026            let { standardDateProps, extendedSettings } = this;
1027            let diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem);
1028            if (!diffSeverity) {
1029                return this.format(start, context);
1030            }
1031            let biggestUnitForPartial = diffSeverity;
1032            if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time
1033                (standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') &&
1034                (standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') &&
1035                (standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) {
1036                biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time
1037            }
1038            let full0 = this.format(start, context);
1039            let full1 = this.format(end, context);
1040            if (full0 === full1) {
1041                return full0;
1042            }
1043            let partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForPartial);
1044            let partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context);
1045            let partial0 = partialFormattingFunc(start);
1046            let partial1 = partialFormattingFunc(end);
1047            let insertion = findCommonInsertion(full0, partial0, full1, partial1);
1048            let separator = extendedSettings.separator || betterDefaultSeparator || context.defaultSeparator || '';
1049            if (insertion) {
1050                return insertion.before + partial0 + separator + partial1 + insertion.after;
1051            }
1052            return full0 + separator + full1;
1053        }
1054        getSmallestUnit() {
1055            switch (this.smallestUnitNum) {
1056                case 7:
1057                case 6:
1058                case 5:
1059                    return 'year';
1060                case 4:
1061                    return 'month';
1062                case 3:
1063                    return 'week';
1064                case 2:
1065                    return 'day';
1066                default:
1067                    return 'time'; // really?
1068            }
1069        }
1070    }
1071    function buildFormattingFunc(standardDateProps, extendedSettings, context) {
1072        let standardDatePropCnt = Object.keys(standardDateProps).length;
1073        if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') {
1074            return (date) => (formatTimeZoneOffset(date.timeZoneOffset));
1075        }
1076        if (standardDatePropCnt === 0 && extendedSettings.week) {
1077            return (date) => (formatWeekNumber(context.computeWeekNumber(date.marker), context.weekText, context.weekTextLong, context.locale, extendedSettings.week));
1078        }
1079        return buildNativeFormattingFunc(standardDateProps, extendedSettings, context);
1080    }
1081    function buildNativeFormattingFunc(standardDateProps, extendedSettings, context) {
1082        standardDateProps = Object.assign({}, standardDateProps); // copy
1083        extendedSettings = Object.assign({}, extendedSettings); // copy
1084        sanitizeSettings(standardDateProps, extendedSettings);
1085        standardDateProps.timeZone = 'UTC'; // we leverage the only guaranteed timeZone for our UTC markers
1086        let normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps);
1087        let zeroFormat; // needed?
1088        if (extendedSettings.omitZeroMinute) {
1089            let zeroProps = Object.assign({}, standardDateProps);
1090            delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings
1091            zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps);
1092        }
1093        return (date) => {
1094            let { marker } = date;
1095            let format;
1096            if (zeroFormat && !marker.getUTCMinutes()) {
1097                format = zeroFormat;
1098            }
1099            else {
1100                format = normalFormat;
1101            }
1102            let s = format.format(marker);
1103            return postProcess(s, date, standardDateProps, extendedSettings, context);
1104        };
1105    }
1106    function sanitizeSettings(standardDateProps, extendedSettings) {
1107        // deal with a browser inconsistency where formatting the timezone
1108        // requires that the hour/minute be present.
1109        if (standardDateProps.timeZoneName) {
1110            if (!standardDateProps.hour) {
1111                standardDateProps.hour = '2-digit';
1112            }
1113            if (!standardDateProps.minute) {
1114                standardDateProps.minute = '2-digit';
1115            }
1116        }
1117        // only support short timezone names
1118        if (standardDateProps.timeZoneName === 'long') {
1119            standardDateProps.timeZoneName = 'short';
1120        }
1121        // if requesting to display seconds, MUST display minutes
1122        if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) {
1123            delete extendedSettings.omitZeroMinute;
1124        }
1125    }
1126    function postProcess(s, date, standardDateProps, extendedSettings, context) {
1127        s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes
1128        if (standardDateProps.timeZoneName === 'short') {
1129            s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ?
1130                'UTC' : // important to normalize for IE, which does "GMT"
1131                formatTimeZoneOffset(date.timeZoneOffset));
1132        }
1133        if (extendedSettings.omitCommas) {
1134            s = s.replace(COMMA_RE, '').trim();
1135        }
1136        if (extendedSettings.omitZeroMinute) {
1137            s = s.replace(':00', ''); // zeroFormat doesn't always achieve this
1138        }
1139        // ^ do anything that might create adjacent spaces before this point,
1140        // because MERIDIEM_RE likes to eat up loading spaces
1141        if (extendedSettings.meridiem === false) {
1142            s = s.replace(MERIDIEM_RE, '').trim();
1143        }
1144        else if (extendedSettings.meridiem === 'narrow') { // a/p
1145            s = s.replace(MERIDIEM_RE, (m0, m1) => m1.toLocaleLowerCase());
1146        }
1147        else if (extendedSettings.meridiem === 'short') { // am/pm
1148            s = s.replace(MERIDIEM_RE, (m0, m1) => `${m1.toLocaleLowerCase()}m`);
1149        }
1150        else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase
1151            s = s.replace(MERIDIEM_RE, (m0) => m0.toLocaleLowerCase());
1152        }
1153        s = s.replace(MULTI_SPACE_RE, ' ');
1154        s = s.trim();
1155        return s;
1156    }
1157    function injectTzoStr(s, tzoStr) {
1158        let replaced = false;
1159        s = s.replace(UTC_RE, () => {
1160            replaced = true;
1161            return tzoStr;
1162        });
1163        // IE11 doesn't include UTC/GMT in the original string, so append to end
1164        if (!replaced) {
1165            s += ` ${tzoStr}`;
1166        }
1167        return s;
1168    }
1169    function formatWeekNumber(num, weekText, weekTextLong, locale, display) {
1170        let parts = [];
1171        if (display === 'long') {
1172            parts.push(weekTextLong);
1173        }
1174        else if (display === 'short' || display === 'narrow') {
1175            parts.push(weekText);
1176        }
1177        if (display === 'long' || display === 'short') {
1178            parts.push(' ');
1179        }
1180        parts.push(locale.simpleNumberFormat.format(num));
1181        if (locale.options.direction === 'rtl') { // TODO: use control characters instead?
1182            parts.reverse();
1183        }
1184        return parts.join('');
1185    }
1186    // Range Formatting Utils
1187    // 0 = exactly the same
1188    // 1 = different by time
1189    // and bigger
1190    function computeMarkerDiffSeverity(d0, d1, ca) {
1191        if (ca.getMarkerYear(d0) !== ca.getMarkerYear(d1)) {
1192            return 5;
1193        }
1194        if (ca.getMarkerMonth(d0) !== ca.getMarkerMonth(d1)) {
1195            return 4;
1196        }
1197        if (ca.getMarkerDay(d0) !== ca.getMarkerDay(d1)) {
1198            return 2;
1199        }
1200        if (timeAsMs(d0) !== timeAsMs(d1)) {
1201            return 1;
1202        }
1203        return 0;
1204    }
1205    function computePartialFormattingOptions(options, biggestUnit) {
1206        let partialOptions = {};
1207        for (let name in options) {
1208            if (!(name in STANDARD_DATE_PROP_SEVERITIES) || // not a date part prop (like timeZone)
1209                STANDARD_DATE_PROP_SEVERITIES[name] <= biggestUnit) {
1210                partialOptions[name] = options[name];
1211            }
1212        }
1213        return partialOptions;
1214    }
1215    function findCommonInsertion(full0, partial0, full1, partial1) {
1216        let i0 = 0;
1217        while (i0 < full0.length) {
1218            let found0 = full0.indexOf(partial0, i0);
1219            if (found0 === -1) {
1220                break;
1221            }
1222            let before0 = full0.substr(0, found0);
1223            i0 = found0 + partial0.length;
1224            let after0 = full0.substr(i0);
1225            let i1 = 0;
1226            while (i1 < full1.length) {
1227                let found1 = full1.indexOf(partial1, i1);
1228                if (found1 === -1) {
1229                    break;
1230                }
1231                let before1 = full1.substr(0, found1);
1232                i1 = found1 + partial1.length;
1233                let after1 = full1.substr(i1);
1234                if (before0 === before1 && after0 === after1) {
1235                    return {
1236                        before: before0,
1237                        after: after0,
1238                    };
1239                }
1240            }
1241        }
1242        return null;
1243    }
1244
1245    function expandZonedMarker(dateInfo, calendarSystem) {
1246        let a = calendarSystem.markerToArray(dateInfo.marker);
1247        return {
1248            marker: dateInfo.marker,
1249            timeZoneOffset: dateInfo.timeZoneOffset,
1250            array: a,
1251            year: a[0],
1252            month: a[1],
1253            day: a[2],
1254            hour: a[3],
1255            minute: a[4],
1256            second: a[5],
1257            millisecond: a[6],
1258        };
1259    }
1260
1261    function createVerboseFormattingArg(start, end, context, betterDefaultSeparator) {
1262        let startInfo = expandZonedMarker(start, context.calendarSystem);
1263        let endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null;
1264        return {
1265            date: startInfo,
1266            start: startInfo,
1267            end: endInfo,
1268            timeZone: context.timeZone,
1269            localeCodes: context.locale.codes,
1270            defaultSeparator: betterDefaultSeparator || context.defaultSeparator,
1271        };
1272    }
1273
1274    /*
1275    TODO: fix the terminology of "formatter" vs "formatting func"
1276    */
1277    /*
1278    At the time of instantiation, this object does not know which cmd-formatting system it will use.
1279    It receives this at the time of formatting, as a setting.
1280    */
1281    class CmdFormatter {
1282        constructor(cmdStr) {
1283            this.cmdStr = cmdStr;
1284        }
1285        format(date, context, betterDefaultSeparator) {
1286            return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, betterDefaultSeparator));
1287        }
1288        formatRange(start, end, context, betterDefaultSeparator) {
1289            return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, betterDefaultSeparator));
1290        }
1291    }
1292
1293    class FuncFormatter {
1294        constructor(func) {
1295            this.func = func;
1296        }
1297        format(date, context, betterDefaultSeparator) {
1298            return this.func(createVerboseFormattingArg(date, null, context, betterDefaultSeparator));
1299        }
1300        formatRange(start, end, context, betterDefaultSeparator) {
1301            return this.func(createVerboseFormattingArg(start, end, context, betterDefaultSeparator));
1302        }
1303    }
1304
1305    function createFormatter(input) {
1306        if (typeof input === 'object' && input) { // non-null object
1307            return new NativeFormatter(input);
1308        }
1309        if (typeof input === 'string') {
1310            return new CmdFormatter(input);
1311        }
1312        if (typeof input === 'function') {
1313            return new FuncFormatter(input);
1314        }
1315        return null;
1316    }
1317
1318    // base options
1319    // ------------
1320    const BASE_OPTION_REFINERS = {
1321        navLinkDayClick: identity,
1322        navLinkWeekClick: identity,
1323        duration: createDuration,
1324        bootstrapFontAwesome: identity,
1325        buttonIcons: identity,
1326        customButtons: identity,
1327        defaultAllDayEventDuration: createDuration,
1328        defaultTimedEventDuration: createDuration,
1329        nextDayThreshold: createDuration,
1330        scrollTime: createDuration,
1331        scrollTimeReset: Boolean,
1332        slotMinTime: createDuration,
1333        slotMaxTime: createDuration,
1334        dayPopoverFormat: createFormatter,
1335        slotDuration: createDuration,
1336        snapDuration: createDuration,
1337        headerToolbar: identity,
1338        footerToolbar: identity,
1339        defaultRangeSeparator: String,
1340        titleRangeSeparator: String,
1341        forceEventDuration: Boolean,
1342        dayHeaders: Boolean,
1343        dayHeaderFormat: createFormatter,
1344        dayHeaderClassNames: identity,
1345        dayHeaderContent: identity,
1346        dayHeaderDidMount: identity,
1347        dayHeaderWillUnmount: identity,
1348        dayCellClassNames: identity,
1349        dayCellContent: identity,
1350        dayCellDidMount: identity,
1351        dayCellWillUnmount: identity,
1352        initialView: String,
1353        aspectRatio: Number,
1354        weekends: Boolean,
1355        weekNumberCalculation: identity,
1356        weekNumbers: Boolean,
1357        weekNumberClassNames: identity,
1358        weekNumberContent: identity,
1359        weekNumberDidMount: identity,
1360        weekNumberWillUnmount: identity,
1361        editable: Boolean,
1362        viewClassNames: identity,
1363        viewDidMount: identity,
1364        viewWillUnmount: identity,
1365        nowIndicator: Boolean,
1366        nowIndicatorClassNames: identity,
1367        nowIndicatorContent: identity,
1368        nowIndicatorDidMount: identity,
1369        nowIndicatorWillUnmount: identity,
1370        showNonCurrentDates: Boolean,
1371        lazyFetching: Boolean,
1372        startParam: String,
1373        endParam: String,
1374        timeZoneParam: String,
1375        timeZone: String,
1376        locales: identity,
1377        locale: identity,
1378        themeSystem: String,
1379        dragRevertDuration: Number,
1380        dragScroll: Boolean,
1381        allDayMaintainDuration: Boolean,
1382        unselectAuto: Boolean,
1383        dropAccept: identity,
1384        eventOrder: parseFieldSpecs,
1385        eventOrderStrict: Boolean,
1386        handleWindowResize: Boolean,
1387        windowResizeDelay: Number,
1388        longPressDelay: Number,
1389        eventDragMinDistance: Number,
1390        expandRows: Boolean,
1391        height: identity,
1392        contentHeight: identity,
1393        direction: String,
1394        weekNumberFormat: createFormatter,
1395        eventResizableFromStart: Boolean,
1396        displayEventTime: Boolean,
1397        displayEventEnd: Boolean,
1398        weekText: String,
1399        weekTextLong: String,
1400        progressiveEventRendering: Boolean,
1401        businessHours: identity,
1402        initialDate: identity,
1403        now: identity,
1404        eventDataTransform: identity,
1405        stickyHeaderDates: identity,
1406        stickyFooterScrollbar: identity,
1407        viewHeight: identity,
1408        defaultAllDay: Boolean,
1409        eventSourceFailure: identity,
1410        eventSourceSuccess: identity,
1411        eventDisplay: String,
1412        eventStartEditable: Boolean,
1413        eventDurationEditable: Boolean,
1414        eventOverlap: identity,
1415        eventConstraint: identity,
1416        eventAllow: identity,
1417        eventBackgroundColor: String,
1418        eventBorderColor: String,
1419        eventTextColor: String,
1420        eventColor: String,
1421        eventClassNames: identity,
1422        eventContent: identity,
1423        eventDidMount: identity,
1424        eventWillUnmount: identity,
1425        selectConstraint: identity,
1426        selectOverlap: identity,
1427        selectAllow: identity,
1428        droppable: Boolean,
1429        unselectCancel: String,
1430        slotLabelFormat: identity,
1431        slotLaneClassNames: identity,
1432        slotLaneContent: identity,
1433        slotLaneDidMount: identity,
1434        slotLaneWillUnmount: identity,
1435        slotLabelClassNames: identity,
1436        slotLabelContent: identity,
1437        slotLabelDidMount: identity,
1438        slotLabelWillUnmount: identity,
1439        dayMaxEvents: identity,
1440        dayMaxEventRows: identity,
1441        dayMinWidth: Number,
1442        slotLabelInterval: createDuration,
1443        allDayText: String,
1444        allDayClassNames: identity,
1445        allDayContent: identity,
1446        allDayDidMount: identity,
1447        allDayWillUnmount: identity,
1448        slotMinWidth: Number,
1449        navLinks: Boolean,
1450        eventTimeFormat: createFormatter,
1451        rerenderDelay: Number,
1452        moreLinkText: identity,
1453        moreLinkHint: identity,
1454        selectMinDistance: Number,
1455        selectable: Boolean,
1456        selectLongPressDelay: Number,
1457        eventLongPressDelay: Number,
1458        selectMirror: Boolean,
1459        eventMaxStack: Number,
1460        eventMinHeight: Number,
1461        eventMinWidth: Number,
1462        eventShortHeight: Number,
1463        slotEventOverlap: Boolean,
1464        plugins: identity,
1465        firstDay: Number,
1466        dayCount: Number,
1467        dateAlignment: String,
1468        dateIncrement: createDuration,
1469        hiddenDays: identity,
1470        fixedWeekCount: Boolean,
1471        validRange: identity,
1472        visibleRange: identity,
1473        titleFormat: identity,
1474        eventInteractive: Boolean,
1475        // only used by list-view, but languages define the value, so we need it in base options
1476        noEventsText: String,
1477        viewHint: identity,
1478        navLinkHint: identity,
1479        closeHint: String,
1480        timeHint: String,
1481        eventHint: String,
1482        moreLinkClick: identity,
1483        moreLinkClassNames: identity,
1484        moreLinkContent: identity,
1485        moreLinkDidMount: identity,
1486        moreLinkWillUnmount: identity,
1487        monthStartFormat: createFormatter,
1488        // for connectors
1489        // (can't be part of plugin system b/c must be provided at runtime)
1490        handleCustomRendering: identity,
1491        customRenderingMetaMap: identity,
1492        customRenderingReplaces: Boolean,
1493    };
1494    // do NOT give a type here. need `typeof BASE_OPTION_DEFAULTS` to give real results.
1495    // raw values.
1496    const BASE_OPTION_DEFAULTS = {
1497        eventDisplay: 'auto',
1498        defaultRangeSeparator: ' - ',
1499        titleRangeSeparator: ' \u2013 ',
1500        defaultTimedEventDuration: '01:00:00',
1501        defaultAllDayEventDuration: { day: 1 },
1502        forceEventDuration: false,
1503        nextDayThreshold: '00:00:00',
1504        dayHeaders: true,
1505        initialView: '',
1506        aspectRatio: 1.35,
1507        headerToolbar: {
1508            start: 'title',
1509            center: '',
1510            end: 'today prev,next',
1511        },
1512        weekends: true,
1513        weekNumbers: false,
1514        weekNumberCalculation: 'local',
1515        editable: false,
1516        nowIndicator: false,
1517        scrollTime: '06:00:00',
1518        scrollTimeReset: true,
1519        slotMinTime: '00:00:00',
1520        slotMaxTime: '24:00:00',
1521        showNonCurrentDates: true,
1522        lazyFetching: true,
1523        startParam: 'start',
1524        endParam: 'end',
1525        timeZoneParam: 'timeZone',
1526        timeZone: 'local',
1527        locales: [],
1528        locale: '',
1529        themeSystem: 'standard',
1530        dragRevertDuration: 500,
1531        dragScroll: true,
1532        allDayMaintainDuration: false,
1533        unselectAuto: true,
1534        dropAccept: '*',
1535        eventOrder: 'start,-duration,allDay,title',
1536        dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' },
1537        handleWindowResize: true,
1538        windowResizeDelay: 100,
1539        longPressDelay: 1000,
1540        eventDragMinDistance: 5,
1541        expandRows: false,
1542        navLinks: false,
1543        selectable: false,
1544        eventMinHeight: 15,
1545        eventMinWidth: 30,
1546        eventShortHeight: 30,
1547        monthStartFormat: { month: 'long', day: 'numeric' },
1548    };
1549    // calendar listeners
1550    // ------------------
1551    const CALENDAR_LISTENER_REFINERS = {
1552        datesSet: identity,
1553        eventsSet: identity,
1554        eventAdd: identity,
1555        eventChange: identity,
1556        eventRemove: identity,
1557        windowResize: identity,
1558        eventClick: identity,
1559        eventMouseEnter: identity,
1560        eventMouseLeave: identity,
1561        select: identity,
1562        unselect: identity,
1563        loading: identity,
1564        // internal
1565        _unmount: identity,
1566        _beforeprint: identity,
1567        _afterprint: identity,
1568        _noEventDrop: identity,
1569        _noEventResize: identity,
1570        _resize: identity,
1571        _scrollRequest: identity,
1572    };
1573    // calendar-specific options
1574    // -------------------------
1575    const CALENDAR_OPTION_REFINERS = {
1576        buttonText: identity,
1577        buttonHints: identity,
1578        views: identity,
1579        plugins: identity,
1580        initialEvents: identity,
vendor: 10,012 bytes, lines 1581-1874
1581        events: identity,
1582        eventSources: identity,
1583    };
1584    const COMPLEX_OPTION_COMPARATORS = {
1585        headerToolbar: isMaybeObjectsEqual,
1586        footerToolbar: isMaybeObjectsEqual,
1587        buttonText: isMaybeObjectsEqual,
1588        buttonHints: isMaybeObjectsEqual,
1589        buttonIcons: isMaybeObjectsEqual,
1590        dateIncrement: isMaybeObjectsEqual,
1591        plugins: isMaybeArraysEqual,
1592        events: isMaybeArraysEqual,
1593        eventSources: isMaybeArraysEqual,
1594        ['resources']: isMaybeArraysEqual,
1595    };
1596    function isMaybeObjectsEqual(a, b) {
1597        if (typeof a === 'object' && typeof b === 'object' && a && b) { // both non-null objects
1598            return isPropsEqual(a, b);
1599        }
1600        return a === b;
1601    }
1602    function isMaybeArraysEqual(a, b) {
1603        if (Array.isArray(a) && Array.isArray(b)) {
1604            return isArraysEqual(a, b);
1605        }
1606        return a === b;
1607    }
1608    // view-specific options
1609    // ---------------------
1610    const VIEW_OPTION_REFINERS = {
1611        type: String,
1612        component: identity,
1613        buttonText: String,
1614        buttonTextKey: String,
1615        dateProfileGeneratorClass: identity,
1616        usesMinMaxTime: Boolean,
1617        classNames: identity,
1618        content: identity,
1619        didMount: identity,
1620        willUnmount: identity,
1621    };
1622    // util funcs
1623    // ----------------------------------------------------------------------------------------------------
1624    function mergeRawOptions(optionSets) {
1625        return mergeProps(optionSets, COMPLEX_OPTION_COMPARATORS);
1626    }
1627    function refineProps(input, refiners) {
1628        let refined = {};
1629        let extra = {};
1630        for (let propName in refiners) {
1631            if (propName in input) {
1632                refined[propName] = refiners[propName](input[propName]);
1633            }
1634        }
1635        for (let propName in input) {
1636            if (!(propName in refiners)) {
1637                extra[propName] = input[propName];
1638            }
1639        }
1640        return { refined, extra };
1641    }
1642    function identity(raw) {
1643        return raw;
1644    }
1645
1646    const { hasOwnProperty } = Object.prototype;
1647    // Merges an array of objects into a single object.
1648    // The second argument allows for an array of property names who's object values will be merged together.
1649    function mergeProps(propObjs, complexPropsMap) {
1650        let dest = {};
1651        if (complexPropsMap) {
1652            for (let name in complexPropsMap) {
1653                if (complexPropsMap[name] === isMaybeObjectsEqual) { // implies that it's object-mergeable
1654                    let complexObjs = [];
1655                    // collect the trailing object values, stopping when a non-object is discovered
1656                    for (let i = propObjs.length - 1; i >= 0; i -= 1) {
1657                        let val = propObjs[i][name];
1658                        if (typeof val === 'object' && val) { // non-null object
1659                            complexObjs.unshift(val);
1660                        }
1661                        else if (val !== undefined) {
1662                            dest[name] = val; // if there were no objects, this value will be used
1663                            break;
1664                        }
1665                    }
1666                    // if the trailing values were objects, use the merged value
1667                    if (complexObjs.length) {
1668                        dest[name] = mergeProps(complexObjs);
1669                    }
1670                }
1671            }
1672        }
1673        // copy values into the destination, going from last to first
1674        for (let i = propObjs.length - 1; i >= 0; i -= 1) {
1675            let props = propObjs[i];
1676            for (let name in props) {
1677                if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign
1678                    dest[name] = props[name];
1679                }
1680            }
1681        }
1682        return dest;
1683    }
1684    function filterHash(hash, func) {
1685        let filtered = {};
1686        for (let key in hash) {
1687            if (func(hash[key], key)) {
1688                filtered[key] = hash[key];
1689            }
1690        }
1691        return filtered;
1692    }
1693    function mapHash(hash, func) {
1694        let newHash = {};
1695        for (let key in hash) {
1696            newHash[key] = func(hash[key], key);
1697        }
1698        return newHash;
1699    }
1700    function arrayToHash(a) {
1701        let hash = {};
1702        for (let item of a) {
1703            hash[item] = true;
1704        }
1705        return hash;
1706    }
1707    // TODO: reassess browser support
1708    // https://caniuse.com/?search=object.values
1709    function hashValuesToArray(obj) {
1710        let a = [];
1711        for (let key in obj) {
1712            a.push(obj[key]);
1713        }
1714        return a;
1715    }
1716    function isPropsEqual(obj0, obj1) {
1717        if (obj0 === obj1) {
1718            return true;
1719        }
1720        for (let key in obj0) {
1721            if (hasOwnProperty.call(obj0, key)) {
1722                if (!(key in obj1)) {
1723                    return false;
1724                }
1725            }
1726        }
1727        for (let key in obj1) {
1728            if (hasOwnProperty.call(obj1, key)) {
1729                if (obj0[key] !== obj1[key]) {
1730                    return false;
1731                }
1732            }
1733        }
1734        return true;
1735    }
1736    const HANDLER_RE = /^on[A-Z]/;
1737    function isNonHandlerPropsEqual(obj0, obj1) {
1738        const keys = getUnequalProps(obj0, obj1);
1739        for (let key of keys) {
1740            if (!HANDLER_RE.test(key)) {
1741                return false;
1742            }
1743        }
1744        return true;
1745    }
1746    function getUnequalProps(obj0, obj1) {
1747        let keys = [];
1748        for (let key in obj0) {
1749            if (hasOwnProperty.call(obj0, key)) {
1750                if (!(key in obj1)) {
1751                    keys.push(key);
1752                }
1753            }
1754        }
1755        for (let key in obj1) {
1756            if (hasOwnProperty.call(obj1, key)) {
1757                if (obj0[key] !== obj1[key]) {
1758                    keys.push(key);
1759                }
1760            }
1761        }
1762        return keys;
1763    }
1764    function compareObjs(oldProps, newProps, equalityFuncs = {}) {
1765        if (oldProps === newProps) {
1766            return true;
1767        }
1768        for (let key in newProps) {
1769            if (key in oldProps && isObjValsEqual(oldProps[key], newProps[key], equalityFuncs[key])) ;
1770            else {
1771                return false;
1772            }
1773        }
1774        // check for props that were omitted in the new
1775        for (let key in oldProps) {
1776            if (!(key in newProps)) {
1777                return false;
1778            }
1779        }
1780        return true;
1781    }
1782    /*
1783    assumed "true" equality for handler names like "onReceiveSomething"
1784    */
1785    function isObjValsEqual(val0, val1, comparator) {
1786        if (val0 === val1 || comparator === true) {
1787            return true;
1788        }
1789        if (comparator) {
1790            return comparator(val0, val1);
1791        }
1792        return false;
1793    }
1794    function collectFromHash(hash, startIndex = 0, endIndex, step = 1) {
1795        let res = [];
1796        if (endIndex == null) {
1797            endIndex = Object.keys(hash).length;
1798        }
1799        for (let i = startIndex; i < endIndex; i += step) {
1800            let val = hash[i];
1801            if (val !== undefined) { // will disregard undefined for sparse arrays
1802                res.push(val);
1803            }
1804        }
1805        return res;
1806    }
1807
1808    let calendarSystemClassMap = {};
1809    function registerCalendarSystem(name, theClass) {
1810        calendarSystemClassMap[name] = theClass;
1811    }
1812    function createCalendarSystem(name) {
1813        return new calendarSystemClassMap[name]();
1814    }
1815    class GregorianCalendarSystem {
1816        getMarkerYear(d) {
1817            return d.getUTCFullYear();
1818        }
1819        getMarkerMonth(d) {
1820            return d.getUTCMonth();
1821        }
1822        getMarkerDay(d) {
1823            return d.getUTCDate();
1824        }
1825        arrayToMarker(arr) {
1826            return arrayToUtcDate(arr);
1827        }
1828        markerToArray(marker) {
1829            return dateToUtcArray(marker);
1830        }
1831    }
1832    registerCalendarSystem('gregory', GregorianCalendarSystem);
1833
1834    const ISO_RE = /^\s*(\d{4})(-?(\d{2})(-?(\d{2})([T ](\d{2}):?(\d{2})(:?(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/;
1835    function parse(str) {
1836        let m = ISO_RE.exec(str);
1837        if (m) {
1838            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));
1839            if (isValidDate(marker)) {
1840                let timeZoneOffset = null;
1841                if (m[13]) {
1842                    timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 +
1843                        Number(m[18] || 0));
1844                }
1845                return {
1846                    marker,
1847                    isTimeUnspecified: !m[6],
1848                    timeZoneOffset,
1849                };
1850            }
1851        }
1852        return null;
1853    }
1854
1855    class DateEnv {
1856        constructor(settings) {
1857            let timeZone = this.timeZone = settings.timeZone;
1858            let isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC';
1859            if (settings.namedTimeZoneImpl && isNamedTimeZone) {
1860                this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone);
1861            }
1862            this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl);
1863            this.calendarSystem = createCalendarSystem(settings.calendarSystem);
1864            this.locale = settings.locale;
1865            this.weekDow = settings.locale.week.dow;
1866            this.weekDoy = settings.locale.week.doy;
1867            if (settings.weekNumberCalculation === 'ISO') {
1868                this.weekDow = 1;
1869                this.weekDoy = 4;
1870            }
1871            if (typeof settings.firstDay === 'number') {
1872                this.weekDow = settings.firstDay;
1873            }
1874            if (typeof settings.weekNumberCalculation === 'function') {
vendor: 2,020 bytes, lines 1875-1925
1875                this.weekNumberFunc = settings.weekNumberCalculation;
1876            }
1877            this.weekText = settings.weekText != null ? settings.weekText : settings.locale.options.weekText;
1878            this.weekTextLong = (settings.weekTextLong != null ? settings.weekTextLong : settings.locale.options.weekTextLong) || this.weekText;
1879            this.cmdFormatter = settings.cmdFormatter;
1880            this.defaultSeparator = settings.defaultSeparator;
1881        }
1882        // Creating / Parsing
1883        createMarker(input) {
1884            let meta = this.createMarkerMeta(input);
1885            if (meta === null) {
1886                return null;
1887            }
1888            return meta.marker;
1889        }
1890        createNowMarker() {
1891            if (this.canComputeOffset) {
1892                return this.timestampToMarker(new Date().valueOf());
1893            }
1894            // if we can't compute the current date val for a timezone,
1895            // better to give the current local date vals than UTC
1896            return arrayToUtcDate(dateToLocalArray(new Date()));
1897        }
1898        createMarkerMeta(input) {
1899            if (typeof input === 'string') {
1900                return this.parse(input);
1901            }
1902            let marker = null;
1903            if (typeof input === 'number') {
1904                marker = this.timestampToMarker(input);
1905            }
1906            else if (input instanceof Date) {
1907                input = input.valueOf();
1908                if (!isNaN(input)) {
1909                    marker = this.timestampToMarker(input);
1910                }
1911            }
1912            else if (Array.isArray(input)) {
1913                marker = arrayToUtcDate(input);
1914            }
1915            if (marker === null || !isValidDate(marker)) {
1916                return null;
1917            }
1918            return { marker, isTimeUnspecified: false, forcedTzo: null };
1919        }
1920        parse(s) {
1921            let parts = parse(s);
1922            if (parts === null) {
1923                return null;
1924            }
1925            let { marker } = parts;
vendor: 32,364 bytes, lines 1926-2732
1926            let forcedTzo = null;
1927            if (parts.timeZoneOffset !== null) {
1928                if (this.canComputeOffset) {
1929                    marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000);
1930                }
1931                else {
1932                    forcedTzo = parts.timeZoneOffset;
1933                }
1934            }
1935            return { marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo };
1936        }
1937        // Accessors
1938        getYear(marker) {
1939            return this.calendarSystem.getMarkerYear(marker);
1940        }
1941        getMonth(marker) {
1942            return this.calendarSystem.getMarkerMonth(marker);
1943        }
1944        getDay(marker) {
1945            return this.calendarSystem.getMarkerDay(marker);
1946        }
1947        // Adding / Subtracting
1948        add(marker, dur) {
1949            let a = this.calendarSystem.markerToArray(marker);
1950            a[0] += dur.years;
1951            a[1] += dur.months;
1952            a[2] += dur.days;
1953            a[6] += dur.milliseconds;
1954            return this.calendarSystem.arrayToMarker(a);
1955        }
1956        subtract(marker, dur) {
1957            let a = this.calendarSystem.markerToArray(marker);
1958            a[0] -= dur.years;
1959            a[1] -= dur.months;
1960            a[2] -= dur.days;
1961            a[6] -= dur.milliseconds;
1962            return this.calendarSystem.arrayToMarker(a);
1963        }
1964        addYears(marker, n) {
1965            let a = this.calendarSystem.markerToArray(marker);
1966            a[0] += n;
1967            return this.calendarSystem.arrayToMarker(a);
1968        }
1969        addMonths(marker, n) {
1970            let a = this.calendarSystem.markerToArray(marker);
1971            a[1] += n;
1972            return this.calendarSystem.arrayToMarker(a);
1973        }
1974        // Diffing Whole Units
1975        diffWholeYears(m0, m1) {
1976            let { calendarSystem } = this;
1977            if (timeAsMs(m0) === timeAsMs(m1) &&
1978                calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) &&
1979                calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) {
1980                return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0);
1981            }
1982            return null;
1983        }
1984        diffWholeMonths(m0, m1) {
1985            let { calendarSystem } = this;
1986            if (timeAsMs(m0) === timeAsMs(m1) &&
1987                calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) {
1988                return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) +
1989                    (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12;
1990            }
1991            return null;
1992        }
1993        // Range / Duration
1994        greatestWholeUnit(m0, m1) {
1995            let n = this.diffWholeYears(m0, m1);
1996            if (n !== null) {
1997                return { unit: 'year', value: n };
1998            }
1999            n = this.diffWholeMonths(m0, m1);
2000            if (n !== null) {
2001                return { unit: 'month', value: n };
2002            }
2003            n = diffWholeWeeks(m0, m1);
2004            if (n !== null) {
2005                return { unit: 'week', value: n };
2006            }
2007            n = diffWholeDays(m0, m1);
2008            if (n !== null) {
2009                return { unit: 'day', value: n };
2010            }
2011            n = diffHours(m0, m1);
2012            if (isInt(n)) {
2013                return { unit: 'hour', value: n };
2014            }
2015            n = diffMinutes(m0, m1);
2016            if (isInt(n)) {
2017                return { unit: 'minute', value: n };
2018            }
2019            n = diffSeconds(m0, m1);
2020            if (isInt(n)) {
2021                return { unit: 'second', value: n };
2022            }
2023            return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() };
2024        }
2025        countDurationsBetween(m0, m1, d) {
2026            // TODO: can use greatestWholeUnit
2027            let diff;
2028            if (d.years) {
2029                diff = this.diffWholeYears(m0, m1);
2030                if (diff !== null) {
2031                    return diff / asRoughYears(d);
2032                }
2033            }
2034            if (d.months) {
2035                diff = this.diffWholeMonths(m0, m1);
2036                if (diff !== null) {
2037                    return diff / asRoughMonths(d);
2038                }
2039            }
2040            if (d.days) {
2041                diff = diffWholeDays(m0, m1);
2042                if (diff !== null) {
2043                    return diff / asRoughDays(d);
2044                }
2045            }
2046            return (m1.valueOf() - m0.valueOf()) / asRoughMs(d);
2047        }
2048        // Start-Of
2049        // these DON'T return zoned-dates. only UTC start-of dates
2050        startOf(m, unit) {
2051            if (unit === 'year') {
2052                return this.startOfYear(m);
2053            }
2054            if (unit === 'month') {
2055                return this.startOfMonth(m);
2056            }
2057            if (unit === 'week') {
2058                return this.startOfWeek(m);
2059            }
2060            if (unit === 'day') {
2061                return startOfDay(m);
2062            }
2063            if (unit === 'hour') {
2064                return startOfHour(m);
2065            }
2066            if (unit === 'minute') {
2067                return startOfMinute(m);
2068            }
2069            if (unit === 'second') {
2070                return startOfSecond(m);
2071            }
2072            return null;
2073        }
2074        startOfYear(m) {
2075            return this.calendarSystem.arrayToMarker([
2076                this.calendarSystem.getMarkerYear(m),
2077            ]);
2078        }
2079        startOfMonth(m) {
2080            return this.calendarSystem.arrayToMarker([
2081                this.calendarSystem.getMarkerYear(m),
2082                this.calendarSystem.getMarkerMonth(m),
2083            ]);
2084        }
2085        startOfWeek(m) {
2086            return this.calendarSystem.arrayToMarker([
2087                this.calendarSystem.getMarkerYear(m),
2088                this.calendarSystem.getMarkerMonth(m),
2089                m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7),
2090            ]);
2091        }
2092        // Week Number
2093        computeWeekNumber(marker) {
2094            if (this.weekNumberFunc) {
2095                return this.weekNumberFunc(this.toDate(marker));
2096            }
2097            return weekOfYear(marker, this.weekDow, this.weekDoy);
2098        }
2099        // TODO: choke on timeZoneName: long
2100        format(marker, formatter, dateOptions = {}) {
2101            return formatter.format({
2102                marker,
2103                timeZoneOffset: dateOptions.forcedTzo != null ?
2104                    dateOptions.forcedTzo :
2105                    this.offsetForMarker(marker),
2106            }, this);
2107        }
2108        formatRange(start, end, formatter, dateOptions = {}) {
2109            if (dateOptions.isEndExclusive) {
2110                end = addMs(end, -1);
2111            }
2112            return formatter.formatRange({
2113                marker: start,
2114                timeZoneOffset: dateOptions.forcedStartTzo != null ?
2115                    dateOptions.forcedStartTzo :
2116                    this.offsetForMarker(start),
2117            }, {
2118                marker: end,
2119                timeZoneOffset: dateOptions.forcedEndTzo != null ?
2120                    dateOptions.forcedEndTzo :
2121                    this.offsetForMarker(end),
2122            }, this, dateOptions.defaultSeparator);
2123        }
2124        /*
2125        DUMB: the omitTime arg is dumb. if we omit the time, we want to omit the timezone offset. and if we do that,
2126        might as well use buildIsoString or some other util directly
2127        */
2128        formatIso(marker, extraOptions = {}) {
2129            let timeZoneOffset = null;
2130            if (!extraOptions.omitTimeZoneOffset) {
2131                if (extraOptions.forcedTzo != null) {
2132                    timeZoneOffset = extraOptions.forcedTzo;
2133                }
2134                else {
2135                    timeZoneOffset = this.offsetForMarker(marker);
2136                }
2137            }
2138            return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime);
2139        }
2140        // TimeZone
2141        timestampToMarker(ms) {
2142            if (this.timeZone === 'local') {
2143                return arrayToUtcDate(dateToLocalArray(new Date(ms)));
2144            }
2145            if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) {
2146                return new Date(ms);
2147            }
2148            return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms));
2149        }
2150        offsetForMarker(m) {
2151            if (this.timeZone === 'local') {
2152                return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset
2153            }
2154            if (this.timeZone === 'UTC') {
2155                return 0;
2156            }
2157            if (this.namedTimeZoneImpl) {
2158                return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m));
2159            }
2160            return null;
2161        }
2162        // Conversion
2163        toDate(m, forcedTzo) {
2164            if (this.timeZone === 'local') {
2165                return arrayToLocalDate(dateToUtcArray(m));
2166            }
2167            if (this.timeZone === 'UTC') {
2168                return new Date(m.valueOf()); // make sure it's a copy
2169            }
2170            if (!this.namedTimeZoneImpl) {
2171                return new Date(m.valueOf() - (forcedTzo || 0));
2172            }
2173            return new Date(m.valueOf() -
2174                this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60);
2175        }
2176    }
2177
2178    class Theme {
2179        constructor(calendarOptions) {
2180            if (this.iconOverrideOption) {
2181                this.setIconOverride(calendarOptions[this.iconOverrideOption]);
2182            }
2183        }
2184        setIconOverride(iconOverrideHash) {
2185            let iconClassesCopy;
2186            let buttonName;
2187            if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object
2188                iconClassesCopy = Object.assign({}, this.iconClasses);
2189                for (buttonName in iconOverrideHash) {
2190                    iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]);
2191                }
2192                this.iconClasses = iconClassesCopy;
2193            }
2194            else if (iconOverrideHash === false) {
2195                this.iconClasses = {};
2196            }
2197        }
2198        applyIconOverridePrefix(className) {
2199            let prefix = this.iconOverridePrefix;
2200            if (prefix && className.indexOf(prefix) !== 0) { // if not already present
2201                className = prefix + className;
2202            }
2203            return className;
2204        }
2205        getClass(key) {
2206            return this.classes[key] || '';
2207        }
2208        getIconClass(buttonName, isRtl) {
2209            let className;
2210            if (isRtl && this.rtlIconClasses) {
2211                className = this.rtlIconClasses[buttonName] || this.iconClasses[buttonName];
2212            }
2213            else {
2214                className = this.iconClasses[buttonName];
2215            }
2216            if (className) {
2217                return `${this.baseIconClass} ${className}`;
2218            }
2219            return '';
2220        }
2221        getCustomButtonIconClass(customButtonProps) {
2222            let className;
2223            if (this.iconOverrideCustomButtonOption) {
2224                className = customButtonProps[this.iconOverrideCustomButtonOption];
2225                if (className) {
2226                    return `${this.baseIconClass} ${this.applyIconOverridePrefix(className)}`;
2227                }
2228            }
2229            return '';
2230        }
2231    }
2232    Theme.prototype.classes = {};
2233    Theme.prototype.iconClasses = {};
2234    Theme.prototype.baseIconClass = '';
2235    Theme.prototype.iconOverridePrefix = '';
2236
2237    /*
2238    NOTE: this can be a public API, especially createElement for hooks.
2239    See examples/typescript-scheduler/src/index.ts
2240    */
2241    function flushSync(runBeforeFlush) {
2242        runBeforeFlush();
2243        let oldDebounceRendering = l$1.debounceRendering; // orig
2244        let callbackQ = [];
2245        function execCallbackSync(callback) {
2246            callbackQ.push(callback);
2247        }
2248        l$1.debounceRendering = execCallbackSync;
2249        D$1(y(FakeComponent, {}), document.createElement('div'));
2250        while (callbackQ.length) {
2251            callbackQ.shift()();
2252        }
2253        l$1.debounceRendering = oldDebounceRendering;
2254    }
2255    class FakeComponent extends x$1 {
2256        render() { return y('div', {}); }
2257        componentDidMount() { this.setState({}); }
2258    }
2259    // TODO: use preact/compat instead?
2260    function createContext(defaultValue) {
2261        let ContextType = G$1(defaultValue);
2262        let origProvider = ContextType.Provider;
2263        ContextType.Provider = function () {
2264            let isNew = !this.getChildContext;
2265            let children = origProvider.apply(this, arguments); // eslint-disable-line prefer-rest-params
2266            if (isNew) {
2267                let subs = [];
2268                this.shouldComponentUpdate = (_props) => {
2269                    if (this.props.value !== _props.value) {
2270                        subs.forEach((c) => {
2271                            c.context = _props.value;
2272                            c.forceUpdate();
2273                        });
2274                    }
2275                };
2276                this.sub = (c) => {
2277                    subs.push(c);
2278                    let old = c.componentWillUnmount;
2279                    c.componentWillUnmount = () => {
2280                        subs.splice(subs.indexOf(c), 1);
2281                        old && old.call(c);
2282                    };
2283                };
2284            }
2285            return children;
2286        };
2287        return ContextType;
2288    }
2289
2290    class ScrollResponder {
2291        constructor(execFunc, emitter, scrollTime, scrollTimeReset) {
2292            this.execFunc = execFunc;
2293            this.emitter = emitter;
2294            this.scrollTime = scrollTime;
2295            this.scrollTimeReset = scrollTimeReset;
2296            this.handleScrollRequest = (request) => {
2297                this.queuedRequest = Object.assign({}, this.queuedRequest || {}, request);
2298                this.drain();
2299            };
2300            emitter.on('_scrollRequest', this.handleScrollRequest);
2301            this.fireInitialScroll();
2302        }
2303        detach() {
2304            this.emitter.off('_scrollRequest', this.handleScrollRequest);
2305        }
2306        update(isDatesNew) {
2307            if (isDatesNew && this.scrollTimeReset) {
2308                this.fireInitialScroll(); // will drain
2309            }
2310            else {
2311                this.drain();
2312            }
2313        }
2314        fireInitialScroll() {
2315            this.handleScrollRequest({
2316                time: this.scrollTime,
2317            });
2318        }
2319        drain() {
2320            if (this.queuedRequest && this.execFunc(this.queuedRequest)) {
2321                this.queuedRequest = null;
2322            }
2323        }
2324    }
2325
2326    const ViewContextType = createContext({}); // for Components
2327    function buildViewContext(viewSpec, viewApi, viewOptions, dateProfileGenerator, dateEnv, nowManager, theme, pluginHooks, dispatch, getCurrentData, emitter, calendarApi, registerInteractiveComponent, unregisterInteractiveComponent) {
2328        return {
2329            dateEnv,
2330            nowManager,
2331            options: viewOptions,
2332            pluginHooks,
2333            emitter,
2334            dispatch,
2335            getCurrentData,
2336            calendarApi,
2337            viewSpec,
2338            viewApi,
2339            dateProfileGenerator,
2340            theme,
2341            isRtl: viewOptions.direction === 'rtl',
2342            addResizeHandler(handler) {
2343                emitter.on('_resize', handler);
2344            },
2345            removeResizeHandler(handler) {
2346                emitter.off('_resize', handler);
2347            },
2348            createScrollResponder(execFunc) {
2349                return new ScrollResponder(execFunc, emitter, createDuration(viewOptions.scrollTime), viewOptions.scrollTimeReset);
2350            },
2351            registerInteractiveComponent,
2352            unregisterInteractiveComponent,
2353        };
2354    }
2355
2356    /* eslint max-classes-per-file: off */
2357    class PureComponent extends x$1 {
2358        shouldComponentUpdate(nextProps, nextState) {
2359            if (this.debug) {
2360                // eslint-disable-next-line no-console
2361                console.log(getUnequalProps(nextProps, this.props), getUnequalProps(nextState, this.state));
2362            }
2363            return !compareObjs(this.props, nextProps, this.propEquality) ||
2364                !compareObjs(this.state, nextState, this.stateEquality);
2365        }
2366        // HACK for freakin' React StrictMode
2367        safeSetState(newState) {
2368            if (!compareObjs(this.state, Object.assign(Object.assign({}, this.state), newState), this.stateEquality)) {
2369                this.setState(newState);
2370            }
2371        }
2372    }
2373    PureComponent.addPropsEquality = addPropsEquality;
2374    PureComponent.addStateEquality = addStateEquality;
2375    PureComponent.contextType = ViewContextType;
2376    PureComponent.prototype.propEquality = {};
2377    PureComponent.prototype.stateEquality = {};
2378    class BaseComponent extends PureComponent {
2379    }
2380    BaseComponent.contextType = ViewContextType;
2381    function addPropsEquality(propEquality) {
2382        let hash = Object.create(this.prototype.propEquality);
2383        Object.assign(hash, propEquality);
2384        this.prototype.propEquality = hash;
2385    }
2386    function addStateEquality(stateEquality) {
2387        let hash = Object.create(this.prototype.stateEquality);
2388        Object.assign(hash, stateEquality);
2389        this.prototype.stateEquality = hash;
2390    }
2391    // use other one
2392    function setRef(ref, current) {
2393        if (typeof ref === 'function') {
2394            ref(current);
2395        }
2396        else if (ref) {
2397            // see https://github.com/facebook/react/issues/13029
2398            ref.current = current;
2399        }
2400    }
2401
2402    class ContentInjector extends BaseComponent {
2403        constructor() {
2404            super(...arguments);
2405            this.id = guid();
2406            this.queuedDomNodes = [];
2407            this.currentDomNodes = [];
2408            this.handleEl = (el) => {
2409                const { options } = this.context;
2410                const { generatorName } = this.props;
2411                if (!options.customRenderingReplaces || !hasCustomRenderingHandler(generatorName, options)) {
2412                    this.updateElRef(el);
2413                }
2414            };
2415            this.updateElRef = (el) => {
2416                if (this.props.elRef) {
2417                    setRef(this.props.elRef, el);
2418                }
2419            };
2420        }
2421        render() {
2422            const { props, context } = this;
2423            const { options } = context;
2424            const { customGenerator, defaultGenerator, renderProps } = props;
2425            const attrs = buildElAttrs(props, [], this.handleEl);
2426            let useDefault = false;
2427            let innerContent;
2428            let queuedDomNodes = [];
2429            let currentGeneratorMeta;
2430            if (customGenerator != null) {
2431                const customGeneratorRes = typeof customGenerator === 'function' ?
2432                    customGenerator(renderProps, y) :
2433                    customGenerator;
2434                if (customGeneratorRes === true) {
2435                    useDefault = true;
2436                }
2437                else {
2438                    const isObject = customGeneratorRes && typeof customGeneratorRes === 'object'; // non-null
2439                    if (isObject && ('html' in customGeneratorRes)) {
2440                        attrs.dangerouslySetInnerHTML = { __html: customGeneratorRes.html };
2441                    }
2442                    else if (isObject && ('domNodes' in customGeneratorRes)) {
2443                        queuedDomNodes = Array.prototype.slice.call(customGeneratorRes.domNodes);
2444                    }
2445                    else if (isObject
2446                        ? i$1(customGeneratorRes) // vdom node
2447                        : typeof customGeneratorRes !== 'function' // primitive value (like string or number)
2448                    ) {
2449                        // use in vdom
2450                        innerContent = customGeneratorRes;
2451                    }
2452                    else {
2453                        // an exotic object for handleCustomRendering
2454                        currentGeneratorMeta = customGeneratorRes;
2455                    }
2456                }
2457            }
2458            else {
2459                useDefault = !hasCustomRenderingHandler(props.generatorName, options);
2460            }
2461            if (useDefault && defaultGenerator) {
2462                innerContent = defaultGenerator(renderProps);
2463            }
2464            this.queuedDomNodes = queuedDomNodes;
2465            this.currentGeneratorMeta = currentGeneratorMeta;
2466            return y(props.elTag, attrs, innerContent);
2467        }
2468        componentDidMount() {
2469            this.applyQueueudDomNodes();
2470            this.triggerCustomRendering(true);
2471        }
2472        componentDidUpdate() {
2473            this.applyQueueudDomNodes();
2474            this.triggerCustomRendering(true);
2475        }
2476        componentWillUnmount() {
2477            this.triggerCustomRendering(false); // TODO: different API for removal?
2478        }
2479        triggerCustomRendering(isActive) {
2480            var _a;
2481            const { props, context } = this;
2482            const { handleCustomRendering, customRenderingMetaMap } = context.options;
2483            if (handleCustomRendering) {
2484                const generatorMeta = (_a = this.currentGeneratorMeta) !== null && _a !== void 0 ? _a : customRenderingMetaMap === null || customRenderingMetaMap === void 0 ? void 0 : customRenderingMetaMap[props.generatorName];
2485                if (generatorMeta) {
2486                    handleCustomRendering(Object.assign(Object.assign({ id: this.id, isActive, containerEl: this.base, reportNewContainerEl: this.updateElRef, // front-end framework tells us about new container els
2487                        generatorMeta }, props), { elClasses: (props.elClasses || []).filter(isTruthy) }));
2488                }
2489            }
2490        }
2491        applyQueueudDomNodes() {
2492            const { queuedDomNodes, currentDomNodes } = this;
2493            const el = this.base;
2494            if (!isArraysEqual(queuedDomNodes, currentDomNodes)) {
2495                currentDomNodes.forEach(removeElement);
2496                for (let newNode of queuedDomNodes) {
2497                    el.appendChild(newNode);
2498                }
2499                this.currentDomNodes = queuedDomNodes;
2500            }
2501        }
2502    }
2503    ContentInjector.addPropsEquality({
2504        elClasses: isArraysEqual,
2505        elStyle: isPropsEqual,
2506        elAttrs: isNonHandlerPropsEqual,
2507        renderProps: isPropsEqual,
2508    });
2509    // Util
2510    /*
2511    Does UI-framework provide custom way of rendering that does not use Preact VDOM
2512    AND does the calendar's options define custom rendering?
2513    AKA. Should we NOT render the default content?
2514    */
2515    function hasCustomRenderingHandler(generatorName, options) {
2516        var _a;
2517        return Boolean(options.handleCustomRendering &&
2518            generatorName &&
2519            ((_a = options.customRenderingMetaMap) === null || _a === void 0 ? void 0 : _a[generatorName]));
2520    }
2521    function buildElAttrs(props, extraClassNames, elRef) {
2522        const attrs = Object.assign(Object.assign({}, props.elAttrs), { ref: elRef });
2523        if (props.elClasses || extraClassNames) {
2524            attrs.className = (props.elClasses || [])
2525                .concat(extraClassNames || [])
2526                .concat(attrs.className || [])
2527                .filter(Boolean)
2528                .join(' ');
2529        }
2530        if (props.elStyle) {
2531            attrs.style = props.elStyle;
2532        }
2533        return attrs;
2534    }
2535    function isTruthy(val) {
2536        return Boolean(val);
2537    }
2538
2539    const RenderId = createContext(0);
2540
2541    class ContentContainer extends x$1 {
2542        constructor() {
2543            super(...arguments);
2544            this.InnerContent = InnerContentInjector.bind(undefined, this);
2545            this.handleEl = (el) => {
2546                this.el = el;
2547                if (this.props.elRef) {
2548                    setRef(this.props.elRef, el);
2549                    if (el && this.didMountMisfire) {
2550                        this.componentDidMount();
2551                    }
2552                }
2553            };
2554        }
2555        render() {
2556            const { props } = this;
2557            const generatedClassNames = generateClassNames(props.classNameGenerator, props.renderProps);
2558            if (props.children) {
2559                const elAttrs = buildElAttrs(props, generatedClassNames, this.handleEl);
2560                const children = props.children(this.InnerContent, props.renderProps, elAttrs);
2561                if (props.elTag) {
2562                    return y(props.elTag, elAttrs, children);
2563                }
2564                else {
2565                    return children;
2566                }
2567            }
2568            else {
2569                return y((ContentInjector), Object.assign(Object.assign({}, props), { elRef: this.handleEl, elTag: props.elTag || 'div', elClasses: (props.elClasses || []).concat(generatedClassNames), renderId: this.context }));
2570            }
2571        }
2572        componentDidMount() {
2573            var _a, _b;
2574            if (this.el) {
2575                (_b = (_a = this.props).didMount) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.props.renderProps), { el: this.el }));
2576            }
2577            else {
2578                this.didMountMisfire = true;
2579            }
2580        }
2581        componentWillUnmount() {
2582            var _a, _b;
2583            (_b = (_a = this.props).willUnmount) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.props.renderProps), { el: this.el }));
2584        }
2585    }
2586    ContentContainer.contextType = RenderId;
2587    function InnerContentInjector(containerComponent, props) {
2588        const parentProps = containerComponent.props;
2589        return y((ContentInjector), Object.assign({ renderProps: parentProps.renderProps, generatorName: parentProps.generatorName, customGenerator: parentProps.customGenerator, defaultGenerator: parentProps.defaultGenerator, renderId: containerComponent.context }, props));
2590    }
2591    // Utils
2592    function generateClassNames(classNameGenerator, renderProps) {
2593        const classNames = typeof classNameGenerator === 'function' ?
2594            classNameGenerator(renderProps) :
2595            classNameGenerator || [];
2596        return typeof classNames === 'string' ? [classNames] : classNames;
2597    }
2598
2599    class ViewContainer extends BaseComponent {
2600        render() {
2601            let { props, context } = this;
2602            let { options } = context;
2603            let renderProps = { view: context.viewApi };
2604            return (y(ContentContainer, Object.assign({}, props, { elTag: props.elTag || 'div', elClasses: [
2605                    ...buildViewClassNames(props.viewSpec),
2606                    ...(props.elClasses || []),
2607                ], renderProps: renderProps, classNameGenerator: options.viewClassNames, generatorName: undefined, didMount: options.viewDidMount, willUnmount: options.viewWillUnmount }), () => props.children));
2608        }
2609    }
2610    function buildViewClassNames(viewSpec) {
2611        return [
2612            `fc-${viewSpec.type}-view`,
2613            'fc-view',
2614        ];
2615    }
2616
2617    function parseRange(input, dateEnv) {
2618        let start = null;
2619        let end = null;
2620        if (input.start) {
2621            start = dateEnv.createMarker(input.start);
2622        }
2623        if (input.end) {
2624            end = dateEnv.createMarker(input.end);
2625        }
2626        if (!start && !end) {
2627            return null;
2628        }
2629        if (start && end && end < start) {
2630            return null;
2631        }
2632        return { start, end };
2633    }
2634    // SIDE-EFFECT: will mutate ranges.
2635    // Will return a new array result.
2636    function invertRanges(ranges, constraintRange) {
2637        let invertedRanges = [];
2638        let { start } = constraintRange; // the end of the previous range. the start of the new range
2639        let i;
2640        let dateRange;
2641        // ranges need to be in order. required for our date-walking algorithm
2642        ranges.sort(compareRanges);
2643        for (i = 0; i < ranges.length; i += 1) {
2644            dateRange = ranges[i];
2645            // add the span of time before the event (if there is any)
2646            if (dateRange.start > start) { // compare millisecond time (skip any ambig logic)
2647                invertedRanges.push({ start, end: dateRange.start });
2648            }
2649            if (dateRange.end > start) {
2650                start = dateRange.end;
2651            }
2652        }
2653        // add the span of time after the last event (if there is any)
2654        if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic)
2655            invertedRanges.push({ start, end: constraintRange.end });
2656        }
2657        return invertedRanges;
2658    }
2659    function compareRanges(range0, range1) {
2660        return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first
2661    }
2662    function intersectRanges(range0, range1) {
2663        let { start, end } = range0;
2664        let newRange = null;
2665        if (range1.start !== null) {
2666            if (start === null) {
2667                start = range1.start;
2668            }
2669            else {
2670                start = new Date(Math.max(start.valueOf(), range1.start.valueOf()));
2671            }
2672        }
2673        if (range1.end != null) {
2674            if (end === null) {
2675                end = range1.end;
2676            }
2677            else {
2678                end = new Date(Math.min(end.valueOf(), range1.end.valueOf()));
2679            }
2680        }
2681        if (start === null || end === null || start < end) {
2682            newRange = { start, end };
2683        }
2684        return newRange;
2685    }
2686    function rangesEqual(range0, range1) {
2687        return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) &&
2688            (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf());
2689    }
2690    function rangesIntersect(range0, range1) {
2691        return (range0.end === null || range1.start === null || range0.end > range1.start) &&
2692            (range0.start === null || range1.end === null || range0.start < range1.end);
2693    }
2694    function rangeContainsRange(outerRange, innerRange) {
2695        return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) &&
2696            (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end));
2697    }
2698    function rangeContainsMarker(range, date) {
2699        return (range.start === null || date >= range.start) &&
2700            (range.end === null || date < range.end);
2701    }
2702    // If the given date is not within the given range, move it inside.
2703    // (If it's past the end, make it one millisecond before the end).
2704    function constrainMarkerToRange(date, range) {
2705        if (range.start != null && date < range.start) {
2706            return range.start;
2707        }
2708        if (range.end != null && date >= range.end) {
2709            return new Date(range.end.valueOf() - 1);
2710        }
2711        return date;
2712    }
2713
2714    /* Date stuff that doesn't belong in datelib core
2715    ----------------------------------------------------------------------------------------------------------------------*/
2716    // given a timed range, computes an all-day range that has the same exact duration,
2717    // but whose start time is aligned with the start of the day.
2718    function computeAlignedDayRange(timedRange) {
2719        let dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1;
2720        let start = startOfDay(timedRange.start);
2721        let end = addDays(start, dayCnt);
2722        return { start, end };
2723    }
2724    // given a timed range, computes an all-day range based on how for the end date bleeds into the next day
2725    // TODO: give nextDayThreshold a default arg
2726    function computeVisibleDayRange(timedRange, nextDayThreshold = createDuration(0)) {
2727        let startDay = null;
2728        let endDay = null;
2729        if (timedRange.end) {
2730            endDay = startOfDay(timedRange.end);
2731            let endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay`
2732            // If the end time is actually inclusively part of the next day and is equal to or
vendor: 14,058 bytes, lines 2733-3027
2733            // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.
2734            // Otherwise, leaving it as inclusive will cause it to exclude `endDay`.
2735            if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) {
2736                endDay = addDays(endDay, 1);
2737            }
2738        }
2739        if (timedRange.start) {
2740            startDay = startOfDay(timedRange.start); // the beginning of the day the range starts
2741            // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day.
2742            if (endDay && endDay <= startDay) {
2743                endDay = addDays(startDay, 1);
2744            }
2745        }
2746        return { start: startDay, end: endDay };
2747    }
2748    // spans from one day into another?
2749    function isMultiDayRange(range) {
2750        let visibleRange = computeVisibleDayRange(range);
2751        return diffDays(visibleRange.start, visibleRange.end) > 1;
2752    }
2753    function diffDates(date0, date1, dateEnv, largeUnit) {
2754        if (largeUnit === 'year') {
2755            return createDuration(dateEnv.diffWholeYears(date0, date1), 'year');
2756        }
2757        if (largeUnit === 'month') {
2758            return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month');
2759        }
2760        return diffDayAndTime(date0, date1); // returns a duration
2761    }
2762
2763    class DateProfileGenerator {
2764        constructor(props) {
2765            this.props = props;
2766            this.initHiddenDays();
2767        }
2768        /* Date Range Computation
2769        ------------------------------------------------------------------------------------------------------------------*/
2770        // Builds a structure with info about what the dates/ranges will be for the "prev" view.
2771        buildPrev(currentDateProfile, currentDate, forceToValid) {
2772            let { dateEnv } = this.props;
2773            let prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
2774            currentDateProfile.dateIncrement);
2775            return this.build(prevDate, -1, forceToValid);
2776        }
2777        // Builds a structure with info about what the dates/ranges will be for the "next" view.
2778        buildNext(currentDateProfile, currentDate, forceToValid) {
2779            let { dateEnv } = this.props;
2780            let nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
2781            currentDateProfile.dateIncrement);
2782            return this.build(nextDate, 1, forceToValid);
2783        }
2784        // Builds a structure holding dates/ranges for rendering around the given date.
2785        // Optional direction param indicates whether the date is being incremented/decremented
2786        // from its previous value. decremented = -1, incremented = 1 (default).
2787        build(currentDate, direction, forceToValid = true) {
2788            let { props } = this;
2789            let validRange;
2790            let currentInfo;
2791            let isRangeAllDay;
2792            let renderRange;
2793            let activeRange;
2794            let isValid;
2795            validRange = this.buildValidRange();
2796            validRange = this.trimHiddenDays(validRange);
2797            if (forceToValid) {
2798                currentDate = constrainMarkerToRange(currentDate, validRange);
2799            }
2800            currentInfo = this.buildCurrentRangeInfo(currentDate, direction);
2801            isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit);
2802            renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay);
2803            renderRange = this.trimHiddenDays(renderRange);
2804            activeRange = renderRange;
2805            if (!props.showNonCurrentDates) {
2806                activeRange = intersectRanges(activeRange, currentInfo.range);
2807            }
2808            activeRange = this.adjustActiveRange(activeRange);
2809            activeRange = intersectRanges(activeRange, validRange); // might return null
2810            // it's invalid if the originally requested date is not contained,
2811            // or if the range is completely outside of the valid range.
2812            isValid = rangesIntersect(currentInfo.range, validRange);
2813            // HACK: constrain to render-range so `currentDate` is more useful to view rendering
2814            if (!rangeContainsMarker(renderRange, currentDate)) {
2815                currentDate = renderRange.start;
2816            }
2817            return {
2818                currentDate,
2819                // constraint for where prev/next operations can go and where events can be dragged/resized to.
2820                // an object with optional start and end properties.
2821                validRange,
2822                // range the view is formally responsible for.
2823                // for example, a month view might have 1st-31st, excluding padded dates
2824                currentRange: currentInfo.range,
2825                // name of largest unit being displayed, like "month" or "week"
2826                currentRangeUnit: currentInfo.unit,
2827                isRangeAllDay,
2828                // dates that display events and accept drag-n-drop
2829                // will be `null` if no dates accept events
2830                activeRange,
2831                // date range with a rendered skeleton
2832                // includes not-active days that need some sort of DOM
2833                renderRange,
2834                // Duration object that denotes the first visible time of any given day
2835                slotMinTime: props.slotMinTime,
2836                // Duration object that denotes the exclusive visible end time of any given day
2837                slotMaxTime: props.slotMaxTime,
2838                isValid,
2839                // how far the current date will move for a prev/next operation
2840                dateIncrement: this.buildDateIncrement(currentInfo.duration),
2841                // pass a fallback (might be null) ^
2842            };
2843        }
2844        // Builds an object with optional start/end properties.
2845        // Indicates the minimum/maximum dates to display.
2846        // not responsible for trimming hidden days.
2847        buildValidRange() {
2848            let input = this.props.validRangeInput;
2849            let simpleInput = typeof input === 'function'
2850                ? input.call(this.props.calendarApi, this.props.dateEnv.toDate(this.props.nowManager.getDateMarker()))
2851                : input;
2852            return this.refineRange(simpleInput) ||
2853                { start: null, end: null }; // completely open-ended
2854        }
2855        // Builds a structure with info about the "current" range, the range that is
2856        // highlighted as being the current month for example.
2857        // See build() for a description of `direction`.
2858        // Guaranteed to have `range` and `unit` properties. `duration` is optional.
2859        buildCurrentRangeInfo(date, direction) {
2860            let { props } = this;
2861            let duration = null;
2862            let unit = null;
2863            let range = null;
2864            let dayCount;
2865            if (props.duration) {
2866                duration = props.duration;
2867                unit = props.durationUnit;
2868                range = this.buildRangeFromDuration(date, direction, duration, unit);
2869            }
2870            else if ((dayCount = this.props.dayCount)) {
2871                unit = 'day';
2872                range = this.buildRangeFromDayCount(date, direction, dayCount);
2873            }
2874            else if ((range = this.buildCustomVisibleRange(date))) {
2875                unit = props.dateEnv.greatestWholeUnit(range.start, range.end).unit;
2876            }
2877            else {
2878                duration = this.getFallbackDuration();
2879                unit = greatestDurationDenominator(duration).unit;
2880                range = this.buildRangeFromDuration(date, direction, duration, unit);
2881            }
2882            return { duration, unit, range };
2883        }
2884        getFallbackDuration() {
2885            return createDuration({ day: 1 });
2886        }
2887        // Returns a new activeRange to have time values (un-ambiguate)
2888        // slotMinTime or slotMaxTime causes the range to expand.
2889        adjustActiveRange(range) {
2890            let { dateEnv, usesMinMaxTime, slotMinTime, slotMaxTime } = this.props;
2891            let { start, end } = range;
2892            if (usesMinMaxTime) {
2893                // expand active range if slotMinTime is negative (why not when positive?)
2894                if (asRoughDays(slotMinTime) < 0) {
2895                    start = startOfDay(start); // necessary?
2896                    start = dateEnv.add(start, slotMinTime);
2897                }
2898                // expand active range if slotMaxTime is beyond one day (why not when negative?)
2899                if (asRoughDays(slotMaxTime) > 1) {
2900                    end = startOfDay(end); // necessary?
2901                    end = addDays(end, -1);
2902                    end = dateEnv.add(end, slotMaxTime);
2903                }
2904            }
2905            return { start, end };
2906        }
2907        // Builds the "current" range when it is specified as an explicit duration.
2908        // `unit` is the already-computed greatestDurationDenominator unit of duration.
2909        buildRangeFromDuration(date, direction, duration, unit) {
2910            let { dateEnv, dateAlignment } = this.props;
2911            let start;
2912            let end;
2913            let res;
2914            // compute what the alignment should be
2915            if (!dateAlignment) {
2916                let { dateIncrement } = this.props;
2917                if (dateIncrement) {
2918                    // use the smaller of the two units
2919                    if (asRoughMs(dateIncrement) < asRoughMs(duration)) {
2920                        dateAlignment = greatestDurationDenominator(dateIncrement).unit;
2921                    }
2922                    else {
2923                        dateAlignment = unit;
2924                    }
2925                }
2926                else {
2927                    dateAlignment = unit;
2928                }
2929            }
2930            // if the view displays a single day or smaller
2931            if (asRoughDays(duration) <= 1) {
2932                if (this.isHiddenDay(start)) {
2933                    start = this.skipHiddenDays(start, direction);
2934                    start = startOfDay(start);
2935                }
2936            }
2937            function computeRes() {
2938                start = dateEnv.startOf(date, dateAlignment);
2939                end = dateEnv.add(start, duration);
2940                res = { start, end };
2941            }
2942            computeRes();
2943            // if range is completely enveloped by hidden days, go past the hidden days
2944            if (!this.trimHiddenDays(res)) {
2945                date = this.skipHiddenDays(date, direction);
2946                computeRes();
2947            }
2948            return res;
2949        }
2950        // Builds the "current" range when a dayCount is specified.
2951        buildRangeFromDayCount(date, direction, dayCount) {
2952            let { dateEnv, dateAlignment } = this.props;
2953            let runningCount = 0;
2954            let start = date;
2955            let end;
2956            if (dateAlignment) {
2957                start = dateEnv.startOf(start, dateAlignment);
2958            }
2959            start = startOfDay(start);
2960            start = this.skipHiddenDays(start, direction);
2961            end = start;
2962            do {
2963                end = addDays(end, 1);
2964                if (!this.isHiddenDay(end)) {
2965                    runningCount += 1;
2966                }
2967            } while (runningCount < dayCount);
2968            return { start, end };
2969        }
2970        // Builds a normalized range object for the "visible" range,
2971        // which is a way to define the currentRange and activeRange at the same time.
2972        buildCustomVisibleRange(date) {
2973            let { props } = this;
2974            let input = props.visibleRangeInput;
2975            let simpleInput = typeof input === 'function'
2976                ? input.call(props.calendarApi, props.dateEnv.toDate(date))
2977                : input;
2978            let range = this.refineRange(simpleInput);
2979            if (range && (range.start == null || range.end == null)) {
2980                return null;
2981            }
2982            return range;
2983        }
2984        // Computes the range that will represent the element/cells for *rendering*,
2985        // but which may have voided days/times.
2986        // not responsible for trimming hidden days.
2987        buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
2988            return currentRange;
2989        }
2990        // Compute the duration value that should be added/substracted to the current date
2991        // when a prev/next operation happens.
2992        buildDateIncrement(fallback) {
2993            let { dateIncrement } = this.props;
2994            let customAlignment;
2995            if (dateIncrement) {
2996                return dateIncrement;
2997            }
2998            if ((customAlignment = this.props.dateAlignment)) {
2999                return createDuration(1, customAlignment);
3000            }
3001            if (fallback) {
3002                return fallback;
3003            }
3004            return createDuration({ days: 1 });
3005        }
3006        refineRange(rangeInput) {
3007            if (rangeInput) {
3008                let range = parseRange(rangeInput, this.props.dateEnv);
3009                if (range) {
3010                    range = computeVisibleDayRange(range);
3011                }
3012                return range;
3013            }
3014            return null;
3015        }
3016        /* Hidden Days
3017        ------------------------------------------------------------------------------------------------------------------*/
3018        // Initializes internal variables related to calculating hidden days-of-week
3019        initHiddenDays() {
3020            let hiddenDays = this.props.hiddenDays || []; // array of day-of-week indices that are hidden
3021            let isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool)
3022            let dayCnt = 0;
3023            let i;
3024            if (this.props.weekends === false) {
3025                hiddenDays.push(0, 6); // 0=sunday, 6=saturday
3026            }
3027            for (i = 0; i < 7; i += 1) {
vendor: 13,107 bytes, lines 3028-3347
3028                if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) {
3029                    dayCnt += 1;
3030                }
3031            }
3032            if (!dayCnt) {
3033                throw new Error('invalid hiddenDays'); // all days were hidden? bad.
3034            }
3035            this.isHiddenDayHash = isHiddenDayHash;
3036        }
3037        // Remove days from the beginning and end of the range that are computed as hidden.
3038        // If the whole range is trimmed off, returns null
3039        trimHiddenDays(range) {
3040            let { start, end } = range;
3041            if (start) {
3042                start = this.skipHiddenDays(start);
3043            }
3044            if (end) {
3045                end = this.skipHiddenDays(end, -1, true);
3046            }
3047            if (start == null || end == null || start < end) {
3048                return { start, end };
3049            }
3050            return null;
3051        }
3052        // Is the current day hidden?
3053        // `day` is a day-of-week index (0-6), or a Date (used for UTC)
3054        isHiddenDay(day) {
3055            if (day instanceof Date) {
3056                day = day.getUTCDay();
3057            }
3058            return this.isHiddenDayHash[day];
3059        }
3060        // Incrementing the current day until it is no longer a hidden day, returning a copy.
3061        // DOES NOT CONSIDER validRange!
3062        // If the initial value of `date` is not a hidden day, don't do anything.
3063        // Pass `isExclusive` as `true` if you are dealing with an end date.
3064        // `inc` defaults to `1` (increment one day forward each time)
3065        skipHiddenDays(date, inc = 1, isExclusive = false) {
3066            while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) {
3067                date = addDays(date, inc);
3068            }
3069            return date;
3070        }
3071    }
3072
3073    function createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) {
3074        return {
3075            instanceId: guid(),
3076            defId,
3077            range,
3078            forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo,
3079            forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo,
3080        };
3081    }
3082
3083    function parseRecurring(refined, defaultAllDay, dateEnv, recurringTypes) {
3084        for (let i = 0; i < recurringTypes.length; i += 1) {
3085            let parsed = recurringTypes[i].parse(refined, dateEnv);
3086            if (parsed) {
3087                let { allDay } = refined;
3088                if (allDay == null) {
3089                    allDay = defaultAllDay;
3090                    if (allDay == null) {
3091                        allDay = parsed.allDayGuess;
3092                        if (allDay == null) {
3093                            allDay = false;
3094                        }
3095                    }
3096                }
3097                return {
3098                    allDay,
3099                    duration: parsed.duration,
3100                    typeData: parsed.typeData,
3101                    typeId: i,
3102                };
3103            }
3104        }
3105        return null;
3106    }
3107    function expandRecurring(eventStore, framingRange, context) {
3108        let { dateEnv, pluginHooks, options } = context;
3109        let { defs, instances } = eventStore;
3110        // remove existing recurring instances
3111        // TODO: bad. always expand events as a second step
3112        instances = filterHash(instances, (instance) => !defs[instance.defId].recurringDef);
3113        for (let defId in defs) {
3114            let def = defs[defId];
3115            if (def.recurringDef) {
3116                let { duration } = def.recurringDef;
3117                if (!duration) {
3118                    duration = def.allDay ?
3119                        options.defaultAllDayEventDuration :
3120                        options.defaultTimedEventDuration;
3121                }
3122                let starts = expandRecurringRanges(def, duration, framingRange, dateEnv, pluginHooks.recurringTypes);
3123                for (let start of starts) {
3124                    let instance = createEventInstance(defId, {
3125                        start,
3126                        end: dateEnv.add(start, duration),
3127                    });
3128                    instances[instance.instanceId] = instance;
3129                }
3130            }
3131        }
3132        return { defs, instances };
3133    }
3134    /*
3135    Event MUST have a recurringDef
3136    */
3137    function expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) {
3138        let typeDef = recurringTypes[eventDef.recurringDef.typeId];
3139        let markers = typeDef.expand(eventDef.recurringDef.typeData, {
3140            start: dateEnv.subtract(framingRange.start, duration),
3141            end: framingRange.end,
3142        }, dateEnv);
3143        // the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to
3144        if (eventDef.allDay) {
3145            markers = markers.map(startOfDay);
3146        }
3147        return markers;
3148    }
3149
3150    const EVENT_NON_DATE_REFINERS = {
3151        id: String,
3152        groupId: String,
3153        title: String,
3154        url: String,
3155        interactive: Boolean,
3156    };
3157    const EVENT_DATE_REFINERS = {
3158        start: identity,
3159        end: identity,
3160        date: identity,
3161        allDay: Boolean,
3162    };
3163    const EVENT_REFINERS = Object.assign(Object.assign(Object.assign({}, EVENT_NON_DATE_REFINERS), EVENT_DATE_REFINERS), { extendedProps: identity });
3164    function parseEvent(raw, eventSource, context, allowOpenRange, refiners = buildEventRefiners(context), defIdMap, instanceIdMap) {
3165        let { refined, extra } = refineEventDef(raw, context, refiners);
3166        let defaultAllDay = computeIsDefaultAllDay(eventSource, context);
3167        let recurringRes = parseRecurring(refined, defaultAllDay, context.dateEnv, context.pluginHooks.recurringTypes);
3168        if (recurringRes) {
3169            let def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', recurringRes.allDay, Boolean(recurringRes.duration), context, defIdMap);
3170            def.recurringDef = {
3171                typeId: recurringRes.typeId,
3172                typeData: recurringRes.typeData,
3173                duration: recurringRes.duration,
3174            };
3175            return { def, instance: null };
3176        }
3177        let singleRes = parseSingle(refined, defaultAllDay, context, allowOpenRange);
3178        if (singleRes) {
3179            let def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', singleRes.allDay, singleRes.hasEnd, context, defIdMap);
3180            let instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo);
3181            if (instanceIdMap && def.publicId && instanceIdMap[def.publicId]) {
3182                instance.instanceId = instanceIdMap[def.publicId];
3183            }
3184            return { def, instance };
3185        }
3186        return null;
3187    }
3188    function refineEventDef(raw, context, refiners = buildEventRefiners(context)) {
3189        return refineProps(raw, refiners);
3190    }
3191    function buildEventRefiners(context) {
3192        return Object.assign(Object.assign(Object.assign({}, EVENT_UI_REFINERS), EVENT_REFINERS), context.pluginHooks.eventRefiners);
3193    }
3194    /*
3195    Will NOT populate extendedProps with the leftover properties.
3196    Will NOT populate date-related props.
3197    */
3198    function parseEventDef(refined, extra, sourceId, allDay, hasEnd, context, defIdMap) {
3199        let def = {
3200            title: refined.title || '',
3201            groupId: refined.groupId || '',
3202            publicId: refined.id || '',
3203            url: refined.url || '',
3204            recurringDef: null,
3205            defId: ((defIdMap && refined.id) ? defIdMap[refined.id] : '') || guid(),
3206            sourceId,
3207            allDay,
3208            hasEnd,
3209            interactive: refined.interactive,
3210            ui: createEventUi(refined, context),
3211            extendedProps: Object.assign(Object.assign({}, (refined.extendedProps || {})), extra),
3212        };
3213        for (let memberAdder of context.pluginHooks.eventDefMemberAdders) {
3214            Object.assign(def, memberAdder(refined));
3215        }
3216        // help out EventImpl from having user modify props
3217        Object.freeze(def.ui.classNames);
3218        Object.freeze(def.extendedProps);
3219        return def;
3220    }
3221    function parseSingle(refined, defaultAllDay, context, allowOpenRange) {
3222        let { allDay } = refined;
3223        let startMeta;
3224        let startMarker = null;
3225        let hasEnd = false;
3226        let endMeta;
3227        let endMarker = null;
3228        let startInput = refined.start != null ? refined.start : refined.date;
3229        startMeta = context.dateEnv.createMarkerMeta(startInput);
3230        if (startMeta) {
3231            startMarker = startMeta.marker;
3232        }
3233        else if (!allowOpenRange) {
3234            return null;
3235        }
3236        if (refined.end != null) {
3237            endMeta = context.dateEnv.createMarkerMeta(refined.end);
3238        }
3239        if (allDay == null) {
3240            if (defaultAllDay != null) {
3241                allDay = defaultAllDay;
3242            }
3243            else {
3244                // fall back to the date props LAST
3245                allDay = (!startMeta || startMeta.isTimeUnspecified) &&
3246                    (!endMeta || endMeta.isTimeUnspecified);
3247            }
3248        }
3249        if (allDay && startMarker) {
3250            startMarker = startOfDay(startMarker);
3251        }
3252        if (endMeta) {
3253            endMarker = endMeta.marker;
3254            if (allDay) {
3255                endMarker = startOfDay(endMarker);
3256            }
3257            if (startMarker && endMarker <= startMarker) {
3258                endMarker = null;
3259            }
3260        }
3261        if (endMarker) {
3262            hasEnd = true;
3263        }
3264        else if (!allowOpenRange) {
3265            hasEnd = context.options.forceEventDuration || false;
3266            endMarker = context.dateEnv.add(startMarker, allDay ?
3267                context.options.defaultAllDayEventDuration :
3268                context.options.defaultTimedEventDuration);
3269        }
3270        return {
3271            allDay,
3272            hasEnd,
3273            range: { start: startMarker, end: endMarker },
3274            forcedStartTzo: startMeta ? startMeta.forcedTzo : null,
3275            forcedEndTzo: endMeta ? endMeta.forcedTzo : null,
3276        };
3277    }
3278    function computeIsDefaultAllDay(eventSource, context) {
3279        let res = null;
3280        if (eventSource) {
3281            res = eventSource.defaultAllDay;
3282        }
3283        if (res == null) {
3284            res = context.options.defaultAllDay;
3285        }
3286        return res;
3287    }
3288
3289    function parseEvents(rawEvents, eventSource, context, allowOpenRange, defIdMap, instanceIdMap) {
3290        let eventStore = createEmptyEventStore();
3291        let eventRefiners = buildEventRefiners(context);
3292        for (let rawEvent of rawEvents) {
3293            let tuple = parseEvent(rawEvent, eventSource, context, allowOpenRange, eventRefiners, defIdMap, instanceIdMap);
3294            if (tuple) {
3295                eventTupleToStore(tuple, eventStore);
3296            }
3297        }
3298        return eventStore;
3299    }
3300    function eventTupleToStore(tuple, eventStore = createEmptyEventStore()) {
3301        eventStore.defs[tuple.def.defId] = tuple.def;
3302        if (tuple.instance) {
3303            eventStore.instances[tuple.instance.instanceId] = tuple.instance;
3304        }
3305        return eventStore;
3306    }
3307    // retrieves events that have the same groupId as the instance specified by `instanceId`
3308    // or they are the same as the instance.
3309    // why might instanceId not be in the store? an event from another calendar?
3310    function getRelevantEvents(eventStore, instanceId) {
3311        let instance = eventStore.instances[instanceId];
3312        if (instance) {
3313            let def = eventStore.defs[instance.defId];
3314            // get events/instances with same group
3315            let newStore = filterEventStoreDefs(eventStore, (lookDef) => isEventDefsGrouped(def, lookDef));
3316            // add the original
3317            // TODO: wish we could use eventTupleToStore or something like it
3318            newStore.defs[def.defId] = def;
3319            newStore.instances[instance.instanceId] = instance;
3320            return newStore;
3321        }
3322        return createEmptyEventStore();
3323    }
3324    function isEventDefsGrouped(def0, def1) {
3325        return Boolean(def0.groupId && def0.groupId === def1.groupId);
3326    }
3327    function createEmptyEventStore() {
3328        return { defs: {}, instances: {} };
3329    }
3330    function mergeEventStores(store0, store1) {
3331        return {
3332            defs: Object.assign(Object.assign({}, store0.defs), store1.defs),
3333            instances: Object.assign(Object.assign({}, store0.instances), store1.instances),
3334        };
3335    }
3336    function filterEventStoreDefs(eventStore, filterFunc) {
3337        let defs = filterHash(eventStore.defs, filterFunc);
3338        let instances = filterHash(eventStore.instances, (instance) => (defs[instance.defId] // still exists?
3339        ));
3340        return { defs, instances };
3341    }
3342    function excludeSubEventStore(master, sub) {
3343        let { defs, instances } = master;
3344        let filteredDefs = {};
3345        let filteredInstances = {};
3346        for (let defId in defs) {
3347            if (!sub.defs[defId]) { // not explicitly excluded
vendor: 7,503 bytes, lines 3348-3532
3348                filteredDefs[defId] = defs[defId];
3349            }
3350        }
3351        for (let instanceId in instances) {
3352            if (!sub.instances[instanceId] && // not explicitly excluded
3353                filteredDefs[instances[instanceId].defId] // def wasn't filtered away
3354            ) {
3355                filteredInstances[instanceId] = instances[instanceId];
3356            }
3357        }
3358        return {
3359            defs: filteredDefs,
3360            instances: filteredInstances,
3361        };
3362    }
3363
3364    function normalizeConstraint(input, context) {
3365        if (Array.isArray(input)) {
3366            return parseEvents(input, null, context, true); // allowOpenRange=true
3367        }
3368        if (typeof input === 'object' && input) { // non-null object
3369            return parseEvents([input], null, context, true); // allowOpenRange=true
3370        }
3371        if (input != null) {
3372            return String(input);
3373        }
3374        return null;
3375    }
3376
3377    function parseClassNames(raw) {
3378        if (Array.isArray(raw)) {
3379            return raw;
3380        }
3381        if (typeof raw === 'string') {
3382            return raw.split(/\s+/);
3383        }
3384        return [];
3385    }
3386
3387    // TODO: better called "EventSettings" or "EventConfig"
3388    // TODO: move this file into structs
3389    // TODO: separate constraint/overlap/allow, because selection uses only that, not other props
3390    const EVENT_UI_REFINERS = {
3391        display: String,
3392        editable: Boolean,
3393        startEditable: Boolean,
3394        durationEditable: Boolean,
3395        constraint: identity,
3396        overlap: identity,
3397        allow: identity,
3398        className: parseClassNames,
3399        classNames: parseClassNames,
3400        color: String,
3401        backgroundColor: String,
3402        borderColor: String,
3403        textColor: String,
3404    };
3405    const EMPTY_EVENT_UI = {
3406        display: null,
3407        startEditable: null,
3408        durationEditable: null,
3409        constraints: [],
3410        overlap: null,
3411        allows: [],
3412        backgroundColor: '',
3413        borderColor: '',
3414        textColor: '',
3415        classNames: [],
3416    };
3417    function createEventUi(refined, context) {
3418        let constraint = normalizeConstraint(refined.constraint, context);
3419        return {
3420            display: refined.display || null,
3421            startEditable: refined.startEditable != null ? refined.startEditable : refined.editable,
3422            durationEditable: refined.durationEditable != null ? refined.durationEditable : refined.editable,
3423            constraints: constraint != null ? [constraint] : [],
3424            overlap: refined.overlap != null ? refined.overlap : null,
3425            allows: refined.allow != null ? [refined.allow] : [],
3426            backgroundColor: refined.backgroundColor || refined.color || '',
3427            borderColor: refined.borderColor || refined.color || '',
3428            textColor: refined.textColor || '',
3429            classNames: (refined.className || []).concat(refined.classNames || []), // join singular and plural
3430        };
3431    }
3432    // TODO: prevent against problems with <2 args!
3433    function combineEventUis(uis) {
3434        return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI);
3435    }
3436    function combineTwoEventUis(item0, item1) {
3437        return {
3438            display: item1.display != null ? item1.display : item0.display,
3439            startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable,
3440            durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable,
3441            constraints: item0.constraints.concat(item1.constraints),
3442            overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap,
3443            allows: item0.allows.concat(item1.allows),
3444            backgroundColor: item1.backgroundColor || item0.backgroundColor,
3445            borderColor: item1.borderColor || item0.borderColor,
3446            textColor: item1.textColor || item0.textColor,
3447            classNames: item0.classNames.concat(item1.classNames),
3448        };
3449    }
3450
3451    const EVENT_SOURCE_REFINERS = {
3452        id: String,
3453        defaultAllDay: Boolean,
3454        url: String,
3455        format: String,
3456        events: identity,
3457        eventDataTransform: identity,
3458        // for any network-related sources
3459        success: identity,
3460        failure: identity,
3461    };
3462    function parseEventSource(raw, context, refiners = buildEventSourceRefiners(context)) {
3463        let rawObj;
3464        if (typeof raw === 'string') {
3465            rawObj = { url: raw };
3466        }
3467        else if (typeof raw === 'function' || Array.isArray(raw)) {
3468            rawObj = { events: raw };
3469        }
3470        else if (typeof raw === 'object' && raw) { // not null
3471            rawObj = raw;
3472        }
3473        if (rawObj) {
3474            let { refined, extra } = refineProps(rawObj, refiners);
3475            let metaRes = buildEventSourceMeta(refined, context);
3476            if (metaRes) {
3477                return {
3478                    _raw: raw,
3479                    isFetching: false,
3480                    latestFetchId: '',
3481                    fetchRange: null,
3482                    defaultAllDay: refined.defaultAllDay,
3483                    eventDataTransform: refined.eventDataTransform,
3484                    success: refined.success,
3485                    failure: refined.failure,
3486                    publicId: refined.id || '',
3487                    sourceId: guid(),
3488                    sourceDefId: metaRes.sourceDefId,
3489                    meta: metaRes.meta,
3490                    ui: createEventUi(refined, context),
3491                    extendedProps: extra,
3492                };
3493            }
3494        }
3495        return null;
3496    }
3497    function buildEventSourceRefiners(context) {
3498        return Object.assign(Object.assign(Object.assign({}, EVENT_UI_REFINERS), EVENT_SOURCE_REFINERS), context.pluginHooks.eventSourceRefiners);
3499    }
3500    function buildEventSourceMeta(raw, context) {
3501        let defs = context.pluginHooks.eventSourceDefs;
3502        for (let i = defs.length - 1; i >= 0; i -= 1) { // later-added plugins take precedence
3503            let def = defs[i];
3504            let meta = def.parseMeta(raw);
3505            if (meta) {
3506                return { sourceDefId: i, meta };
3507            }
3508        }
3509        return null;
3510    }
3511
3512    function reduceEventStore(eventStore, action, eventSources, dateProfile, context) {
3513        switch (action.type) {
3514            case 'RECEIVE_EVENTS': // raw
3515                return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, context);
3516            case 'RESET_RAW_EVENTS':
3517                return resetRawEvents(eventStore, eventSources[action.sourceId], action.rawEvents, dateProfile.activeRange, context);
3518            case 'ADD_EVENTS': // already parsed, but not expanded
3519                return addEvent(eventStore, action.eventStore, // new ones
3520                dateProfile ? dateProfile.activeRange : null, context);
3521            case 'RESET_EVENTS':
3522                return action.eventStore;
3523            case 'MERGE_EVENTS': // already parsed and expanded
3524                return mergeEventStores(eventStore, action.eventStore);
3525            case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
3526            case 'NEXT':
3527            case 'CHANGE_DATE':
3528            case 'CHANGE_VIEW_TYPE':
3529                if (dateProfile) {
3530                    return expandRecurring(eventStore, dateProfile.activeRange, context);
3531                }
3532                return eventStore;
vendor: 13,211 bytes, lines 3533-3846
3533            case 'REMOVE_EVENTS':
3534                return excludeSubEventStore(eventStore, action.eventStore);
3535            case 'REMOVE_EVENT_SOURCE':
3536                return excludeEventsBySourceId(eventStore, action.sourceId);
3537            case 'REMOVE_ALL_EVENT_SOURCES':
3538                return filterEventStoreDefs(eventStore, (eventDef) => (!eventDef.sourceId // only keep events with no source id
3539                ));
3540            case 'REMOVE_ALL_EVENTS':
3541                return createEmptyEventStore();
3542            default:
3543                return eventStore;
3544        }
3545    }
3546    function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, context) {
3547        if (eventSource && // not already removed
3548            fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources
3549        ) {
3550            let subset = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context);
3551            if (fetchRange) {
3552                subset = expandRecurring(subset, fetchRange, context);
3553            }
3554            return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset);
3555        }
3556        return eventStore;
3557    }
3558    function resetRawEvents(existingEventStore, eventSource, rawEvents, activeRange, context) {
3559        const { defIdMap, instanceIdMap } = buildPublicIdMaps(existingEventStore);
3560        let newEventStore = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context, false, defIdMap, instanceIdMap);
3561        return expandRecurring(newEventStore, activeRange, context);
3562    }
3563    function transformRawEvents(rawEvents, eventSource, context) {
3564        let calEachTransform = context.options.eventDataTransform;
3565        let sourceEachTransform = eventSource ? eventSource.eventDataTransform : null;
3566        if (sourceEachTransform) {
3567            rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform);
3568        }
3569        if (calEachTransform) {
3570            rawEvents = transformEachRawEvent(rawEvents, calEachTransform);
3571        }
3572        return rawEvents;
3573    }
3574    function transformEachRawEvent(rawEvents, func) {
3575        let refinedEvents;
3576        if (!func) {
3577            refinedEvents = rawEvents;
3578        }
3579        else {
3580            refinedEvents = [];
3581            for (let rawEvent of rawEvents) {
3582                let refinedEvent = func(rawEvent);
3583                if (refinedEvent) {
3584                    refinedEvents.push(refinedEvent);
3585                }
3586                else if (refinedEvent == null) {
3587                    refinedEvents.push(rawEvent);
3588                } // if a different falsy value, do nothing
3589            }
3590        }
3591        return refinedEvents;
3592    }
3593    function addEvent(eventStore, subset, expandRange, context) {
3594        if (expandRange) {
3595            subset = expandRecurring(subset, expandRange, context);
3596        }
3597        return mergeEventStores(eventStore, subset);
3598    }
3599    function rezoneEventStoreDates(eventStore, oldDateEnv, newDateEnv) {
3600        let { defs } = eventStore;
3601        let instances = mapHash(eventStore.instances, (instance) => {
3602            let def = defs[instance.defId];
3603            if (def.allDay) {
3604                return instance; // isn't dependent on timezone
3605            }
3606            return Object.assign(Object.assign({}, instance), { range: {
3607                    start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)),
3608                    end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo)),
3609                }, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo });
3610        });
3611        return { defs, instances };
3612    }
3613    function excludeEventsBySourceId(eventStore, sourceId) {
3614        return filterEventStoreDefs(eventStore, (eventDef) => eventDef.sourceId !== sourceId);
3615    }
3616    // QUESTION: why not just return instances? do a general object-property-exclusion util
3617    function excludeInstances(eventStore, removals) {
3618        return {
3619            defs: eventStore.defs,
3620            instances: filterHash(eventStore.instances, (instance) => !removals[instance.instanceId]),
3621        };
3622    }
3623    function buildPublicIdMaps(eventStore) {
3624        const { defs, instances } = eventStore;
3625        const defIdMap = {};
3626        const instanceIdMap = {};
3627        for (let defId in defs) {
3628            const def = defs[defId];
3629            const { publicId } = def;
3630            if (publicId) {
3631                defIdMap[publicId] = defId;
3632            }
3633        }
3634        for (let instanceId in instances) {
3635            const instance = instances[instanceId];
3636            const def = defs[instance.defId];
3637            const { publicId } = def;
3638            if (publicId) {
3639                instanceIdMap[publicId] = instanceId;
3640            }
3641        }
3642        return { defIdMap, instanceIdMap };
3643    }
3644
3645    class Emitter {
3646        constructor() {
3647            this.handlers = {};
3648            this.thisContext = null;
3649        }
3650        setThisContext(thisContext) {
3651            this.thisContext = thisContext;
3652        }
3653        setOptions(options) {
3654            this.options = options;
3655        }
3656        on(type, handler) {
3657            addToHash(this.handlers, type, handler);
3658        }
3659        off(type, handler) {
3660            removeFromHash(this.handlers, type, handler);
3661        }
3662        trigger(type, ...args) {
3663            let attachedHandlers = this.handlers[type] || [];
3664            let optionHandler = this.options && this.options[type];
3665            let handlers = [].concat(optionHandler || [], attachedHandlers);
3666            for (let handler of handlers) {
3667                handler.apply(this.thisContext, args);
3668            }
3669        }
3670        hasHandlers(type) {
3671            return Boolean((this.handlers[type] && this.handlers[type].length) ||
3672                (this.options && this.options[type]));
3673        }
3674    }
3675    function addToHash(hash, type, handler) {
3676        (hash[type] || (hash[type] = []))
3677            .push(handler);
3678    }
3679    function removeFromHash(hash, type, handler) {
3680        if (handler) {
3681            if (hash[type]) {
3682                hash[type] = hash[type].filter((func) => func !== handler);
3683            }
3684        }
3685        else {
3686            delete hash[type]; // remove all handler funcs for this type
3687        }
3688    }
3689
3690    const DEF_DEFAULTS = {
3691        startTime: '09:00',
3692        endTime: '17:00',
3693        daysOfWeek: [1, 2, 3, 4, 5],
3694        display: 'inverse-background',
3695        classNames: 'fc-non-business',
3696        groupId: '_businessHours', // so multiple defs get grouped
3697    };
3698    /*
3699    TODO: pass around as EventDefHash!!!
3700    */
3701    function parseBusinessHours(input, context) {
3702        return parseEvents(refineInputs(input), null, context);
3703    }
3704    function refineInputs(input) {
3705        let rawDefs;
3706        if (input === true) {
3707            rawDefs = [{}]; // will get DEF_DEFAULTS verbatim
3708        }
3709        else if (Array.isArray(input)) {
3710            // if specifying an array, every sub-definition NEEDS a day-of-week
3711            rawDefs = input.filter((rawDef) => rawDef.daysOfWeek);
3712        }
3713        else if (typeof input === 'object' && input) { // non-null object
3714            rawDefs = [input];
3715        }
3716        else { // is probably false
3717            rawDefs = [];
3718        }
3719        rawDefs = rawDefs.map((rawDef) => (Object.assign(Object.assign({}, DEF_DEFAULTS), rawDef)));
3720        return rawDefs;
3721    }
3722
3723    function triggerDateSelect(selection, pev, context) {
3724        context.emitter.trigger('select', Object.assign(Object.assign({}, buildDateSpanApiWithContext(selection, context)), { jsEvent: pev ? pev.origEvent : null, view: context.viewApi || context.calendarApi.view }));
3725    }
3726    function triggerDateUnselect(pev, context) {
3727        context.emitter.trigger('unselect', {
3728            jsEvent: pev ? pev.origEvent : null,
3729            view: context.viewApi || context.calendarApi.view,
3730        });
3731    }
3732    function buildDateSpanApiWithContext(dateSpan, context) {
3733        let props = {};
3734        for (let transform of context.pluginHooks.dateSpanTransforms) {
3735            Object.assign(props, transform(dateSpan, context));
3736        }
3737        Object.assign(props, buildDateSpanApi(dateSpan, context.dateEnv));
3738        return props;
3739    }
3740    // Given an event's allDay status and start date, return what its fallback end date should be.
3741    // TODO: rename to computeDefaultEventEnd
3742    function getDefaultEventEnd(allDay, marker, context) {
3743        let { dateEnv, options } = context;
3744        let end = marker;
3745        if (allDay) {
3746            end = startOfDay(end);
3747            end = dateEnv.add(end, options.defaultAllDayEventDuration);
3748        }
3749        else {
3750            end = dateEnv.add(end, options.defaultTimedEventDuration);
3751        }
3752        return end;
3753    }
3754
3755    // applies the mutation to ALL defs/instances within the event store
3756    function applyMutationToEventStore(eventStore, eventConfigBase, mutation, context) {
3757        let eventConfigs = compileEventUis(eventStore.defs, eventConfigBase);
3758        let dest = createEmptyEventStore();
3759        for (let defId in eventStore.defs) {
3760            let def = eventStore.defs[defId];
3761            dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, context);
3762        }
3763        for (let instanceId in eventStore.instances) {
3764            let instance = eventStore.instances[instanceId];
3765            let def = dest.defs[instance.defId]; // important to grab the newly modified def
3766            dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, context);
3767        }
3768        return dest;
3769    }
3770    function applyMutationToEventDef(eventDef, eventConfig, mutation, context) {
3771        let standardProps = mutation.standardProps || {};
3772        // if hasEnd has not been specified, guess a good value based on deltas.
3773        // if duration will change, there's no way the default duration will persist,
3774        // and thus, we need to mark the event as having a real end
3775        if (standardProps.hasEnd == null &&
3776            eventConfig.durationEditable &&
3777            (mutation.startDelta || mutation.endDelta)) {
3778            standardProps.hasEnd = true; // TODO: is this mutation okay?
3779        }
3780        let copy = Object.assign(Object.assign(Object.assign({}, eventDef), standardProps), { ui: Object.assign(Object.assign({}, eventDef.ui), standardProps.ui) });
3781        if (mutation.extendedProps) {
3782            copy.extendedProps = Object.assign(Object.assign({}, copy.extendedProps), mutation.extendedProps);
3783        }
3784        for (let applier of context.pluginHooks.eventDefMutationAppliers) {
3785            applier(copy, mutation, context);
3786        }
3787        if (!copy.hasEnd && context.options.forceEventDuration) {
3788            copy.hasEnd = true;
3789        }
3790        return copy;
3791    }
3792    function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef
3793    eventConfig, mutation, context) {
3794        let { dateEnv } = context;
3795        let forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true;
3796        let clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false;
3797        let copy = Object.assign({}, eventInstance);
3798        if (forceAllDay) {
3799            copy.range = computeAlignedDayRange(copy.range);
3800        }
3801        if (mutation.datesDelta && eventConfig.startEditable) {
3802            copy.range = {
3803                start: dateEnv.add(copy.range.start, mutation.datesDelta),
3804                end: dateEnv.add(copy.range.end, mutation.datesDelta),
3805            };
3806        }
3807        if (mutation.startDelta && eventConfig.durationEditable) {
3808            copy.range = {
3809                start: dateEnv.add(copy.range.start, mutation.startDelta),
3810                end: copy.range.end,
3811            };
3812        }
3813        if (mutation.endDelta && eventConfig.durationEditable) {
3814            copy.range = {
3815                start: copy.range.start,
3816                end: dateEnv.add(copy.range.end, mutation.endDelta),
3817            };
3818        }
3819        if (clearEnd) {
3820            copy.range = {
3821                start: copy.range.start,
3822                end: getDefaultEventEnd(eventDef.allDay, copy.range.start, context),
3823            };
3824        }
3825        // in case event was all-day but the supplied deltas were not
3826        // better util for this?
3827        if (eventDef.allDay) {
3828            copy.range = {
3829                start: startOfDay(copy.range.start),
3830                end: startOfDay(copy.range.end),
3831            };
3832        }
3833        // handle invalid durations
3834        if (copy.range.end < copy.range.start) {
3835            copy.range.end = getDefaultEventEnd(eventDef.allDay, copy.range.start, context);
3836        }
3837        return copy;
3838    }
3839
3840    class EventSourceImpl {
3841        constructor(context, internalEventSource) {
3842            this.context = context;
3843            this.internalEventSource = internalEventSource;
3844        }
3845        remove() {
3846            this.context.dispatch({
vendor: 26,429 bytes, lines 3847-4514
3847                type: 'REMOVE_EVENT_SOURCE',
3848                sourceId: this.internalEventSource.sourceId,
3849            });
3850        }
3851        refetch() {
3852            this.context.dispatch({
3853                type: 'FETCH_EVENT_SOURCES',
3854                sourceIds: [this.internalEventSource.sourceId],
3855                isRefetch: true,
3856            });
3857        }
3858        get id() {
3859            return this.internalEventSource.publicId;
3860        }
3861        get url() {
3862            return this.internalEventSource.meta.url;
3863        }
3864        get format() {
3865            return this.internalEventSource.meta.format; // TODO: bad. not guaranteed
3866        }
3867    }
3868
3869    class EventImpl {
3870        // instance will be null if expressing a recurring event that has no current instances,
3871        // OR if trying to validate an incoming external event that has no dates assigned
3872        constructor(context, def, instance) {
3873            this._context = context;
3874            this._def = def;
3875            this._instance = instance || null;
3876        }
3877        /*
3878        TODO: make event struct more responsible for this
3879        */
3880        setProp(name, val) {
3881            if (name in EVENT_DATE_REFINERS) {
3882                console.warn('Could not set date-related prop \'name\'. Use one of the date-related methods instead.');
3883                // TODO: make proper aliasing system?
3884            }
3885            else if (name === 'id') {
3886                val = EVENT_NON_DATE_REFINERS[name](val);
3887                this.mutate({
3888                    standardProps: { publicId: val }, // hardcoded internal name
3889                });
3890            }
3891            else if (name in EVENT_NON_DATE_REFINERS) {
3892                val = EVENT_NON_DATE_REFINERS[name](val);
3893                this.mutate({
3894                    standardProps: { [name]: val },
3895                });
3896            }
3897            else if (name in EVENT_UI_REFINERS) {
3898                let ui = EVENT_UI_REFINERS[name](val);
3899                if (name === 'color') {
3900                    ui = { backgroundColor: val, borderColor: val };
3901                }
3902                else if (name === 'editable') {
3903                    ui = { startEditable: val, durationEditable: val };
3904                }
3905                else {
3906                    ui = { [name]: val };
3907                }
3908                this.mutate({
3909                    standardProps: { ui },
3910                });
3911            }
3912            else {
3913                console.warn(`Could not set prop '${name}'. Use setExtendedProp instead.`);
3914            }
3915        }
3916        setExtendedProp(name, val) {
3917            this.mutate({
3918                extendedProps: { [name]: val },
3919            });
3920        }
3921        setStart(startInput, options = {}) {
3922            let { dateEnv } = this._context;
3923            let start = dateEnv.createMarker(startInput);
3924            if (start && this._instance) { // TODO: warning if parsed bad
3925                let instanceRange = this._instance.range;
3926                let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!?
3927                if (options.maintainDuration) {
3928                    this.mutate({ datesDelta: startDelta });
3929                }
3930                else {
3931                    this.mutate({ startDelta });
3932                }
3933            }
3934        }
3935        setEnd(endInput, options = {}) {
3936            let { dateEnv } = this._context;
3937            let end;
3938            if (endInput != null) {
3939                end = dateEnv.createMarker(endInput);
3940                if (!end) {
3941                    return; // TODO: warning if parsed bad
3942                }
3943            }
3944            if (this._instance) {
3945                if (end) {
3946                    let endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity);
3947                    this.mutate({ endDelta });
3948                }
3949                else {
3950                    this.mutate({ standardProps: { hasEnd: false } });
3951                }
3952            }
3953        }
3954        setDates(startInput, endInput, options = {}) {
3955            let { dateEnv } = this._context;
3956            let standardProps = { allDay: options.allDay };
3957            let start = dateEnv.createMarker(startInput);
3958            let end;
3959            if (!start) {
3960                return; // TODO: warning if parsed bad
3961            }
3962            if (endInput != null) {
3963                end = dateEnv.createMarker(endInput);
3964                if (!end) { // TODO: warning if parsed bad
3965                    return;
3966                }
3967            }
3968            if (this._instance) {
3969                let instanceRange = this._instance.range;
3970                // when computing the diff for an event being converted to all-day,
3971                // compute diff off of the all-day values the way event-mutation does.
3972                if (options.allDay === true) {
3973                    instanceRange = computeAlignedDayRange(instanceRange);
3974                }
3975                let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity);
3976                if (end) {
3977                    let endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity);
3978                    if (durationsEqual(startDelta, endDelta)) {
3979                        this.mutate({ datesDelta: startDelta, standardProps });
3980                    }
3981                    else {
3982                        this.mutate({ startDelta, endDelta, standardProps });
3983                    }
3984                }
3985                else { // means "clear the end"
3986                    standardProps.hasEnd = false;
3987                    this.mutate({ datesDelta: startDelta, standardProps });
3988                }
3989            }
3990        }
3991        moveStart(deltaInput) {
3992            let delta = createDuration(deltaInput);
3993            if (delta) { // TODO: warning if parsed bad
3994                this.mutate({ startDelta: delta });
3995            }
3996        }
3997        moveEnd(deltaInput) {
3998            let delta = createDuration(deltaInput);
3999            if (delta) { // TODO: warning if parsed bad
4000                this.mutate({ endDelta: delta });
4001            }
4002        }
4003        moveDates(deltaInput) {
4004            let delta = createDuration(deltaInput);
4005            if (delta) { // TODO: warning if parsed bad
4006                this.mutate({ datesDelta: delta });
4007            }
4008        }
4009        setAllDay(allDay, options = {}) {
4010            let standardProps = { allDay };
4011            let { maintainDuration } = options;
4012            if (maintainDuration == null) {
4013                maintainDuration = this._context.options.allDayMaintainDuration;
4014            }
4015            if (this._def.allDay !== allDay) {
4016                standardProps.hasEnd = maintainDuration;
4017            }
4018            this.mutate({ standardProps });
4019        }
4020        formatRange(formatInput) {
4021            let { dateEnv } = this._context;
4022            let instance = this._instance;
4023            let formatter = createFormatter(formatInput);
4024            if (this._def.hasEnd) {
4025                return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, {
4026                    forcedStartTzo: instance.forcedStartTzo,
4027                    forcedEndTzo: instance.forcedEndTzo,
4028                });
4029            }
4030            return dateEnv.format(instance.range.start, formatter, {
4031                forcedTzo: instance.forcedStartTzo,
4032            });
4033        }
4034        mutate(mutation) {
4035            let instance = this._instance;
4036            if (instance) {
4037                let def = this._def;
4038                let context = this._context;
4039                let { eventStore } = context.getCurrentData();
4040                let relevantEvents = getRelevantEvents(eventStore, instance.instanceId);
4041                let eventConfigBase = {
4042                    '': {
4043                        display: '',
4044                        startEditable: true,
4045                        durationEditable: true,
4046                        constraints: [],
4047                        overlap: null,
4048                        allows: [],
4049                        backgroundColor: '',
4050                        borderColor: '',
4051                        textColor: '',
4052                        classNames: [],
4053                    },
4054                };
4055                relevantEvents = applyMutationToEventStore(relevantEvents, eventConfigBase, mutation, context);
4056                let oldEvent = new EventImpl(context, def, instance); // snapshot
4057                this._def = relevantEvents.defs[def.defId];
4058                this._instance = relevantEvents.instances[instance.instanceId];
4059                context.dispatch({
4060                    type: 'MERGE_EVENTS',
4061                    eventStore: relevantEvents,
4062                });
4063                context.emitter.trigger('eventChange', {
4064                    oldEvent,
4065                    event: this,
4066                    relatedEvents: buildEventApis(relevantEvents, context, instance),
4067                    revert() {
4068                        context.dispatch({
4069                            type: 'RESET_EVENTS',
4070                            eventStore, // the ORIGINAL store
4071                        });
4072                    },
4073                });
4074            }
4075        }
4076        remove() {
4077            let context = this._context;
4078            let asStore = eventApiToStore(this);
4079            context.dispatch({
4080                type: 'REMOVE_EVENTS',
4081                eventStore: asStore,
4082            });
4083            context.emitter.trigger('eventRemove', {
4084                event: this,
4085                relatedEvents: [],
4086                revert() {
4087                    context.dispatch({
4088                        type: 'MERGE_EVENTS',
4089                        eventStore: asStore,
4090                    });
4091                },
4092            });
4093        }
4094        get source() {
4095            let { sourceId } = this._def;
4096            if (sourceId) {
4097                return new EventSourceImpl(this._context, this._context.getCurrentData().eventSources[sourceId]);
4098            }
4099            return null;
4100        }
4101        get start() {
4102            return this._instance ?
4103                this._context.dateEnv.toDate(this._instance.range.start) :
4104                null;
4105        }
4106        get end() {
4107            return (this._instance && this._def.hasEnd) ?
4108                this._context.dateEnv.toDate(this._instance.range.end) :
4109                null;
4110        }
4111        get startStr() {
4112            let instance = this._instance;
4113            if (instance) {
4114                return this._context.dateEnv.formatIso(instance.range.start, {
4115                    omitTime: this._def.allDay,
4116                    forcedTzo: instance.forcedStartTzo,
4117                });
4118            }
4119            return '';
4120        }
4121        get endStr() {
4122            let instance = this._instance;
4123            if (instance && this._def.hasEnd) {
4124                return this._context.dateEnv.formatIso(instance.range.end, {
4125                    omitTime: this._def.allDay,
4126                    forcedTzo: instance.forcedEndTzo,
4127                });
4128            }
4129            return '';
4130        }
4131        // computable props that all access the def
4132        // TODO: find a TypeScript-compatible way to do this at scale
4133        get id() { return this._def.publicId; }
4134        get groupId() { return this._def.groupId; }
4135        get allDay() { return this._def.allDay; }
4136        get title() { return this._def.title; }
4137        get url() { return this._def.url; }
4138        get display() { return this._def.ui.display || 'auto'; } // bad. just normalize the type earlier
4139        get startEditable() { return this._def.ui.startEditable; }
4140        get durationEditable() { return this._def.ui.durationEditable; }
4141        get constraint() { return this._def.ui.constraints[0] || null; }
4142        get overlap() { return this._def.ui.overlap; }
4143        get allow() { return this._def.ui.allows[0] || null; }
4144        get backgroundColor() { return this._def.ui.backgroundColor; }
4145        get borderColor() { return this._def.ui.borderColor; }
4146        get textColor() { return this._def.ui.textColor; }
4147        // NOTE: user can't modify these because Object.freeze was called in event-def parsing
4148        get classNames() { return this._def.ui.classNames; }
4149        get extendedProps() { return this._def.extendedProps; }
4150        toPlainObject(settings = {}) {
4151            let def = this._def;
4152            let { ui } = def;
4153            let { startStr, endStr } = this;
4154            let res = {
4155                allDay: def.allDay,
4156            };
4157            if (def.title) {
4158                res.title = def.title;
4159            }
4160            if (startStr) {
4161                res.start = startStr;
4162            }
4163            if (endStr) {
4164                res.end = endStr;
4165            }
4166            if (def.publicId) {
4167                res.id = def.publicId;
4168            }
4169            if (def.groupId) {
4170                res.groupId = def.groupId;
4171            }
4172            if (def.url) {
4173                res.url = def.url;
4174            }
4175            if (ui.display && ui.display !== 'auto') {
4176                res.display = ui.display;
4177            }
4178            // TODO: what about recurring-event properties???
4179            // TODO: include startEditable/durationEditable/constraint/overlap/allow
4180            if (settings.collapseColor && ui.backgroundColor && ui.backgroundColor === ui.borderColor) {
4181                res.color = ui.backgroundColor;
4182            }
4183            else {
4184                if (ui.backgroundColor) {
4185                    res.backgroundColor = ui.backgroundColor;
4186                }
4187                if (ui.borderColor) {
4188                    res.borderColor = ui.borderColor;
4189                }
4190            }
4191            if (ui.textColor) {
4192                res.textColor = ui.textColor;
4193            }
4194            if (ui.classNames.length) {
4195                res.classNames = ui.classNames;
4196            }
4197            if (Object.keys(def.extendedProps).length) {
4198                if (settings.collapseExtendedProps) {
4199                    Object.assign(res, def.extendedProps);
4200                }
4201                else {
4202                    res.extendedProps = def.extendedProps;
4203                }
4204            }
4205            return res;
4206        }
4207        toJSON() {
4208            return this.toPlainObject();
4209        }
4210    }
4211    function eventApiToStore(eventApi) {
4212        let def = eventApi._def;
4213        let instance = eventApi._instance;
4214        return {
4215            defs: { [def.defId]: def },
4216            instances: instance
4217                ? { [instance.instanceId]: instance }
4218                : {},
4219        };
4220    }
4221    function buildEventApis(eventStore, context, excludeInstance) {
4222        let { defs, instances } = eventStore;
4223        let eventApis = [];
4224        let excludeInstanceId = excludeInstance ? excludeInstance.instanceId : '';
4225        for (let id in instances) {
4226            let instance = instances[id];
4227            let def = defs[instance.defId];
4228            if (instance.instanceId !== excludeInstanceId) {
4229                eventApis.push(new EventImpl(context, def, instance));
4230            }
4231        }
4232        return eventApis;
4233    }
4234
4235    /*
4236    Specifying nextDayThreshold signals that all-day ranges should be sliced.
4237    */
4238    function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) {
4239        let inverseBgByGroupId = {};
4240        let inverseBgByDefId = {};
4241        let defByGroupId = {};
4242        let bgRanges = [];
4243        let fgRanges = [];
4244        let eventUis = compileEventUis(eventStore.defs, eventUiBases);
4245        for (let defId in eventStore.defs) {
4246            let def = eventStore.defs[defId];
4247            let ui = eventUis[def.defId];
4248            if (ui.display === 'inverse-background') {
4249                if (def.groupId) {
4250                    inverseBgByGroupId[def.groupId] = [];
4251                    if (!defByGroupId[def.groupId]) {
4252                        defByGroupId[def.groupId] = def;
4253                    }
4254                }
4255                else {
4256                    inverseBgByDefId[defId] = [];
4257                }
4258            }
4259        }
4260        for (let instanceId in eventStore.instances) {
4261            let instance = eventStore.instances[instanceId];
4262            let def = eventStore.defs[instance.defId];
4263            let ui = eventUis[def.defId];
4264            let origRange = instance.range;
4265            let normalRange = (!def.allDay && nextDayThreshold) ?
4266                computeVisibleDayRange(origRange, nextDayThreshold) :
4267                origRange;
4268            let slicedRange = intersectRanges(normalRange, framingRange);
4269            if (slicedRange) {
4270                if (ui.display === 'inverse-background') {
4271                    if (def.groupId) {
4272                        inverseBgByGroupId[def.groupId].push(slicedRange);
4273                    }
4274                    else {
4275                        inverseBgByDefId[instance.defId].push(slicedRange);
4276                    }
4277                }
4278                else if (ui.display !== 'none') {
4279                    (ui.display === 'background' ? bgRanges : fgRanges).push({
4280                        def,
4281                        ui,
4282                        instance,
4283                        range: slicedRange,
4284                        isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(),
4285                        isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf(),
4286                    });
4287                }
4288            }
4289        }
4290        for (let groupId in inverseBgByGroupId) { // BY GROUP
4291            let ranges = inverseBgByGroupId[groupId];
4292            let invertedRanges = invertRanges(ranges, framingRange);
4293            for (let invertedRange of invertedRanges) {
4294                let def = defByGroupId[groupId];
4295                let ui = eventUis[def.defId];
4296                bgRanges.push({
4297                    def,
4298                    ui,
4299                    instance: null,
4300                    range: invertedRange,
4301                    isStart: false,
4302                    isEnd: false,
4303                });
4304            }
4305        }
4306        for (let defId in inverseBgByDefId) {
4307            let ranges = inverseBgByDefId[defId];
4308            let invertedRanges = invertRanges(ranges, framingRange);
4309            for (let invertedRange of invertedRanges) {
4310                bgRanges.push({
4311                    def: eventStore.defs[defId],
4312                    ui: eventUis[defId],
4313                    instance: null,
4314                    range: invertedRange,
4315                    isStart: false,
4316                    isEnd: false,
4317                });
4318            }
4319        }
4320        return { bg: bgRanges, fg: fgRanges };
4321    }
4322    function hasBgRendering(def) {
4323        return def.ui.display === 'background' || def.ui.display === 'inverse-background';
4324    }
4325    function setElSeg(el, seg) {
4326        el.fcSeg = seg;
4327    }
4328    function getElSeg(el) {
4329        return el.fcSeg ||
4330            el.parentNode.fcSeg || // for the harness
4331            null;
4332    }
4333    // event ui computation
4334    function compileEventUis(eventDefs, eventUiBases) {
4335        return mapHash(eventDefs, (eventDef) => compileEventUi(eventDef, eventUiBases));
4336    }
4337    function compileEventUi(eventDef, eventUiBases) {
4338        let uis = [];
4339        if (eventUiBases['']) {
4340            uis.push(eventUiBases['']);
4341        }
4342        if (eventUiBases[eventDef.defId]) {
4343            uis.push(eventUiBases[eventDef.defId]);
4344        }
4345        uis.push(eventDef.ui);
4346        return combineEventUis(uis);
4347    }
4348    function sortEventSegs(segs, eventOrderSpecs) {
4349        let objs = segs.map(buildSegCompareObj);
4350        objs.sort((obj0, obj1) => compareByFieldSpecs(obj0, obj1, eventOrderSpecs));
4351        return objs.map((c) => c._seg);
4352    }
4353    // returns a object with all primitive props that can be compared
4354    function buildSegCompareObj(seg) {
4355        let { eventRange } = seg;
4356        let eventDef = eventRange.def;
4357        let range = eventRange.instance ? eventRange.instance.range : eventRange.range;
4358        let start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events
4359        let end = range.end ? range.end.valueOf() : 0; // "
4360        return Object.assign(Object.assign(Object.assign({}, eventDef.extendedProps), eventDef), { id: eventDef.publicId, start,
4361            end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg });
4362    }
4363    function computeSegDraggable(seg, context) {
4364        let { pluginHooks } = context;
4365        let transformers = pluginHooks.isDraggableTransformers;
4366        let { def, ui } = seg.eventRange;
4367        let val = ui.startEditable;
4368        for (let transformer of transformers) {
4369            val = transformer(val, def, ui, context);
4370        }
4371        return val;
4372    }
4373    function computeSegStartResizable(seg, context) {
4374        return seg.isStart && seg.eventRange.ui.durationEditable && context.options.eventResizableFromStart;
4375    }
4376    function computeSegEndResizable(seg, context) {
4377        return seg.isEnd && seg.eventRange.ui.durationEditable;
4378    }
4379    function buildSegTimeText(seg, timeFormat, context, defaultDisplayEventTime, // defaults to true
4380    defaultDisplayEventEnd, // defaults to true
4381    startOverride, endOverride) {
4382        let { dateEnv, options } = context;
4383        let { displayEventTime, displayEventEnd } = options;
4384        let eventDef = seg.eventRange.def;
4385        let eventInstance = seg.eventRange.instance;
4386        if (displayEventTime == null) {
4387            displayEventTime = defaultDisplayEventTime !== false;
4388        }
4389        if (displayEventEnd == null) {
4390            displayEventEnd = defaultDisplayEventEnd !== false;
4391        }
4392        let wholeEventStart = eventInstance.range.start;
4393        let wholeEventEnd = eventInstance.range.end;
4394        let segStart = startOverride || seg.start || seg.eventRange.range.start;
4395        let segEnd = endOverride || seg.end || seg.eventRange.range.end;
4396        let isStartDay = startOfDay(wholeEventStart).valueOf() === startOfDay(segStart).valueOf();
4397        let isEndDay = startOfDay(addMs(wholeEventEnd, -1)).valueOf() === startOfDay(addMs(segEnd, -1)).valueOf();
4398        if (displayEventTime && !eventDef.allDay && (isStartDay || isEndDay)) {
4399            segStart = isStartDay ? wholeEventStart : segStart;
4400            segEnd = isEndDay ? wholeEventEnd : segEnd;
4401            if (displayEventEnd && eventDef.hasEnd) {
4402                return dateEnv.formatRange(segStart, segEnd, timeFormat, {
4403                    forcedStartTzo: startOverride ? null : eventInstance.forcedStartTzo,
4404                    forcedEndTzo: endOverride ? null : eventInstance.forcedEndTzo,
4405                });
4406            }
4407            return dateEnv.format(segStart, timeFormat, {
4408                forcedTzo: startOverride ? null : eventInstance.forcedStartTzo, // nooooo, same
4409            });
4410        }
4411        return '';
4412    }
4413    function getSegMeta(seg, todayRange, nowDate) {
4414        let segRange = seg.eventRange.range;
4415        return {
4416            isPast: segRange.end <= (nowDate || todayRange.start),
4417            isFuture: segRange.start >= (nowDate || todayRange.end),
4418            isToday: todayRange && rangeContainsMarker(todayRange, segRange.start),
4419        };
4420    }
4421    function getEventClassNames(props) {
4422        let classNames = ['fc-event'];
4423        if (props.isMirror) {
4424            classNames.push('fc-event-mirror');
4425        }
4426        if (props.isDraggable) {
4427            classNames.push('fc-event-draggable');
4428        }
4429        if (props.isStartResizable || props.isEndResizable) {
4430            classNames.push('fc-event-resizable');
4431        }
4432        if (props.isDragging) {
4433            classNames.push('fc-event-dragging');
4434        }
4435        if (props.isResizing) {
4436            classNames.push('fc-event-resizing');
4437        }
4438        if (props.isSelected) {
4439            classNames.push('fc-event-selected');
4440        }
4441        if (props.isStart) {
4442            classNames.push('fc-event-start');
4443        }
4444        if (props.isEnd) {
4445            classNames.push('fc-event-end');
4446        }
4447        if (props.isPast) {
4448            classNames.push('fc-event-past');
4449        }
4450        if (props.isToday) {
4451            classNames.push('fc-event-today');
4452        }
4453        if (props.isFuture) {
4454            classNames.push('fc-event-future');
4455        }
4456        return classNames;
4457    }
4458    function buildEventRangeKey(eventRange) {
4459        return eventRange.instance
4460            ? eventRange.instance.instanceId
4461            : `${eventRange.def.defId}:${eventRange.range.start.toISOString()}`;
4462        // inverse-background events don't have specific instances. TODO: better solution
4463    }
4464    function getSegAnchorAttrs(seg, context) {
4465        let { def, instance } = seg.eventRange;
4466        let { url } = def;
4467        if (url) {
4468            return { href: url };
4469        }
4470        let { emitter, options } = context;
4471        let { eventInteractive } = options;
4472        if (eventInteractive == null) {
4473            eventInteractive = def.interactive;
4474            if (eventInteractive == null) {
4475                eventInteractive = Boolean(emitter.hasHandlers('eventClick'));
4476            }
4477        }
4478        // mock what happens in EventClicking
4479        if (eventInteractive) {
4480            // only attach keyboard-related handlers because click handler is already done in EventClicking
4481            return createAriaKeyboardAttrs((ev) => {
4482                emitter.trigger('eventClick', {
4483                    el: ev.target,
4484                    event: new EventImpl(context, def, instance),
4485                    jsEvent: ev,
4486                    view: context.viewApi,
4487                });
4488            });
4489        }
4490        return {};
4491    }
4492
4493    const STANDARD_PROPS = {
4494        start: identity,
4495        end: identity,
4496        allDay: Boolean,
4497    };
4498    function parseDateSpan(raw, dateEnv, defaultDuration) {
4499        let span = parseOpenDateSpan(raw, dateEnv);
4500        let { range } = span;
4501        if (!range.start) {
4502            return null;
4503        }
4504        if (!range.end) {
4505            if (defaultDuration == null) {
4506                return null;
4507            }
4508            range.end = dateEnv.add(range.start, defaultDuration);
4509        }
4510        return span;
4511    }
4512    /*
4513    TODO: somehow combine with parseRange?
4514    Will return null if the start/end props were present but parsed invali
vendor: 4,807 bytes, lines 4514-4636
4514dly.
4515    */
4516    function parseOpenDateSpan(raw, dateEnv) {
4517        let { refined: standardProps, extra } = refineProps(raw, STANDARD_PROPS);
4518        let startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null;
4519        let endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null;
4520        let { allDay } = standardProps;
4521        if (allDay == null) {
4522            allDay = (startMeta && startMeta.isTimeUnspecified) &&
4523                (!endMeta || endMeta.isTimeUnspecified);
4524        }
4525        return Object.assign({ range: {
4526                start: startMeta ? startMeta.marker : null,
4527                end: endMeta ? endMeta.marker : null,
4528            }, allDay }, extra);
4529    }
4530    function isDateSpansEqual(span0, span1) {
4531        return rangesEqual(span0.range, span1.range) &&
4532            span0.allDay === span1.allDay &&
4533            isSpanPropsEqual(span0, span1);
4534    }
4535    // the NON-DATE-RELATED props
4536    function isSpanPropsEqual(span0, span1) {
4537        for (let propName in span1) {
4538            if (propName !== 'range' && propName !== 'allDay') {
4539                if (span0[propName] !== span1[propName]) {
4540                    return false;
4541                }
4542            }
4543        }
4544        // are there any props that span0 has that span1 DOESN'T have?
4545        // both have range/allDay, so no need to special-case.
4546        for (let propName in span0) {
4547            if (!(propName in span1)) {
4548                return false;
4549            }
4550        }
4551        return true;
4552    }
4553    function buildDateSpanApi(span, dateEnv) {
4554        return Object.assign(Object.assign({}, buildRangeApi(span.range, dateEnv, span.allDay)), { allDay: span.allDay });
4555    }
4556    function buildRangeApiWithTimeZone(range, dateEnv, omitTime) {
4557        return Object.assign(Object.assign({}, buildRangeApi(range, dateEnv, omitTime)), { timeZone: dateEnv.timeZone });
4558    }
4559    function buildRangeApi(range, dateEnv, omitTime) {
4560        return {
4561            start: dateEnv.toDate(range.start),
4562            end: dateEnv.toDate(range.end),
4563            startStr: dateEnv.formatIso(range.start, { omitTime }),
4564            endStr: dateEnv.formatIso(range.end, { omitTime }),
4565        };
4566    }
4567    function fabricateEventRange(dateSpan, eventUiBases, context) {
4568        let res = refineEventDef({ editable: false }, context);
4569        let def = parseEventDef(res.refined, res.extra, '', // sourceId
4570        dateSpan.allDay, true, // hasEnd
4571        context);
4572        return {
4573            def,
4574            ui: compileEventUi(def, eventUiBases),
4575            instance: createEventInstance(def.defId, dateSpan.range),
4576            range: dateSpan.range,
4577            isStart: true,
4578            isEnd: true,
4579        };
4580    }
4581
4582    /*
4583    given a function that resolves a result asynchronously.
4584    the function can either call passed-in success and failure callbacks,
4585    or it can return a promise.
4586    if you need to pass additional params to func, bind them first.
4587    */
4588    function unpromisify(func, normalizedSuccessCallback, normalizedFailureCallback) {
4589        // guard against success/failure callbacks being called more than once
4590        // and guard against a promise AND callback being used together.
4591        let isResolved = false;
4592        let wrappedSuccess = function (res) {
4593            if (!isResolved) {
4594                isResolved = true;
4595                normalizedSuccessCallback(res);
4596            }
4597        };
4598        let wrappedFailure = function (error) {
4599            if (!isResolved) {
4600                isResolved = true;
4601                normalizedFailureCallback(error);
4602            }
4603        };
4604        let res = func(wrappedSuccess, wrappedFailure);
4605        if (res && typeof res.then === 'function') {
4606            res.then(wrappedSuccess, wrappedFailure);
4607        }
4608    }
4609
4610    class JsonRequestError extends Error {
4611        constructor(message, response) {
4612            super(message);
4613            this.response = response;
4614        }
4615    }
4616    function requestJson(method, url, params) {
4617        method = method.toUpperCase();
4618        const fetchOptions = {
4619            method,
4620        };
4621        if (method === 'GET') {
4622            url += (url.indexOf('?') === -1 ? '?' : '&') +
4623                new URLSearchParams(params);
4624        }
4625        else {
4626            fetchOptions.body = new URLSearchParams(params);
4627            fetchOptions.headers = {
4628                'Content-Type': 'application/x-www-form-urlencoded',
4629            };
4630        }
4631        return fetch(url, fetchOptions).then((fetchRes) => {
4632            if (fetchRes.ok) {
4633                return fetchRes.json().then((parsedResponse) => {
4634                    return [parsedResponse, fetchRes];
4635                }, () => {
4636                    throw new JsonRequestError('Failure parsing JSON', fetchRes
4636);
4637                });
4638            }
4639            else {
4640                throw new JsonRequestError('Request failed', fetchRes);
4641            }
4642        });
4643    }
4644
4645    let canVGrowWithinCell;
4646    function getCanVGrowWithinCell() {
4647        if (canVGrowWithinCell == null) {
4648            canVGrowWithinCell = computeCanVGrowWithinCell();
4649        }
4650        return canVGrowWithinCell;
4651    }
4652    function computeCanVGrowWithinCell() {
4653        // for SSR, because this function is call immediately at top-level
4654        // TODO: just make this logic execute top-level, immediately, instead of doing lazily
4655        if (typeof document === 'undefined') {
4656            return true;
4657        }
4658        let el = document.createElement('div');
4659        el.style.position = 'absolute';
4660        el.style.top = '0px';
4661        el.style.left = '0px';
4662        el.innerHTML = '<table><tr><td><div></div></td></tr></table>';
4663        el.querySelector('table').style.height = '100px';
4664        el.querySelector('div').style.height = '100%';
4665        document.body.appendChild(el);
4666        let div = el.querySelector('div');
4667        let possible = div.offsetHeight > 0;
4668        document.body.removeChild(el);
4669        return possible;
4670    }
4671
4672    class CalendarRoot extends BaseComponent {
4673        constructor() {
4674            super(...arguments);
4675            this.state = {
4676                forPrint: false,
4677            };
4678            this.handleBeforePrint = () => {
4679                flushSync(() => {
4680                    this.setState({ forPrint: true });
4681                });
4682            };
4683            this.handleAfterPrint = () => {
4684                flushSync(() => {
4685                    this.setState({ forPrint: false });
4686                });
4687            };
4688        }
4689        render() {
4690            let { props } = this;
4691            let { options } = props;
4692            let { forPrint } = this.state;
4693            let isHeightAuto = forPrint || options.height === 'auto' || options.contentHeight === 'auto';
4694            let height = (!isHeightAuto && options.height != null) ? options.height : '';
4695            let classNames = [
4696                'fc',
4697                forPrint ? 'fc-media-print' : 'fc-media-screen',
4698                `fc-direction-${options.direction}`,
4699                props.theme.getClass('root'),
4700            ];
4701            if (!getCanVGrowWithinCell()) {
4702                classNames.push('fc-liquid-hack');
4703            }
4704            return props.children(classNames, height, isHeightAuto, forPrint);
4705        }
4706        componentDidMount() {
4707            let { emitter } = this.props;
4708            emitter.on('_beforeprint', this.handleBeforePrint);
4709            emitter.on('_afterprint', this.handleAfterPrint);
4710        }
4711        componentWillUnmount() {
4712            let { emitter } = this.props;
4713            emitter.off('_beforeprint', this.handleBeforePrint);
4714            emitter.off('_afterprint', this.handleAfterPrint);
4715        }
4716    }
4717
4718    class Interaction {
4719        constructor(settings) {
4720            this.component = settings.component;
4721            this.isHitComboAllowed = settings.isHitComboAllowed || null;
4722        }
4723        destroy() {
4724        }
4725    }
4726    function parseInteractionSettings(component, input) {
4727        return {
4728            component,
4729            el: input.el,
4730            useEventCenter: input.useEventCenter != null ? input.useEventCenter : true,
4731            isHitComboAllowed: input.isHitComboAllowed || null,
4732        };
4733    }
4734    function interactionSettingsToStore(settings) {
4735        return {
4736            [settings.component.uid]: settings,
4737        };
4738    }
4739    // global state
4740    const interactionSettingsStore = {};
4741
4742    class NowTimer extends x$1 {
4743        constructor(props, context) {
4744            super(props, context);
4745            this.handleRefresh = () => {
4746                let timing = this.computeTiming();
4747                if (timing.state.nowDate.valueOf() !== this.state.nowDate.valueOf()) {
4748                    this.setState(timing.state);
4749                }
4750                this.clearTimeout();
4751                this.setTimeout(timing.waitMs);
4752            };
4753            this.handleVisibilityChange = () => {
4754                if (!document.hidden) {
4755                    this.handleRefresh();
4756                }
4757            };
4758            this.state = this.computeTiming().state;
4759        }
4760        render() {
4761            let { props, state } = this;
4762            return props.children(state.nowDate, state.todayRange);
4763        }
4764        componentDidMount() {
4765            this.setTimeout();
4766            this.context.nowManager.addResetListener(this.handleRefresh);
4767            // fired tab becomes visible after being hidden
4768            document.addEventListener('visibilitychange', this.handleVisibilityChange);
4769        }
4770        componentDidUpdate(prevProps) {
4771            if (prevProps.unit !== this.props.unit) {
4772                this.clearTimeout();
4773                this.setTimeout();
4774            }
4775        }
4776        componentWillUnmount() {
4777            this.clearTimeout();
4778            this.context.nowManager.removeResetListener(this.handleRefresh);
4779            document.removeEventListener('visibilitychange', this.handleVisibilityChange);
4780        }
4781        computeTiming() {
4782            let { props, context } = this;
4783            let unroundedNow = context.nowManager.getDateMarker();
4784            let currentUnitStart = context.dateEnv.startOf(unroundedNow, props.unit);
4785            let nextUnitStart = context.dateEnv.add(currentUnitStart, createDuration(1, props.unit));
4786            let waitMs = nextUnitStart.valueOf() - unroundedNow.valueOf();
4787            // there is a max setTimeout ms value (https://stackoverflow.com/a/3468650/96342)
4788            // ensure no longer than a day
4789            waitMs = Math.min(1000 * 60 * 60 * 24, waitMs);
4790            return {
4791                state: { nowDate: currentUnitStart, todayRange: buildDayRange(currentUnitStart) },
4792                waitMs,
4793            };
4794        }
4795        setTimeout(waitMs = this.computeTiming().waitMs) {
4796            // NOTE: timeout could take longer than expected if tab sleeps,
4797            // which is why we listen to 'visibilitychange'
4798            this.timeoutId = setTimeout(() => {
4799                // NOTE: timeout could also return *earlier* than expected, and we need to wait 2 ms more
4800                // This is why use use same waitMs from computeTiming, so we don't skip an interval while
4801                // .setState() is executing
4802                const timing = this.computeTiming();
4803                this.setState(timing.state, () => {
4804                    this.setTimeout(timing.waitMs);
4805                });
4806            }, waitMs);
4807        }
4808        clearTimeout() {
4809            if (this.timeoutId) {
4810                clearTimeout(this.timeoutId);
4811            }
4812        }
4813    }
4814    NowTimer.contextType = ViewContextType;
4815    function buildDayRange(date) {
4816        let start = startOfDay(date);
4817        let end = addDays(start, 1);
4818        return { start, end };
4819    }
4820
4821    class CalendarImpl {
4822        getCurrentData() {
4823            return this.currentDataManager.getCurrentData();
4824        }
4825        dispatch(action) {
4826            this.currentDataManager.dispatch(action);
4827        }
4828        get view() { return this.getCurrentData().viewApi; }
4829        batchRendering(callback) {
4830            callback();
4831        }
4832        updateSize() {
4833            this.trigger('_resize', true);
4834        }
4835        // Options
4836        // -----------------------------------------------------------------------------------------------------------------
4837        setOption(name, val) {
4838            this.dispatch({
4839                type: 'SET_OPTION',
4840                optionName: name,
4841                rawOptionValue: val,
4842            });
4843        }
4844        getOption(name) {
4845            return this.currentDataManager.currentCalendarOptionsInput[name];
4846        }
4847        getAvailableLocaleCodes() {
4848            return Object.keys(this.getCurrentData().availableRawLocales);
4849        }
4850        // Trigger
4851        // -----------------------------------------------------------------------------------------------------------------
4852        on(handlerName, handler) {
4853            let { currentDataManager } = this;
4854            if (currentDataManager.currentCalendarOptionsRefiners[handlerName]) {
4855                currentDataManager.emitter.on(handlerName, handler);
4856            }
4857            else {
4858                console.warn(`Unknown listener name '${handlerName}'`);
4859            }
4860        }
4861        off(handlerName, handler) {
4862            this.currentDataManager.emitter.off(handlerName, handler);
4863        }
4864        // not meant for public use
4865        trigger(handlerName, ...args) {
4866            this.currentDataManager.emitter.trigger(handlerName, ...args);
4867        }
4868        // View
4869        // -----------------------------------------------------------------------------------------------------------------
4870        changeView(viewType, dateOrRange) {
4871            this.batchRendering(() => {
4872                this.unselect();
4873                if (dateOrRange) {
4874                    if (dateOrRange.start && dateOrRange.end) { // a range
4875                        this.dispatch({
4876                            type: 'CHANGE_VIEW_TYPE',
4877                            viewType,
4878                        });
4879                        this.dispatch({
4880                            type: 'SET_OPTION',
4881                            optionName: 'visibleRange',
4882                            rawOptionValue: dateOrRange,
4883                        });
4884                    }
4885                    else {
4886                        let { dateEnv } = this.getCurrentData();
4887                        this.dispatch({
4888                            type: 'CHANGE_VIEW_TYPE',
4889                            viewType,
4890                            dateMarker: dateEnv.createMarker(dateOrRange),
4891                        });
4892                    }
4893                }
4894                else {
4895                    this.dispatch({
4896                        type: 'CHANGE_VIEW_TYPE',
4897                        viewType,
4898                    });
4899                }
4900            });
4901        }
vendor: 21,614 bytes, lines 4902-5433
4902        // Forces navigation to a view for the given date.
4903        // `viewType` can be a specific view name or a generic one like "week" or "day".
4904        // needs to change
4905        zoomTo(dateMarker, viewType) {
4906            let state = this.getCurrentData();
4907            let spec;
4908            viewType = viewType || 'day'; // day is default zoom
4909            spec = state.viewSpecs[viewType] || this.getUnitViewSpec(viewType);
4910            this.unselect();
4911            if (spec) {
4912                this.dispatch({
4913                    type: 'CHANGE_VIEW_TYPE',
4914                    viewType: spec.type,
4915                    dateMarker,
4916                });
4917            }
4918            else {
4919                this.dispatch({
4920                    type: 'CHANGE_DATE',
4921                    dateMarker,
4922                });
4923            }
4924        }
4925        // Given a duration singular unit, like "week" or "day", finds a matching view spec.
4926        // Preference is given to views that have corresponding buttons.
4927        getUnitViewSpec(unit) {
4928            let { viewSpecs, toolbarConfig } = this.getCurrentData();
4929            let viewTypes = [].concat(toolbarConfig.header ? toolbarConfig.header.viewsWithButtons : [], toolbarConfig.footer ? toolbarConfig.footer.viewsWithButtons : []);
4930            let i;
4931            let spec;
4932            for (let viewType in viewSpecs) {
4933                viewTypes.push(viewType);
4934            }
4935            for (i = 0; i < viewTypes.length; i += 1) {
4936                spec = viewSpecs[viewTypes[i]];
4937                if (spec) {
4938                    if (spec.singleUnit === unit) {
4939                        return spec;
4940                    }
4941                }
4942            }
4943            return null;
4944        }
4945        // Current Date
4946        // -----------------------------------------------------------------------------------------------------------------
4947        prev() {
4948            this.unselect();
4949            this.dispatch({ type: 'PREV' });
4950        }
4951        next() {
4952            this.unselect();
4953            this.dispatch({ type: 'NEXT' });
4954        }
4955        prevYear() {
4956            let state = this.getCurrentData();
4957            this.unselect();
4958            this.dispatch({
4959                type: 'CHANGE_DATE',
4960                dateMarker: state.dateEnv.addYears(state.currentDate, -1),
4961            });
4962        }
4963        nextYear() {
4964            let state = this.getCurrentData();
4965            this.unselect();
4966            this.dispatch({
4967                type: 'CHANGE_DATE',
4968                dateMarker: state.dateEnv.addYears(state.currentDate, 1),
4969            });
4970        }
4971        today() {
4972            let state = this.getCurrentData();
4973            this.unselect();
4974            this.dispatch({
4975                type: 'CHANGE_DATE',
4976                dateMarker: state.nowManager.getDateMarker(),
4977            });
4978        }
4979        gotoDate(zonedDateInput) {
4980            let state = this.getCurrentData();
4981            this.unselect();
4982            this.dispatch({
4983                type: 'CHANGE_DATE',
4984                dateMarker: state.dateEnv.createMarker(zonedDateInput),
4985            });
4986        }
4987        incrementDate(deltaInput) {
4988            let state = this.getCurrentData();
4989            let delta = createDuration(deltaInput);
4990            if (delta) { // else, warn about invalid input?
4991                this.unselect();
4992                this.dispatch({
4993                    type: 'CHANGE_DATE',
4994                    dateMarker: state.dateEnv.add(state.currentDate, delta),
4995                });
4996            }
4997        }
4998        getDate() {
4999            let state = this.getCurrentData();
5000            return state.dateEnv.toDate(state.currentDate);
5001        }
5002        // Date Formatting Utils
5003        // -----------------------------------------------------------------------------------------------------------------
5004        formatDate(d, formatter) {
5005            let { dateEnv } = this.getCurrentData();
5006            return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter));
5007        }
5008        // `settings` is for formatter AND isEndExclusive
5009        formatRange(d0, d1, settings) {
5010            let { dateEnv } = this.getCurrentData();
5011            return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings), settings);
5012        }
5013        formatIso(d, omitTime) {
5014            let { dateEnv } = this.getCurrentData();
5015            return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime });
5016        }
5017        // Date Selection / Event Selection / DayClick
5018        // -----------------------------------------------------------------------------------------------------------------
5019        select(dateOrObj, endDate) {
5020            let selectionInput;
5021            if (endDate == null) {
5022                if (dateOrObj.start != null) {
5023                    selectionInput = dateOrObj;
5024                }
5025                else {
5026                    selectionInput = {
5027                        start: dateOrObj,
5028                        end: null,
5029                    };
5030                }
5031            }
5032            else {
5033                selectionInput = {
5034                    start: dateOrObj,
5035                    end: endDate,
5036                };
5037            }
5038            let state = this.getCurrentData();
5039            let selection = parseDateSpan(selectionInput, state.dateEnv, createDuration({ days: 1 }));
5040            if (selection) { // throw parse error otherwise?
5041                this.dispatch({ type: 'SELECT_DATES', selection });
5042                triggerDateSelect(selection, null, state);
5043            }
5044        }
5045        unselect(pev) {
5046            let state = this.getCurrentData();
5047            if (state.dateSelection) {
5048                this.dispatch({ type: 'UNSELECT_DATES' });
5049                triggerDateUnselect(pev, state);
5050            }
5051        }
5052        // Public Events API
5053        // -----------------------------------------------------------------------------------------------------------------
5054        addEvent(eventInput, sourceInput) {
5055            if (eventInput instanceof EventImpl) {
5056                let def = eventInput._def;
5057                let instance = eventInput._instance;
5058                let currentData = this.getCurrentData();
5059                // not already present? don't want to add an old snapshot
5060                if (!currentData.eventStore.defs[def.defId]) {
5061                    this.dispatch({
5062                        type: 'ADD_EVENTS',
5063                        eventStore: eventTupleToStore({ def, instance }), // TODO: better util for two args?
5064                    });
5065                    this.triggerEventAdd(eventInput);
5066                }
5067                return eventInput;
5068            }
5069            let state = this.getCurrentData();
5070            let eventSource;
5071            if (sourceInput instanceof EventSourceImpl) {
5072                eventSource = sourceInput.internalEventSource;
5073            }
5074            else if (typeof sourceInput === 'boolean') {
5075                if (sourceInput) { // true. part of the first event source
5076                    [eventSource] = hashValuesToArray(state.eventSources);
5077                }
5078            }
5079            else if (sourceInput != null) { // an ID. accepts a number too
5080                let sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function
5081                if (!sourceApi) {
5082                    console.warn(`Could not find an event source with ID "${sourceInput}"`); // TODO: test
5083                    return null;
5084                }
5085                eventSource = sourceApi.internalEventSource;
5086            }
5087            let tuple = parseEvent(eventInput, eventSource, state, false);
5088            if (tuple) {
5089                let newEventApi = new EventImpl(state, tuple.def, tuple.def.recurringDef ? null : tuple.instance);
5090                this.dispatch({
5091                    type: 'ADD_EVENTS',
5092                    eventStore: eventTupleToStore(tuple),
5093                });
5094                this.triggerEventAdd(newEventApi);
5095                return newEventApi;
5096            }
5097            return null;
5098        }
5099        triggerEventAdd(eventApi) {
5100            let { emitter } = this.getCurrentData();
5101            emitter.trigger('eventAdd', {
5102                event: eventApi,
5103                relatedEvents: [],
5104                revert: () => {
5105                    this.dispatch({
5106                        type: 'REMOVE_EVENTS',
5107                        eventStore: eventApiToStore(eventApi),
5108                    });
5109                },
5110            });
5111        }
5112        // TODO: optimize
5113        getEventById(id) {
5114            let state = this.getCurrentData();
5115            let { defs, instances } = state.eventStore;
5116            id = String(id);
5117            for (let defId in defs) {
5118                let def = defs[defId];
5119                if (def.publicId === id) {
5120                    if (def.recurringDef) {
5121                        return new EventImpl(state, def, null);
5122                    }
5123                    for (let instanceId in instances) {
5124                        let instance = instances[instanceId];
5125                        if (instance.defId === def.defId) {
5126                            return new EventImpl(state, def, instance);
5127                        }
5128                    }
5129                }
5130            }
5131            return null;
5132        }
5133        getEvents() {
5134            let currentData = this.getCurrentData();
5135            return buildEventApis(currentData.eventStore, currentData);
5136        }
5137        removeAllEvents() {
5138            this.dispatch({ type: 'REMOVE_ALL_EVENTS' });
5139        }
5140        // Public Event Sources API
5141        // -----------------------------------------------------------------------------------------------------------------
5142        getEventSources() {
5143            let state = this.getCurrentData();
5144            let sourceHash = state.eventSources;
5145            let sourceApis = [];
5146            for (let internalId in sourceHash) {
5147                sourceApis.push(new EventSourceImpl(state, sourceHash[internalId]));
5148            }
5149            return sourceApis;
5150        }
5151        getEventSourceById(id) {
5152            let state = this.getCurrentData();
5153            let sourceHash = state.eventSources;
5154            id = String(id);
5155            for (let sourceId in sourceHash) {
5156                if (sourceHash[sourceId].publicId === id) {
5157                    return new EventSourceImpl(state, sourceHash[sourceId]);
5158                }
5159            }
5160            return null;
5161        }
5162        addEventSource(sourceInput) {
5163            let state = this.getCurrentData();
5164            if (sourceInput instanceof EventSourceImpl) {
5165                // not already present? don't want to add an old snapshot
5166                if (!state.eventSources[sourceInput.internalEventSource.sourceId]) {
5167                    this.dispatch({
5168                        type: 'ADD_EVENT_SOURCES',
5169                        sources: [sourceInput.internalEventSource],
5170                    });
5171                }
5172                return sourceInput;
5173            }
5174            let eventSource = parseEventSource(sourceInput, state);
5175            if (eventSource) { // TODO: error otherwise?
5176                this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] });
5177                return new EventSourceImpl(state, eventSource);
5178            }
5179            return null;
5180        }
5181        removeAllEventSources() {
5182            this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' });
5183        }
5184        refetchEvents() {
5185            this.dispatch({ type: 'FETCH_EVENT_SOURCES', isRefetch: true });
5186        }
5187        // Scroll
5188        // -----------------------------------------------------------------------------------------------------------------
5189        scrollToTime(timeInput) {
5190            let time = createDuration(timeInput);
5191            if (time) {
5192                this.trigger('_scrollRequest', { time });
5193            }
5194        }
5195    }
5196
5197    function pointInsideRect(point, rect) {
5198        return point.left >= rect.left &&
5199            point.left < rect.right &&
5200            point.top >= rect.top &&
5201            point.top < rect.bottom;
5202    }
5203    // Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false
5204    function intersectRects(rect1, rect2) {
5205        let res = {
5206            left: Math.max(rect1.left, rect2.left),
5207            right: Math.min(rect1.right, rect2.right),
5208            top: Math.max(rect1.top, rect2.top),
5209            bottom: Math.min(rect1.bottom, rect2.bottom),
5210        };
5211        if (res.left < res.right && res.top < res.bottom) {
5212            return res;
5213        }
5214        return false;
5215    }
5216    function translateRect(rect, deltaX, deltaY) {
5217        return {
5218            left: rect.left + deltaX,
5219            right: rect.right + deltaX,
5220            top: rect.top + deltaY,
5221            bottom: rect.bottom + deltaY,
5222        };
5223    }
5224    // Returns a new point that will have been moved to reside within the given rectangle
5225    function constrainPoint(point, rect) {
5226        return {
5227            left: Math.min(Math.max(point.left, rect.left), rect.right),
5228            top: Math.min(Math.max(point.top, rect.top), rect.bottom),
5229        };
5230    }
5231    // Returns a point that is the center of the given rectangle
5232    function getRectCenter(rect) {
5233        return {
5234            left: (rect.left + rect.right) / 2,
5235            top: (rect.top + rect.bottom) / 2,
5236        };
5237    }
5238    // Subtracts point2's coordinates from point1's coordinates, returning a delta
5239    function diffPoints(point1, point2) {
5240        return {
5241            left: point1.left - point2.left,
5242            top: point1.top - point2.top,
5243        };
5244    }
5245
5246    const EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere
5247    class Splitter {
5248        constructor() {
5249            this.getKeysForEventDefs = memoize(this._getKeysForEventDefs);
5250            this.splitDateSelection = memoize(this._splitDateSpan);
5251            this.splitEventStore = memoize(this._splitEventStore);
5252            this.splitIndividualUi = memoize(this._splitIndividualUi);
5253            this.splitEventDrag = memoize(this._splitInteraction);
5254            this.splitEventResize = memoize(this._splitInteraction);
5255            this.eventUiBuilders = {}; // TODO: typescript protection
5256        }
5257        splitProps(props) {
5258            let keyInfos = this.getKeyInfo(props);
5259            let defKeys = this.getKeysForEventDefs(props.eventStore);
5260            let dateSelections = this.splitDateSelection(props.dateSelection);
5261            let individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases*
5262            let eventStores = this.splitEventStore(props.eventStore, defKeys);
5263            let eventDrags = this.splitEventDrag(props.eventDrag);
5264            let eventResizes = this.splitEventResize(props.eventResize);
5265            let splitProps = {};
5266            this.eventUiBuilders = mapHash(keyInfos, (info, key) => this.eventUiBuilders[key] || memoize(buildEventUiForKey));
5267            for (let key in keyInfos) {
5268                let keyInfo = keyInfos[key];
5269                let eventStore = eventStores[key] || EMPTY_EVENT_STORE;
5270                let buildEventUi = this.eventUiBuilders[key];
5271                splitProps[key] = {
5272                    businessHours: keyInfo.businessHours || props.businessHours,
5273                    dateSelection: dateSelections[key] || null,
5274                    eventStore,
5275                    eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]),
5276                    eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '',
5277                    eventDrag: eventDrags[key] || null,
5278                    eventResize: eventResizes[key] || null,
5279                };
5280            }
5281            return splitProps;
5282        }
5283        _splitDateSpan(dateSpan) {
5284            let dateSpans = {};
5285            if (dateSpan) {
5286                let keys = this.getKeysForDateSpan(dateSpan);
5287                for (let key of keys) {
5288                    dateSpans[key] = dateSpan;
5289                }
5290            }
5291            return dateSpans;
5292        }
5293        _getKeysForEventDefs(eventStore) {
5294            return mapHash(eventStore.defs, (eventDef) => this.getKeysForEventDef(eventDef));
5295        }
5296        _splitEventStore(eventStore, defKeys) {
5297            let { defs, instances } = eventStore;
5298            let splitStores = {};
5299            for (let defId in defs) {
5300                for (let key of defKeys[defId]) {
5301                    if (!splitStores[key]) {
5302                        splitStores[key] = createEmptyEventStore();
5303                    }
5304                    splitStores[key].defs[defId] = defs[defId];
5305                }
5306            }
5307            for (let instanceId in instances) {
5308                let instance = instances[instanceId];
5309                for (let key of defKeys[instance.defId]) {
5310                    if (splitStores[key]) { // must have already been created
5311                        splitStores[key].instances[instanceId] = instance;
5312                    }
5313                }
5314            }
5315            return splitStores;
5316        }
5317        _splitIndividualUi(eventUiBases, defKeys) {
5318            let splitHashes = {};
5319            for (let defId in eventUiBases) {
5320                if (defId) { // not the '' key
5321                    for (let key of defKeys[defId]) {
5322                        if (!splitHashes[key]) {
5323                            splitHashes[key] = {};
5324                        }
5325                        splitHashes[key][defId] = eventUiBases[defId];
5326                    }
5327                }
5328            }
5329            return splitHashes;
5330        }
5331        _splitInteraction(interaction) {
5332            let splitStates = {};
5333            if (interaction) {
5334                let affectedStores = this._splitEventStore(interaction.affectedEvents, this._getKeysForEventDefs(interaction.affectedEvents));
5335                // can't rely on defKeys because event data is mutated
5336                let mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents);
5337                let mutatedStores = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId);
5338                let populate = (key) => {
5339                    if (!splitStates[key]) {
5340                        splitStates[key] = {
5341                            affectedEvents: affectedStores[key] || EMPTY_EVENT_STORE,
5342                            mutatedEvents: mutatedStores[key] || EMPTY_EVENT_STORE,
5343                            isEvent: interaction.isEvent,
5344                        };
5345                    }
5346                };
5347                for (let key in affectedStores) {
5348                    populate(key);
5349                }
5350                for (let key in mutatedStores) {
5351                    populate(key);
5352                }
5353            }
5354            return splitStates;
5355        }
5356    }
5357    function buildEventUiForKey(allUi, eventUiForKey, individualUi) {
5358        let baseParts = [];
5359        if (allUi) {
5360            baseParts.push(allUi);
5361        }
5362        if (eventUiForKey) {
5363            baseParts.push(eventUiForKey);
5364        }
5365        let stuff = {
5366            '': combineEventUis(baseParts),
5367        };
5368        if (individualUi) {
5369            Object.assign(stuff, individualUi);
5370        }
5371        return stuff;
5372    }
5373
5374    function getDateMeta(date, todayRange, nowDate, dateProfile) {
5375        return {
5376            dow: date.getUTCDay(),
5377            isDisabled: Boolean(dateProfile && (!dateProfile.activeRange || !rangeContainsMarker(dateProfile.activeRange, date))),
5378            isOther: Boolean(dateProfile && !rangeContainsMarker(dateProfile.currentRange, date)),
5379            isToday: Boolean(todayRange && rangeContainsMarker(todayRange, date)),
5380            isPast: Boolean(nowDate ? (date < nowDate) : todayRange ? (date < todayRange.start) : false),
5381            isFuture: Boolean(nowDate ? (date > nowDate) : todayRange ? (date >= todayRange.end) : false),
5382        };
5383    }
5384    function getDayClassNames(meta, theme) {
5385        let classNames = [
5386            'fc-day',
5387            `fc-day-${DAY_IDS[meta.dow]}`,
5388        ];
5389        if (meta.isDisabled) {
5390            classNames.push('fc-day-disabled');
5391        }
5392        else {
5393            if (meta.isToday) {
5394                classNames.push('fc-day-today');
5395                classNames.push(theme.getClass('today'));
5396            }
5397            if (meta.isPast) {
5398                classNames.push('fc-day-past');
5399            }
5400            if (meta.isFuture) {
5401                classNames.push('fc-day-future');
5402            }
5403            if (meta.isOther) {
5404                classNames.push('fc-day-other');
5405            }
5406        }
5407        return classNames;
5408    }
5409    function getSlotClassNames(meta, theme) {
5410        let classNames = [
5411            'fc-slot',
5412            `fc-slot-${DAY_IDS[meta.dow]}`,
5413        ];
5414        if (meta.isDisabled) {
5415            classNames.push('fc-slot-disabled');
5416        }
5417        else {
5418            if (meta.isToday) {
5419                classNames.push('fc-slot-today');
5420                classNames.push(theme.getClass('today'));
5421            }
5422            if (meta.isPast) {
5423                classNames.push('fc-slot-past');
5424            }
5425            if (meta.isFuture) {
5426                classNames.push('fc-slot-future');
5427            }
5428        }
5429        return classNames;
5430    }
5431
5432    const DAY_FORMAT = createFormatter({ year: 'numeric', month: 'long', day: 'numeric' });
5433    const WEEK_FORMAT = createFormatter({ week: 'long' });
vendor: 7,255 bytes, lines 5434-5614
5434    function buildNavLinkAttrs(context, dateMarker, viewType = 'day', isTabbable = true) {
5435        const { dateEnv, options, calendarApi } = context;
5436        let dateStr = dateEnv.format(dateMarker, viewType === 'week' ? WEEK_FORMAT : DAY_FORMAT);
5437        if (options.navLinks) {
5438            let zonedDate = dateEnv.toDate(dateMarker);
5439            const handleInteraction = (ev) => {
5440                let customAction = viewType === 'day' ? options.navLinkDayClick :
5441                    viewType === 'week' ? options.navLinkWeekClick : null;
5442                if (typeof customAction === 'function') {
5443                    customAction.call(calendarApi, dateEnv.toDate(dateMarker), ev);
5444                }
5445                else {
5446                    if (typeof customAction === 'string') {
5447                        viewType = customAction;
5448                    }
5449                    calendarApi.zoomTo(dateMarker, viewType);
5450                }
5451            };
5452            return Object.assign({ title: formatWithOrdinals(options.navLinkHint, [dateStr, zonedDate], dateStr), 'data-navlink': '' }, (isTabbable
5453                ? createAriaClickAttrs(handleInteraction)
5454                : { onClick: handleInteraction }));
5455        }
5456        return { 'aria-label': dateStr };
5457    }
5458
5459    let _isRtlScrollbarOnLeft = null;
5460    function getIsRtlScrollbarOnLeft() {
5461        if (_isRtlScrollbarOnLeft === null) {
5462            _isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft();
5463        }
5464        return _isRtlScrollbarOnLeft;
5465    }
5466    function computeIsRtlScrollbarOnLeft() {
5467        let outerEl = document.createElement('div');
5468        applyStyle(outerEl, {
5469            position: 'absolute',
5470            top: -1000,
5471            left: 0,
5472            border: 0,
5473            padding: 0,
5474            overflow: 'scroll',
5475            direction: 'rtl',
5476        });
5477        outerEl.innerHTML = '<div></div>';
5478        document.body.appendChild(outerEl);
5479        let innerEl = outerEl.firstChild;
5480        let res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left;
5481        removeElement(outerEl);
5482        return res;
5483    }
5484
5485    let _scrollbarWidths;
5486    function getScrollbarWidths() {
5487        if (!_scrollbarWidths) {
5488            _scrollbarWidths = computeScrollbarWidths();
5489        }
5490        return _scrollbarWidths;
5491    }
5492    function computeScrollbarWidths() {
5493        let el = document.createElement('div');
5494        el.style.overflow = 'scroll';
5495        el.style.position = 'absolute';
5496        el.style.top = '-9999px';
5497        el.style.left = '-9999px';
5498        document.body.appendChild(el);
5499        let res = computeScrollbarWidthsForEl(el);
5500        document.body.removeChild(el);
5501        return res;
5502    }
5503    // WARNING: will include border
5504    function computeScrollbarWidthsForEl(el) {
5505        return {
5506            x: el.offsetHeight - el.clientHeight,
5507            y: el.offsetWidth - el.clientWidth,
5508        };
5509    }
5510
5511    function computeEdges(el, getPadding = false) {
5512        let computedStyle = window.getComputedStyle(el);
5513        let borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0;
5514        let borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0;
5515        let borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0;
5516        let borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
5517        let badScrollbarWidths = computeScrollbarWidthsForEl(el); // includes border!
5518        let scrollbarLeftRight = badScrollbarWidths.y - borderLeft - borderRight;
5519        let scrollbarBottom = badScrollbarWidths.x - borderTop - borderBottom;
5520        let res = {
5521            borderLeft,
5522            borderRight,
5523            borderTop,
5524            borderBottom,
5525            scrollbarBottom,
5526            scrollbarLeft: 0,
5527            scrollbarRight: 0,
5528        };
5529        if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side?
5530            res.scrollbarLeft = scrollbarLeftRight;
5531        }
5532        else {
5533            res.scrollbarRight = scrollbarLeftRight;
5534        }
5535        if (getPadding) {
5536            res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0;
5537            res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0;
5538            res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0;
5539            res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0;
5540        }
5541        return res;
5542    }
5543    function computeInnerRect(el, goWithinPadding = false, doFromWindowViewport) {
5544        let outerRect = doFromWindowViewport ? el.getBoundingClientRect() : computeRect(el);
5545        let edges = computeEdges(el, goWithinPadding);
5546        let res = {
5547            left: outerRect.left + edges.borderLeft + edges.scrollbarLeft,
5548            right: outerRect.right - edges.borderRight - edges.scrollbarRight,
5549            top: outerRect.top + edges.borderTop,
5550            bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom,
5551        };
5552        if (goWithinPadding) {
5553            res.left += edges.paddingLeft;
5554            res.right -= edges.paddingRight;
5555            res.top += edges.paddingTop;
5556            res.bottom -= edges.paddingBottom;
5557        }
5558        return res;
5559    }
5560    function computeRect(el) {
5561        let rect = el.getBoundingClientRect();
5562        return {
5563            left: rect.left + window.scrollX,
5564            top: rect.top + window.scrollY,
5565            right: rect.right + window.scrollX,
5566            bottom: rect.bottom + window.scrollY,
5567        };
5568    }
5569    function computeClippedClientRect(el) {
5570        let clippingParents = getClippingParents(el);
5571        let rect = el.getBoundingClientRect();
5572        for (let clippingParent of clippingParents) {
5573            let intersection = intersectRects(rect, clippingParent.getBoundingClientRect());
5574            if (intersection) {
5575                rect = intersection;
5576            }
5577            else {
5578                return null;
5579            }
5580        }
5581        return rect;
5582    }
5583    // does not return window
5584    function getClippingParents(el) {
5585        let parents = [];
5586        while (el instanceof HTMLElement) { // will stop when gets to document or null
5587            let computedStyle = window.getComputedStyle(el);
5588            if (computedStyle.position === 'fixed') {
5589                break;
5590            }
5591            if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) {
5592                parents.push(el);
5593            }
5594            el = el.parentNode;
5595        }
5596        return parents;
5597    }
5598
5599    /*
5600    Records offset information for a set of elements, relative to an origin element.
5601    Can record the left/right OR the top/bottom OR both.
5602    Provides methods for querying the cache by position.
5603    */
5604    class PositionCache {
5605        constructor(originEl, els, isHorizontal, isVertical) {
5606            this.els = els;
5607            let originClientRect = this.originClientRect = originEl.getBoundingClientRect(); // relative to viewport top-left
5608            if (isHorizontal) {
5609                this.buildElHorizontals(originClientRect.left);
5610            }
5611            if (isVertical) {
5612                this.buildElVerticals(originClientRect.top);
5613            }
5614        }
vendor: 4,074 bytes, lines 5615-5724
5615        // Populates the left/right internal coordinate arrays
5616        buildElHorizontals(originClientLeft) {
5617            let lefts = [];
5618            let rights = [];
5619            for (let el of this.els) {
5620                let rect = el.getBoundingClientRect();
5621                lefts.push(rect.left - originClientLeft);
5622                rights.push(rect.right - originClientLeft);
5623            }
5624            this.lefts = lefts;
5625            this.rights = rights;
5626        }
5627        // Populates the top/bottom internal coordinate arrays
5628        buildElVerticals(originClientTop) {
5629            let tops = [];
5630            let bottoms = [];
5631            for (let el of this.els) {
5632                let rect = el.getBoundingClientRect();
5633                tops.push(rect.top - originClientTop);
5634                bottoms.push(rect.bottom - originClientTop);
5635            }
5636            this.tops = tops;
5637            this.bottoms = bottoms;
5638        }
5639        // Given a left offset (from document left), returns the index of the el that it horizontally intersects.
5640        // If no intersection is made, returns undefined.
5641        leftToIndex(leftPosition) {
5642            let { lefts, rights } = this;
5643            let len = lefts.length;
5644            let i;
5645            for (i = 0; i < len; i += 1) {
5646                if (leftPosition >= lefts[i] && leftPosition < rights[i]) {
5647                    return i;
5648                }
5649            }
5650            return undefined; // TODO: better
5651        }
5652        // Given a top offset (from document top), returns the index of the el that it vertically intersects.
5653        // If no intersection is made, returns undefined.
5654        topToIndex(topPosition) {
5655            let { tops, bottoms } = this;
5656            let len = tops.length;
5657            let i;
5658            for (i = 0; i < len; i += 1) {
5659                if (topPosition >= tops[i] && topPosition < bottoms[i]) {
5660                    return i;
5661                }
5662            }
5663            return undefined; // TODO: better
5664        }
5665        // Gets the width of the element at the given index
5666        getWidth(leftIndex) {
5667            return this.rights[leftIndex] - this.lefts[leftIndex];
5668        }
5669        // Gets the height of the element at the given index
5670        getHeight(topIndex) {
5671            return this.bottoms[topIndex] - this.tops[topIndex];
5672        }
5673        similarTo(otherCache) {
5674            return similarNumArrays(this.tops || [], otherCache.tops || []) &&
5675                similarNumArrays(this.bottoms || [], otherCache.bottoms || []) &&
5676                similarNumArrays(this.lefts || [], otherCache.lefts || []) &&
5677                similarNumArrays(this.rights || [], otherCache.rights || []);
5678        }
5679    }
5680    function similarNumArrays(a, b) {
5681        const len = a.length;
5682        if (len !== b.length) {
5683            return false;
5684        }
5685        for (let i = 0; i < len; i++) {
5686            if (Math.round(a[i]) !== Math.round(b[i])) {
5687                return false;
5688            }
5689        }
5690        return true;
5691    }
5692
5693    /* eslint max-classes-per-file: "off" */
5694    /*
5695    An object for getting/setting scroll-related information for an element.
5696    Internally, this is done very differently for window versus DOM element,
5697    so this object serves as a common interface.
5698    */
5699    class ScrollController {
5700        getMaxScrollTop() {
5701            return this.getScrollHeight() - this.getClientHeight();
5702        }
5703        getMaxScrollLeft() {
5704            return this.getScrollWidth() - this.getClientWidth();
5705        }
5706        canScrollVertically() {
5707            return this.getMaxScrollTop() > 0;
5708        }
5709        canScrollHorizontally() {
5710            return this.getMaxScrollLeft() > 0;
5711        }
5712        canScrollUp() {
5713            return this.getScrollTop() > 0;
5714        }
5715        canScrollDown() {
5716            return this.getScrollTop() < this.getMaxScrollTop();
5717        }
5718        canScrollLeft() {
5719            return this.getScrollLeft() > 0;
5720        }
5721        canScrollRight() {
5722            return this.getScrollLeft() < this.getMaxScrollLeft();
5723        }
5724    }
vendor: 8,421 bytes, lines 5725-5934
5725    class ElementScrollController extends ScrollController {
5726        constructor(el) {
5727            super();
5728            this.el = el;
5729        }
5730        getScrollTop() {
5731            return this.el.scrollTop;
5732        }
5733        getScrollLeft() {
5734            return this.el.scrollLeft;
5735        }
5736        setScrollTop(top) {
5737            this.el.scrollTop = top;
5738        }
5739        setScrollLeft(left) {
5740            this.el.scrollLeft = left;
5741        }
5742        getScrollWidth() {
5743            return this.el.scrollWidth;
5744        }
5745        getScrollHeight() {
5746            return this.el.scrollHeight;
5747        }
5748        getClientHeight() {
5749            return this.el.clientHeight;
5750        }
5751        getClientWidth() {
5752            return this.el.clientWidth;
5753        }
5754    }
5755    class WindowScrollController extends ScrollController {
5756        getScrollTop() {
5757            return window.scrollY;
5758        }
5759        getScrollLeft() {
5760            return window.scrollX;
5761        }
5762        setScrollTop(n) {
5763            window.scroll(window.scrollX, n);
5764        }
5765        setScrollLeft(n) {
5766            window.scroll(n, window.scrollY);
5767        }
5768        getScrollWidth() {
5769            return document.documentElement.scrollWidth;
5770        }
5771        getScrollHeight() {
5772            return document.documentElement.scrollHeight;
5773        }
5774        getClientHeight() {
5775            return document.documentElement.clientHeight;
5776        }
5777        getClientWidth() {
5778            return document.documentElement.clientWidth;
5779        }
5780    }
5781
5782    /*
5783    an INTERACTABLE date component
5784
5785    PURPOSES:
5786    - hook up to fg, fill, and mirror renderers
5787    - interface for dragging and hits
5788    */
5789    class DateComponent extends BaseComponent {
5790        constructor() {
5791            super(...arguments);
5792            this.uid = guid();
5793        }
5794        // Hit System
5795        // -----------------------------------------------------------------------------------------------------------------
5796        prepareHits() {
5797        }
5798        queryHit(positionLeft, positionTop, elWidth, elHeight) {
5799            return null; // this should be abstract
5800        }
5801        // Pointer Interaction Utils
5802        // -----------------------------------------------------------------------------------------------------------------
5803        isValidSegDownEl(el) {
5804            return !this.props.eventDrag && // HACK
5805                !this.props.eventResize && // HACK
5806                !elementClosest(el, '.fc-event-mirror');
5807        }
5808        isValidDateDownEl(el) {
5809            return !elementClosest(el, '.fc-event:not(.fc-bg-event)') &&
5810                !elementClosest(el, '.fc-more-link') && // a "more.." link
5811                !elementClosest(el, 'a[data-navlink]') && // a clickable nav link
5812                !elementClosest(el, '.fc-popover'); // hack
5813        }
5814    }
5815
5816    class NamedTimeZoneImpl {
5817        constructor(timeZoneName) {
5818            this.timeZoneName = timeZoneName;
5819        }
5820    }
5821
5822    class SegHierarchy {
5823        constructor(getEntryThickness = (entry) => {
5824            // if no thickness known, assume 1 (if 0, so small it always fits)
5825            return entry.thickness || 1;
5826        }) {
5827            this.getEntryThickness = getEntryThickness;
5828            // settings
5829            this.strictOrder = false;
5830            this.allowReslicing = false;
5831            this.maxCoord = -1; // -1 means no max
5832            this.maxStackCnt = -1; // -1 means no max
5833            this.levelCoords = []; // ordered
5834            this.entriesByLevel = []; // parallel with levelCoords
5835            this.stackCnts = {}; // TODO: use better technique!?
5836        }
5837        addSegs(inputs) {
5838            let hiddenEntries = [];
5839            for (let input of inputs) {
5840                this.insertEntry(input, hiddenEntries);
5841            }
5842            return hiddenEntries;
5843        }
5844        insertEntry(entry, hiddenEntries) {
5845            let insertion = this.findInsertion(entry);
5846            if (this.isInsertionValid(insertion, entry)) {
5847                this.insertEntryAt(entry, insertion);
5848            }
5849            else {
5850                this.handleInvalidInsertion(insertion, entry, hiddenEntries);
5851            }
5852        }
5853        isInsertionValid(insertion, entry) {
5854            return (this.maxCoord === -1 || insertion.levelCoord + this.getEntryThickness(entry) <= this.maxCoord) &&
5855                (this.maxStackCnt === -1 || insertion.stackCnt < this.maxStackCnt);
5856        }
5857        handleInvalidInsertion(insertion, entry, hiddenEntries) {
5858            if (this.allowReslicing && insertion.touchingEntry) {
5859                const hiddenEntry = Object.assign(Object.assign({}, entry), { span: intersectSpans(entry.span, insertion.touchingEntry.span) });
5860                hiddenEntries.push(hiddenEntry);
5861                this.splitEntry(entry, insertion.touchingEntry, hiddenEntries);
5862            }
5863            else {
5864                hiddenEntries.push(entry);
5865            }
5866        }
5867        /*
5868        Does NOT add what hit the `barrier` into hiddenEntries. Should already be done.
5869        */
5870        splitEntry(entry, barrier, hiddenEntries) {
5871            let entrySpan = entry.span;
5872            let barrierSpan = barrier.span;
5873            if (entrySpan.start < barrierSpan.start) {
5874                this.insertEntry({
5875                    index: entry.index,
5876                    thickness: entry.thickness,
5877                    span: { start: entrySpan.start, end: barrierSpan.start },
5878                }, hiddenEntries);
5879            }
5880            if (entrySpan.end > barrierSpan.end) {
5881                this.insertEntry({
5882                    index: entry.index,
5883                    thickness: entry.thickness,
5884                    span: { start: barrierSpan.end, end: entrySpan.end },
5885                }, hiddenEntries);
5886            }
5887        }
5888        insertEntryAt(entry, insertion) {
5889            let { entriesByLevel, levelCoords } = this;
5890            if (insertion.lateral === -1) {
5891                // create a new level
5892                insertAt(levelCoords, insertion.level, insertion.levelCoord);
5893                insertAt(entriesByLevel, insertion.level, [entry]);
5894            }
5895            else {
5896                // insert into existing level
5897                insertAt(entriesByLevel[insertion.level], insertion.lateral, entry);
5898            }
5899            this.stackCnts[buildEntryKey(entry)] = insertion.stackCnt;
5900        }
5901        /*
5902        does not care about limits
5903        */
5904        findInsertion(newEntry) {
5905            let { levelCoords, entriesByLevel, strictOrder, stackCnts } = this;
5906            let levelCnt = levelCoords.length;
5907            let candidateCoord = 0;
5908            let touchingLevel = -1;
5909            let touchingLateral = -1;
5910            let touchingEntry = null;
5911            let stackCnt = 0;
5912            for (let trackingLevel = 0; trackingLevel < levelCnt; trackingLevel += 1) {
5913                const trackingCoord = levelCoords[trackingLevel];
5914                // if the current level is past the placed entry, we have found a good empty space and can stop.
5915                // if strictOrder, keep finding more lateral intersections.
5916                if (!strictOrder && trackingCoord >= candidateCoord + this.getEntryThickness(newEntry)) {
5917                    break;
5918                }
5919                let trackingEntries = entriesByLevel[trackingLevel];
5920                let trackingEntry;
5921                let searchRes = binarySearch(trackingEntries, newEntry.span.start, getEntrySpanEnd); // find first entry after newEntry's end
5922                let lateralIndex = searchRes[0] + searchRes[1]; // if exact match (which doesn't collide), go to next one
5923                while ( // loop through entries that horizontally intersect
5924                (trackingEntry = trackingEntries[lateralIndex]) && // but not past the whole entry list
5925                    trackingEntry.span.start < newEntry.span.end // and not entirely past newEntry
5926                ) {
5927                    let trackingEntryBottom = trackingCoord + this.getEntryThickness(trackingEntry);
5928                    // intersects into the top of the candidate?
5929                    if (trackingEntryBottom > candidateCoord) {
5930                        candidateCoord = trackingEntryBottom;
5931                        touchingEntry = trackingEntry;
5932                        touchingLevel = trackingLevel;
5933                        touchingLateral = lateralIndex;
5934                    }
vendor: 4,242 bytes, lines 5935-6041
5935                    // butts up against top of candidate? (will happen if just intersected as well)
5936                    if (trackingEntryBottom === candidateCoord) {
5937                        // accumulate the highest possible stackCnt of the trackingEntries that butt up
5938                        stackCnt = Math.max(stackCnt, stackCnts[buildEntryKey(trackingEntry)] + 1);
5939                    }
5940                    lateralIndex += 1;
5941                }
5942            }
5943            // the destination level will be after touchingEntry's level. find it
5944            let destLevel = 0;
5945            if (touchingEntry) {
5946                destLevel = touchingLevel + 1;
5947                while (destLevel < levelCnt && levelCoords[destLevel] < candidateCoord) {
5948                    destLevel += 1;
5949                }
5950            }
5951            // if adding to an existing level, find where to insert
5952            let destLateral = -1;
5953            if (destLevel < levelCnt && levelCoords[destLevel] === candidateCoord) {
5954                destLateral = binarySearch(entriesByLevel[destLevel], newEntry.span.end, getEntrySpanEnd)[0];
5955            }
5956            return {
5957                touchingLevel,
5958                touchingLateral,
5959                touchingEntry,
5960                stackCnt,
5961                levelCoord: candidateCoord,
5962                level: destLevel,
5963                lateral: destLateral,
5964            };
5965        }
5966        // sorted by levelCoord (lowest to highest)
5967        toRects() {
5968            let { entriesByLevel, levelCoords } = this;
5969            let levelCnt = entriesByLevel.length;
5970            let rects = [];
5971            for (let level = 0; level < levelCnt; level += 1) {
5972                let entries = entriesByLevel[level];
5973                let levelCoord = levelCoords[level];
5974                for (let entry of entries) {
5975                    rects.push(Object.assign(Object.assign({}, entry), { thickness: this.getEntryThickness(entry), levelCoord }));
5976                }
5977            }
5978            return rects;
5979        }
5980    }
5981    function getEntrySpanEnd(entry) {
5982        return entry.span.end;
5983    }
5984    function buildEntryKey(entry) {
5985        return entry.index + ':' + entry.span.start;
5986    }
5987    // returns groups with entries sorted by input order
5988    function groupIntersectingEntries(entries) {
5989        let merges = [];
5990        for (let entry of entries) {
5991            let filteredMerges = [];
5992            let hungryMerge = {
5993                span: entry.span,
5994                entries: [entry],
5995            };
5996            for (let merge of merges) {
5997                if (intersectSpans(merge.span, hungryMerge.span)) {
5998                    hungryMerge = {
5999                        entries: merge.entries.concat(hungryMerge.entries),
6000                        span: joinSpans(merge.span, hungryMerge.span),
6001                    };
6002                }
6003                else {
6004                    filteredMerges.push(merge);
6005                }
6006            }
6007            filteredMerges.push(hungryMerge);
6008            merges = filteredMerges;
6009        }
6010        return merges;
6011    }
6012    function joinSpans(span0, span1) {
6013        return {
6014            start: Math.min(span0.start, span1.start),
6015            end: Math.max(span0.end, span1.end),
6016        };
6017    }
6018    function intersectSpans(span0, span1) {
6019        let start = Math.max(span0.start, span1.start);
6020        let end = Math.min(span0.end, span1.end);
6021        if (start < end) {
6022            return { start, end };
6023        }
6024        return null;
6025    }
6026    // general util
6027    // ---------------------------------------------------------------------------------------------------------------------
6028    function insertAt(arr, index, item) {
6029        arr.splice(index, 0, item);
6030    }
6031    function binarySearch(a, searchVal, getItemVal) {
6032        let startIndex = 0;
6033        let endIndex = a.length; // exclusive
6034        if (!endIndex || searchVal < getItemVal(a[startIndex])) { // no items OR before first item
6035            return [0, 0];
6036        }
6037        if (searchVal > getItemVal(a[endIndex - 1])) { // after last item
6038            return [endIndex, 0];
6039        }
6040        while (startIndex < endIndex) {
6041            let middleIndex = Math.floor(startIndex + (endIndex - startIndex) / 2);
vendor: 8,015 bytes, lines 6042-6204
6042            let middleVal = getItemVal(a[middleIndex]);
6043            if (searchVal < middleVal) {
6044                endIndex = middleIndex;
6045            }
6046            else if (searchVal > middleVal) {
6047                startIndex = middleIndex + 1;
6048            }
6049            else { // equal!
6050                return [middleIndex, 1];
6051            }
6052        }
6053        return [startIndex, 0];
6054    }
6055
6056    /*
6057    An abstraction for a dragging interaction originating on an event.
6058    Does higher-level things than PointerDragger, such as possibly:
6059    - a "mirror" that moves with the pointer
6060    - a minimum number of pixels or other criteria for a true drag to begin
6061
6062    subclasses must emit:
6063    - pointerdown
6064    - dragstart
6065    - dragmove
6066    - pointerup
6067    - dragend
6068    */
6069    class ElementDragging {
6070        constructor(el, selector) {
6071            this.emitter = new Emitter();
6072        }
6073        destroy() {
6074        }
6075        setMirrorIsVisible(bool) {
6076            // optional if subclass doesn't want to support a mirror
6077        }
6078        setMirrorNeedsRevert(bool) {
6079            // optional if subclass doesn't want to support a mirror
6080        }
6081        setAutoScrollEnabled(bool) {
6082            // optional
6083        }
6084    }
6085
6086    // TODO: get rid of this in favor of options system,
6087    // tho it's really easy to access this globally rather than pass thru options.
6088    const config = {};
6089
6090    /*
6091    Information about what will happen when an external element is dragged-and-dropped
6092    onto a calendar. Contains information for creating an event.
6093    */
6094    const DRAG_META_REFINERS = {
6095        startTime: createDuration,
6096        duration: createDuration,
6097        create: Boolean,
6098        sourceId: String,
6099    };
6100    function parseDragMeta(raw) {
6101        let { refined, extra } = refineProps(raw, DRAG_META_REFINERS);
6102        return {
6103            startTime: refined.startTime || null,
6104            duration: refined.duration || null,
6105            create: refined.create != null ? refined.create : true,
6106            sourceId: refined.sourceId,
6107            leftoverProps: extra,
6108        };
6109    }
6110
6111    // Computes a default column header formatting string if `colFormat` is not explicitly defined
6112    function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
6113        // if more than one week row, or if there are a lot of columns with not much space,
6114        // put just the day numbers will be in each cell
6115        if (!datesRepDistinctDays || dayCnt > 10) {
6116            return createFormatter({ weekday: 'short' }); // "Sat"
6117        }
6118        if (dayCnt > 1) {
6119            return createFormatter({ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }); // "Sat 11/12"
6120        }
6121        return createFormatter({ weekday: 'long' }); // "Saturday"
6122    }
6123
6124    const CLASS_NAME = 'fc-col-header-cell'; // do the cushion too? no
6125    function renderInner$1(renderProps) {
6126        return renderProps.text;
6127    }
6128
6129    // BAD name for this class now. used in the Header
6130    class TableDateCell extends BaseComponent {
6131        render() {
6132            let { dateEnv, options, theme, viewApi } = this.context;
6133            let { props } = this;
6134            let { date, dateProfile } = props;
6135            let dayMeta = getDateMeta(date, props.todayRange, null, dateProfile);
6136            let classNames = [CLASS_NAME].concat(getDayClassNames(dayMeta, theme));
6137            let text = dateEnv.format(date, props.dayHeaderFormat);
6138            // if colCnt is 1, we are already in a day-view and don't need a navlink
6139            let navLinkAttrs = (!dayMeta.isDisabled && props.colCnt > 1)
6140                ? buildNavLinkAttrs(this.context, date)
6141                : {};
6142            let publicDate = dateEnv.toDate(date);
6143            // workaround for Luxon (and maybe moment) returning prior-days when start-of-day
6144            // in DST gap: https://github.com/fullcalendar/fullcalendar/issues/7633
6145            if (dateEnv.namedTimeZoneImpl) {
6146                publicDate = addMs(publicDate, 3600000); // add an hour
6147            }
6148            let renderProps = Object.assign(Object.assign(Object.assign({ date: publicDate, view: viewApi }, props.extraRenderProps), { text }), dayMeta);
6149            return (y(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", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner$1, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContainer) => (y("div", { className: "fc-scrollgrid-sync-inner" }, !dayMeta.isDisabled && (y(InnerContainer, { elTag: "a", elAttrs: navLinkAttrs, elClasses: [
6150                    'fc-col-header-cell-cushion',
6151                    props.isSticky && 'fc-sticky',
6152                ] }))))));
6153        }
6154    }
6155
6156    const WEEKDAY_FORMAT = createFormatter({ weekday: 'long' });
6157    class TableDowCell extends BaseComponent {
6158        render() {
6159            let { props } = this;
6160            let { dateEnv, theme, viewApi, options } = this.context;
6161            let date = addDays(new Date(259200000), props.dow); // start with Sun, 04 Jan 1970 00:00:00 GMT
6162            let dateMeta = {
6163                dow: props.dow,
6164                isDisabled: false,
6165                isFuture: false,
6166                isPast: false,
6167                isToday: false,
6168                isOther: false,
6169            };
6170            let text = dateEnv.format(date, props.dayHeaderFormat);
6171            let renderProps = Object.assign(Object.assign(Object.assign(Object.assign({ // TODO: make this public?
6172                date }, dateMeta), { view: viewApi }), props.extraRenderProps), { text });
6173            return (y(ContentContainer, { elTag: "th", elClasses: [
6174                    CLASS_NAME,
6175                    ...getDayClassNames(dateMeta, theme),
6176                    ...(props.extraClassNames || []),
6177                ], elAttrs: Object.assign({ role: 'columnheader', colSpan: props.colSpan }, props.extraDataAttrs), renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner$1, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => (y("div", { className: "fc-scrollgrid-sync-inner" },
6178                y(InnerContent, { elTag: "a", elClasses: [
6179                        'fc-col-header-cell-cushion',
6180                        props.isSticky && 'fc-sticky',
6181                    ], elAttrs: {
6182                        'aria-label': dateEnv.format(date, WEEKDAY_FORMAT),
6183                    } })))));
6184        }
6185    }
6186
6187    class DayHeader extends BaseComponent {
6188        constructor() {
6189            super(...arguments);
6190            this.createDayHeaderFormatter = memoize(createDayHeaderFormatter);
6191        }
6192        render() {
6193            let { context } = this;
6194            let { dates, dateProfile, datesRepDistinctDays, renderIntro } = this.props;
6195            let dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dates.length);
6196            return (y(NowTimer, { unit: "day" }, (nowDate, todayRange) => (y("tr", { role: "row" },
6197                renderIntro && renderIntro('day'),
6198                dates.map((date) => (datesRepDistinctDays ? (y(TableDateCell, { key: date.toISOString(), date: date, dateProfile: dateProfile, todayRange: todayRange, colCnt: dates.length, dayHeaderFormat: dayHeaderFormat })) : (y(TableDowCell, { key: date.getUTCDay(), dow: date.getUTCDay(), dayHeaderFormat: dayHeaderFormat }))))))));
6199        }
6200    }
6201    function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) {
6202        return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt);
6203    }
6204
vendor: 16,759 bytes, lines 6205-6550
6205    class DaySeriesModel {
6206        constructor(range, dateProfileGenerator) {
6207            let date = range.start;
6208            let { end } = range;
6209            let indices = [];
6210            let dates = [];
6211            let dayIndex = -1;
6212            while (date < end) { // loop each day from start to end
6213                if (dateProfileGenerator.isHiddenDay(date)) {
6214                    indices.push(dayIndex + 0.5); // mark that it's between indices
6215                }
6216                else {
6217                    dayIndex += 1;
6218                    indices.push(dayIndex);
6219                    dates.push(date);
6220                }
6221                date = addDays(date, 1);
6222            }
6223            this.dates = dates;
6224            this.indices = indices;
6225            this.cnt = dates.length;
6226        }
6227        sliceRange(range) {
6228            let firstIndex = this.getDateDayIndex(range.start); // inclusive first index
6229            let lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index
6230            let clippedFirstIndex = Math.max(0, firstIndex);
6231            let clippedLastIndex = Math.min(this.cnt - 1, lastIndex);
6232            // deal with in-between indices
6233            clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell
6234            clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell
6235            if (clippedFirstIndex <= clippedLastIndex) {
6236                return {
6237                    firstIndex: clippedFirstIndex,
6238                    lastIndex: clippedLastIndex,
6239                    isStart: firstIndex === clippedFirstIndex,
6240                    isEnd: lastIndex === clippedLastIndex,
6241                };
6242            }
6243            return null;
6244        }
6245        // Given a date, returns its chronolocial cell-index from the first cell of the grid.
6246        // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.
6247        // If before the first offset, returns a negative number.
6248        // If after the last offset, returns an offset past the last cell offset.
6249        // Only works for *start* dates of cells. Will not work for exclusive end dates for cells.
6250        getDateDayIndex(date) {
6251            let { indices } = this;
6252            let dayOffset = Math.floor(diffDays(this.dates[0], date));
6253            if (dayOffset < 0) {
6254                return indices[0] - 1;
6255            }
6256            if (dayOffset >= indices.length) {
6257                return indices[indices.length - 1] + 1;
6258            }
6259            return indices[dayOffset];
6260        }
6261    }
6262
6263    class DayTableModel {
6264        constructor(daySeries, breakOnWeeks) {
6265            let { dates } = daySeries;
6266            let daysPerRow;
6267            let firstDay;
6268            let rowCnt;
6269            if (breakOnWeeks) {
6270                // count columns until the day-of-week repeats
6271                firstDay = dates[0].getUTCDay();
6272                for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow += 1) {
6273                    if (dates[daysPerRow].getUTCDay() === firstDay) {
6274                        break;
6275                    }
6276                }
6277                rowCnt = Math.ceil(dates.length / daysPerRow);
6278            }
6279            else {
6280                rowCnt = 1;
6281                daysPerRow = dates.length;
6282            }
6283            this.rowCnt = rowCnt;
6284            this.colCnt = daysPerRow;
6285            this.daySeries = daySeries;
6286            this.cells = this.buildCells();
6287            this.headerDates = this.buildHeaderDates();
6288        }
6289        buildCells() {
6290            let rows = [];
6291            for (let row = 0; row < this.rowCnt; row += 1) {
6292                let cells = [];
6293                for (let col = 0; col < this.colCnt; col += 1) {
6294                    cells.push(this.buildCell(row, col));
6295                }
6296                rows.push(cells);
6297            }
6298            return rows;
6299        }
6300        buildCell(row, col) {
6301            let date = this.daySeries.dates[row * this.colCnt + col];
6302            return {
6303                key: date.toISOString(),
6304                date,
6305            };
6306        }
6307        buildHeaderDates() {
6308            let dates = [];
6309            for (let col = 0; col < this.colCnt; col += 1) {
6310                dates.push(this.cells[0][col].date);
6311            }
6312            return dates;
6313        }
6314        sliceRange(range) {
6315            let { colCnt } = this;
6316            let seriesSeg = this.daySeries.sliceRange(range);
6317            let segs = [];
6318            if (seriesSeg) {
6319                let { firstIndex, lastIndex } = seriesSeg;
6320                let index = firstIndex;
6321                while (index <= lastIndex) {
6322                    let row = Math.floor(index / colCnt);
6323                    let nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1);
6324                    segs.push({
6325                        row,
6326                        firstCol: index % colCnt,
6327                        lastCol: (nextIndex - 1) % colCnt,
6328                        isStart: seriesSeg.isStart && index === firstIndex,
6329                        isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex,
6330                    });
6331                    index = nextIndex;
6332                }
6333            }
6334            return segs;
6335        }
6336    }
6337
6338    class Slicer {
6339        constructor() {
6340            this.sliceBusinessHours = memoize(this._sliceBusinessHours);
6341            this.sliceDateSelection = memoize(this._sliceDateSpan);
6342            this.sliceEventStore = memoize(this._sliceEventStore);
6343            this.sliceEventDrag = memoize(this._sliceInteraction);
6344            this.sliceEventResize = memoize(this._sliceInteraction);
6345            this.forceDayIfListItem = false; // hack
6346        }
6347        sliceProps(props, dateProfile, nextDayThreshold, context, ...extraArgs) {
6348            let { eventUiBases } = props;
6349            let eventSegs = this.sliceEventStore(props.eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs);
6350            return {
6351                dateSelectionSegs: this.sliceDateSelection(props.dateSelection, dateProfile, nextDayThreshold, eventUiBases, context, ...extraArgs),
6352                businessHourSegs: this.sliceBusinessHours(props.businessHours, dateProfile, nextDayThreshold, context, ...extraArgs),
6353                fgEventSegs: eventSegs.fg,
6354                bgEventSegs: eventSegs.bg,
6355                eventDrag: this.sliceEventDrag(props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs),
6356                eventResize: this.sliceEventResize(props.eventResize, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs),
6357                eventSelection: props.eventSelection,
6358            }; // TODO: give interactionSegs?
6359        }
6360        sliceNowDate(// does not memoize
6361        date, dateProfile, nextDayThreshold, context, ...extraArgs) {
6362            return this._sliceDateSpan({ range: { start: date, end: addMs(date, 1) }, allDay: false }, // add 1 ms, protect against null range
6363            dateProfile, nextDayThreshold, {}, context, ...extraArgs);
6364        }
6365        _sliceBusinessHours(businessHours, dateProfile, nextDayThreshold, context, ...extraArgs) {
6366            if (!businessHours) {
6367                return [];
6368            }
6369            return this._sliceEventStore(expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), context), {}, dateProfile, nextDayThreshold, ...extraArgs).bg;
6370        }
6371        _sliceEventStore(eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs) {
6372            if (eventStore) {
6373                let rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
6374                return {
6375                    bg: this.sliceEventRanges(rangeRes.bg, extraArgs),
6376                    fg: this.sliceEventRanges(rangeRes.fg, extraArgs),
6377                };
6378            }
6379            return { bg: [], fg: [] };
6380        }
6381        _sliceInteraction(interaction, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs) {
6382            if (!interaction) {
6383                return null;
6384            }
6385            let rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
6386            return {
6387                segs: this.sliceEventRanges(rangeRes.fg, extraArgs),
6388                affectedInstances: interaction.affectedEvents.instances,
6389                isEvent: interaction.isEvent,
6390            };
6391        }
6392        _sliceDateSpan(dateSpan, dateProfile, nextDayThreshold, eventUiBases, context, ...extraArgs) {
6393            if (!dateSpan) {
6394                return [];
6395            }
6396            let activeRange = computeActiveRange(dateProfile, Boolean(nextDayThreshold));
6397            let activeDateSpanRange = intersectRanges(dateSpan.range, activeRange);
6398            if (activeDateSpanRange) {
6399                dateSpan = Object.assign(Object.assign({}, dateSpan), { range: activeDateSpanRange });
6400                let eventRange = fabricateEventRange(dateSpan, eventUiBases, context);
6401                let segs = this.sliceRange(dateSpan.range, ...extraArgs);
6402                for (let seg of segs) {
6403                    seg.eventRange = eventRange;
6404                }
6405                return segs;
6406            }
6407            return [];
6408        }
6409        /*
6410        "complete" seg means it has component and eventRange
6411        */
6412        sliceEventRanges(eventRanges, extraArgs) {
6413            let segs = [];
6414            for (let eventRange of eventRanges) {
6415                segs.push(...this.sliceEventRange(eventRange, extraArgs));
6416            }
6417            return segs;
6418        }
6419        /*
6420        "complete" seg means it has component and eventRange
6421        */
6422        sliceEventRange(eventRange, extraArgs) {
6423            let dateRange = eventRange.range;
6424            // hack to make multi-day events that are being force-displayed as list-items to take up only one day
6425            if (this.forceDayIfListItem && eventRange.ui.display === 'list-item') {
6426                dateRange = {
6427                    start: dateRange.start,
6428                    end: addDays(dateRange.start, 1),
6429                };
6430            }
6431            let segs = this.sliceRange(dateRange, ...extraArgs);
6432            for (let seg of segs) {
6433                seg.eventRange = eventRange;
6434                seg.isStart = eventRange.isStart && seg.isStart;
6435                seg.isEnd = eventRange.isEnd && seg.isEnd;
6436            }
6437            return segs;
6438        }
6439    }
6440    /*
6441    for incorporating slotMinTime/slotMaxTime if appropriate
6442    TODO: should be part of DateProfile!
6443    TimelineDateProfile already does this btw
6444    */
6445    function computeActiveRange(dateProfile, isComponentAllDay) {
6446        let range = dateProfile.activeRange;
6447        if (isComponentAllDay) {
6448            return range;
6449        }
6450        return {
6451            start: addMs(range.start, dateProfile.slotMinTime.milliseconds),
6452            end: addMs(range.end, dateProfile.slotMaxTime.milliseconds - 864e5), // 864e5 = ms in a day
6453        };
6454    }
6455
6456    // high-level segmenting-aware tester functions
6457    // ------------------------------------------------------------------------------------------------------------------------
6458    function isInteractionValid(interaction, dateProfile, context) {
6459        let { instances } = interaction.mutatedEvents;
6460        for (let instanceId in instances) {
6461            if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) {
6462                return false;
6463            }
6464        }
6465        return isNewPropsValid({ eventDrag: interaction }, context); // HACK: the eventDrag props is used for ALL interactions
6466    }
6467    function isDateSelectionValid(dateSelection, dateProfile, context) {
6468        if (!rangeContainsRange(dateProfile.validRange, dateSelection.range)) {
6469            return false;
6470        }
6471        return isNewPropsValid({ dateSelection }, context);
6472    }
6473    function isNewPropsValid(newProps, context) {
6474        let calendarState = context.getCurrentData();
6475        let props = Object.assign({ businessHours: calendarState.businessHours, dateSelection: '', eventStore: calendarState.eventStore, eventUiBases: calendarState.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps);
6476        return (context.pluginHooks.isPropsValid || isPropsValid)(props, context);
6477    }
6478    function isPropsValid(state, context, dateSpanMeta = {}, filterConfig) {
6479        if (state.eventDrag && !isInteractionPropsValid(state, context, dateSpanMeta, filterConfig)) {
6480            return false;
6481        }
6482        if (state.dateSelection && !isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig)) {
6483            return false;
6484        }
6485        return true;
6486    }
6487    // Moving Event Validation
6488    // ------------------------------------------------------------------------------------------------------------------------
6489    function isInteractionPropsValid(state, context, dateSpanMeta, filterConfig) {
6490        let currentState = context.getCurrentData();
6491        let interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions
6492        let subjectEventStore = interaction.mutatedEvents;
6493        let subjectDefs = subjectEventStore.defs;
6494        let subjectInstances = subjectEventStore.instances;
6495        let subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ?
6496            state.eventUiBases :
6497            { '': currentState.selectionConfig });
6498        if (filterConfig) {
6499            subjectConfigs = mapHash(subjectConfigs, filterConfig);
6500        }
6501        // exclude the subject events. TODO: exclude defs too?
6502        let otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances);
6503        let otherDefs = otherEventStore.defs;
6504        let otherInstances = otherEventStore.instances;
6505        let otherConfigs = compileEventUis(otherDefs, state.eventUiBases);
6506        for (let subjectInstanceId in subjectInstances) {
6507            let subjectInstance = subjectInstances[subjectInstanceId];
6508            let subjectRange = subjectInstance.range;
6509            let subjectConfig = subjectConfigs[subjectInstance.defId];
6510            let subjectDef = subjectDefs[subjectInstance.defId];
6511            // constraint
6512            if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, context)) {
6513                return false;
6514            }
6515            // overlap
6516            let { eventOverlap } = context.options;
6517            let eventOverlapFunc = typeof eventOverlap === 'function' ? eventOverlap : null;
6518            for (let otherInstanceId in otherInstances) {
6519                let otherInstance = otherInstances[otherInstanceId];
6520                // intersect! evaluate
6521                if (rangesIntersect(subjectRange, otherInstance.range)) {
6522                    let otherOverlap = otherConfigs[otherInstance.defId].overlap;
6523                    // consider the other event's overlap. only do this if the subject event is a "real" event
6524                    if (otherOverlap === false && interaction.isEvent) {
6525                        return false;
6526                    }
6527                    if (subjectConfig.overlap === false) {
6528                        return false;
6529                    }
6530                    if (eventOverlapFunc && !eventOverlapFunc(new EventImpl(context, otherDefs[otherInstance.defId], otherInstance), // still event
6531                    new EventImpl(context, subjectDef, subjectInstance))) {
6532                        return false;
6533                    }
6534                }
6535            }
6536            // allow (a function)
6537            let calendarEventStore = currentState.eventStore; // need global-to-calendar, not local to component (splittable)state
6538            for (let subjectAllow of subjectConfig.allows) {
6539                let subjectDateSpan = Object.assign(Object.assign({}, dateSpanMeta), { range: subjectInstance.range, allDay: subjectDef.allDay });
6540                let origDef = calendarEventStore.defs[subjectDef.defId];
6541                let origInstance = calendarEventStore.instances[subjectInstanceId];
6542                let eventApi;
6543                if (origDef) { // was previously in the calendar
6544                    eventApi = new EventImpl(context, origDef, origInstance);
6545                }
6546                else { // was an external event
6547                    eventApi = new EventImpl(context, subjectDef); // no instance, because had no dates
6548                }
6549                if (!subjectAllow(buildDateSpanApiWithContext(subjectDateSpan, context), eventApi)) {
6550                    return false;
vendor: 40,919 bytes, lines 6551-7380
6551                }
6552            }
6553        }
6554        return true;
6555    }
6556    // Date Selection Validation
6557    // ------------------------------------------------------------------------------------------------------------------------
6558    function isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig) {
6559        let relevantEventStore = state.eventStore;
6560        let relevantDefs = relevantEventStore.defs;
6561        let relevantInstances = relevantEventStore.instances;
6562        let selection = state.dateSelection;
6563        let selectionRange = selection.range;
6564        let { selectionConfig } = context.getCurrentData();
6565        if (filterConfig) {
6566            selectionConfig = filterConfig(selectionConfig);
6567        }
6568        // constraint
6569        if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, context)) {
6570            return false;
6571        }
6572        // overlap
6573        let { selectOverlap } = context.options;
6574        let selectOverlapFunc = typeof selectOverlap === 'function' ? selectOverlap : null;
6575        for (let relevantInstanceId in relevantInstances) {
6576            let relevantInstance = relevantInstances[relevantInstanceId];
6577            // intersect! evaluate
6578            if (rangesIntersect(selectionRange, relevantInstance.range)) {
6579                if (selectionConfig.overlap === false) {
6580                    return false;
6581                }
6582                if (selectOverlapFunc && !selectOverlapFunc(new EventImpl(context, relevantDefs[relevantInstance.defId], relevantInstance), null)) {
6583                    return false;
6584                }
6585            }
6586        }
6587        // allow (a function)
6588        for (let selectionAllow of selectionConfig.allows) {
6589            let fullDateSpan = Object.assign(Object.assign({}, dateSpanMeta), selection);
6590            if (!selectionAllow(buildDateSpanApiWithContext(fullDateSpan, context), null)) {
6591                return false;
6592            }
6593        }
6594        return true;
6595    }
6596    // Constraint Utils
6597    // ------------------------------------------------------------------------------------------------------------------------
6598    function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, context) {
6599        for (let constraint of constraints) {
6600            if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, context), subjectRange)) {
6601                return false;
6602            }
6603        }
6604        return true;
6605    }
6606    function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours
6607    otherEventStore, // for if constraint is an even group ID
6608    businessHoursUnexpanded, // for if constraint is 'businessHours'
6609    context) {
6610        if (constraint === 'businessHours') {
6611            return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, context));
6612        }
6613        if (typeof constraint === 'string') { // an group ID
6614            return eventStoreToRanges(filterEventStoreDefs(otherEventStore, (eventDef) => eventDef.groupId === constraint));
6615        }
6616        if (typeof constraint === 'object' && constraint) { // non-null object
6617            return eventStoreToRanges(expandRecurring(constraint, subjectRange, context));
6618        }
6619        return []; // if it's false
6620    }
6621    // TODO: move to event-store file?
6622    function eventStoreToRanges(eventStore) {
6623        let { instances } = eventStore;
6624        let ranges = [];
6625        for (let instanceId in instances) {
6626            ranges.push(instances[instanceId].range);
6627        }
6628        return ranges;
6629    }
6630    // TODO: move to geom file?
6631    function anyRangesContainRange(outerRanges, innerRange) {
6632        for (let outerRange of outerRanges) {
6633            if (rangeContainsRange(outerRange, innerRange)) {
6634                return true;
6635            }
6636        }
6637        return false;
6638    }
6639
6640    const VISIBLE_HIDDEN_RE = /^(visible|hidden)$/;
6641    class Scroller extends BaseComponent {
6642        constructor() {
6643            super(...arguments);
6644            this.handleEl = (el) => {
6645                this.el = el;
6646                setRef(this.props.elRef, el);
6647            };
6648        }
6649        render() {
6650            let { props } = this;
6651            let { liquid, liquidIsAbsolute } = props;
6652            let isAbsolute = liquid && liquidIsAbsolute;
6653            let className = ['fc-scroller'];
6654            if (liquid) {
6655                if (liquidIsAbsolute) {
6656                    className.push('fc-scroller-liquid-absolute');
6657                }
6658                else {
6659                    className.push('fc-scroller-liquid');
6660                }
6661            }
6662            return (y("div", { ref: this.handleEl, className: className.join(' '), style: {
6663                    overflowX: props.overflowX,
6664                    overflowY: props.overflowY,
6665                    left: (isAbsolute && -(props.overcomeLeft || 0)) || '',
6666                    right: (isAbsolute && -(props.overcomeRight || 0)) || '',
6667                    bottom: (isAbsolute && -(props.overcomeBottom || 0)) || '',
6668                    marginLeft: (!isAbsolute && -(props.overcomeLeft || 0)) || '',
6669                    marginRight: (!isAbsolute && -(props.overcomeRight || 0)) || '',
6670                    marginBottom: (!isAbsolute && -(props.overcomeBottom || 0)) || '',
6671                    maxHeight: props.maxHeight || '',
6672                } }, props.children));
6673        }
6674        needsXScrolling() {
6675            if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {
6676                return false;
6677            }
6678            // testing scrollWidth>clientWidth is unreliable cross-browser when pixel heights aren't integers.
6679            // much more reliable to see if children are taller than the scroller, even tho doesn't account for
6680            // inner-child margins and absolute positioning
6681            let { el } = this;
6682            let realClientWidth = this.el.getBoundingClientRect().width - this.getYScrollbarWidth();
6683            let { children } = el;
6684            for (let i = 0; i < children.length; i += 1) {
6685                let childEl = children[i];
6686                if (childEl.getBoundingClientRect().width > realClientWidth) {
6687                    return true;
6688                }
6689            }
6690            return false;
6691        }
6692        needsYScrolling() {
6693            if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {
6694                return false;
6695            }
6696            // testing scrollHeight>clientHeight is unreliable cross-browser when pixel heights aren't integers.
6697            // much more reliable to see if children are taller than the scroller, even tho doesn't account for
6698            // inner-child margins and absolute positioning
6699            let { el } = this;
6700            let realClientHeight = this.el.getBoundingClientRect().height - this.getXScrollbarWidth();
6701            let { children } = el;
6702            for (let i = 0; i < children.length; i += 1) {
6703                let childEl = children[i];
6704                if (childEl.getBoundingClientRect().height > realClientHeight) {
6705                    return true;
6706                }
6707            }
6708            return false;
6709        }
6710        getXScrollbarWidth() {
6711            if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {
6712                return 0;
6713            }
6714            return this.el.offsetHeight - this.el.clientHeight; // only works because we guarantee no borders. TODO: add to CSS with important?
6715        }
6716        getYScrollbarWidth() {
6717            if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {
6718                return 0;
6719            }
6720            return this.el.offsetWidth - this.el.clientWidth; // only works because we guarantee no borders. TODO: add to CSS with important?
6721        }
6722    }
6723
6724    /*
6725    TODO: somehow infer OtherArgs from masterCallback?
6726    TODO: infer RefType from masterCallback if provided
6727    */
6728    class RefMap {
6729        constructor(masterCallback) {
6730            this.masterCallback = masterCallback;
6731            this.currentMap = {};
6732            this.depths = {};
6733            this.callbackMap = {};
6734            this.handleValue = (val, key) => {
6735                let { depths, currentMap } = this;
6736                let removed = false;
6737                let added = false;
6738                if (val !== null) {
6739                    // for bug... ACTUALLY: can probably do away with this now that callers don't share numeric indices anymore
6740                    removed = (key in currentMap);
6741                    currentMap[key] = val;
6742                    depths[key] = (depths[key] || 0) + 1;
6743                    added = true;
6744                }
6745                else {
6746                    depths[key] -= 1;
6747                    if (!depths[key]) {
6748                        delete currentMap[key];
6749                        delete this.callbackMap[key];
6750                        removed = true;
6751                    }
6752                }
6753                if (this.masterCallback) {
6754                    if (removed) {
6755                        this.masterCallback(null, String(key));
6756                    }
6757                    if (added) {
6758                        this.masterCallback(val, String(key));
6759                    }
6760                }
6761            };
6762        }
6763        createRef(key) {
6764            let refCallback = this.callbackMap[key];
6765            if (!refCallback) {
6766                refCallback = this.callbackMap[key] = (val) => {
6767                    this.handleValue(val, String(key));
6768                };
6769            }
6770            return refCallback;
6771        }
6772        // TODO: check callers that don't care about order. should use getAll instead
6773        // NOTE: this method has become less valuable now that we are encouraged to map order by some other index
6774        // TODO: provide ONE array-export function, buildArray, which fails on non-numeric indexes. caller can manipulate and "collect"
6775        collect(startIndex, endIndex, step) {
6776            return collectFromHash(this.currentMap, startIndex, endIndex, step);
6777        }
6778        getAll() {
6779            return hashValuesToArray(this.currentMap);
6780        }
6781    }
6782
6783    function computeShrinkWidth(chunkEls) {
6784        let shrinkCells = findElements(chunkEls, '.fc-scrollgrid-shrink');
6785        let largestWidth = 0;
6786        for (let shrinkCell of shrinkCells) {
6787            largestWidth = Math.max(largestWidth, computeSmallestCellWidth(shrinkCell));
6788        }
6789        return Math.ceil(largestWidth); // <table> elements work best with integers. round up to ensure contents fits
6790    }
6791    function getSectionHasLiquidHeight(props, sectionConfig) {
6792        return props.liquid && sectionConfig.liquid; // does the section do liquid-height? (need to have whole scrollgrid liquid-height as well)
6793    }
6794    function getAllowYScrolling(props, sectionConfig) {
6795        return sectionConfig.maxHeight != null || // if its possible for the height to max out, we might need scrollbars
6796            getSectionHasLiquidHeight(props, sectionConfig); // if the section is liquid height, it might condense enough to require scrollbars
6797    }
6798    // TODO: ONLY use `arg`. force out internal function to use same API
6799    function renderChunkContent(sectionConfig, chunkConfig, arg, isHeader) {
6800        let { expandRows } = arg;
6801        let content = typeof chunkConfig.content === 'function' ?
6802            chunkConfig.content(arg) :
6803            y('table', {
6804                role: 'presentation',
6805                className: [
6806                    chunkConfig.tableClassName,
6807                    sectionConfig.syncRowHeights ? 'fc-scrollgrid-sync-table' : '',
6808                ].join(' '),
6809                style: {
6810                    minWidth: arg.tableMinWidth,
6811                    width: arg.clientWidth,
6812                    height: expandRows ? arg.clientHeight : '', // css `height` on a <table> serves as a min-height
6813                },
6814            }, arg.tableColGroupNode, y(isHeader ? 'thead' : 'tbody', {
6815                role: 'presentation',
6816            }, typeof chunkConfig.rowContent === 'function'
6817                ? chunkConfig.rowContent(arg)
6818                : chunkConfig.rowContent));
6819        return content;
6820    }
6821    function isColPropsEqual(cols0, cols1) {
6822        return isArraysEqual(cols0, cols1, isPropsEqual);
6823    }
6824    function renderMicroColGroup(cols, shrinkWidth) {
6825        let colNodes = [];
6826        /*
6827        for ColProps with spans, it would have been great to make a single <col span="">
6828        HOWEVER, Chrome was getting messing up distributing the width to <td>/<th> elements with colspans.
6829        SOLUTION: making individual <col> elements makes Chrome behave.
6830        */
6831        for (let colProps of cols) {
6832            let span = colProps.span || 1;
6833            for (let i = 0; i < span; i += 1) {
6834                colNodes.push(y("col", { style: {
6835                        width: colProps.width === 'shrink' ? sanitizeShrinkWidth(shrinkWidth) : (colProps.width || ''),
6836                        minWidth: colProps.minWidth || '',
6837                    } }));
6838            }
6839        }
6840        return y('colgroup', {}, ...colNodes);
6841    }
6842    function sanitizeShrinkWidth(shrinkWidth) {
6843        /* why 4? if we do 0, it will kill any border, which are needed for computeSmallestCellWidth
6844        4 accounts for 2 2-pixel borders. TODO: better solution? */
6845        return shrinkWidth == null ? 4 : shrinkWidth;
6846    }
6847    function hasShrinkWidth(cols) {
6848        for (let col of cols) {
6849            if (col.width === 'shrink') {
6850                return true;
6851            }
6852        }
6853        return false;
6854    }
6855    function getScrollGridClassNames(liquid, context) {
6856        let classNames = [
6857            'fc-scrollgrid',
6858            context.theme.getClass('table'),
6859        ];
6860        if (liquid) {
6861            classNames.push('fc-scrollgrid-liquid');
6862        }
6863        return classNames;
6864    }
6865    function getSectionClassNames(sectionConfig, wholeTableVGrow) {
6866        let classNames = [
6867            'fc-scrollgrid-section',
6868            `fc-scrollgrid-section-${sectionConfig.type}`,
6869            sectionConfig.className, // used?
6870        ];
6871        if (wholeTableVGrow && sectionConfig.liquid && sectionConfig.maxHeight == null) {
6872            classNames.push('fc-scrollgrid-section-liquid');
6873        }
6874        if (sectionConfig.isSticky) {
6875            classNames.push('fc-scrollgrid-section-sticky');
6876        }
6877        return classNames;
6878    }
6879    function renderScrollShim(arg) {
6880        return (y("div", { className: "fc-scrollgrid-sticky-shim", style: {
6881                width: arg.clientWidth,
6882                minWidth: arg.tableMinWidth,
6883            } }));
6884    }
6885    function getStickyHeaderDates(options) {
6886        let { stickyHeaderDates } = options;
6887        if (stickyHeaderDates == null || stickyHeaderDates === 'auto') {
6888            stickyHeaderDates = options.height === 'auto' || options.viewHeight === 'auto';
6889        }
6890        return stickyHeaderDates;
6891    }
6892    function getStickyFooterScrollbar(options) {
6893        let { stickyFooterScrollbar } = options;
6894        if (stickyFooterScrollbar == null || stickyFooterScrollbar === 'auto') {
6895            stickyFooterScrollbar = options.height === 'auto' || options.viewHeight === 'auto';
6896        }
6897        return stickyFooterScrollbar;
6898    }
6899
6900    class SimpleScrollGrid extends BaseComponent {
6901        constructor() {
6902            super(...arguments);
6903            this.processCols = memoize((a) => a, isColPropsEqual); // so we get same `cols` props every time
6904            // yucky to memoize VNodes, but much more efficient for consumers
6905            this.renderMicroColGroup = memoize(renderMicroColGroup);
6906            this.scrollerRefs = new RefMap();
6907            this.scrollerElRefs = new RefMap(this._handleScrollerEl.bind(this));
6908            this.state = {
6909                shrinkWidth: null,
6910                forceYScrollbars: false,
6911                scrollerClientWidths: {},
6912                scrollerClientHeights: {},
6913            };
6914            // TODO: can do a really simple print-view. dont need to join rows
6915            this.handleSizing = () => {
6916                this.safeSetState(Object.assign({ shrinkWidth: this.computeShrinkWidth() }, this.computeScrollerDims()));
6917            };
6918        }
6919        render() {
6920            let { props, state, context } = this;
6921            let sectionConfigs = props.sections || [];
6922            let cols = this.processCols(props.cols);
6923            let microColGroupNode = this.renderMicroColGroup(cols, state.shrinkWidth);
6924            let classNames = getScrollGridClassNames(props.liquid, context);
6925            if (props.collapsibleWidth) {
6926                classNames.push('fc-scrollgrid-collapsible');
6927            }
6928            // TODO: make DRY
6929            let configCnt = sectionConfigs.length;
6930            let configI = 0;
6931            let currentConfig;
6932            let headSectionNodes = [];
6933            let bodySectionNodes = [];
6934            let footSectionNodes = [];
6935            while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'header') {
6936                headSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));
6937                configI += 1;
6938            }
6939            while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'body') {
6940                bodySectionNodes.push(this.renderSection(currentConfig, microColGroupNode, false));
6941                configI += 1;
6942            }
6943            while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'footer') {
6944                footSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));
6945                configI += 1;
6946            }
6947            // firefox bug: when setting height on table and there is a thead or tfoot,
6948            // the necessary height:100% on the liquid-height body section forces the *whole* table to be taller. (bug #5524)
6949            // use getCanVGrowWithinCell as a way to detect table-stupid firefox.
6950            // if so, use a simpler dom structure, jam everything into a lone tbody.
6951            let isBuggy = !getCanVGrowWithinCell();
6952            const roleAttrs = { role: 'rowgroup' };
6953            return y('table', {
6954                role: 'grid',
6955                className: classNames.join(' '),
6956                style: { height: props.height },
6957            }, Boolean(!isBuggy && headSectionNodes.length) && y('thead', roleAttrs, ...headSectionNodes), Boolean(!isBuggy && bodySectionNodes.length) && y('tbody', roleAttrs, ...bodySectionNodes), Boolean(!isBuggy && footSectionNodes.length) && y('tfoot', roleAttrs, ...footSectionNodes), isBuggy && y('tbody', roleAttrs, ...headSectionNodes, ...bodySectionNodes, ...footSectionNodes));
6958        }
6959        renderSection(sectionConfig, microColGroupNode, isHeader) {
6960            if ('outerContent' in sectionConfig) {
6961                return (y(_, { key: sectionConfig.key }, sectionConfig.outerContent));
6962            }
6963            return (y("tr", { key: sectionConfig.key, role: "presentation", className: getSectionClassNames(sectionConfig, this.props.liquid).join(' ') }, this.renderChunkTd(sectionConfig, microColGroupNode, sectionConfig.chunk, isHeader)));
6964        }
6965        renderChunkTd(sectionConfig, microColGroupNode, chunkConfig, isHeader) {
6966            if ('outerContent' in chunkConfig) {
6967                return chunkConfig.outerContent;
6968            }
6969            let { props } = this;
6970            let { forceYScrollbars, scrollerClientWidths, scrollerClientHeights } = this.state;
6971            let needsYScrolling = getAllowYScrolling(props, sectionConfig); // TODO: do lazily. do in section config?
6972            let isLiquid = getSectionHasLiquidHeight(props, sectionConfig);
6973            // for `!props.liquid` - is WHOLE scrollgrid natural height?
6974            // TODO: do same thing in advanced scrollgrid? prolly not b/c always has horizontal scrollbars
6975            let overflowY = !props.liquid ? 'visible' :
6976                forceYScrollbars ? 'scroll' :
6977                    !needsYScrolling ? 'hidden' :
6978                        'auto';
6979            let sectionKey = sectionConfig.key;
6980            let content = renderChunkContent(sectionConfig, chunkConfig, {
6981                tableColGroupNode: microColGroupNode,
6982                tableMinWidth: '',
6983                clientWidth: (!props.collapsibleWidth && scrollerClientWidths[sectionKey] !== undefined) ? scrollerClientWidths[sectionKey] : null,
6984                clientHeight: scrollerClientHeights[sectionKey] !== undefined ? scrollerClientHeights[sectionKey] : null,
6985                expandRows: sectionConfig.expandRows,
6986                syncRowHeights: false,
6987                rowSyncHeights: [],
6988                reportRowHeightChange: () => { },
6989            }, isHeader);
6990            return y(isHeader ? 'th' : 'td', {
6991                ref: chunkConfig.elRef,
6992                role: 'presentation',
6993            }, y("div", { className: `fc-scroller-harness${isLiquid ? ' fc-scroller-harness-liquid' : ''}` },
6994                y(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
6995                    : true }, content)));
6996        }
6997        _handleScrollerEl(scrollerEl, key) {
6998            let section = getSectionByKey(this.props.sections, key);
6999            if (section) {
7000                setRef(section.chunk.scrollerElRef, scrollerEl);
7001            }
7002        }
7003        componentDidMount() {
7004            this.handleSizing();
7005            this.context.addResizeHandler(this.handleSizing);
7006        }
7007        componentDidUpdate() {
7008            // TODO: need better solution when state contains non-sizing things
7009            this.handleSizing();
7010        }
7011        componentWillUnmount() {
7012            this.context.removeResizeHandler(this.handleSizing);
7013        }
7014        computeShrinkWidth() {
7015            return hasShrinkWidth(this.props.cols)
7016                ? computeShrinkWidth(this.scrollerElRefs.getAll())
7017                : 0;
7018        }
7019        computeScrollerDims() {
7020            let scrollbarWidth = getScrollbarWidths();
7021            let { scrollerRefs, scrollerElRefs } = this;
7022            let forceYScrollbars = false;
7023            let scrollerClientWidths = {};
7024            let scrollerClientHeights = {};
7025            for (let sectionKey in scrollerRefs.currentMap) {
7026                let scroller = scrollerRefs.currentMap[sectionKey];
7027                if (scroller && scroller.needsYScrolling()) {
7028                    forceYScrollbars = true;
7029                    break;
7030                }
7031            }
7032            for (let section of this.props.sections) {
7033                let sectionKey = section.key;
7034                let scrollerEl = scrollerElRefs.currentMap[sectionKey];
7035                if (scrollerEl) {
7036                    let harnessEl = scrollerEl.parentNode; // TODO: weird way to get this. need harness b/c doesn't include table borders
7037                    scrollerClientWidths[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().width - (forceYScrollbars
7038                        ? scrollbarWidth.y // use global because scroller might not have scrollbars yet but will need them in future
7039                        : 0));
7040                    scrollerClientHeights[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().height);
7041                }
7042            }
7043            return { forceYScrollbars, scrollerClientWidths, scrollerClientHeights };
7044        }
7045    }
7046    SimpleScrollGrid.addStateEquality({
7047        scrollerClientWidths: isPropsEqual,
7048        scrollerClientHeights: isPropsEqual,
7049    });
7050    function getSectionByKey(sections, key) {
7051        for (let section of sections) {
7052            if (section.key === key) {
7053                return section;
7054            }
7055        }
7056        return null;
7057    }
7058
7059    class EventContainer extends BaseComponent {
7060        constructor() {
7061            super(...arguments);
7062            this.handleEl = (el) => {
7063                this.el = el;
7064                if (el) {
7065                    setElSeg(el, this.props.seg);
7066                }
7067            };
7068        }
7069        render() {
7070            const { props, context } = this;
7071            const { options } = context;
7072            const { seg } = props;
7073            const { eventRange } = seg;
7074            const { ui } = eventRange;
7075            const renderProps = {
7076                event: new EventImpl(context, eventRange.def, eventRange.instance),
7077                view: context.viewApi,
7078                timeText: props.timeText,
7079                textColor: ui.textColor,
7080                backgroundColor: ui.backgroundColor,
7081                borderColor: ui.borderColor,
7082                isDraggable: !props.disableDragging && computeSegDraggable(seg, context),
7083                isStartResizable: !props.disableResizing && computeSegStartResizable(seg, context),
7084                isEndResizable: !props.disableResizing && computeSegEndResizable(seg),
7085                isMirror: Boolean(props.isDragging || props.isResizing || props.isDateSelecting),
7086                isStart: Boolean(seg.isStart),
7087                isEnd: Boolean(seg.isEnd),
7088                isPast: Boolean(props.isPast),
7089                isFuture: Boolean(props.isFuture),
7090                isToday: Boolean(props.isToday),
7091                isSelected: Boolean(props.isSelected),
7092                isDragging: Boolean(props.isDragging),
7093                isResizing: Boolean(props.isResizing),
7094            };
7095            return (y(ContentContainer, Object.assign({}, props /* contains children */, { elRef: this.handleEl, elClasses: [
7096                    ...getEventClassNames(renderProps),
7097                    ...seg.eventRange.ui.classNames,
7098                    ...(props.elClasses || []),
7099                ], renderProps: renderProps, generatorName: "eventContent", customGenerator: options.eventContent, defaultGenerator: props.defaultGenerator, classNameGenerator: options.eventClassNames, didMount: options.eventDidMount, willUnmount: options.eventWillUnmount })));
7100        }
7101        componentDidUpdate(prevProps) {
7102            if (this.el && this.props.seg !== prevProps.seg) {
7103                setElSeg(this.el, this.props.seg);
7104            }
7105        }
7106    }
7107
7108    // should not be a purecomponent
7109    class StandardEvent extends BaseComponent {
7110        render() {
7111            let { props, context } = this;
7112            let { options } = context;
7113            let { seg } = props;
7114            let { ui } = seg.eventRange;
7115            let timeFormat = options.eventTimeFormat || props.defaultTimeFormat;
7116            let timeText = buildSegTimeText(seg, timeFormat, context, props.defaultDisplayEventTime, props.defaultDisplayEventEnd);
7117            return (y(EventContainer, Object.assign({}, props /* includes elRef */, { elTag: "a", elStyle: {
7118                    borderColor: ui.borderColor,
7119                    backgroundColor: ui.backgroundColor,
7120                }, elAttrs: getSegAnchorAttrs(seg, context), defaultGenerator: renderInnerContent$1$1, timeText: timeText }), (InnerContent, eventContentArg) => (y(_, null,
7121                y(InnerContent, { elTag: "div", elClasses: ['fc-event-main'], elStyle: { color: eventContentArg.textColor } }),
7122                Boolean(eventContentArg.isStartResizable) && (y("div", { className: "fc-event-resizer fc-event-resizer-start" })),
7123                Boolean(eventContentArg.isEndResizable) && (y("div", { className: "fc-event-resizer fc-event-resizer-end" }))))));
7124        }
7125    }
7126    function renderInnerContent$1$1(innerProps) {
7127        return (y("div", { className: "fc-event-main-frame" },
7128            innerProps.timeText && (y("div", { className: "fc-event-time" }, innerProps.timeText)),
7129            y("div", { className: "fc-event-title-container" },
7130                y("div", { className: "fc-event-title fc-sticky" }, innerProps.event.title || y(_, null, "\u00A0")))));
7131    }
7132
7133    const NowIndicatorContainer = (props) => (y(ViewContextType.Consumer, null, (context) => {
7134        let { options } = context;
7135        let renderProps = {
7136            isAxis: props.isAxis,
7137            date: context.dateEnv.toDate(props.date),
7138            view: context.viewApi,
7139        };
7140        return (y(ContentContainer, Object.assign({}, props /* includes children */, { elTag: props.elTag || 'div', renderProps: renderProps, generatorName: "nowIndicatorContent", customGenerator: options.nowIndicatorContent, classNameGenerator: options.nowIndicatorClassNames, didMount: options.nowIndicatorDidMount, willUnmount: options.nowIndicatorWillUnmount })));
7141    }));
7142
7143    const DAY_NUM_FORMAT = createFormatter({ day: 'numeric' });
7144    class DayCellContainer extends BaseComponent {
7145        constructor() {
7146            super(...arguments);
7147            this.refineRenderProps = memoizeObjArg(refineRenderProps);
7148        }
7149        render() {
7150            let { props, context } = this;
7151            let { options } = context;
7152            let renderProps = this.refineRenderProps({
7153                date: props.date,
7154                dateProfile: props.dateProfile,
7155                todayRange: props.todayRange,
7156                isMonthStart: props.isMonthStart || false,
7157                showDayNumber: props.showDayNumber,
7158                extraRenderProps: props.extraRenderProps,
7159                viewApi: context.viewApi,
7160                dateEnv: context.dateEnv,
7161                monthStartFormat: options.monthStartFormat,
7162            });
7163            return (y(ContentContainer, Object.assign({}, props /* includes children */, { elClasses: [
7164                    ...getDayClassNames(renderProps, context.theme),
7165                    ...(props.elClasses || []),
7166                ], elAttrs: Object.assign(Object.assign({}, props.elAttrs), (renderProps.isDisabled ? {} : { 'data-date': formatDayString(props.date) })), renderProps: renderProps, generatorName: "dayCellContent", customGenerator: options.dayCellContent, defaultGenerator: props.defaultGenerator, classNameGenerator: 
7167                // don't use custom classNames if disabled
7168                renderProps.isDisabled ? undefined : options.dayCellClassNames, didMount: options.dayCellDidMount, willUnmount: options.dayCellWillUnmount })));
7169        }
7170    }
7171    function hasCustomDayCellContent(options) {
7172        return Boolean(options.dayCellContent || hasCustomRenderingHandler('dayCellContent', options));
7173    }
7174    function refineRenderProps(raw) {
7175        let { date, dateEnv, dateProfile, isMonthStart } = raw;
7176        let dayMeta = getDateMeta(date, raw.todayRange, null, dateProfile);
7177        let dayNumberText = raw.showDayNumber ? (dateEnv.format(date, isMonthStart ? raw.monthStartFormat : DAY_NUM_FORMAT)) : '';
7178        return Object.assign(Object.assign(Object.assign({ date: dateEnv.toDate(date), view: raw.viewApi }, dayMeta), { isMonthStart,
7179            dayNumberText }), raw.extraRenderProps);
7180    }
7181
7182    class BgEvent extends BaseComponent {
7183        render() {
7184            let { props } = this;
7185            let { seg } = props;
7186            return (y(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 }));
7187        }
7188    }
7189    function renderInnerContent$3(props) {
7190        let { title } = props.event;
7191        return title && (y("div", { className: "fc-event-title" }, props.event.title));
7192    }
7193    function renderFill(fillType) {
7194        return (y("div", { className: `fc-${fillType}` }));
7195    }
7196
7197    const WeekNumberContainer = (props) => (y(ViewContextType.Consumer, null, (context) => {
7198        let { dateEnv, options } = context;
7199        let { date } = props;
7200        let format = options.weekNumberFormat || props.defaultFormat;
7201        let num = dateEnv.computeWeekNumber(date); // TODO: somehow use for formatting as well?
7202        let text = dateEnv.format(date, format);
7203        let renderProps = { num, text, date };
7204        return (y(ContentContainer // why isn't WeekNumberContentArg being auto-detected?
7205        , Object.assign({}, props /* includes children */, { renderProps: renderProps, generatorName: "weekNumberContent", customGenerator: options.weekNumberContent, defaultGenerator: renderInner, classNameGenerator: options.weekNumberClassNames, didMount: options.weekNumberDidMount, willUnmount: options.weekNumberWillUnmount })));
7206    }));
7207    function renderInner(innerProps) {
7208        return innerProps.text;
7209    }
7210
7211    const PADDING_FROM_VIEWPORT = 10;
7212    class Popover extends BaseComponent {
7213        constructor() {
7214            super(...arguments);
7215            this.state = {
7216                titleId: getUniqueDomId(),
7217            };
7218            this.handleRootEl = (el) => {
7219                this.rootEl = el;
7220                if (this.props.elRef) {
7221                    setRef(this.props.elRef, el);
7222                }
7223            };
7224            // Triggered when the user clicks *anywhere* in the document, for the autoHide feature
7225            this.handleDocumentMouseDown = (ev) => {
7226                // only hide the popover if the click happened outside the popover
7227                const target = getEventTargetViaRoot(ev);
7228                if (!this.rootEl.contains(target)) {
7229                    this.handleCloseClick();
7230                }
7231            };
7232            this.handleDocumentKeyDown = (ev) => {
7233                if (ev.key === 'Escape') {
7234                    this.handleCloseClick();
7235                }
7236            };
7237            this.handleCloseClick = () => {
7238                let { onClose } = this.props;
7239                if (onClose) {
7240                    onClose();
7241                }
7242            };
7243        }
7244        render() {
7245            let { theme, options } = this.context;
7246            let { props, state } = this;
7247            let classNames = [
7248                'fc-popover',
7249                theme.getClass('popover'),
7250            ].concat(props.extraClassNames || []);
7251            return j(y("div", Object.assign({}, props.extraAttrs, { id: props.id, className: classNames.join(' '), "aria-labelledby": state.titleId, ref: this.handleRootEl }),
7252                y("div", { className: 'fc-popover-header ' + theme.getClass('popoverHeader') },
7253                    y("span", { className: "fc-popover-title", id: state.titleId }, props.title),
7254                    y("span", { className: 'fc-popover-close ' + theme.getIconClass('close'), title: options.closeHint, onClick: this.handleCloseClick })),
7255                y("div", { className: 'fc-popover-body ' + theme.getClass('popoverContent') }, props.children)), props.parentEl);
7256        }
7257        componentDidMount() {
7258            document.addEventListener('mousedown', this.handleDocumentMouseDown);
7259            document.addEventListener('keydown', this.handleDocumentKeyDown);
7260            this.updateSize();
7261        }
7262        componentWillUnmount() {
7263            document.removeEventListener('mousedown', this.handleDocumentMouseDown);
7264            document.removeEventListener('keydown', this.handleDocumentKeyDown);
7265        }
7266        updateSize() {
7267            let { isRtl } = this.context;
7268            let { alignmentEl, alignGridTop } = this.props;
7269            let { rootEl } = this;
7270            let alignmentRect = computeClippedClientRect(alignmentEl);
7271            if (alignmentRect) {
7272                let popoverDims = rootEl.getBoundingClientRect();
7273                // position relative to viewport
7274                let popoverTop = alignGridTop
7275                    ? elementClosest(alignmentEl, '.fc-scrollgrid').getBoundingClientRect().top
7276                    : alignmentRect.top;
7277                let popoverLeft = isRtl ? alignmentRect.right - popoverDims.width : alignmentRect.left;
7278                // constrain
7279                popoverTop = Math.max(popoverTop, PADDING_FROM_VIEWPORT);
7280                popoverLeft = Math.min(popoverLeft, document.documentElement.clientWidth - PADDING_FROM_VIEWPORT - popoverDims.width);
7281                popoverLeft = Math.max(popoverLeft, PADDING_FROM_VIEWPORT);
7282                let origin = rootEl.offsetParent.getBoundingClientRect();
7283                applyStyle(rootEl, {
7284                    top: popoverTop - origin.top,
7285                    left: popoverLeft - origin.left,
7286                });
7287            }
7288        }
7289    }
7290
7291    class MorePopover extends DateComponent {
7292        constructor() {
7293            super(...arguments);
7294            this.handleRootEl = (rootEl) => {
7295                this.rootEl = rootEl;
7296                if (rootEl) {
7297                    this.context.registerInteractiveComponent(this, {
7298                        el: rootEl,
7299                        useEventCenter: false,
7300                    });
7301                }
7302                else {
7303                    this.context.unregisterInteractiveComponent(this);
7304                }
7305            };
7306        }
7307        render() {
7308            let { options, dateEnv } = this.context;
7309            let { props } = this;
7310            let { startDate, todayRange, dateProfile } = props;
7311            let title = dateEnv.format(startDate, options.dayPopoverFormat);
7312            return (y(DayCellContainer, { elRef: this.handleRootEl, date: startDate, dateProfile: dateProfile, todayRange: todayRange }, (InnerContent, renderProps, elAttrs) => (y(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 },
7313                hasCustomDayCellContent(options) && (y(InnerContent, { elTag: "div", elClasses: ['fc-more-popover-misc'] })),
7314                props.children))));
7315        }
7316        queryHit(positionLeft, positionTop, elWidth, elHeight) {
7317            let { rootEl, props } = this;
7318            if (positionLeft >= 0 && positionLeft < elWidth &&
7319                positionTop >= 0 && positionTop < elHeight) {
7320                return {
7321                    dateProfile: props.dateProfile,
7322                    dateSpan: Object.assign({ allDay: !props.forceTimed, range: {
7323                            start: props.startDate,
7324                            end: props.endDate,
7325                        } }, props.extraDateSpan),
7326                    dayEl: rootEl,
7327                    rect: {
7328                        left: 0,
7329                        top: 0,
7330                        right: elWidth,
7331                        bottom: elHeight,
7332                    },
7333                    layer: 1, // important when comparing with hits from other components
7334                };
7335            }
7336            return null;
7337        }
7338    }
7339
7340    class MoreLinkContainer extends BaseComponent {
7341        constructor() {
7342            super(...arguments);
7343            this.state = {
7344                isPopoverOpen: false,
7345                popoverId: getUniqueDomId(),
7346            };
7347            this.handleLinkEl = (linkEl) => {
7348                this.linkEl = linkEl;
7349                if (this.props.elRef) {
7350                    setRef(this.props.elRef, linkEl);
7351                }
7352            };
7353            this.handleClick = (ev) => {
7354                let { props, context } = this;
7355                let { moreLinkClick } = context.options;
7356                let date = computeRange(props).start;
7357                function buildPublicSeg(seg) {
7358                    let { def, instance, range } = seg.eventRange;
7359                    return {
7360                        event: new EventImpl(context, def, instance),
7361                        start: context.dateEnv.toDate(range.start),
7362                        end: context.dateEnv.toDate(range.end),
7363                        isStart: seg.isStart,
7364                        isEnd: seg.isEnd,
7365                    };
7366                }
7367                if (typeof moreLinkClick === 'function') {
7368                    moreLinkClick = moreLinkClick({
7369                        date,
7370                        allDay: Boolean(props.allDayDate),
7371                        allSegs: props.allSegs.map(buildPublicSeg),
7372                        hiddenSegs: props.hiddenSegs.map(buildPublicSeg),
7373                        jsEvent: ev,
7374                        view: context.viewApi,
7375                    });
7376                }
7377                if (!moreLinkClick || moreLinkClick === 'popover') {
7378                    this.setState({ isPopoverOpen: true });
7379                }
7380                else if (typeof moreLinkClick === 'string') { // a view n
vendor: 4,546 bytes, lines 7380-7485
7380ame
7381                    context.calendarApi.zoomTo(date, moreLinkClick);
7382                }
7383            };
7384            this.handlePopoverClose = () => {
7385                this.setState({ isPopoverOpen: false });
7386            };
7387        }
7388        render() {
7389            let { props, state } = this;
7390            return (y(ViewContextType.Consumer, null, (context) => {
7391                let { viewApi, options, calendarApi } = context;
7392                let { moreLinkText } = options;
7393                let { moreCnt } = props;
7394                let range = computeRange(props);
7395                let text = typeof moreLinkText === 'function' // TODO: eventually use formatWithOrdinals
7396                    ? moreLinkText.call(calendarApi, moreCnt)
7397                    : `+${moreCnt} ${moreLinkText}`;
7398                let hint = formatWithOrdinals(options.moreLinkHint, [moreCnt], text);
7399                let renderProps = {
7400                    num: moreCnt,
7401                    shortText: `+${moreCnt}`,
7402                    text,
7403                    view: viewApi,
7404                };
7405                return (y(_, null,
7406                    Boolean(props.moreCnt) && (y(ContentContainer, { elTag: props.elTag || 'a', elRef: this.handleLinkEl, elClasses: [
7407                            ...(props.elClasses || []),
7408                            'fc-more-link',
7409                        ], elStyle: props.elStyle, 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", customGenerator: options.moreLinkContent, defaultGenerator: props.defaultGenerator || renderMoreLinkInner$1, classNameGenerator: options.moreLinkClassNames, didMount: options.moreLinkDidMount, willUnmount: options.moreLinkWillUnmount }, props.children)),
7410                    state.isPopoverOpen && (y(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 ?
7411                            props.alignmentElRef.current :
7412                            this.linkEl, alignGridTop: props.alignGridTop, forceTimed: props.forceTimed, onClose: this.handlePopoverClose }, props.popoverContent()))));
7413            }));
7414        }
7415        componentDidMount() {
7416            this.updateParentEl();
7417        }
7418        componentDidUpdate() {
7419            this.updateParentEl();
7420        }
7421        updateParentEl() {
7422            if (this.linkEl) {
7423                this.parentEl = elementClosest(this.linkEl, '.fc-view-harness');
7424            }
7425        }
7426    }
7427    function renderMoreLinkInner$1(props) {
7428        return props.text;
7429    }
7430    function computeRange(props) {
7431        if (props.allDayDate) {
7432            return {
7433                start: props.allDayDate,
7434                end: addDays(props.allDayDate, 1),
7435            };
7436        }
7437        let { hiddenSegs } = props;
7438        return {
7439            start: computeEarliestSegStart(hiddenSegs),
7440            end: computeLatestSegEnd(hiddenSegs),
7441        };
7442    }
7443    function computeEarliestSegStart(segs) {
7444        return segs.reduce(pickEarliestStart).eventRange.range.start;
7445    }
7446    function pickEarliestStart(seg0, seg1) {
7447        return seg0.eventRange.range.start < seg1.eventRange.range.start ? seg0 : seg1;
7448    }
7449    function computeLatestSegEnd(segs) {
7450        return segs.reduce(pickLatestEnd).eventRange.range.end;
7451    }
7452    function pickLatestEnd(seg0, seg1) {
7453        return seg0.eventRange.range.end > seg1.eventRange.range.end ? seg0 : seg1;
7454    }
7455
7456    class Store {
7457        constructor() {
7458            this.handlers = [];
7459        }
7460        set(value) {
7461            this.currentValue = value;
7462            for (let handler of this.handlers) {
7463                handler(value);
7464            }
7465        }
7466        subscribe(handler) {
7467            this.handlers.push(handler);
7468            if (this.currentValue !== undefined) {
7469                handler(this.currentValue);
7470            }
7471        }
7472    }
7473
7474    /*
7475    Subscribers will get a LIST of CustomRenderings
7476    */
7477    class CustomRenderingStore extends Store {
7478        constructor() {
7479            super(...arguments);
7480            this.map = new Map();
7481        }
7482        // for consistent order
7483        handle(customRendering) {
7484            const { map } = this;
7485            let updated = false;
7486            if (customRendering.isActive) {
7487                map.set(customRendering.id, customRendering);
7488                updated = true;
7489            }
7490            else if (map.has(customRendering.id)) {
7491                map.delete(customRendering.id);
7492                updated = true;
7493            }
7494            if (updated) {
7495                this.set(map);
7496            }
7497        }
7498    }
7499
7500    var internal = {
7501        __proto__: null,
7502        BASE_OPTION_DEFAULTS: BASE_OPTION_DEFAULTS,
7503        BaseComponent: BaseComponent,
7504        BgEvent: BgEvent,
7505        CalendarImpl: CalendarImpl,
7506        CalendarRoot: CalendarRoot,
7507        ContentContainer: ContentContainer,
7508        CustomRenderingStore: CustomRenderingStore,
7509        DateComponent: DateComponent,
7510        DateEnv: DateEnv,
7511        DateProfileGenerator: DateProfileGenerator,
7512        DayCellContainer: DayCellContainer,
7513        DayHeader: DayHeader,
7514        DaySeriesModel: DaySeriesModel,
7515        DayTableModel: DayTableModel,
7516        DelayedRunner: DelayedRunner,
7517        ElementDragging: ElementDragging,
7518        ElementScrollController: ElementScrollController,
7519        Emitter: Emitter,
7520        EventContainer: EventContainer,
7521        EventImpl: EventImpl,
7522        Interaction: Interaction,
7523        MoreLinkContainer: MoreLinkContainer,
7524        NamedTimeZoneImpl: NamedTimeZoneImpl,
7525        NowIndicatorContainer: NowIndicatorContainer,
7526        NowTimer: NowTimer,
7527        PositionCache: PositionCache,
7528        RefMap: RefMap,
7529        ScrollController: ScrollController,
7530        ScrollResponder: ScrollResponder,
7531        Scroller: Scroller,
7532        SegHierarchy: SegHierarchy,
7533        SimpleScrollGrid: SimpleScrollGrid,
7534        Slicer: Slicer,
7535        Splitter: Splitter,
7536        StandardEvent: StandardEvent,
7537        TableDateCell: TableDateCell,
7538        TableDowCell: TableDowCell,
7539        Theme: Theme,
7540        ViewContainer: ViewContainer,
7541        ViewContextType: ViewContextType,
7542        WeekNumberContainer: WeekNumberContainer,
7543        WindowScrollController: WindowScrollController,
7544        addDays: addDays,
7545        addDurations: addDurations,
7546        addMs: addMs,
7547        addWeeks: addWeeks,
7548        allowContextMenu: allowContextMenu,
7549        allowSelection: allowSelection,
7550        applyMutationToEventStore: applyMutationToEventStore,
7551        applyStyle: applyStyle,
7552        asCleanDays: asCleanDays,
7553        asRoughMinutes: asRoughMinutes,
7554        asRoughMs: asRoughMs,
7555        asRoughSeconds: asRoughSeconds,
7556        binarySearch: binarySearch,
7557        buildElAttrs: buildElAttrs,
7558        buildEntryKey: buildEntryKey,
7559        buildEventApis: buildEventApis,
7560        buildEventRangeKey: buildEventRangeKey,
7561        buildIsoString: buildIsoString,
7562        buildNavLinkAttrs: buildNavLinkAttrs,
7563        buildSegTimeText: buildSegTimeText,
7564        collectFromHash: collectFromHash,
7565        combineEventUis: combineEventUis,
7566        compareByFieldSpecs: compareByFieldSpecs,
7567        compareNumbers: compareNumbers,
7568        compareObjs: compareObjs,
7569        computeEarliestSegStart: computeEarliestSegStart,
7570        computeEdges: computeEdges,
7571        computeFallbackHeaderFormat: computeFallbackHeaderFormat,
7572        computeInnerRect: computeInnerRect,
7573        computeRect: computeRect,
7574        computeShrinkWidth: computeShrinkWidth,
7575        computeVisibleDayRange: computeVisibleDayRange,
7576        config: config,
7577        constrainPoint: constrainPoint,
7578        createDuration: createDuration,
7579        createEmptyEventStore: createEmptyEventStore,
7580        createEventInstance: createEventInstance,
7581        createEventUi: createEventUi,
7582        createFormatter: createFormatter,
7583        diffDates: diffDates,
7584        diffDayAndTime: diffDayAndTime,
7585        diffDays: diffDays,
7586        diffPoints: diffPoints,
7587        diffWeeks: diffWeeks,
7588        diffWholeDays: diffWholeDays,
7589        diffWholeWeeks: diffWholeWeeks,
7590        disableCursor: disableCursor,
7591        elementClosest: elementClosest,
7592        elementMatches: elementMatches,
7593        enableCursor: enableCursor,
7594        eventTupleToStore: eventTupleToStore,
7595        filterHash: filterHash,
7596        findDirectChildren: findDirectChildren,
7597        findElements: findElements,
7598        flexibleCompare: flexibleCompare,
7599        formatDayString: formatDayString,
7600        formatIsoMonthStr: formatIsoMonthStr,
7601        formatIsoTimeString: formatIsoTimeString,
7602        getAllowYScrolling: getAllowYScrolling,
7603        getCanVGrowWithinCell: getCanVGrowWithinCell,
7604        getClippingParents: getClippingParents,
7605        getDateMeta: getDateMeta,
7606        getDayClassNames: getDayClassNames,
7607        getDefaultEventEnd: getDefaultEventEnd,
7608        getElSeg: getElSeg,
7609        getEntrySpanEnd: getEntrySpanEnd,
7610        getEventTargetViaRoot: getEventTargetViaRoot,
7611        getIsRtlScrollbarOnLeft: getIsRtlScrollbarOnLeft,
7612        getRectCenter: getRectCenter,
7613        getRelevantEvents: getRelevantEvents,
7614        getScrollGridClassNames: getScrollGridClassNames,
7615        getScrollbarWidths: getScrollbarWidths,
7616        getSectionClassNames: getSectionClassNames,
7617        getSectionHasLiquidHeight: getSectionHasLiquidHeight,
7618        getSegAnchorAttrs: getSegAnchorAttrs,
7619        getSegMeta: getSegMeta,
7620        getSlotClassNames: getSlotClassNames,
7621        getStickyFooterScrollbar: getStickyFooterScrollbar,
7622        getStickyHeaderDates: getStickyHeaderDates,
7623        getUniqueDomId: getUniqueDomId,
7624        greatestDurationDenominator: greatestDurationDenominator,
7625        groupIntersectingEntries: groupIntersectingEntries,
7626        guid: guid,
7627        hasBgRendering: hasBgRendering,
7628        hasCustomDayCellContent: hasCustomDayCellContent,
7629        hasShrinkWidth: hasShrinkWidth,
7630        identity: identity,
7631        injectStyles: injectStyles,
7632        interactionSettingsStore: interactionSettingsStore,
7633        interactionSettingsToStore: interactionSettingsToStore,
7634        intersectRanges: intersectRanges,
vendor: 7,523 bytes, lines 7635-7829
7635        intersectRects: intersectRects,
7636        intersectSpans: intersectSpans,
7637        isArraysEqual: isArraysEqual,
7638        isColPropsEqual: isColPropsEqual,
7639        isDateSelectionValid: isDateSelectionValid,
7640        isDateSpansEqual: isDateSpansEqual,
7641        isInt: isInt,
7642        isInteractionValid: isInteractionValid,
7643        isMultiDayRange: isMultiDayRange,
7644        isPropsEqual: isPropsEqual,
7645        isPropsValid: isPropsValid,
7646        isValidDate: isValidDate,
7647        mapHash: mapHash,
7648        memoize: memoize,
7649        memoizeArraylike: memoizeArraylike,
7650        memoizeHashlike: memoizeHashlike,
7651        memoizeObjArg: memoizeObjArg,
7652        mergeEventStores: mergeEventStores,
7653        multiplyDuration: multiplyDuration,
7654        padStart: padStart,
7655        parseBusinessHours: parseBusinessHours,
7656        parseClassNames: parseClassNames,
7657        parseDragMeta: parseDragMeta,
7658        parseEventDef: parseEventDef,
7659        parseFieldSpecs: parseFieldSpecs,
7660        parseMarker: parse,
7661        pointInsideRect: pointInsideRect,
7662        preventContextMenu: preventContextMenu,
7663        preventDefault: preventDefault,
7664        preventSelection: preventSelection,
7665        rangeContainsMarker: rangeContainsMarker,
7666        rangeContainsRange: rangeContainsRange,
7667        rangesEqual: rangesEqual,
7668        rangesIntersect: rangesIntersect,
7669        refineEventDef: refineEventDef,
7670        refineProps: refineProps,
7671        removeElement: removeElement,
7672        removeExact: removeExact,
7673        renderChunkContent: renderChunkContent,
7674        renderFill: renderFill,
7675        renderMicroColGroup: renderMicroColGroup,
7676        renderScrollShim: renderScrollShim,
7677        requestJson: requestJson,
7678        sanitizeShrinkWidth: sanitizeShrinkWidth,
7679        setRef: setRef,
7680        sliceEventStore: sliceEventStore,
7681        sortEventSegs: sortEventSegs,
7682        startOfDay: startOfDay,
7683        translateRect: translateRect,
7684        triggerDateSelect: triggerDateSelect,
7685        unpromisify: unpromisify,
7686        whenTransitionDone: whenTransitionDone,
7687        wholeDivideDurations: wholeDivideDurations
7688    };
7689
7690    var preact = {
7691        __proto__: null,
7692        createPortal: j,
7693        createContext: createContext,
7694        flushSync: flushSync,
7695        Component: x$1,
7696        Fragment: _,
7697        cloneElement: F$1,
7698        createElement: y,
7699        createRef: d,
7700        h: y,
7701        hydrate: E,
7702        get isValidElement () { return i$1; },
7703        get options () { return l$1; },
7704        render: D$1,
7705        toChildArray: j$2
7706    };
7707
7708    const globalLocales = [];
7709
7710    const MINIMAL_RAW_EN_LOCALE = {
7711        code: 'en',
7712        week: {
7713            dow: 0,
7714            doy: 4, // 4 days need to be within the year to be considered the first week
7715        },
7716        direction: 'ltr',
7717        buttonText: {
7718            prev: 'prev',
7719            next: 'next',
7720            prevYear: 'prev year',
7721            nextYear: 'next year',
7722            year: 'year',
7723            today: 'today',
7724            month: 'month',
7725            week: 'week',
7726            day: 'day',
7727            list: 'list',
7728        },
7729        weekText: 'W',
7730        weekTextLong: 'Week',
7731        closeHint: 'Close',
7732        timeHint: 'Time',
7733        eventHint: 'Event',
7734        allDayText: 'all-day',
7735        moreLinkText: 'more',
7736        noEventsText: 'No events to display',
7737    };
7738    const RAW_EN_LOCALE = Object.assign(Object.assign({}, MINIMAL_RAW_EN_LOCALE), { 
7739        // Includes things we don't want other locales to inherit,
7740        // things that derive from other translatable strings.
7741        buttonHints: {
7742            prev: 'Previous $0',
7743            next: 'Next $0',
7744            today(buttonText, unit) {
7745                return (unit === 'day')
7746                    ? 'Today'
7747                    : `This ${buttonText}`;
7748            },
7749        }, viewHint: '$0 view', navLinkHint: 'Go to $0', moreLinkHint(eventCnt) {
7750            return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;
7751        } });
7752    function organizeRawLocales(explicitRawLocales) {
7753        let defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en';
7754        let allRawLocales = globalLocales.concat(explicitRawLocales);
7755        let rawLocaleMap = {
7756            en: RAW_EN_LOCALE,
7757        };
7758        for (let rawLocale of allRawLocales) {
7759            rawLocaleMap[rawLocale.code] = rawLocale;
7760        }
7761        return {
7762            map: rawLocaleMap,
7763            defaultCode,
7764        };
7765    }
7766    function buildLocale(inputSingular, available) {
7767        if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) {
7768            return parseLocale(inputSingular.code, [inputSingular.code], inputSingular);
7769        }
7770        return queryLocale(inputSingular, available);
7771    }
7772    function queryLocale(codeArg, available) {
7773        let codes = [].concat(codeArg || []); // will convert to array
7774        let raw = queryRawLocale(codes, available) || RAW_EN_LOCALE;
7775        return parseLocale(codeArg, codes, raw);
7776    }
7777    function queryRawLocale(codes, available) {
7778        for (let i = 0; i < codes.length; i += 1) {
7779            let parts = codes[i].toLocaleLowerCase().split('-');
7780            for (let j = parts.length; j > 0; j -= 1) {
7781                let simpleId = parts.slice(0, j).join('-');
7782                if (available[simpleId]) {
7783                    return available[simpleId];
7784                }
7785            }
7786        }
7787        return null;
7788    }
7789    function parseLocale(codeArg, codes, raw) {
7790        let merged = mergeProps([MINIMAL_RAW_EN_LOCALE, raw], ['buttonText']);
7791        delete merged.code; // don't want this part of the options
7792        let { week } = merged;
7793        delete merged.week;
7794        return {
7795            codeArg,
7796            codes,
7797            week,
7798            simpleNumberFormat: new Intl.NumberFormat(codeArg),
7799            options: merged,
7800        };
7801    }
7802
7803    // TODO: easier way to add new hooks? need to update a million things
7804    function createPlugin(input) {
7805        return {
7806            id: guid(),
7807            name: input.name,
7808            premiumReleaseDate: input.premiumReleaseDate ? new Date(input.premiumReleaseDate) : undefined,
7809            deps: input.deps || [],
7810            reducers: input.reducers || [],
7811            isLoadingFuncs: input.isLoadingFuncs || [],
7812            contextInit: [].concat(input.contextInit || []),
7813            eventRefiners: input.eventRefiners || {},
7814            eventDefMemberAdders: input.eventDefMemberAdders || [],
7815            eventSourceRefiners: input.eventSourceRefiners || {},
7816            isDraggableTransformers: input.isDraggableTransformers || [],
7817            eventDragMutationMassagers: input.eventDragMutationMassagers || [],
7818            eventDefMutationAppliers: input.eventDefMutationAppliers || [],
7819            dateSelectionTransformers: input.dateSelectionTransformers || [],
7820            datePointTransforms: input.datePointTransforms || [],
7821            dateSpanTransforms: input.dateSpanTransforms || [],
7822            views: input.views || {},
7823            viewPropsTransformers: input.viewPropsTransformers || [],
7824            isPropsValid: input.isPropsValid || null,
7825            externalDefTransforms: input.externalDefTransforms || [],
7826            viewContainerAppends: input.viewContainerAppends || [],
7827            eventDropTransformers: input.eventDropTransformers || [],
7828            componentInteractions: input.componentInteractions || [],
7829            calendarInteractions: input.calendarInteractions || [],
vendor: 22,582 bytes, lines 7830-8323
7830            themeClasses: input.themeClasses || {},
7831            eventSourceDefs: input.eventSourceDefs || [],
7832            cmdFormatter: input.cmdFormatter,
7833            recurringTypes: input.recurringTypes || [],
7834            namedTimeZonedImpl: input.namedTimeZonedImpl,
7835            initialView: input.initialView || '',
7836            elementDraggingImpl: input.elementDraggingImpl,
7837            optionChangeHandlers: input.optionChangeHandlers || {},
7838            scrollGridImpl: input.scrollGridImpl || null,
7839            listenerRefiners: input.listenerRefiners || {},
7840            optionRefiners: input.optionRefiners || {},
7841            propSetHandlers: input.propSetHandlers || {},
7842        };
7843    }
7844    function buildPluginHooks(pluginDefs, globalDefs) {
7845        let currentPluginIds = {};
7846        let hooks = {
7847            premiumReleaseDate: undefined,
7848            reducers: [],
7849            isLoadingFuncs: [],
7850            contextInit: [],
7851            eventRefiners: {},
7852            eventDefMemberAdders: [],
7853            eventSourceRefiners: {},
7854            isDraggableTransformers: [],
7855            eventDragMutationMassagers: [],
7856            eventDefMutationAppliers: [],
7857            dateSelectionTransformers: [],
7858            datePointTransforms: [],
7859            dateSpanTransforms: [],
7860            views: {},
7861            viewPropsTransformers: [],
7862            isPropsValid: null,
7863            externalDefTransforms: [],
7864            viewContainerAppends: [],
7865            eventDropTransformers: [],
7866            componentInteractions: [],
7867            calendarInteractions: [],
7868            themeClasses: {},
7869            eventSourceDefs: [],
7870            cmdFormatter: null,
7871            recurringTypes: [],
7872            namedTimeZonedImpl: null,
7873            initialView: '',
7874            elementDraggingImpl: null,
7875            optionChangeHandlers: {},
7876            scrollGridImpl: null,
7877            listenerRefiners: {},
7878            optionRefiners: {},
7879            propSetHandlers: {},
7880        };
7881        function addDefs(defs) {
7882            for (let def of defs) {
7883                const pluginName = def.name;
7884                const currentId = currentPluginIds[pluginName];
7885                if (currentId === undefined) {
7886                    currentPluginIds[pluginName] = def.id;
7887                    addDefs(def.deps);
7888                    hooks = combineHooks(hooks, def);
7889                }
7890                else if (currentId !== def.id) {
7891                    // different ID than the one already added
7892                    console.warn(`Duplicate plugin '${pluginName}'`);
7893                }
7894            }
7895        }
7896        if (pluginDefs) {
7897            addDefs(pluginDefs);
7898        }
7899        addDefs(globalDefs);
7900        return hooks;
7901    }
7902    function buildBuildPluginHooks() {
7903        let currentOverrideDefs = [];
7904        let currentGlobalDefs = [];
7905        let currentHooks;
7906        return (overrideDefs, globalDefs) => {
7907            if (!currentHooks || !isArraysEqual(overrideDefs, currentOverrideDefs) || !isArraysEqual(globalDefs, currentGlobalDefs)) {
7908                currentHooks = buildPluginHooks(overrideDefs, globalDefs);
7909            }
7910            currentOverrideDefs = overrideDefs;
7911            currentGlobalDefs = globalDefs;
7912            return currentHooks;
7913        };
7914    }
7915    function combineHooks(hooks0, hooks1) {
7916        return {
7917            premiumReleaseDate: compareOptionalDates(hooks0.premiumReleaseDate, hooks1.premiumReleaseDate),
7918            reducers: hooks0.reducers.concat(hooks1.reducers),
7919            isLoadingFuncs: hooks0.isLoadingFuncs.concat(hooks1.isLoadingFuncs),
7920            contextInit: hooks0.contextInit.concat(hooks1.contextInit),
7921            eventRefiners: Object.assign(Object.assign({}, hooks0.eventRefiners), hooks1.eventRefiners),
7922            eventDefMemberAdders: hooks0.eventDefMemberAdders.concat(hooks1.eventDefMemberAdders),
7923            eventSourceRefiners: Object.assign(Object.assign({}, hooks0.eventSourceRefiners), hooks1.eventSourceRefiners),
7924            isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers),
7925            eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers),
7926            eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers),
7927            dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers),
7928            datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms),
7929            dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms),
7930            views: Object.assign(Object.assign({}, hooks0.views), hooks1.views),
7931            viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers),
7932            isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid,
7933            externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms),
7934            viewContainerAppends: hooks0.viewContainerAppends.concat(hooks1.viewContainerAppends),
7935            eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers),
7936            calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions),
7937            componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions),
7938            themeClasses: Object.assign(Object.assign({}, hooks0.themeClasses), hooks1.themeClasses),
7939            eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs),
7940            cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter,
7941            recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes),
7942            namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl,
7943            initialView: hooks0.initialView || hooks1.initialView,
7944            elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl,
7945            optionChangeHandlers: Object.assign(Object.assign({}, hooks0.optionChangeHandlers), hooks1.optionChangeHandlers),
7946            scrollGridImpl: hooks1.scrollGridImpl || hooks0.scrollGridImpl,
7947            listenerRefiners: Object.assign(Object.assign({}, hooks0.listenerRefiners), hooks1.listenerRefiners),
7948            optionRefiners: Object.assign(Object.assign({}, hooks0.optionRefiners), hooks1.optionRefiners),
7949            propSetHandlers: Object.assign(Object.assign({}, hooks0.propSetHandlers), hooks1.propSetHandlers),
7950        };
7951    }
7952    function compareOptionalDates(date0, date1) {
7953        if (date0 === undefined) {
7954            return date1;
7955        }
7956        if (date1 === undefined) {
7957            return date0;
7958        }
7959        return new Date(Math.max(date0.valueOf(), date1.valueOf()));
7960    }
7961
7962    class StandardTheme extends Theme {
7963    }
7964    StandardTheme.prototype.classes = {
7965        root: 'fc-theme-standard',
7966        tableCellShaded: 'fc-cell-shaded',
7967        buttonGroup: 'fc-button-group',
7968        button: 'fc-button fc-button-primary',
7969        buttonActive: 'fc-button-active',
7970    };
7971    StandardTheme.prototype.baseIconClass = 'fc-icon';
7972    StandardTheme.prototype.iconClasses = {
7973        close: 'fc-icon-x',
7974        prev: 'fc-icon-chevron-left',
7975        next: 'fc-icon-chevron-right',
7976        prevYear: 'fc-icon-chevrons-left',
7977        nextYear: 'fc-icon-chevrons-right',
7978    };
7979    StandardTheme.prototype.rtlIconClasses = {
7980        prev: 'fc-icon-chevron-right',
7981        next: 'fc-icon-chevron-left',
7982        prevYear: 'fc-icon-chevrons-right',
7983        nextYear: 'fc-icon-chevrons-left',
7984    };
7985    StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; // TODO: make TS-friendly
7986    StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon';
7987    StandardTheme.prototype.iconOverridePrefix = 'fc-icon-';
7988
7989    function compileViewDefs(defaultConfigs, overrideConfigs) {
7990        let hash = {};
7991        let viewType;
7992        for (viewType in defaultConfigs) {
7993            ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
7994        }
7995        for (viewType in overrideConfigs) {
7996            ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
7997        }
7998        return hash;
7999    }
8000    function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
8001        if (hash[viewType]) {
8002            return hash[viewType];
8003        }
8004        let viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs);
8005        if (viewDef) {
8006            hash[viewType] = viewDef;
8007        }
8008        return viewDef;
8009    }
8010    function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
8011        let defaultConfig = defaultConfigs[viewType];
8012        let overrideConfig = overrideConfigs[viewType];
8013        let queryProp = (name) => ((defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] :
8014            ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null));
8015        let theComponent = queryProp('component');
8016        let superType = queryProp('superType');
8017        let superDef = null;
8018        if (superType) {
8019            if (superType === viewType) {
8020                throw new Error('Can\'t have a custom view type that references itself');
8021            }
8022            superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs);
8023        }
8024        if (!theComponent && superDef) {
8025            theComponent = superDef.component;
8026        }
8027        if (!theComponent) {
8028            return null; // don't throw a warning, might be settings for a single-unit view
8029        }
8030        return {
8031            type: viewType,
8032            component: theComponent,
8033            defaults: Object.assign(Object.assign({}, (superDef ? superDef.defaults : {})), (defaultConfig ? defaultConfig.rawOptions : {})),
8034            overrides: Object.assign(Object.assign({}, (superDef ? superDef.overrides : {})), (overrideConfig ? overrideConfig.rawOptions : {})),
8035        };
8036    }
8037
8038    function parseViewConfigs(inputs) {
8039        return mapHash(inputs, parseViewConfig);
8040    }
8041    function parseViewConfig(input) {
8042        let rawOptions = typeof input === 'function' ?
8043            { component: input } :
8044            input;
8045        let { component } = rawOptions;
8046        if (rawOptions.content) {
8047            // TODO: remove content/classNames/didMount/etc from options?
8048            component = createViewHookComponent(rawOptions);
8049        }
8050        else if (component && !(component.prototype instanceof BaseComponent)) {
8051            // WHY?: people were using `component` property for `content`
8052            // TODO: converge on one setting name
8053            component = createViewHookComponent(Object.assign(Object.assign({}, rawOptions), { content: component }));
8054        }
8055        return {
8056            superType: rawOptions.type,
8057            component: component,
8058            rawOptions, // includes type and component too :(
8059        };
8060    }
8061    function createViewHookComponent(options) {
8062        return (viewProps) => (y(ViewContextType.Consumer, null, (context) => (y(ContentContainer, { elTag: "div", elClasses: buildViewClassNames(context.viewSpec), renderProps: Object.assign(Object.assign({}, viewProps), { nextDayThreshold: context.options.nextDayThreshold }), generatorName: undefined, customGenerator: options.content, classNameGenerator: options.classNames, didMount: options.didMount, willUnmount: options.willUnmount }))));
8063    }
8064
8065    function buildViewSpecs(defaultInputs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
8066        let defaultConfigs = parseViewConfigs(defaultInputs);
8067        let overrideConfigs = parseViewConfigs(optionOverrides.views);
8068        let viewDefs = compileViewDefs(defaultConfigs, overrideConfigs);
8069        return mapHash(viewDefs, (viewDef) => buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults));
8070    }
8071    function buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
8072        let durationInput = viewDef.overrides.duration ||
8073            viewDef.defaults.duration ||
8074            dynamicOptionOverrides.duration ||
8075            optionOverrides.duration;
8076        let duration = null;
8077        let durationUnit = '';
8078        let singleUnit = '';
8079        let singleUnitOverrides = {};
8080        if (durationInput) {
8081            duration = createDurationCached(durationInput);
8082            if (duration) { // valid?
8083                let denom = greatestDurationDenominator(duration);
8084                durationUnit = denom.unit;
8085                if (denom.value === 1) {
8086                    singleUnit = durationUnit;
8087                    singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].rawOptions : {};
8088                }
8089            }
8090        }
8091        let queryButtonText = (optionsSubset) => {
8092            let buttonTextMap = optionsSubset.buttonText || {};
8093            let buttonTextKey = viewDef.defaults.buttonTextKey;
8094            if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) {
8095                return buttonTextMap[buttonTextKey];
8096            }
8097            if (buttonTextMap[viewDef.type] != null) {
8098                return buttonTextMap[viewDef.type];
8099            }
8100            if (buttonTextMap[singleUnit] != null) {
8101                return buttonTextMap[singleUnit];
8102            }
8103            return null;
8104        };
8105        let queryButtonTitle = (optionsSubset) => {
8106            let buttonHints = optionsSubset.buttonHints || {};
8107            let buttonKey = viewDef.defaults.buttonTextKey; // use same key as text
8108            if (buttonKey != null && buttonHints[buttonKey] != null) {
8109                return buttonHints[buttonKey];
8110            }
8111            if (buttonHints[viewDef.type] != null) {
8112                return buttonHints[viewDef.type];
8113            }
8114            if (buttonHints[singleUnit] != null) {
8115                return buttonHints[singleUnit];
8116            }
8117            return null;
8118        };
8119        return {
8120            type: viewDef.type,
8121            component: viewDef.component,
8122            duration,
8123            durationUnit,
8124            singleUnit,
8125            optionDefaults: viewDef.defaults,
8126            optionOverrides: Object.assign(Object.assign({}, singleUnitOverrides), viewDef.overrides),
8127            buttonTextOverride: queryButtonText(dynamicOptionOverrides) ||
8128                queryButtonText(optionOverrides) || // constructor-specified buttonText lookup hash takes precedence
8129                viewDef.overrides.buttonText,
8130            buttonTextDefault: queryButtonText(localeDefaults) ||
8131                viewDef.defaults.buttonText ||
8132                queryButtonText(BASE_OPTION_DEFAULTS) ||
8133                viewDef.type,
8134            // not DRY
8135            buttonTitleOverride: queryButtonTitle(dynamicOptionOverrides) ||
8136                queryButtonTitle(optionOverrides) ||
8137                viewDef.overrides.buttonHint,
8138            buttonTitleDefault: queryButtonTitle(localeDefaults) ||
8139                viewDef.defaults.buttonHint ||
8140                queryButtonTitle(BASE_OPTION_DEFAULTS),
8141            // will eventually fall back to buttonText
8142        };
8143    }
8144    // hack to get memoization working
8145    let durationInputMap = {};
8146    function createDurationCached(durationInput) {
8147        let json = JSON.stringify(durationInput);
8148        let res = durationInputMap[json];
8149        if (res === undefined) {
8150            res = createDuration(durationInput);
8151            durationInputMap[json] = res;
8152        }
8153        return res;
8154    }
8155
8156    function reduceViewType(viewType, action) {
8157        switch (action.type) {
8158            case 'CHANGE_VIEW_TYPE':
8159                viewType = action.viewType;
8160        }
8161        return viewType;
8162    }
8163
8164    function reduceCurrentDate(currentDate, action) {
8165        switch (action.type) {
8166            case 'CHANGE_DATE':
8167                return action.dateMarker;
8168            default:
8169                return currentDate;
8170        }
8171    }
8172    // should be initialized once and stay constant
8173    // this will change too
8174    function getInitialDate(options, dateEnv, nowManager) {
8175        let initialDateInput = options.initialDate;
8176        // compute the initial ambig-timezone date
8177        if (initialDateInput != null) {
8178            return dateEnv.createMarker(initialDateInput);
8179        }
8180        return nowManager.getDateMarker();
8181    }
8182
8183    function reduceDynamicOptionOverrides(dynamicOptionOverrides, action) {
8184        switch (action.type) {
8185            case 'SET_OPTION':
8186                return Object.assign(Object.assign({}, dynamicOptionOverrides), { [action.optionName]: action.rawOptionValue });
8187            default:
8188                return dynamicOptionOverrides;
8189        }
8190    }
8191
8192    function reduceDateProfile(currentDateProfile, action, currentDate, dateProfileGenerator) {
8193        let dp;
8194        switch (action.type) {
8195            case 'CHANGE_VIEW_TYPE':
8196                return dateProfileGenerator.build(action.dateMarker || currentDate);
8197            case 'CHANGE_DATE':
8198                return dateProfileGenerator.build(action.dateMarker);
8199            case 'PREV':
8200                dp = dateProfileGenerator.buildPrev(currentDateProfile, currentDate);
8201                if (dp.isValid) {
8202                    return dp;
8203                }
8204                break;
8205            case 'NEXT':
8206                dp = dateProfileGenerator.buildNext(currentDateProfile, currentDate);
8207                if (dp.isValid) {
8208                    return dp;
8209                }
8210                break;
8211        }
8212        return currentDateProfile;
8213    }
8214
8215    function initEventSources(calendarOptions, dateProfile, context) {
8216        let activeRange = dateProfile ? dateProfile.activeRange : null;
8217        return addSources({}, parseInitialSources(calendarOptions, context), activeRange, context);
8218    }
8219    function reduceEventSources(eventSources, action, dateProfile, context) {
8220        let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
8221        switch (action.type) {
8222            case 'ADD_EVENT_SOURCES': // already parsed
8223                return addSources(eventSources, action.sources, activeRange, context);
8224            case 'REMOVE_EVENT_SOURCE':
8225                return removeSource(eventSources, action.sourceId);
8226            case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
8227            case 'NEXT':
8228            case 'CHANGE_DATE':
8229            case 'CHANGE_VIEW_TYPE':
8230                if (dateProfile) {
8231                    return fetchDirtySources(eventSources, activeRange, context);
8232                }
8233                return eventSources;
8234            case 'FETCH_EVENT_SOURCES':
8235                return fetchSourcesByIds(eventSources, action.sourceIds ? // why no type?
8236                    arrayToHash(action.sourceIds) :
8237                    excludeStaticSources(eventSources, context), activeRange, action.isRefetch || false, context);
8238            case 'RECEIVE_EVENTS':
8239            case 'RECEIVE_EVENT_ERROR':
8240                return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange);
8241            case 'REMOVE_ALL_EVENT_SOURCES':
8242                return {};
8243            default:
8244                return eventSources;
8245        }
8246    }
8247    function reduceEventSourcesNewTimeZone(eventSources, dateProfile, context) {
8248        let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
8249        return fetchSourcesByIds(eventSources, excludeStaticSources(eventSources, context), activeRange, true, context);
8250    }
8251    function computeEventSourcesLoading(eventSources) {
8252        for (let sourceId in eventSources) {
8253            if (eventSources[sourceId].isFetching) {
8254                return true;
8255            }
8256        }
8257        return false;
8258    }
8259    function addSources(eventSourceHash, sources, fetchRange, context) {
8260        let hash = {};
8261        for (let source of sources) {
8262            hash[source.sourceId] = source;
8263        }
8264        if (fetchRange) {
8265            hash = fetchDirtySources(hash, fetchRange, context);
8266        }
8267        return Object.assign(Object.assign({}, eventSourceHash), hash);
8268    }
8269    function removeSource(eventSourceHash, sourceId) {
8270        return filterHash(eventSourceHash, (eventSource) => eventSource.sourceId !== sourceId);
8271    }
8272    function fetchDirtySources(sourceHash, fetchRange, context) {
8273        return fetchSourcesByIds(sourceHash, filterHash(sourceHash, (eventSource) => isSourceDirty(eventSource, fetchRange, context)), fetchRange, false, context);
8274    }
8275    function isSourceDirty(eventSource, fetchRange, context) {
8276        if (!doesSourceNeedRange(eventSource, context)) {
8277            return !eventSource.latestFetchId;
8278        }
8279        return !context.options.lazyFetching ||
8280            !eventSource.fetchRange ||
8281            eventSource.isFetching || // always cancel outdated in-progress fetches
8282            fetchRange.start < eventSource.fetchRange.start ||
8283            fetchRange.end > eventSource.fetchRange.end;
8284    }
8285    function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, isRefetch, context) {
8286        let nextSources = {};
8287        for (let sourceId in prevSources) {
8288            let source = prevSources[sourceId];
8289            if (sourceIdHash[sourceId]) {
8290                nextSources[sourceId] = fetchSource(source, fetchRange, isRefetch, context);
8291            }
8292            else {
8293                nextSources[sourceId] = source;
8294            }
8295        }
8296        return nextSources;
8297    }
8298    function fetchSource(eventSource, fetchRange, isRefetch, context) {
8299        let { options, calendarApi } = context;
8300        let sourceDef = context.pluginHooks.eventSourceDefs[eventSource.sourceDefId];
8301        let fetchId = guid();
8302        sourceDef.fetch({
8303            eventSource,
8304            range: fetchRange,
8305            isRefetch,
8306            context,
8307        }, (res) => {
8308            let { rawEvents } = res;
8309            if (options.eventSourceSuccess) {
8310                rawEvents = options.eventSourceSuccess.call(calendarApi, rawEvents, res.response) || rawEvents;
8311            }
8312            if (eventSource.success) {
8313                rawEvents = eventSource.success.call(calendarApi, rawEvents, res.response) || rawEvents;
8314            }
8315            context.dispatch({
8316                type: 'RECEIVE_EVENTS',
8317                sourceId: eventSource.sourceId,
8318                fetchId,
8319                fetchRange,
8320                rawEvents,
8321            });
8322        }, (error) => {
8323            let errorHandled = false;
vendor: 4,583 bytes, lines 8324-8443
8324            if (options.eventSourceFailure) {
8325                options.eventSourceFailure.call(calendarApi, error);
8326                errorHandled = true;
8327            }
8328            if (eventSource.failure) {
8329                eventSource.failure(error);
8330                errorHandled = true;
8331            }
8332            if (!errorHandled) {
8333                console.warn(error.message, error);
8334            }
8335            context.dispatch({
8336                type: 'RECEIVE_EVENT_ERROR',
8337                sourceId: eventSource.sourceId,
8338                fetchId,
8339                fetchRange,
8340                error,
8341            });
8342        });
8343        return Object.assign(Object.assign({}, eventSource), { isFetching: true, latestFetchId: fetchId });
8344    }
8345    function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) {
8346        let eventSource = sourceHash[sourceId];
8347        if (eventSource && // not already removed
8348            fetchId === eventSource.latestFetchId) {
8349            return Object.assign(Object.assign({}, sourceHash), { [sourceId]: Object.assign(Object.assign({}, eventSource), { isFetching: false, fetchRange }) });
8350        }
8351        return sourceHash;
8352    }
8353    function excludeStaticSources(eventSources, context) {
8354        return filterHash(eventSources, (eventSource) => doesSourceNeedRange(eventSource, context));
8355    }
8356    function parseInitialSources(rawOptions, context) {
8357        let refiners = buildEventSourceRefiners(context);
8358        let rawSources = [].concat(rawOptions.eventSources || []);
8359        let sources = []; // parsed
8360        if (rawOptions.initialEvents) {
8361            rawSources.unshift(rawOptions.initialEvents);
8362        }
8363        if (rawOptions.events) {
8364            rawSources.unshift(rawOptions.events);
8365        }
8366        for (let rawSource of rawSources) {
8367            let source = parseEventSource(rawSource, context, refiners);
8368            if (source) {
8369                sources.push(source);
8370            }
8371        }
8372        return sources;
8373    }
8374    function doesSourceNeedRange(eventSource, context) {
8375        let defs = context.pluginHooks.eventSourceDefs;
8376        return !defs[eventSource.sourceDefId].ignoreRange;
8377    }
8378
8379    function reduceDateSelection(currentSelection, action) {
8380        switch (action.type) {
8381            case 'UNSELECT_DATES':
8382                return null;
8383            case 'SELECT_DATES':
8384                return action.selection;
8385            default:
8386                return currentSelection;
8387        }
8388    }
8389
8390    function reduceSelectedEvent(currentInstanceId, action) {
8391        switch (action.type) {
8392            case 'UNSELECT_EVENT':
8393                return '';
8394            case 'SELECT_EVENT':
8395                return action.eventInstanceId;
8396            default:
8397                return currentInstanceId;
8398        }
8399    }
8400
8401    function reduceEventDrag(currentDrag, action) {
8402        let newDrag;
8403        switch (action.type) {
8404            case 'UNSET_EVENT_DRAG':
8405                return null;
8406            case 'SET_EVENT_DRAG':
8407                newDrag = action.state;
8408                return {
8409                    affectedEvents: newDrag.affectedEvents,
8410                    mutatedEvents: newDrag.mutatedEvents,
8411                    isEvent: newDrag.isEvent,
8412                };
8413            default:
8414                return currentDrag;
8415        }
8416    }
8417
8418    function reduceEventResize(currentResize, action) {
8419        let newResize;
8420        switch (action.type) {
8421            case 'UNSET_EVENT_RESIZE':
8422                return null;
8423            case 'SET_EVENT_RESIZE':
8424                newResize = action.state;
8425                return {
8426                    affectedEvents: newResize.affectedEvents,
8427                    mutatedEvents: newResize.mutatedEvents,
8428                    isEvent: newResize.isEvent,
8429                };
8430            default:
8431                return currentResize;
8432        }
8433    }
8434
8435    function parseToolbars(calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
8436        let header = calendarOptions.headerToolbar ? parseToolbar(calendarOptions.headerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
8437        let footer = calendarOptions.footerToolbar ? parseToolbar(calendarOptions.footerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
8438        return { header, footer };
8439    }
8440    function parseToolbar(sectionStrHash, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
8441        let sectionWidgets = {};
8442        let viewsWithButtons = [];
8443        let hasTitle = false;
vendor: 13,629 bytes, lines 8444-8768
8444        for (let sectionName in sectionStrHash) {
8445            let sectionStr = sectionStrHash[sectionName];
8446            let sectionRes = parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi);
8447            sectionWidgets[sectionName] = sectionRes.widgets;
8448            viewsWithButtons.push(...sectionRes.viewsWithButtons);
8449            hasTitle = hasTitle || sectionRes.hasTitle;
8450        }
8451        return { sectionWidgets, viewsWithButtons, hasTitle };
8452    }
8453    /*
8454    BAD: querying icons and text here. should be done at render time
8455    */
8456    function parseSection(sectionStr, calendarOptions, // defaults+overrides, then refined
8457    calendarOptionOverrides, // overrides only!, unrefined :(
8458    theme, viewSpecs, calendarApi) {
8459        let isRtl = calendarOptions.direction === 'rtl';
8460        let calendarCustomButtons = calendarOptions.customButtons || {};
8461        let calendarButtonTextOverrides = calendarOptionOverrides.buttonText || {};
8462        let calendarButtonText = calendarOptions.buttonText || {};
8463        let calendarButtonHintOverrides = calendarOptionOverrides.buttonHints || {};
8464        let calendarButtonHints = calendarOptions.buttonHints || {};
8465        let sectionSubstrs = sectionStr ? sectionStr.split(' ') : [];
8466        let viewsWithButtons = [];
8467        let hasTitle = false;
8468        let widgets = sectionSubstrs.map((buttonGroupStr) => (buttonGroupStr.split(',').map((buttonName) => {
8469            if (buttonName === 'title') {
8470                hasTitle = true;
8471                return { buttonName };
8472            }
8473            let customButtonProps;
8474            let viewSpec;
8475            let buttonClick;
8476            let buttonIcon; // only one of these will be set
8477            let buttonText; // "
8478            let buttonHint;
8479            // ^ for the title="" attribute, for accessibility
8480            if ((customButtonProps = calendarCustomButtons[buttonName])) {
8481                buttonClick = (ev) => {
8482                    if (customButtonProps.click) {
8483                        customButtonProps.click.call(ev.target, ev, ev.target); // TODO: use Calendar this context?
8484                    }
8485                };
8486                (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) ||
8487                    (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
8488                    (buttonText = customButtonProps.text);
8489                buttonHint = customButtonProps.hint || customButtonProps.text;
8490            }
8491            else if ((viewSpec = viewSpecs[buttonName])) {
8492                viewsWithButtons.push(buttonName);
8493                buttonClick = () => {
8494                    calendarApi.changeView(buttonName);
8495                };
8496                (buttonText = viewSpec.buttonTextOverride) ||
8497                    (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
8498                    (buttonText = viewSpec.buttonTextDefault);
8499                let textFallback = viewSpec.buttonTextOverride ||
8500                    viewSpec.buttonTextDefault;
8501                buttonHint = formatWithOrdinals(viewSpec.buttonTitleOverride ||
8502                    viewSpec.buttonTitleDefault ||
8503                    calendarOptions.viewHint, [textFallback, buttonName], // view-name = buttonName
8504                textFallback);
8505            }
8506            else if (calendarApi[buttonName]) { // a calendarApi method
8507                buttonClick = () => {
8508                    calendarApi[buttonName]();
8509                };
8510                (buttonText = calendarButtonTextOverrides[buttonName]) ||
8511                    (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
8512                    (buttonText = calendarButtonText[buttonName]); // everything else is considered default
8513                if (buttonName === 'prevYear' || buttonName === 'nextYear') {
8514                    let prevOrNext = buttonName === 'prevYear' ? 'prev' : 'next';
8515                    buttonHint = formatWithOrdinals(calendarButtonHintOverrides[prevOrNext] ||
8516                        calendarButtonHints[prevOrNext], [
8517                        calendarButtonText.year || 'year',
8518                        'year',
8519                    ], calendarButtonText[buttonName]);
8520                }
8521                else {
8522                    buttonHint = (navUnit) => formatWithOrdinals(calendarButtonHintOverrides[buttonName] ||
8523                        calendarButtonHints[buttonName], [
8524                        calendarButtonText[navUnit] || navUnit,
8525                        navUnit,
8526                    ], calendarButtonText[buttonName]);
8527                }
8528            }
8529            return { buttonName, buttonClick, buttonIcon, buttonText, buttonHint };
8530        })));
8531        return { widgets, viewsWithButtons, hasTitle };
8532    }
8533
8534    // always represents the current view. otherwise, it'd need to change value every time date changes
8535    class ViewImpl {
8536        constructor(type, getCurrentData, dateEnv) {
8537            this.type = type;
8538            this.getCurrentData = getCurrentData;
8539            this.dateEnv = dateEnv;
8540        }
8541        get calendar() {
8542            return this.getCurrentData().calendarApi;
8543        }
8544        get title() {
8545            return this.getCurrentData().viewTitle;
8546        }
8547        get activeStart() {
8548            return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.start);
8549        }
8550        get activeEnd() {
8551            return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.end);
8552        }
8553        get currentStart() {
8554            return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.start);
8555        }
8556        get currentEnd() {
8557            return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.end);
8558        }
8559        getOption(name) {
8560            return this.getCurrentData().options[name]; // are the view-specific options
8561        }
8562    }
8563
8564    let eventSourceDef$2 = {
8565        ignoreRange: true,
8566        parseMeta(refined) {
8567            if (Array.isArray(refined.events)) {
8568                return refined.events;
8569            }
8570            return null;
8571        },
8572        fetch(arg, successCallback) {
8573            successCallback({
8574                rawEvents: arg.eventSource.meta,
8575            });
8576        },
8577    };
8578    const arrayEventSourcePlugin = createPlugin({
8579        name: 'array-event-source',
8580        eventSourceDefs: [eventSourceDef$2],
8581    });
8582
8583    let eventSourceDef$1 = {
8584        parseMeta(refined) {
8585            if (typeof refined.events === 'function') {
8586                return refined.events;
8587            }
8588            return null;
8589        },
8590        fetch(arg, successCallback, errorCallback) {
8591            const { dateEnv } = arg.context;
8592            const func = arg.eventSource.meta;
8593            unpromisify(func.bind(null, buildRangeApiWithTimeZone(arg.range, dateEnv)), (rawEvents) => successCallback({ rawEvents }), errorCallback);
8594        },
8595    };
8596    const funcEventSourcePlugin = createPlugin({
8597        name: 'func-event-source',
8598        eventSourceDefs: [eventSourceDef$1],
8599    });
8600
8601    const JSON_FEED_EVENT_SOURCE_REFINERS = {
8602        method: String,
8603        extraParams: identity,
8604        startParam: String,
8605        endParam: String,
8606        timeZoneParam: String,
8607    };
8608
8609    let eventSourceDef = {
8610        parseMeta(refined) {
8611            if (refined.url && (refined.format === 'json' || !refined.format)) {
8612                return {
8613                    url: refined.url,
8614                    format: 'json',
8615                    method: (refined.method || 'GET').toUpperCase(),
8616                    extraParams: refined.extraParams,
8617                    startParam: refined.startParam,
8618                    endParam: refined.endParam,
8619                    timeZoneParam: refined.timeZoneParam,
8620                };
8621            }
8622            return null;
8623        },
8624        fetch(arg, successCallback, errorCallback) {
8625            const { meta } = arg.eventSource;
8626            const requestParams = buildRequestParams(meta, arg.range, arg.context);
8627            requestJson(meta.method, meta.url, requestParams).then(([rawEvents, response]) => {
8628                successCallback({ rawEvents, response });
8629            }, errorCallback);
8630        },
8631    };
8632    const jsonFeedEventSourcePlugin = createPlugin({
8633        name: 'json-event-source',
8634        eventSourceRefiners: JSON_FEED_EVENT_SOURCE_REFINERS,
8635        eventSourceDefs: [eventSourceDef],
8636    });
8637    function buildRequestParams(meta, range, context) {
8638        let { dateEnv, options } = context;
8639        let startParam;
8640        let endParam;
8641        let timeZoneParam;
8642        let customRequestParams;
8643        let params = {};
8644        startParam = meta.startParam;
8645        if (startParam == null) {
8646            startParam = options.startParam;
8647        }
8648        endParam = meta.endParam;
8649        if (endParam == null) {
8650            endParam = options.endParam;
8651        }
8652        timeZoneParam = meta.timeZoneParam;
8653        if (timeZoneParam == null) {
8654            timeZoneParam = options.timeZoneParam;
8655        }
8656        // retrieve any outbound GET/POST data from the options
8657        if (typeof meta.extraParams === 'function') {
8658            // supplied as a function that returns a key/value object
8659            customRequestParams = meta.extraParams();
8660        }
8661        else {
8662            // probably supplied as a straight key/value object
8663            customRequestParams = meta.extraParams || {};
8664        }
8665        Object.assign(params, customRequestParams);
8666        params[startParam] = dateEnv.formatIso(range.start);
8667        params[endParam] = dateEnv.formatIso(range.end);
8668        if (dateEnv.timeZone !== 'local') {
8669            params[timeZoneParam] = dateEnv.timeZone;
8670        }
8671        return params;
8672    }
8673
8674    const SIMPLE_RECURRING_REFINERS = {
8675        daysOfWeek: identity,
8676        startTime: createDuration,
8677        endTime: createDuration,
8678        duration: createDuration,
8679        startRecur: identity,
8680        endRecur: identity,
8681    };
8682
8683    let recurring = {
8684        parse(refined, dateEnv) {
8685            if (refined.daysOfWeek || refined.startTime || refined.endTime || refined.startRecur || refined.endRecur) {
8686                let recurringData = {
8687                    daysOfWeek: refined.daysOfWeek || null,
8688                    startTime: refined.startTime || null,
8689                    endTime: refined.endTime || null,
8690                    startRecur: refined.startRecur ? dateEnv.createMarker(refined.startRecur) : null,
8691                    endRecur: refined.endRecur ? dateEnv.createMarker(refined.endRecur) : null,
8692                    dateEnv,
8693                };
8694                let duration;
8695                if (refined.duration) {
8696                    duration = refined.duration;
8697                }
8698                if (!duration && refined.startTime && refined.endTime) {
8699                    duration = subtractDurations(refined.endTime, refined.startTime);
8700                }
8701                return {
8702                    allDayGuess: Boolean(!refined.startTime && !refined.endTime),
8703                    duration,
8704                    typeData: recurringData, // doesn't need endTime anymore but oh well
8705                };
8706            }
8707            return null;
8708        },
8709        expand(typeData, framingRange, dateEnv) {
8710            let clippedFramingRange = intersectRanges(framingRange, { start: typeData.startRecur, end: typeData.endRecur });
8711            if (clippedFramingRange) {
8712                return expandRanges(typeData.daysOfWeek, typeData.startTime, typeData.dateEnv, dateEnv, clippedFramingRange);
8713            }
8714            return [];
8715        },
8716    };
8717    const simpleRecurringEventsPlugin = createPlugin({
8718        name: 'simple-recurring-event',
8719        recurringTypes: [recurring],
8720        eventRefiners: SIMPLE_RECURRING_REFINERS,
8721    });
8722    function expandRanges(daysOfWeek, startTime, eventDateEnv, calendarDateEnv, framingRange) {
8723        let dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null;
8724        let dayMarker = startOfDay(framingRange.start);
8725        let endMarker = framingRange.end;
8726        let instanceStarts = [];
8727        while (dayMarker < endMarker) {
8728            let instanceStart;
8729            // if everyday, or this particular day-of-week
8730            if (!dowHash || dowHash[dayMarker.getUTCDay()]) {
8731                if (startTime) {
8732                    instanceStart = calendarDateEnv.add(dayMarker, startTime);
8733                }
8734                else {
8735                    instanceStart = dayMarker;
8736                }
8737                instanceStarts.push(calendarDateEnv.createMarker(eventDateEnv.toDate(instanceStart)));
8738            }
8739            dayMarker = addDays(dayMarker, 1);
8740        }
8741        return instanceStarts;
8742    }
8743
8744    const changeHandlerPlugin = createPlugin({
8745        name: 'change-handler',
8746        optionChangeHandlers: {
8747            events(events, context) {
8748                handleEventSources([events], context);
8749            },
8750            eventSources: handleEventSources,
8751        },
8752    });
8753    /*
8754    BUG: if `event` was supplied, all previously-given `eventSources` will be wiped out
8755    */
8756    function handleEventSources(inputs, context) {
8757        let unfoundSources = hashValuesToArray(context.getCurrentData().eventSources);
8758        if (unfoundSources.length === 1 &&
8759            inputs.length === 1 &&
8760            Array.isArray(unfoundSources[0]._raw) &&
8761            Array.isArray(inputs[0])) {
8762            context.dispatch({
8763                type: 'RESET_RAW_EVENTS',
8764                sourceId: unfoundSources[0].sourceId,
8765                rawEvents: inputs[0],
8766            });
8767            return;
8768        }
8769        let newInputs = [];
8770        for (let input of inputs) {
8771            let inputFound = false;
8772            for (let i = 0; i < unfoundSources.length; i += 1) {
8773                if (unfoundSources[i]._raw === input) {
8774                    unfoundSources.splice(i, 1); // delete
8775                    inputFound = true;
8776                    break;
8777                }
8778            }
8779            if (!inputFound) {
8780                newInputs.push(input);
8781            }
8782        }
8783        for (let unfoundSource of unfoundSources) {
8784            context.dispatch({
8785                type: 'REMOVE_EVENT_SOURCE',
8786                sourceId: unfoundSource.sourceId,
8787            });
8788        }
8789        for (let newInput of newInputs) {
8790            context.calendarApi.addEventSource(newInput);
8791        }
8792    }
8793
8794    function handleDateProfile(dateProfile, context) {
8795        context.emitter.trigger('datesSet', Object.assign(Object.assign({}, buildRangeApiWithTimeZone(dateProfile.activeRange, context.dateEnv)), { view: context.viewApi }));
8796    }
8797
8798    function handleEventStore(eventStore, context) {
8799        let { emitter } = context;
8800        if (emitter.hasHandlers('eventsSet')) {
8801            emitter.trigger('eventsSet', buildEventApis(eventStore, context));
8802        }
8803    }
8804
8805    /*
8806    this array is exposed on the root namespace so that UMD plugins can add to it.
8807    see the rollup-bundles script.
8808    */
8809    const globalPlugins = [
8810        arrayEventSourcePlugin,
8811        funcEventSourcePlugin,
8812        jsonFeedEventSourcePlugin,
8813        simpleRecurringEventsPlugin,
8814        changeHandlerPlugin,
8815        createPlugin({
8816            name: 'misc',
8817            isLoadingFuncs: [
8818                (state) => computeEventSourcesLoading(state.eventSources),
8819            ],
8820            propSetHandlers: {
8821                dateProfile: handleDateProfile,
8822                eventStore: handleEventStore,
8823            },
8824        }),
8825    ];
8826
8827    class TaskRunner {
8828        constructor(runTaskOption, drainedOption) {
8829            this.runTaskOption = runTaskOption;
8830            this.drainedOption = drainedOption;
8831            this.queue = [];
8832            this.delayedRunner = new DelayedRunner(this.drain.bind(this));
8833        }
8834        request(task, delay) {
8835            this.queue.push(task);
8836            this.delayedRunner.request(delay);
8837        }
8838        pause(scope) {
8839            this.delayedRunner.pause(scope);
8840        }
8841        resume(scope, force) {
8842            this.delayedRunner.resume(scope, force);
8843        }
8844        drain() {
8845            let { queue } = this;
8846            while (queue.length) {
8847                let completedTasks = [];
8848                let task;
8849                while ((task = queue.shift())) {
8850                    this.runTask(task);
8851                    completedTasks.push(task);
8852                }
8853                this.drained(completedTasks);
8854            } // keep going, in case new tasks were added in the drained handler
8855        }
8856        runTask(task) {
8857            if (this.runTaskOption) {
8858                this.runTaskOption(task);
8859            }
8860        }
8861        drained(completedTasks) {
8862            if (this.drainedOption) {
8863                this.drainedOption(completedTasks);
8864            }
8865        }
8866    }
8867
8868    // Computes what the title at the top of the calendarApi should be for this view
8869    function buildTitle(dateProfile, viewOptions, dateEnv) {
8870        let range;
8871        // for views that span a large unit of time, show the proper interval, ignoring stray days before and after
8872        if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) {
8873            range = dateProfile.currentRange;
8874        }
8875        else { // for day units or smaller, use the actual day range
8876            range = dateProfile.activeRange;
8877        }
8878        return dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || buildTitleFormat(dateProfile)), {
8879            isEndExclusive: dateProfile.isRangeAllDay,
8880            defaultSeparator: viewOptions.titleRangeSeparator,
8881        });
8882    }
8883    // Generates the format string that should be used to generate the title for the current date range.
8884    // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
8885    function buildTitleFormat(dateProfile) {
8886        let { currentRangeUnit } = dateProfile;
8887        if (currentRangeUnit === 'year') {
8888            return { year: 'numeric' };
8889        }
8890        if (currentRangeUnit === 'month') {
8891            return { year: 'numeric', month: 'long' }; // like "September 2014"
8892        }
8893        let days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end);
8894        if (days !== null && days > 1) {
8895            // multi-day range. shorter, like "Sep 9 - 10 2014"
8896            return { year: 'numeric', month: 'short', day: 'numeric' };
8897        }
8898        // one day. longer, like "September 9 2014"
8899        return { year: 'numeric', month: 'long', day: 'numeric' };
8900    }
8901
8902    /*
8903    TODO: test switching timezones when NO timezone plugin
8904    */
8905    class CalendarNowManager {
8906        constructor() {
8907            this.resetListeners = new Set();
8908        }
8909        handleInput(dateEnv, // will change if timezone setup changed
8910        nowInput) {
8911            const oldDateEnv = this.dateEnv;
8912            if (dateEnv !== oldDateEnv) {
8913                if (typeof nowInput === 'function') {
8914                    this.nowFn = nowInput;
8915                }
8916                else if (!oldDateEnv) { // first time?
8917                    this.nowAnchorDate = dateEnv.toDate(nowInput
8918                        ? dateEnv.createMarker(nowInput)
8919                        : dateEnv.createNowMarker());
8920                    this.nowAnchorQueried = Date.now();
8921                }
8922                this.dateEnv = dateEnv;
8923                // not first time? fire reset handlers
8924                if (oldDateEnv) {
8925                    for (const resetListener of this.resetListeners.values()) {
8926                        resetListener();
8927                    }
8928                }
8929            }
8930        }
8931        getDateMarker() {
8932            return this.nowAnchorDate
8933                ? this.dateEnv.timestampToMarker(this.nowAnchorDate.valueOf() +
8934                    (Date.now() - this.nowAnchorQueried))
8935                : this.dateEnv.createMarker(this.nowFn());
8936        }
8937        addResetListener(handler) {
8938            this.resetListeners.add(handler);
8939        }
8940        removeResetListener(handler) {
8941            this.resetListeners.delete(handler);
8942        }
8943    }
8944
8945    // in future refactor, do the redux-style function(state=initial) for initial-state
8946    // also, whatever is happening in constructor, have it happen in action queue too
8947    class CalendarDataManager {
8948        constructor(props) {
8949            this.computeCurrentViewData = memoize(this._computeCurrentViewData);
vendor: 42,267 bytes, lines 8950-9769
8950            this.organizeRawLocales = memoize(organizeRawLocales);
8951            this.buildLocale = memoize(buildLocale);
8952            this.buildPluginHooks = buildBuildPluginHooks();
8953            this.buildDateEnv = memoize(buildDateEnv$1);
8954            this.buildTheme = memoize(buildTheme);
8955            this.parseToolbars = memoize(parseToolbars);
8956            this.buildViewSpecs = memoize(buildViewSpecs);
8957            this.buildDateProfileGenerator = memoizeObjArg(buildDateProfileGenerator);
8958            this.buildViewApi = memoize(buildViewApi);
8959            this.buildViewUiProps = memoizeObjArg(buildViewUiProps);
8960            this.buildEventUiBySource = memoize(buildEventUiBySource, isPropsEqual);
8961            this.buildEventUiBases = memoize(buildEventUiBases);
8962            this.parseContextBusinessHours = memoizeObjArg(parseContextBusinessHours);
8963            this.buildTitle = memoize(buildTitle);
8964            this.nowManager = new CalendarNowManager();
8965            this.emitter = new Emitter();
8966            this.actionRunner = new TaskRunner(this._handleAction.bind(this), this.updateData.bind(this));
8967            this.currentCalendarOptionsInput = {};
8968            this.currentCalendarOptionsRefined = {};
8969            this.currentViewOptionsInput = {};
8970            this.currentViewOptionsRefined = {};
8971            this.currentCalendarOptionsRefiners = {};
8972            this.optionsForRefining = [];
8973            this.optionsForHandling = [];
8974            this.getCurrentData = () => this.data;
8975            this.dispatch = (action) => {
8976                this.actionRunner.request(action); // protects against recursive calls to _handleAction
8977            };
8978            this.props = props;
8979            this.actionRunner.pause();
8980            this.nowManager = new CalendarNowManager();
8981            let dynamicOptionOverrides = {};
8982            let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
8983            let currentViewType = optionsData.calendarOptions.initialView || optionsData.pluginHooks.initialView;
8984            let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
8985            // wire things up
8986            // TODO: not DRY
8987            props.calendarApi.currentDataManager = this;
8988            this.emitter.setThisContext(props.calendarApi);
8989            this.emitter.setOptions(currentViewData.options);
8990            let calendarContext = {
8991                nowManager: this.nowManager,
8992                dateEnv: optionsData.dateEnv,
8993                options: optionsData.calendarOptions,
8994                pluginHooks: optionsData.pluginHooks,
8995                calendarApi: props.calendarApi,
8996                dispatch: this.dispatch,
8997                emitter: this.emitter,
8998                getCurrentData: this.getCurrentData,
8999            };
9000            let currentDate = getInitialDate(optionsData.calendarOptions, optionsData.dateEnv, this.nowManager);
9001            let dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
9002            if (!rangeContainsMarker(dateProfile.activeRange, currentDate)) {
9003                currentDate = dateProfile.currentRange.start;
9004            }
9005            // needs to be after setThisContext
9006            for (let callback of optionsData.pluginHooks.contextInit) {
9007                callback(calendarContext);
9008            }
9009            // NOT DRY
9010            let eventSources = initEventSources(optionsData.calendarOptions, dateProfile, calendarContext);
9011            let initialState = {
9012                dynamicOptionOverrides,
9013                currentViewType,
9014                currentDate,
9015                dateProfile,
9016                businessHours: this.parseContextBusinessHours(calendarContext),
9017                eventSources,
9018                eventUiBases: {},
9019                eventStore: createEmptyEventStore(),
9020                renderableEventStore: createEmptyEventStore(),
9021                dateSelection: null,
9022                eventSelection: '',
9023                eventDrag: null,
9024                eventResize: null,
9025                selectionConfig: this.buildViewUiProps(calendarContext).selectionConfig,
9026            };
9027            let contextAndState = Object.assign(Object.assign({}, calendarContext), initialState);
9028            for (let reducer of optionsData.pluginHooks.reducers) {
9029                Object.assign(initialState, reducer(null, null, contextAndState));
9030            }
9031            if (computeIsLoading(initialState, calendarContext)) {
9032                this.emitter.trigger('loading', true); // NOT DRY
9033            }
9034            this.state = initialState;
9035            this.updateData();
9036            this.actionRunner.resume();
9037        }
9038        resetOptions(optionOverrides, changedOptionNames) {
9039            let { props } = this;
9040            if (changedOptionNames === undefined) {
9041                props.optionOverrides = optionOverrides;
9042            }
9043            else {
9044                props.optionOverrides = Object.assign(Object.assign({}, (props.optionOverrides || {})), optionOverrides);
9045                this.optionsForRefining.push(...changedOptionNames);
9046            }
9047            if (changedOptionNames === undefined || changedOptionNames.length) {
9048                this.actionRunner.request({
9049                    type: 'NOTHING',
9050                });
9051            }
9052        }
9053        _handleAction(action) {
9054            let { props, state, emitter } = this;
9055            let dynamicOptionOverrides = reduceDynamicOptionOverrides(state.dynamicOptionOverrides, action);
9056            let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
9057            let currentViewType = reduceViewType(state.currentViewType, action);
9058            let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
9059            // wire things up
9060            // TODO: not DRY
9061            props.calendarApi.currentDataManager = this;
9062            emitter.setThisContext(props.calendarApi);
9063            emitter.setOptions(currentViewData.options);
9064            let calendarContext = {
9065                nowManager: this.nowManager,
9066                dateEnv: optionsData.dateEnv,
9067                options: optionsData.calendarOptions,
9068                pluginHooks: optionsData.pluginHooks,
9069                calendarApi: props.calendarApi,
9070                dispatch: this.dispatch,
9071                emitter,
9072                getCurrentData: this.getCurrentData,
9073            };
9074            let { currentDate, dateProfile } = state;
9075            if (this.data && this.data.dateProfileGenerator !== currentViewData.dateProfileGenerator) { // hack
9076                dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
9077            }
9078            currentDate = reduceCurrentDate(currentDate, action);
9079            dateProfile = reduceDateProfile(dateProfile, action, currentDate, currentViewData.dateProfileGenerator);
9080            if (action.type === 'PREV' || // TODO: move this logic into DateProfileGenerator
9081                action.type === 'NEXT' || // "
9082                !rangeContainsMarker(dateProfile.currentRange, currentDate)) {
9083                currentDate = dateProfile.currentRange.start;
9084            }
9085            let eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendarContext);
9086            let eventStore = reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendarContext);
9087            let isEventsLoading = computeEventSourcesLoading(eventSources); // BAD. also called in this func in computeIsLoading
9088            let renderableEventStore = (isEventsLoading && !currentViewData.options.progressiveEventRendering) ?
9089                (state.renderableEventStore || eventStore) : // try from previous state
9090                eventStore;
9091            let { eventUiSingleBase, selectionConfig } = this.buildViewUiProps(calendarContext); // will memoize obj
9092            let eventUiBySource = this.buildEventUiBySource(eventSources);
9093            let eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource);
9094            let newState = {
9095                dynamicOptionOverrides,
9096                currentViewType,
9097                currentDate,
9098                dateProfile,
9099                eventSources,
9100                eventStore,
9101                renderableEventStore,
9102                selectionConfig,
9103                eventUiBases,
9104                businessHours: this.parseContextBusinessHours(calendarContext),
9105                dateSelection: reduceDateSelection(state.dateSelection, action),
9106                eventSelection: reduceSelectedEvent(state.eventSelection, action),
9107                eventDrag: reduceEventDrag(state.eventDrag, action),
9108                eventResize: reduceEventResize(state.eventResize, action),
9109            };
9110            let contextAndState = Object.assign(Object.assign({}, calendarContext), newState);
9111            for (let reducer of optionsData.pluginHooks.reducers) {
9112                Object.assign(newState, reducer(state, action, contextAndState)); // give the OLD state, for old value
9113            }
9114            let wasLoading = computeIsLoading(state, calendarContext);
9115            let isLoading = computeIsLoading(newState, calendarContext);
9116            // TODO: use propSetHandlers in plugin system
9117            if (!wasLoading && isLoading) {
9118                emitter.trigger('loading', true);
9119            }
9120            else if (wasLoading && !isLoading) {
9121                emitter.trigger('loading', false);
9122            }
9123            this.state = newState;
9124            if (props.onAction) {
9125                props.onAction(action);
9126            }
9127        }
9128        updateData() {
9129            let { props, state } = this;
9130            let oldData = this.data;
9131            let optionsData = this.computeOptionsData(props.optionOverrides, state.dynamicOptionOverrides, props.calendarApi);
9132            let currentViewData = this.computeCurrentViewData(state.currentViewType, optionsData, props.optionOverrides, state.dynamicOptionOverrides);
9133            let data = this.data = Object.assign(Object.assign(Object.assign({ nowManager: this.nowManager, viewTitle: this.buildTitle(state.dateProfile, currentViewData.options, optionsData.dateEnv), calendarApi: props.calendarApi, dispatch: this.dispatch, emitter: this.emitter, getCurrentData: this.getCurrentData }, optionsData), currentViewData), state);
9134            let changeHandlers = optionsData.pluginHooks.optionChangeHandlers;
9135            let oldCalendarOptions = oldData && oldData.calendarOptions;
9136            let newCalendarOptions = optionsData.calendarOptions;
9137            if (oldCalendarOptions && oldCalendarOptions !== newCalendarOptions) {
9138                if (oldCalendarOptions.timeZone !== newCalendarOptions.timeZone) {
9139                    // hack
9140                    state.eventSources = data.eventSources = reduceEventSourcesNewTimeZone(data.eventSources, state.dateProfile, data);
9141                    state.eventStore = data.eventStore = rezoneEventStoreDates(data.eventStore, oldData.dateEnv, data.dateEnv);
9142                    state.renderableEventStore = data.renderableEventStore = rezoneEventStoreDates(data.renderableEventStore, oldData.dateEnv, data.dateEnv);
9143                }
9144                for (let optionName in changeHandlers) {
9145                    if (this.optionsForHandling.indexOf(optionName) !== -1 ||
9146                        oldCalendarOptions[optionName] !== newCalendarOptions[optionName]) {
9147                        changeHandlers[optionName](newCalendarOptions[optionName], data);
9148                    }
9149                }
9150            }
9151            this.optionsForHandling = [];
9152            if (props.onData) {
9153                props.onData(data);
9154            }
9155        }
9156        computeOptionsData(optionOverrides, dynamicOptionOverrides, calendarApi) {
9157            // TODO: blacklist options that are handled by optionChangeHandlers
9158            if (!this.optionsForRefining.length &&
9159                optionOverrides === this.stableOptionOverrides &&
9160                dynamicOptionOverrides === this.stableDynamicOptionOverrides) {
9161                return this.stableCalendarOptionsData;
9162            }
9163            let { refinedOptions, pluginHooks, localeDefaults, availableLocaleData, extra, } = this.processRawCalendarOptions(optionOverrides, dynamicOptionOverrides);
9164            warnUnknownOptions(extra);
9165            let dateEnv = this.buildDateEnv(refinedOptions.timeZone, refinedOptions.locale, refinedOptions.weekNumberCalculation, refinedOptions.firstDay, refinedOptions.weekText, pluginHooks, availableLocaleData, refinedOptions.defaultRangeSeparator);
9166            let viewSpecs = this.buildViewSpecs(pluginHooks.views, this.stableOptionOverrides, this.stableDynamicOptionOverrides, localeDefaults);
9167            let theme = this.buildTheme(refinedOptions, pluginHooks);
9168            let toolbarConfig = this.parseToolbars(refinedOptions, this.stableOptionOverrides, theme, viewSpecs, calendarApi);
9169            return this.stableCalendarOptionsData = {
9170                calendarOptions: refinedOptions,
9171                pluginHooks,
9172                dateEnv,
9173                viewSpecs,
9174                theme,
9175                toolbarConfig,
9176                localeDefaults,
9177                availableRawLocales: availableLocaleData.map,
9178            };
9179        }
9180        // always called from behind a memoizer
9181        processRawCalendarOptions(optionOverrides, dynamicOptionOverrides) {
9182            let { locales, locale } = mergeRawOptions([
9183                BASE_OPTION_DEFAULTS,
9184                optionOverrides,
9185                dynamicOptionOverrides,
9186            ]);
9187            let availableLocaleData = this.organizeRawLocales(locales);
9188            let availableRawLocales = availableLocaleData.map;
9189            let localeDefaults = this.buildLocale(locale || availableLocaleData.defaultCode, availableRawLocales).options;
9190            let pluginHooks = this.buildPluginHooks(optionOverrides.plugins || [], globalPlugins);
9191            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);
9192            let extra = {};
9193            let raw = mergeRawOptions([
9194                BASE_OPTION_DEFAULTS,
9195                localeDefaults,
9196                optionOverrides,
9197                dynamicOptionOverrides,
9198            ]);
9199            let refined = {};
9200            let currentRaw = this.currentCalendarOptionsInput;
9201            let currentRefined = this.currentCalendarOptionsRefined;
9202            let anyChanges = false;
9203            for (let optionName in raw) {
9204                if (this.optionsForRefining.indexOf(optionName) === -1 && (raw[optionName] === currentRaw[optionName] || (COMPLEX_OPTION_COMPARATORS[optionName] &&
9205                    (optionName in currentRaw) &&
9206                    COMPLEX_OPTION_COMPARATORS[optionName](currentRaw[optionName], raw[optionName])))) {
9207                    refined[optionName] = currentRefined[optionName];
9208                }
9209                else if (refiners[optionName]) {
9210                    refined[optionName] = refiners[optionName](raw[optionName]);
9211                    anyChanges = true;
9212                }
9213                else {
9214                    extra[optionName] = currentRaw[optionName];
9215                }
9216            }
9217            if (anyChanges) {
9218                this.currentCalendarOptionsInput = raw;
9219                this.currentCalendarOptionsRefined = refined;
9220                this.stableOptionOverrides = optionOverrides;
9221                this.stableDynamicOptionOverrides = dynamicOptionOverrides;
9222            }
9223            this.optionsForHandling.push(...this.optionsForRefining);
9224            this.optionsForRefining = [];
9225            return {
9226                rawOptions: this.currentCalendarOptionsInput,
9227                refinedOptions: this.currentCalendarOptionsRefined,
9228                pluginHooks,
9229                availableLocaleData,
9230                localeDefaults,
9231                extra,
9232            };
9233        }
9234        _computeCurrentViewData(viewType, optionsData, optionOverrides, dynamicOptionOverrides) {
9235            let viewSpec = optionsData.viewSpecs[viewType];
9236            if (!viewSpec) {
9237                throw new Error(`viewType "${viewType}" is not available. Please make sure you've loaded all neccessary plugins`);
9238            }
9239            let { refinedOptions, extra } = this.processRawViewOptions(viewSpec, optionsData.pluginHooks, optionsData.localeDefaults, optionOverrides, dynamicOptionOverrides);
9240            warnUnknownOptions(extra);
9241            this.nowManager.handleInput(optionsData.dateEnv, refinedOptions.now);
9242            let dateProfileGenerator = this.buildDateProfileGenerator({
9243                dateProfileGeneratorClass: viewSpec.optionDefaults.dateProfileGeneratorClass,
9244                nowManager: this.nowManager,
9245                duration: viewSpec.duration,
9246                durationUnit: viewSpec.durationUnit,
9247                usesMinMaxTime: viewSpec.optionDefaults.usesMinMaxTime,
9248                dateEnv: optionsData.dateEnv,
9249                calendarApi: this.props.calendarApi,
9250                slotMinTime: refinedOptions.slotMinTime,
9251                slotMaxTime: refinedOptions.slotMaxTime,
9252                showNonCurrentDates: refinedOptions.showNonCurrentDates,
9253                dayCount: refinedOptions.dayCount,
9254                dateAlignment: refinedOptions.dateAlignment,
9255                dateIncrement: refinedOptions.dateIncrement,
9256                hiddenDays: refinedOptions.hiddenDays,
9257                weekends: refinedOptions.weekends,
9258                validRangeInput: refinedOptions.validRange,
9259                visibleRangeInput: refinedOptions.visibleRange,
9260                fixedWeekCount: refinedOptions.fixedWeekCount,
9261            });
9262            let viewApi = this.buildViewApi(viewType, this.getCurrentData, optionsData.dateEnv);
9263            return { viewSpec, options: refinedOptions, dateProfileGenerator, viewApi };
9264        }
9265        processRawViewOptions(viewSpec, pluginHooks, localeDefaults, optionOverrides, dynamicOptionOverrides) {
9266            let raw = mergeRawOptions([
9267                BASE_OPTION_DEFAULTS,
9268                viewSpec.optionDefaults,
9269                localeDefaults,
9270                optionOverrides,
9271                viewSpec.optionOverrides,
9272                dynamicOptionOverrides,
9273            ]);
9274            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);
9275            let refined = {};
9276            let currentRaw = this.currentViewOptionsInput;
9277            let currentRefined = this.currentViewOptionsRefined;
9278            let anyChanges = false;
9279            let extra = {};
9280            for (let optionName in raw) {
9281                if (raw[optionName] === currentRaw[optionName] ||
9282                    (COMPLEX_OPTION_COMPARATORS[optionName] &&
9283                        COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], currentRaw[optionName]))) {
9284                    refined[optionName] = currentRefined[optionName];
9285                }
9286                else {
9287                    if (raw[optionName] === this.currentCalendarOptionsInput[optionName] ||
9288                        (COMPLEX_OPTION_COMPARATORS[optionName] &&
9289                            COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], this.currentCalendarOptionsInput[optionName]))) {
9290                        if (optionName in this.currentCalendarOptionsRefined) { // might be an "extra" prop
9291                            refined[optionName] = this.currentCalendarOptionsRefined[optionName];
9292                        }
9293                    }
9294                    else if (refiners[optionName]) {
9295                        refined[optionName] = refiners[optionName](raw[optionName]);
9296                    }
9297                    else {
9298                        extra[optionName] = raw[optionName];
9299                    }
9300                    anyChanges = true;
9301                }
9302            }
9303            if (anyChanges) {
9304                this.currentViewOptionsInput = raw;
9305                this.currentViewOptionsRefined = refined;
9306            }
9307            return {
9308                rawOptions: this.currentViewOptionsInput,
9309                refinedOptions: this.currentViewOptionsRefined,
9310                extra,
9311            };
9312        }
9313    }
9314    function buildDateEnv$1(timeZone, explicitLocale, weekNumberCalculation, firstDay, weekText, pluginHooks, availableLocaleData, defaultSeparator) {
9315        let locale = buildLocale(explicitLocale || availableLocaleData.defaultCode, availableLocaleData.map);
9316        return new DateEnv({
9317            calendarSystem: 'gregory',
9318            timeZone,
9319            namedTimeZoneImpl: pluginHooks.namedTimeZonedImpl,
9320            locale,
9321            weekNumberCalculation,
9322            firstDay,
9323            weekText,
9324            cmdFormatter: pluginHooks.cmdFormatter,
9325            defaultSeparator,
9326        });
9327    }
9328    function buildTheme(options, pluginHooks) {
9329        let ThemeClass = pluginHooks.themeClasses[options.themeSystem] || StandardTheme;
9330        return new ThemeClass(options);
9331    }
9332    function buildDateProfileGenerator(props) {
9333        let DateProfileGeneratorClass = props.dateProfileGeneratorClass || DateProfileGenerator;
9334        return new DateProfileGeneratorClass(props);
9335    }
9336    function buildViewApi(type, getCurrentData, dateEnv) {
9337        return new ViewImpl(type, getCurrentData, dateEnv);
9338    }
9339    function buildEventUiBySource(eventSources) {
9340        return mapHash(eventSources, (eventSource) => eventSource.ui);
9341    }
9342    function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) {
9343        let eventUiBases = { '': eventUiSingleBase };
9344        for (let defId in eventDefs) {
9345            let def = eventDefs[defId];
9346            if (def.sourceId && eventUiBySource[def.sourceId]) {
9347                eventUiBases[defId] = eventUiBySource[def.sourceId];
9348            }
9349        }
9350        return eventUiBases;
9351    }
9352    function buildViewUiProps(calendarContext) {
9353        let { options } = calendarContext;
9354        return {
9355            eventUiSingleBase: createEventUi({
9356                display: options.eventDisplay,
9357                editable: options.editable,
9358                startEditable: options.eventStartEditable,
9359                durationEditable: options.eventDurationEditable,
9360                constraint: options.eventConstraint,
9361                overlap: typeof options.eventOverlap === 'boolean' ? options.eventOverlap : undefined,
9362                allow: options.eventAllow,
9363                backgroundColor: options.eventBackgroundColor,
9364                borderColor: options.eventBorderColor,
9365                textColor: options.eventTextColor,
9366                color: options.eventColor,
9367                // classNames: options.eventClassNames // render hook will handle this
9368            }, calendarContext),
9369            selectionConfig: createEventUi({
9370                constraint: options.selectConstraint,
9371                overlap: typeof options.selectOverlap === 'boolean' ? options.selectOverlap : undefined,
9372                allow: options.selectAllow,
9373            }, calendarContext),
9374        };
9375    }
9376    function computeIsLoading(state, context) {
9377        for (let isLoadingFunc of context.pluginHooks.isLoadingFuncs) {
9378            if (isLoadingFunc(state)) {
9379                return true;
9380            }
9381        }
9382        return false;
9383    }
9384    function parseContextBusinessHours(calendarContext) {
9385        return parseBusinessHours(calendarContext.options.businessHours, calendarContext);
9386    }
9387    function warnUnknownOptions(options, viewName) {
9388        for (let optionName in options) {
9389            console.warn(`Unknown option '${optionName}'` +
9390                (viewName ? ` for view '${viewName}'` : ''));
9391        }
9392    }
9393
9394    class ToolbarSection extends BaseComponent {
9395        render() {
9396            let children = this.props.widgetGroups.map((widgetGroup) => this.renderWidgetGroup(widgetGroup));
9397            return y('div', { className: 'fc-toolbar-chunk' }, ...children);
9398        }
9399        renderWidgetGroup(widgetGroup) {
9400            let { props } = this;
9401            let { theme } = this.context;
9402            let children = [];
9403            let isOnlyButtons = true;
9404            for (let widget of widgetGroup) {
9405                let { buttonName, buttonClick, buttonText, buttonIcon, buttonHint } = widget;
9406                if (buttonName === 'title') {
9407                    isOnlyButtons = false;
9408                    children.push(y("h2", { className: "fc-toolbar-title", id: props.titleId }, props.title));
9409                }
9410                else {
9411                    let isPressed = buttonName === props.activeButton;
9412                    let isDisabled = (!props.isTodayEnabled && buttonName === 'today') ||
9413                        (!props.isPrevEnabled && buttonName === 'prev') ||
9414                        (!props.isNextEnabled && buttonName === 'next');
9415                    let buttonClasses = [`fc-${buttonName}-button`, theme.getClass('button')];
9416                    if (isPressed) {
9417                        buttonClasses.push(theme.getClass('buttonActive'));
9418                    }
9419                    children.push(y("button", { type: "button", title: typeof buttonHint === 'function' ? buttonHint(props.navUnit) : buttonHint, disabled: isDisabled, "aria-pressed": isPressed, className: buttonClasses.join(' '), onClick: buttonClick }, buttonText || (buttonIcon ? y("span", { className: buttonIcon, role: "img" }) : '')));
9420                }
9421            }
9422            if (children.length > 1) {
9423                let groupClassName = (isOnlyButtons && theme.getClass('buttonGroup')) || '';
9424                return y('div', { className: groupClassName }, ...children);
9425            }
9426            return children[0];
9427        }
9428    }
9429
9430    class Toolbar extends BaseComponent {
9431        render() {
9432            let { model, extraClassName } = this.props;
9433            let forceLtr = false;
9434            let startContent;
9435            let endContent;
9436            let sectionWidgets = model.sectionWidgets;
9437            let centerContent = sectionWidgets.center;
9438            if (sectionWidgets.left) {
9439                forceLtr = true;
9440                startContent = sectionWidgets.left;
9441            }
9442            else {
9443                startContent = sectionWidgets.start;
9444            }
9445            if (sectionWidgets.right) {
9446                forceLtr = true;
9447                endContent = sectionWidgets.right;
9448            }
9449            else {
9450                endContent = sectionWidgets.end;
9451            }
9452            let classNames = [
9453                extraClassName || '',
9454                'fc-toolbar',
9455                forceLtr ? 'fc-toolbar-ltr' : '',
9456            ];
9457            return (y("div", { className: classNames.join(' ') },
9458                this.renderSection('start', startContent || []),
9459                this.renderSection('center', centerContent || []),
9460                this.renderSection('end', endContent || [])));
9461        }
9462        renderSection(key, widgetGroups) {
9463            let { props } = this;
9464            return (y(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 }));
9465        }
9466    }
9467
9468    class ViewHarness extends BaseComponent {
9469        constructor() {
9470            super(...arguments);
9471            this.state = {
9472                availableWidth: null,
9473            };
9474            this.handleEl = (el) => {
9475                this.el = el;
9476                setRef(this.props.elRef, el);
9477                this.updateAvailableWidth();
9478            };
9479            this.handleResize = () => {
9480                this.updateAvailableWidth();
9481            };
9482        }
9483        render() {
9484            let { props, state } = this;
9485            let { aspectRatio } = props;
9486            let classNames = [
9487                'fc-view-harness',
9488                (aspectRatio || props.liquid || props.height)
9489                    ? 'fc-view-harness-active' // harness controls the height
9490                    : 'fc-view-harness-passive', // let the view do the height
9491            ];
9492            let height = '';
9493            let paddingBottom = '';
9494            if (aspectRatio) {
9495                if (state.availableWidth !== null) {
9496                    height = state.availableWidth / aspectRatio;
9497                }
9498                else {
9499                    // while waiting to know availableWidth, we can't set height to *zero*
9500                    // because will cause lots of unnecessary scrollbars within scrollgrid.
9501                    // BETTER: don't start rendering ANYTHING yet until we know container width
9502                    // NOTE: why not always use paddingBottom? Causes height oscillation (issue 5606)
9503                    paddingBottom = `${(1 / aspectRatio) * 100}%`;
9504                }
9505            }
9506            else {
9507                height = props.height || '';
9508            }
9509            return (y("div", { "aria-labelledby": props.labeledById, ref: this.handleEl, className: classNames.join(' '), style: { height, paddingBottom } }, props.children));
9510        }
9511        componentDidMount() {
9512            this.context.addResizeHandler(this.handleResize);
9513        }
9514        componentWillUnmount() {
9515            this.context.removeResizeHandler(this.handleResize);
9516        }
9517        updateAvailableWidth() {
9518            if (this.el && // needed. but why?
9519                this.props.aspectRatio // aspectRatio is the only height setting that needs availableWidth
9520            ) {
9521                this.setState({ availableWidth: this.el.offsetWidth });
9522            }
9523        }
9524    }
9525
9526    /*
9527    Detects when the user clicks on an event within a DateComponent
9528    */
9529    class EventClicking extends Interaction {
9530        constructor(settings) {
9531            super(settings);
9532            this.handleSegClick = (ev, segEl) => {
9533                let { component } = this;
9534                let { context } = component;
9535                let seg = getElSeg(segEl);
9536                if (seg && // might be the <div> surrounding the more link
9537                    component.isValidSegDownEl(ev.target)) {
9538                    // our way to simulate a link click for elements that can't be <a> tags
9539                    // grab before trigger fired in case trigger trashes DOM thru rerendering
9540                    let hasUrlContainer = elementClosest(ev.target, '.fc-event-forced-url');
9541                    let url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : '';
9542                    context.emitter.trigger('eventClick', {
9543                        el: segEl,
9544                        event: new EventImpl(component.context, seg.eventRange.def, seg.eventRange.instance),
9545                        jsEvent: ev,
9546                        view: context.viewApi,
9547                    });
9548                    if (url && !ev.defaultPrevented) {
9549                        window.location.href = url;
9550                    }
9551                }
9552            };
9553            this.destroy = listenBySelector(settings.el, 'click', '.fc-event', // on both fg and bg events
9554            this.handleSegClick);
9555        }
9556    }
9557
9558    /*
9559    Triggers events and adds/removes core classNames when the user's pointer
9560    enters/leaves event-elements of a component.
9561    */
9562    class EventHovering extends Interaction {
9563        constructor(settings) {
9564            super(settings);
9565            // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it
9566            this.handleEventElRemove = (el) => {
9567                if (el === this.currentSegEl) {
9568                    this.handleSegLeave(null, this.currentSegEl);
9569                }
9570            };
9571            this.handleSegEnter = (ev, segEl) => {
9572                if (getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper
9573                    this.currentSegEl = segEl;
9574                    this.triggerEvent('eventMouseEnter', ev, segEl);
9575                }
9576            };
9577            this.handleSegLeave = (ev, segEl) => {
9578                if (this.currentSegEl) {
9579                    this.currentSegEl = null;
9580                    this.triggerEvent('eventMouseLeave', ev, segEl);
9581                }
9582            };
9583            this.removeHoverListeners = listenToHoverBySelector(settings.el, '.fc-event', // on both fg and bg events
9584            this.handleSegEnter, this.handleSegLeave);
9585        }
9586        destroy() {
9587            this.removeHoverListeners();
9588        }
9589        triggerEvent(publicEvName, ev, segEl) {
9590            let { component } = this;
9591            let { context } = component;
9592            let seg = getElSeg(segEl);
9593            if (!ev || component.isValidSegDownEl(ev.target)) {
9594                context.emitter.trigger(publicEvName, {
9595                    el: segEl,
9596                    event: new EventImpl(context, seg.eventRange.def, seg.eventRange.instance),
9597                    jsEvent: ev,
9598                    view: context.viewApi,
9599                });
9600            }
9601        }
9602    }
9603
9604    class CalendarContent extends PureComponent {
9605        constructor() {
9606            super(...arguments);
9607            this.buildViewContext = memoize(buildViewContext);
9608            this.buildViewPropTransformers = memoize(buildViewPropTransformers);
9609            this.buildToolbarProps = memoize(buildToolbarProps);
9610            this.headerRef = d();
9611            this.footerRef = d();
9612            this.interactionsStore = {};
9613            // eslint-disable-next-line
9614            this.state = {
9615                viewLabelId: getUniqueDomId(),
9616            };
9617            // Component Registration
9618            // -----------------------------------------------------------------------------------------------------------------
9619            this.registerInteractiveComponent = (component, settingsInput) => {
9620                let settings = parseInteractionSettings(component, settingsInput);
9621                let DEFAULT_INTERACTIONS = [
9622                    EventClicking,
9623                    EventHovering,
9624                ];
9625                let interactionClasses = DEFAULT_INTERACTIONS.concat(this.props.pluginHooks.componentInteractions);
9626                let interactions = interactionClasses.map((TheInteractionClass) => new TheInteractionClass(settings));
9627                this.interactionsStore[component.uid] = interactions;
9628                interactionSettingsStore[component.uid] = settings;
9629            };
9630            this.unregisterInteractiveComponent = (component) => {
9631                let listeners = this.interactionsStore[component.uid];
9632                if (listeners) {
9633                    for (let listener of listeners) {
9634                        listener.destroy();
9635                    }
9636                    delete this.interactionsStore[component.uid];
9637                }
9638                delete interactionSettingsStore[component.uid];
9639            };
9640            // Resizing
9641            // -----------------------------------------------------------------------------------------------------------------
9642            this.resizeRunner = new DelayedRunner(() => {
9643                this.props.emitter.trigger('_resize', true); // should window resizes be considered "forced" ?
9644                this.props.emitter.trigger('windowResize', { view: this.props.viewApi });
9645            });
9646            this.handleWindowResize = (ev) => {
9647                let { options } = this.props;
9648                if (options.handleWindowResize &&
9649                    ev.target === window // avoid jqui events
9650                ) {
9651                    this.resizeRunner.request(options.windowResizeDelay);
9652                }
9653            };
9654        }
9655        /*
9656        renders INSIDE of an outer div
9657        */
9658        render() {
9659            let { props } = this;
9660            let { toolbarConfig, options } = props;
9661            let viewVGrow = false;
9662            let viewHeight = '';
9663            let viewAspectRatio;
9664            if (props.isHeightAuto || props.forPrint) {
9665                viewHeight = '';
9666            }
9667            else if (options.height != null) {
9668                viewVGrow = true;
9669            }
9670            else if (options.contentHeight != null) {
9671                viewHeight = options.contentHeight;
9672            }
9673            else {
9674                viewAspectRatio = Math.max(options.aspectRatio, 0.5); // prevent from getting too tall
9675            }
9676            let viewContext = this.buildViewContext(props.viewSpec, props.viewApi, props.options, props.dateProfileGenerator, props.dateEnv, props.nowManager, props.theme, props.pluginHooks, props.dispatch, props.getCurrentData, props.emitter, props.calendarApi, this.registerInteractiveComponent, this.unregisterInteractiveComponent);
9677            let viewLabelId = (toolbarConfig.header && toolbarConfig.header.hasTitle)
9678                ? this.state.viewLabelId
9679                : undefined;
9680            return (y(ViewContextType.Provider, { value: viewContext },
9681                y(NowTimer, { unit: "day" }, (nowDate) => {
9682                    let toolbarProps = this.buildToolbarProps(props.viewSpec, props.dateProfile, props.dateProfileGenerator, props.currentDate, nowDate, props.viewTitle);
9683                    return (y(_, null,
9684                        toolbarConfig.header && (y(Toolbar, Object.assign({ ref: this.headerRef, extraClassName: "fc-header-toolbar", model: toolbarConfig.header, titleId: viewLabelId }, toolbarProps))),
9685                        y(ViewHarness, { liquid: viewVGrow, height: viewHeight, aspectRatio: viewAspectRatio, labeledById: viewLabelId },
9686                            this.renderView(props),
9687                            this.buildAppendContent()),
9688                        toolbarConfig.footer && (y(Toolbar, Object.assign({ ref: this.footerRef, extraClassName: "fc-footer-toolbar", model: toolbarConfig.footer, titleId: "" }, toolbarProps)))));
9689                })));
9690        }
9691        componentDidMount() {
9692            let { props } = this;
9693            this.calendarInteractions = props.pluginHooks.calendarInteractions
9694                .map((CalendarInteractionClass) => new CalendarInteractionClass(props));
9695            window.addEventListener('resize', this.handleWindowResize);
9696            let { propSetHandlers } = props.pluginHooks;
9697            for (let propName in propSetHandlers) {
9698                propSetHandlers[propName](props[propName], props);
9699            }
9700        }
9701        componentDidUpdate(prevProps) {
9702            let { props } = this;
9703            let { propSetHandlers } = props.pluginHooks;
9704            for (let propName in propSetHandlers) {
9705                if (props[propName] !== prevProps[propName]) {
9706                    propSetHandlers[propName](props[propName], props);
9707                }
9708            }
9709        }
9710        componentWillUnmount() {
9711            window.removeEventListener('resize', this.handleWindowResize);
9712            this.resizeRunner.clear();
9713            for (let interaction of this.calendarInteractions) {
9714                interaction.destroy();
9715            }
9716            this.props.emitter.trigger('_unmount');
9717        }
9718        buildAppendContent() {
9719            let { props } = this;
9720            let children = props.pluginHooks.viewContainerAppends.map((buildAppendContent) => buildAppendContent(props));
9721            return y(_, {}, ...children);
9722        }
9723        renderView(props) {
9724            let { pluginHooks } = props;
9725            let { viewSpec } = props;
9726            let viewProps = {
9727                dateProfile: props.dateProfile,
9728                businessHours: props.businessHours,
9729                eventStore: props.renderableEventStore,
9730                eventUiBases: props.eventUiBases,
9731                dateSelection: props.dateSelection,
9732                eventSelection: props.eventSelection,
9733                eventDrag: props.eventDrag,
9734                eventResize: props.eventResize,
9735                isHeightAuto: props.isHeightAuto,
9736                forPrint: props.forPrint,
9737            };
9738            let transformers = this.buildViewPropTransformers(pluginHooks.viewPropsTransformers);
9739            for (let transformer of transformers) {
9740                Object.assign(viewProps, transformer.transform(viewProps, props));
9741            }
9742            let ViewComponent = viewSpec.component;
9743            return (y(ViewComponent, Object.assign({}, viewProps)));
9744        }
9745    }
9746    function buildToolbarProps(viewSpec, dateProfile, dateProfileGenerator, currentDate, now, title) {
9747        // don't force any date-profiles to valid date profiles (the `false`) so that we can tell if it's invalid
9748        let todayInfo = dateProfileGenerator.build(now, undefined, false); // TODO: need `undefined` or else INFINITE LOOP for some reason
9749        let prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate, false);
9750        let nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate, false);
9751        return {
9752            title,
9753            activeButton: viewSpec.type,
9754            navUnit: viewSpec.singleUnit,
9755            isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now),
9756            isPrevEnabled: prevInfo.isValid,
9757            isNextEnabled: nextInfo.isValid,
9758        };
9759    }
9760    // Plugin
9761    // -----------------------------------------------------------------------------------------------------------------
9762    function buildViewPropTransformers(theClasses) {
9763        return theClasses.map((TheClass) => new TheClass());
9764    }
9765
9766    class Calendar extends CalendarImpl {
9767        constructor(el, optionOverrides = {}) {
9768            super();
9769            this.isRendering = false;
9770            this.isRendered = false;
9771            this.currentClassNames = [];
9772            this.customContentRenderId = 0;
9773            this.handleAction = (action) => {
9774                // actions we know we want to render immediately
9775                switch (action.type) {
9776                    case 'SET_EVENT_DRAG':
9777                    case 'SET_EVENT_RESIZE':
9778                        this.renderRunner.tryDrain();
9779                }
9780            };
9781            this.handleData = (data) => {
9782                this.currentData = data;
9783                this.renderRunner.request(data.calendarOptions.rerenderDelay);
9784            };
9785            this.handleRenderRequest = () => {
9786                if (this.isRendering) {
9787                    this.isRendered = true;
9788                    let { currentData } = this;
9789                    flushSync(() => {
9790                        D$1(y(CalendarRoot, { options: currentData.calendarOptions, theme: currentData.theme, emitter: currentData.emitter }, (classNames, height, isHeightAuto, forPrint) => {
9791                            this.setClassNames(classNames);
9792                            this.setHeight(height);
9793                            return (y(RenderId.Provider, { value: this.customContentRenderId },
9794                                y(CalendarContent, Object.assign({ isHeightAuto: isHeightAuto, forPrint: forPrint }, currentData))));
9795                        }), this.el);
9796                    });
9797                }
9798                else if (this.isRendered) {
9799                    this.isRendered = false;
9800                    D$1(null, this.el);
9801                    this.setClassNames([]);
9802                    this.setHeight('');
9803                }
9804            };
9805            ensureElHasStyles(el);
9806            this.el = el;
9807            this.renderRunner = new DelayedRunner(this.handleRenderRequest);
9808            new CalendarDataManager({
9809                optionOverrides,
9810                calendarApi: this,
9811                onAction: this.handleAction,
9812                onData: this.handleData,
9813            });
9814        }
9815        render() {
9816            let wasRendering = this.isRendering;
9817            if (!wasRendering) {
9818                this.isRendering = true;
9819            }
9820            else {
9821                this.customContentRenderId += 1;
9822            }
9823            this.renderRunner.request();
9824            if (wasRendering) {
9825                this.updateSize();
9826            }
9827        }
9828        destroy() {
9829            if (this.isRendering) {
9830                this.isRendering = false;
9831                this.renderRunner.request();
9832            }
9833        }
9834        updateSize() {
9835            flushSync(() => {
9836                super.updateSize();
9837            });
9838        }
9839        batchRendering(func) {
9840            this.renderRunner.pause('batchRendering');
9841            func();
9842            this.renderRunner.resume('batchRendering');
9843        }
9844        pauseRendering() {
9845            this.renderRunner.pause('pauseRendering');
9846        }
9847        resumeRendering() {
9848            this.renderRunner.resume('pauseRendering', true);
9849        }
9850        resetOptions(optionOverrides, changedOptionNames) {
9851            this.currentDataManager.resetOptions(optionOverrides, changedOptionNames);
9852        }
9853        setClassNames(classNames) {
9854            if (!isArraysEqual(classNames, this.currentClassNames)) {
9855                let { classList } = this.el;
9856                for (let className of this.currentClassNames) {
9857                    classList.remove(className);
9858                }
9859                for (let className of classNames) {
9860                    classList.add(className);
9861                }
9862                this.currentClassNames = classNames;
9863            }
9864        }
9865        setHeight(height) {
9866            applyStyleProp(this.el, 'height', height);
9867        }
9868    }
9869
9870    function formatDate(dateInput, options = {}) {
9871        let dateEnv = buildDateEnv(options);
9872        let formatter = createFormatter(options);
9873        let dateMeta = dateEnv.createMarkerMeta(dateInput);
9874        if (!dateMeta) { // TODO: warning?
9875            return '';
9876        }
9877        return dateEnv.format(dateMeta.marker, formatter, {
9878            forcedTzo: dateMeta.forcedTzo,
9879        });
9880    }
9881    function formatRange(startInput, endInput, options) {
9882        let dateEnv = buildDateEnv(typeof options === 'object' && options ? options : {}); // pass in if non-null object
9883        let formatter = createFormatter(options);
9884        let startMeta = dateEnv.createMarkerMeta(startInput);
9885        let endMeta = dateEnv.createMarkerMeta(endInput);
9886        if (!startMeta || !endMeta) { // TODO: warning?
9887            return '';
9888        }
9889        return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, {
9890            forcedStartTzo: startMeta.forcedTzo,
9891            forcedEndTzo: endMeta.forcedTzo,
9892            isEndExclusive: options.isEndExclusive,
9893            defaultSeparator: BASE_OPTION_DEFAULTS.defaultRangeSeparator,
9894        });
9895    }
9896    // TODO: more DRY and optimized
9897    function buildDateEnv(settings) {
9898        let locale = buildLocale(settings.locale || 'en', organizeRawLocales([]).map); // TODO: don't hardcode 'en' everywhere
9899        return new DateEnv(Object.assign(Object.assign({ timeZone: BASE_OPTION_DEFAULTS.timeZone, calendarSystem: 'gregory' }, settings), { locale }));
9900    }
9901
9902    // HELPERS
9903    /*
9904    if nextDayThreshold is specified, slicing is done in an all-day fashion.
9905    you can get nextDayThreshold from context.nextDayThreshold
9906    */
9907    function sliceEvents(props, allDay) {
9908        return sliceEventStore(props.eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? props.nextDayThreshold : null).fg;
9909    }
9910
9911    const version = '6.1.17';
9912
9913    config.touchMouseIgnoreWait = 500;
9914    let ignoreMouseDepth = 0;
9915    let listenerCnt = 0;
9916    let isWindowTouchMoveCancelled = false;
vendor: 4,736 bytes, lines 9917-10004
9917    /*
9918    Uses a "pointer" abstraction, which monitors UI events for both mouse and touch.
9919    Tracks when the pointer "drags" on a certain element, meaning down+move+up.
9920
9921    Also, tracks if there was touch-scrolling.
9922    Also, can prevent touch-scrolling from happening.
9923    Also, can fire pointermove events when scrolling happens underneath, even when no real pointer movement.
9924
9925    emits:
9926    - pointerdown
9927    - pointermove
9928    - pointerup
9929    */
9930    class PointerDragging {
9931        constructor(containerEl) {
9932            this.subjectEl = null;
9933            // options that can be directly assigned by caller
9934            this.selector = ''; // will cause subjectEl in all emitted events to be this element
9935            this.handleSelector = '';
9936            this.shouldIgnoreMove = false;
9937            this.shouldWatchScroll = true; // for simulating pointermove on scroll
9938            // internal states
9939            this.isDragging = false;
9940            this.isTouchDragging = false;
9941            this.wasTouchScroll = false;
9942            // Mouse
9943            // ----------------------------------------------------------------------------------------------------
9944            this.handleMouseDown = (ev) => {
9945                if (!this.shouldIgnoreMouse() &&
9946                    isPrimaryMouseButton(ev) &&
9947                    this.tryStart(ev)) {
9948                    let pev = this.createEventFromMouse(ev, true);
9949                    this.emitter.trigger('pointerdown', pev);
9950                    this.initScrollWatch(pev);
9951                    if (!this.shouldIgnoreMove) {
9952                        document.addEventListener('mousemove', this.handleMouseMove);
9953                    }
9954                    document.addEventListener('mouseup', this.handleMouseUp);
9955                }
9956            };
9957            this.handleMouseMove = (ev) => {
9958                let pev = this.createEventFromMouse(ev);
9959                this.recordCoords(pev);
9960                this.emitter.trigger('pointermove', pev);
9961            };
9962            this.handleMouseUp = (ev) => {
9963                document.removeEventListener('mousemove', this.handleMouseMove);
9964                document.removeEventListener('mouseup', this.handleMouseUp);
9965                this.emitter.trigger('pointerup', this.createEventFromMouse(ev));
9966                this.cleanup(); // call last so that pointerup has access to props
9967            };
9968            // Touch
9969            // ----------------------------------------------------------------------------------------------------
9970            this.handleTouchStart = (ev) => {
9971                if (this.tryStart(ev)) {
9972                    this.isTouchDragging = true;
9973                    let pev = this.createEventFromTouch(ev, true);
9974                    this.emitter.trigger('pointerdown', pev);
9975                    this.initScrollWatch(pev);
9976                    // unlike mouse, need to attach to target, not document
9977                    // https://stackoverflow.com/a/45760014
9978                    let targetEl = ev.target;
9979                    if (!this.shouldIgnoreMove) {
9980                        targetEl.addEventListener('touchmove', this.handleTouchMove);
9981                    }
9982                    targetEl.addEventListener('touchend', this.handleTouchEnd);
9983                    targetEl.addEventListener('touchcancel', this.handleTouchEnd); // treat it as a touch end
9984                    // attach a handler to get called when ANY scroll action happens on the page.
9985                    // this was impossible to do with normal on/off because 'scroll' doesn't bubble.
9986                    // http://stackoverflow.com/a/32954565/96342
9987                    window.addEventListener('scroll', this.handleTouchScroll, true);
9988                }
9989            };
9990            this.handleTouchMove = (ev) => {
9991                let pev = this.createEventFromTouch(ev);
9992                this.recordCoords(pev);
9993                this.emitter.trigger('pointermove', pev);
9994            };
9995            this.handleTouchEnd = (ev) => {
9996                if (this.isDragging) { // done to guard against touchend followed by touchcancel
9997                    let targetEl = ev.target;
9998                    targetEl.removeEventListener('touchmove', this.handleTouchMove);
9999                    targetEl.removeEventListener('touchend', this.handleTouchEnd);
10000                    targetEl.removeEventListener('touchcancel', this.handleTouchEnd);
10001                    window.removeEventListener('scroll', this.handleTouchScroll, true); // useCaptured=true
10002                    this.emitter.trigger('pointerup', this.createEventFromTouch(ev));
10003                    this.cleanup(); // call last so that pointerup has access to props
10004                    this.isTouchDragging = false;
vendor: 15,183 bytes, lines 10005-10396
10005                    startIgnoringMouse();
10006                }
10007            };
10008            this.handleTouchScroll = () => {
10009                this.wasTouchScroll = true;
10010            };
10011            this.handleScroll = (ev) => {
10012                if (!this.shouldIgnoreMove) {
10013                    let pageX = (window.scrollX - this.prevScrollX) + this.prevPageX;
10014                    let pageY = (window.scrollY - this.prevScrollY) + this.prevPageY;
10015                    this.emitter.trigger('pointermove', {
10016                        origEvent: ev,
10017                        isTouch: this.isTouchDragging,
10018                        subjectEl: this.subjectEl,
10019                        pageX,
10020                        pageY,
10021                        deltaX: pageX - this.origPageX,
10022                        deltaY: pageY - this.origPageY,
10023                    });
10024                }
10025            };
10026            this.containerEl = containerEl;
10027            this.emitter = new Emitter();
10028            containerEl.addEventListener('mousedown', this.handleMouseDown);
10029            containerEl.addEventListener('touchstart', this.handleTouchStart, { passive: true });
10030            listenerCreated();
10031        }
10032        destroy() {
10033            this.containerEl.removeEventListener('mousedown', this.handleMouseDown);
10034            this.containerEl.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
10035            listenerDestroyed();
10036        }
10037        tryStart(ev) {
10038            let subjectEl = this.querySubjectEl(ev);
10039            let downEl = ev.target;
10040            if (subjectEl &&
10041                (!this.handleSelector || elementClosest(downEl, this.handleSelector))) {
10042                this.subjectEl = subjectEl;
10043                this.isDragging = true; // do this first so cancelTouchScroll will work
10044                this.wasTouchScroll = false;
10045                return true;
10046            }
10047            return false;
10048        }
10049        cleanup() {
10050            isWindowTouchMoveCancelled = false;
10051            this.isDragging = false;
10052            this.subjectEl = null;
10053            // keep wasTouchScroll around for later access
10054            this.destroyScrollWatch();
10055        }
10056        querySubjectEl(ev) {
10057            if (this.selector) {
10058                return elementClosest(ev.target, this.selector);
10059            }
10060            return this.containerEl;
10061        }
10062        shouldIgnoreMouse() {
10063            return ignoreMouseDepth || this.isTouchDragging;
10064        }
10065        // can be called by user of this class, to cancel touch-based scrolling for the current drag
10066        cancelTouchScroll() {
10067            if (this.isDragging) {
10068                isWindowTouchMoveCancelled = true;
10069            }
10070        }
10071        // Scrolling that simulates pointermoves
10072        // ----------------------------------------------------------------------------------------------------
10073        initScrollWatch(ev) {
10074            if (this.shouldWatchScroll) {
10075                this.recordCoords(ev);
10076                window.addEventListener('scroll', this.handleScroll, true); // useCapture=true
10077            }
10078        }
10079        recordCoords(ev) {
10080            if (this.shouldWatchScroll) {
10081                this.prevPageX = ev.pageX;
10082                this.prevPageY = ev.pageY;
10083                this.prevScrollX = window.scrollX;
10084                this.prevScrollY = window.scrollY;
10085            }
10086        }
10087        destroyScrollWatch() {
10088            if (this.shouldWatchScroll) {
10089                window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true
10090            }
10091        }
10092        // Event Normalization
10093        // ----------------------------------------------------------------------------------------------------
10094        createEventFromMouse(ev, isFirst) {
10095            let deltaX = 0;
10096            let deltaY = 0;
10097            // TODO: repeat code
10098            if (isFirst) {
10099                this.origPageX = ev.pageX;
10100                this.origPageY = ev.pageY;
10101            }
10102            else {
10103                deltaX = ev.pageX - this.origPageX;
10104                deltaY = ev.pageY - this.origPageY;
10105            }
10106            return {
10107                origEvent: ev,
10108                isTouch: false,
10109                subjectEl: this.subjectEl,
10110                pageX: ev.pageX,
10111                pageY: ev.pageY,
10112                deltaX,
10113                deltaY,
10114            };
10115        }
10116        createEventFromTouch(ev, isFirst) {
10117            let touches = ev.touches;
10118            let pageX;
10119            let pageY;
10120            let deltaX = 0;
10121            let deltaY = 0;
10122            // if touch coords available, prefer,
10123            // because FF would give bad ev.pageX ev.pageY
10124            if (touches && touches.length) {
10125                pageX = touches[0].pageX;
10126                pageY = touches[0].pageY;
10127            }
10128            else {
10129                pageX = ev.pageX;
10130                pageY = ev.pageY;
10131            }
10132            // TODO: repeat code
10133            if (isFirst) {
10134                this.origPageX = pageX;
10135                this.origPageY = pageY;
10136            }
10137            else {
10138                deltaX = pageX - this.origPageX;
10139                deltaY = pageY - this.origPageY;
10140            }
10141            return {
10142                origEvent: ev,
10143                isTouch: true,
10144                subjectEl: this.subjectEl,
10145                pageX,
10146                pageY,
10147                deltaX,
10148                deltaY,
10149            };
10150        }
10151    }
10152    // Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)
10153    function isPrimaryMouseButton(ev) {
10154        return ev.button === 0 && !ev.ctrlKey;
10155    }
10156    // Ignoring fake mouse events generated by touch
10157    // ----------------------------------------------------------------------------------------------------
10158    function startIgnoringMouse() {
10159        ignoreMouseDepth += 1;
10160        setTimeout(() => {
10161            ignoreMouseDepth -= 1;
10162        }, config.touchMouseIgnoreWait);
10163    }
10164    // We want to attach touchmove as early as possible for Safari
10165    // ----------------------------------------------------------------------------------------------------
10166    function listenerCreated() {
10167        listenerCnt += 1;
10168        if (listenerCnt === 1) {
10169            window.addEventListener('touchmove', onWindowTouchMove, { passive: false });
10170        }
10171    }
10172    function listenerDestroyed() {
10173        listenerCnt -= 1;
10174        if (!listenerCnt) {
10175            window.removeEventListener('touchmove', onWindowTouchMove, { passive: false });
10176        }
10177    }
10178    function onWindowTouchMove(ev) {
10179        if (isWindowTouchMoveCancelled) {
10180            ev.preventDefault();
10181        }
10182    }
10183
10184    /*
10185    An effect in which an element follows the movement of a pointer across the screen.
10186    The moving element is a clone of some other element.
10187    Must call start + handleMove + stop.
10188    */
10189    class ElementMirror {
10190        constructor() {
10191            this.isVisible = false; // must be explicitly enabled
10192            this.sourceEl = null;
10193            this.mirrorEl = null;
10194            this.sourceElRect = null; // screen coords relative to viewport
10195            // options that can be set directly by caller
10196            this.parentNode = document.body; // HIGHLY SUGGESTED to set this to sidestep ShadowDOM issues
10197            this.zIndex = 9999;
10198            this.revertDuration = 0;
10199        }
10200        start(sourceEl, pageX, pageY) {
10201            this.sourceEl = sourceEl;
10202            this.sourceElRect = this.sourceEl.getBoundingClientRect();
10203            this.origScreenX = pageX - window.scrollX;
10204            this.origScreenY = pageY - window.scrollY;
10205            this.deltaX = 0;
10206            this.deltaY = 0;
10207            this.updateElPosition();
10208        }
10209        handleMove(pageX, pageY) {
10210            this.deltaX = (pageX - window.scrollX) - this.origScreenX;
10211            this.deltaY = (pageY - window.scrollY) - this.origScreenY;
10212            this.updateElPosition();
10213        }
10214        // can be called before start
10215        setIsVisible(bool) {
10216            if (bool) {
10217                if (!this.isVisible) {
10218                    if (this.mirrorEl) {
10219                        this.mirrorEl.style.display = '';
10220                    }
10221                    this.isVisible = bool; // needs to happen before updateElPosition
10222                    this.updateElPosition(); // because was not updating the position while invisible
10223                }
10224            }
10225            else if (this.isVisible) {
10226                if (this.mirrorEl) {
10227                    this.mirrorEl.style.display = 'none';
10228                }
10229                this.isVisible = bool;
10230            }
10231        }
10232        // always async
10233        stop(needsRevertAnimation, callback) {
10234            let done = () => {
10235                this.cleanup();
10236                callback();
10237            };
10238            if (needsRevertAnimation &&
10239                this.mirrorEl &&
10240                this.isVisible &&
10241                this.revertDuration && // if 0, transition won't work
10242                (this.deltaX || this.deltaY) // if same coords, transition won't work
10243            ) {
10244                this.doRevertAnimation(done, this.revertDuration);
10245            }
10246            else {
10247                setTimeout(done, 0);
10248            }
10249        }
10250        doRevertAnimation(callback, revertDuration) {
10251            let mirrorEl = this.mirrorEl;
10252            let finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened
10253            mirrorEl.style.transition =
10254                'top ' + revertDuration + 'ms,' +
10255                    'left ' + revertDuration + 'ms';
10256            applyStyle(mirrorEl, {
10257                left: finalSourceElRect.left,
10258                top: finalSourceElRect.top,
10259            });
10260            whenTransitionDone(mirrorEl, () => {
10261                mirrorEl.style.transition = '';
10262                callback();
10263            });
10264        }
10265        cleanup() {
10266            if (this.mirrorEl) {
10267                removeElement(this.mirrorEl);
10268                this.mirrorEl = null;
10269            }
10270            this.sourceEl = null;
10271        }
10272        updateElPosition() {
10273            if (this.sourceEl && this.isVisible) {
10274                applyStyle(this.getMirrorEl(), {
10275                    left: this.sourceElRect.left + this.deltaX,
10276                    top: this.sourceElRect.top + this.deltaY,
10277                });
10278            }
10279        }
10280        getMirrorEl() {
10281            let sourceElRect = this.sourceElRect;
10282            let mirrorEl = this.mirrorEl;
10283            if (!mirrorEl) {
10284                mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true
10285                // we don't want long taps or any mouse interaction causing selection/menus.
10286                // would use preventSelection(), but that prevents selectstart, causing problems.
10287                mirrorEl.style.userSelect = 'none';
10288                mirrorEl.style.webkitUserSelect = 'none';
10289                mirrorEl.style.pointerEvents = 'none';
10290                mirrorEl.classList.add('fc-event-dragging');
10291                applyStyle(mirrorEl, {
10292                    position: 'fixed',
10293                    zIndex: this.zIndex,
10294                    visibility: '',
10295                    boxSizing: 'border-box',
10296                    width: sourceElRect.right - sourceElRect.left,
10297                    height: sourceElRect.bottom - sourceElRect.top,
10298                    right: 'auto',
10299                    bottom: 'auto',
10300                    margin: 0,
10301                });
10302                this.parentNode.appendChild(mirrorEl);
10303            }
10304            return mirrorEl;
10305        }
10306    }
10307
10308    /*
10309    Is a cache for a given element's scroll information (all the info that ScrollController stores)
10310    in addition the "client rectangle" of the element.. the area within the scrollbars.
10311
10312    The cache can be in one of two modes:
10313    - doesListening:false - ignores when the container is scrolled by someone else
10314    - doesListening:true - watch for scrolling and update the cache
10315    */
10316    class ScrollGeomCache extends ScrollController {
10317        constructor(scrollController, doesListening) {
10318            super();
10319            this.handleScroll = () => {
10320                this.scrollTop = this.scrollController.getScrollTop();
10321                this.scrollLeft = this.scrollController.getScrollLeft();
10322                this.handleScrollChange();
10323            };
10324            this.scrollController = scrollController;
10325            this.doesListening = doesListening;
10326            this.scrollTop = this.origScrollTop = scrollController.getScrollTop();
10327            this.scrollLeft = this.origScrollLeft = scrollController.getScrollLeft();
10328            this.scrollWidth = scrollController.getScrollWidth();
10329            this.scrollHeight = scrollController.getScrollHeight();
10330            this.clientWidth = scrollController.getClientWidth();
10331            this.clientHeight = scrollController.getClientHeight();
10332            this.clientRect = this.computeClientRect(); // do last in case it needs cached values
10333            if (this.doesListening) {
10334                this.getEventTarget().addEventListener('scroll', this.handleScroll);
10335            }
10336        }
10337        destroy() {
10338            if (this.doesListening) {
10339                this.getEventTarget().removeEventListener('scroll', this.handleScroll);
10340            }
10341        }
10342        getScrollTop() {
10343            return this.scrollTop;
10344        }
10345        getScrollLeft() {
10346            return this.scrollLeft;
10347        }
10348        setScrollTop(top) {
10349            this.scrollController.setScrollTop(top);
10350            if (!this.doesListening) {
10351                // we are not relying on the element to normalize out-of-bounds scroll values
10352                // so we need to sanitize ourselves
10353                this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0);
10354                this.handleScrollChange();
10355            }
10356        }
10357        setScrollLeft(top) {
10358            this.scrollController.setScrollLeft(top);
10359            if (!this.doesListening) {
10360                // we are not relying on the element to normalize out-of-bounds scroll values
10361                // so we need to sanitize ourselves
10362                this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0);
10363                this.handleScrollChange();
10364            }
10365        }
10366        getClientWidth() {
10367            return this.clientWidth;
10368        }
10369        getClientHeight() {
10370            return this.clientHeight;
10371        }
10372        getScrollWidth() {
10373            return this.scrollWidth;
10374        }
10375        getScrollHeight() {
10376            return this.scrollHeight;
10377        }
10378        handleScrollChange() {
10379        }
10380    }
10381
10382    class ElementScrollGeomCache extends ScrollGeomCache {
10383        constructor(el, doesListening) {
10384            super(new ElementScrollController(el), doesListening);
10385        }
10386        getEventTarget() {
10387            return this.scrollController.el;
10388        }
10389        computeClientRect() {
10390            return computeInnerRect(this.scrollController.el);
10391        }
10392    }
10393
10394    class WindowScrollGeomCache extends ScrollGeomCache {
10395        constructor(doesListening) {
10396            super(new 
vendor: 8,881 bytes, lines 10396-10600
10396WindowScrollController(), doesListening);
10397        }
10398        getEventTarget() {
10399            return window;
10400        }
10401        computeClientRect() {
10402            return {
10403                left: this.scrollLeft,
10404                right: this.scrollLeft + this.clientWidth,
10405                top: this.scrollTop,
10406                bottom: this.scrollTop + this.clientHeight,
10407            };
10408        }
10409        // the window is the only scroll object that changes it's rectangle relative
10410        // to the document's topleft as it scrolls
10411        handleScrollChange() {
10412            this.clientRect = this.computeClientRect();
10413        }
10414    }
10415
10416    // If available we are using native "performance" API instead of "Date"
10417    // Read more about it on MDN:
10418    // https://developer.mozilla.org/en-US/docs/Web/API/Performance
10419    const getTime = typeof performance === 'function' ? performance.now : Date.now;
10420    /*
10421    For a pointer interaction, automatically scrolls certain scroll containers when the pointer
10422    approaches the edge.
10423
10424    The caller must call start + handleMove + stop.
10425    */
10426    class AutoScroller {
10427        constructor() {
10428            // options that can be set by caller
10429            this.isEnabled = true;
10430            this.scrollQuery = [window, '.fc-scroller'];
10431            this.edgeThreshold = 50; // pixels
10432            this.maxVelocity = 300; // pixels per second
10433            // internal state
10434            this.pointerScreenX = null;
10435            this.pointerScreenY = null;
10436            this.isAnimating = false;
10437            this.scrollCaches = null;
10438            // protect against the initial pointerdown being too close to an edge and starting the scroll
10439            this.everMovedUp = false;
10440            this.everMovedDown = false;
10441            this.everMovedLeft = false;
10442            this.everMovedRight = false;
10443            this.animate = () => {
10444                if (this.isAnimating) { // wasn't cancelled between animation calls
10445                    let edge = this.computeBestEdge(this.pointerScreenX + window.scrollX, this.pointerScreenY + window.scrollY);
10446                    if (edge) {
10447                        let now = getTime();
10448                        this.handleSide(edge, (now - this.msSinceRequest) / 1000);
10449                        this.requestAnimation(now);
10450                    }
10451                    else {
10452                        this.isAnimating = false; // will stop animation
10453                    }
10454                }
10455            };
10456        }
10457        start(pageX, pageY, scrollStartEl) {
10458            if (this.isEnabled) {
10459                this.scrollCaches = this.buildCaches(scrollStartEl);
10460                this.pointerScreenX = null;
10461                this.pointerScreenY = null;
10462                this.everMovedUp = false;
10463                this.everMovedDown = false;
10464                this.everMovedLeft = false;
10465                this.everMovedRight = false;
10466                this.handleMove(pageX, pageY);
10467            }
10468        }
10469        handleMove(pageX, pageY) {
10470            if (this.isEnabled) {
10471                let pointerScreenX = pageX - window.scrollX;
10472                let pointerScreenY = pageY - window.scrollY;
10473                let yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY;
10474                let xDelta = this.pointerScreenX === null ? 0 : pointerScreenX - this.pointerScreenX;
10475                if (yDelta < 0) {
10476                    this.everMovedUp = true;
10477                }
10478                else if (yDelta > 0) {
10479                    this.everMovedDown = true;
10480                }
10481                if (xDelta < 0) {
10482                    this.everMovedLeft = true;
10483                }
10484                else if (xDelta > 0) {
10485                    this.everMovedRight = true;
10486                }
10487                this.pointerScreenX = pointerScreenX;
10488                this.pointerScreenY = pointerScreenY;
10489                if (!this.isAnimating) {
10490                    this.isAnimating = true;
10491                    this.requestAnimation(getTime());
10492                }
10493            }
10494        }
10495        stop() {
10496            if (this.isEnabled) {
10497                this.isAnimating = false; // will stop animation
10498                for (let scrollCache of this.scrollCaches) {
10499                    scrollCache.destroy();
10500                }
10501                this.scrollCaches = null;
10502            }
10503        }
10504        requestAnimation(now) {
10505            this.msSinceRequest = now;
10506            requestAnimationFrame(this.animate);
10507        }
10508        handleSide(edge, seconds) {
10509            let { scrollCache } = edge;
10510            let { edgeThreshold } = this;
10511            let invDistance = edgeThreshold - edge.distance;
10512            let velocity = // the closer to the edge, the faster we scroll
10513             ((invDistance * invDistance) / (edgeThreshold * edgeThreshold)) * // quadratic
10514                this.maxVelocity * seconds;
10515            let sign = 1;
10516            switch (edge.name) {
10517                case 'left':
10518                    sign = -1;
10519                // falls through
10520                case 'right':
10521                    scrollCache.setScrollLeft(scrollCache.getScrollLeft() + velocity * sign);
10522                    break;
10523                case 'top':
10524                    sign = -1;
10525                // falls through
10526                case 'bottom':
10527                    scrollCache.setScrollTop(scrollCache.getScrollTop() + velocity * sign);
10528                    break;
10529            }
10530        }
10531        // left/top are relative to document topleft
10532        computeBestEdge(left, top) {
10533            let { edgeThreshold } = this;
10534            let bestSide = null;
10535            let scrollCaches = this.scrollCaches || [];
10536            for (let scrollCache of scrollCaches) {
10537                let rect = scrollCache.clientRect;
10538                let leftDist = left - rect.left;
10539                let rightDist = rect.right - left;
10540                let topDist = top - rect.top;
10541                let bottomDist = rect.bottom - top;
10542                // completely within the rect?
10543                if (leftDist >= 0 && rightDist >= 0 && topDist >= 0 && bottomDist >= 0) {
10544                    if (topDist <= edgeThreshold && this.everMovedUp && scrollCache.canScrollUp() &&
10545                        (!bestSide || bestSide.distance > topDist)) {
10546                        bestSide = { scrollCache, name: 'top', distance: topDist };
10547                    }
10548                    if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() &&
10549                        (!bestSide || bestSide.distance > bottomDist)) {
10550                        bestSide = { scrollCache, name: 'bottom', distance: bottomDist };
10551                    }
10552                    /*
10553                    TODO: fix broken RTL scrolling. canScrollLeft always returning false
10554                    https://github.com/fullcalendar/fullcalendar/issues/4837
10555                    */
10556                    if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() &&
10557                        (!bestSide || bestSide.distance > leftDist)) {
10558                        bestSide = { scrollCache, name: 'left', distance: leftDist };
10559                    }
10560                    if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() &&
10561                        (!bestSide || bestSide.distance > rightDist)) {
10562                        bestSide = { scrollCache, name: 'right', distance: rightDist };
10563                    }
10564                }
10565            }
10566            return bestSide;
10567        }
10568        buildCaches(scrollStartEl) {
10569            return this.queryScrollEls(scrollStartEl).map((el) => {
10570                if (el === window) {
10571                    return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls
10572                }
10573                return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls
10574            });
10575        }
10576        queryScrollEls(scrollStartEl) {
10577            let els = [];
10578            for (let query of this.scrollQuery) {
10579                if (typeof query === 'object') {
10580                    els.push(query);
10581                }
10582                else {
10583                    /*
10584                    TODO: in the future, always have auto-scroll happen on element where current Hit came from
10585                    Ticket: https://github.com/fullcalendar/fullcalendar/issues/4593
10586                    */
10587                    els.push(...Array.prototype.slice.call(scrollStartEl.getRootNode().querySelectorAll(query)));
10588                }
10589            }
10590            return els;
10591        }
10592    }
10593
10594    /*
10595    Monitors dragging on an element. Has a number of high-level features:
10596    - minimum distance required before dragging
10597    - minimum wait time ("delay") before dragging
10598    - a mirror element that follows the pointer
10599    */
10600    class FeaturefulElementDragging extends 
vendor: 3,622 bytes, lines 10600-10665
10600ElementDragging {
10601        constructor(containerEl, selector) {
10602            super(containerEl);
10603            this.containerEl = containerEl;
10604            // options that can be directly set by caller
10605            // the caller can also set the PointerDragging's options as well
10606            this.delay = null;
10607            this.minDistance = 0;
10608            this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag
10609            this.mirrorNeedsRevert = false;
10610            this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup
10611            this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation
10612            this.isDelayEnded = false;
10613            this.isDistanceSurpassed = false;
10614            this.delayTimeoutId = null;
10615            this.onPointerDown = (ev) => {
10616                if (!this.isDragging) { // so new drag doesn't happen while revert animation is going
10617                    this.isInteracting = true;
10618                    this.isDelayEnded = false;
10619                    this.isDistanceSurpassed = false;
10620                    preventSelection(document.body);
10621                    preventContextMenu(document.body);
10622                    // prevent links from being visited if there's an eventual drag.
10623                    // also prevents selection in older browsers (maybe?).
10624                    // not necessary for touch, besides, browser would complain about passiveness.
10625                    if (!ev.isTouch) {
10626                        ev.origEvent.preventDefault();
10627                    }
10628                    this.emitter.trigger('pointerdown', ev);
10629                    if (this.isInteracting && // not destroyed via pointerdown handler
10630                        !this.pointer.shouldIgnoreMove) {
10631                        // actions related to initiating dragstart+dragmove+dragend...
10632                        this.mirror.setIsVisible(false); // reset. caller must set-visible
10633                        this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down
10634                        this.startDelay(ev);
10635                        if (!this.minDistance) {
10636                            this.handleDistanceSurpassed(ev);
10637                        }
10638                    }
10639                }
10640            };
10641            this.onPointerMove = (ev) => {
10642                if (this.isInteracting) {
10643                    this.emitter.trigger('pointermove', ev);
10644                    if (!this.isDistanceSurpassed) {
10645                        let minDistance = this.minDistance;
10646                        let distanceSq; // current distance from the origin, squared
10647                        let { deltaX, deltaY } = ev;
10648                        distanceSq = deltaX * deltaX + deltaY * deltaY;
10649                        if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem
10650                            this.handleDistanceSurpassed(ev);
10651                        }
10652                    }
10653                    if (this.isDragging) {
10654                        // a real pointer move? (not one simulated by scrolling)
10655                        if (ev.origEvent.type !== 'scroll') {
10656                            this.mirror.handleMove(ev.pageX, ev.pageY);
10657                            this.autoScroller.handleMove(ev.pageX, ev.pageY);
10658                        }
10659                        this.emitter.trigger('dragmove', ev);
10660                    }
10661                }
10662            };
10663            this.onPointerUp = (ev) => {
10664                if (this.isInteracting) {
10665                    this.isInteracting = false;
10666                    allowSelection(document.body);
10667                    allowContextMenu(document.body);
10668                    this.emitter.trigger('pointerup', ev); // can potentially set mirrorNeedsRevert
10669                    if (this.isDragging) {
10670                        this.autoScroller.stop();
10671                        this.tryStopDrag(ev); // which will stop the mirror
10672                    }
10673                    if (this.delayTimeoutId) {
10674                        clearTimeout(this.delayTimeoutId);
10675                        this.delayTimeoutId = null;
10676                    }
10677                }
10678            };
10679            let pointer = this.pointer = new PointerDragging(containerEl);
10680            pointer.emitter.on('pointerdown', this.onPointerDown);
10681            pointer.emitter.on('pointermove', this.onPointerMove);
10682            pointer.emitter.on('pointerup', this.onPointerUp);
10683            if (selector) {
10684                pointer.selector = selector;
10685            }
10686            this.mirror = new ElementMirror();
10687            this.autoScroller = new AutoScroller();
10688        }
10689        destroy() {
10690            this.pointer.destroy();
10691            // HACK: simulate a pointer-up to end the current drag
vendor: 3,896 bytes, lines 10692-10789
10692            // TODO: fire 'dragend' directly and stop interaction. discourage use of pointerup event (b/c might not fire)
10693            this.onPointerUp({});
10694        }
10695        startDelay(ev) {
10696            if (typeof this.delay === 'number') {
10697                this.delayTimeoutId = setTimeout(() => {
10698                    this.delayTimeoutId = null;
10699                    this.handleDelayEnd(ev);
10700                }, this.delay); // not assignable to number!
10701            }
10702            else {
10703                this.handleDelayEnd(ev);
10704            }
10705        }
10706        handleDelayEnd(ev) {
10707            this.isDelayEnded = true;
10708            this.tryStartDrag(ev);
10709        }
10710        handleDistanceSurpassed(ev) {
10711            this.isDistanceSurpassed = true;
10712            this.tryStartDrag(ev);
10713        }
10714        tryStartDrag(ev) {
10715            if (this.isDelayEnded && this.isDistanceSurpassed) {
10716                if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) {
10717                    this.isDragging = true;
10718                    this.mirrorNeedsRevert = false;
10719                    this.autoScroller.start(ev.pageX, ev.pageY, this.containerEl);
10720                    this.emitter.trigger('dragstart', ev);
10721                    if (this.touchScrollAllowed === false) {
10722                        this.pointer.cancelTouchScroll();
10723                    }
10724                }
10725            }
10726        }
10727        tryStopDrag(ev) {
10728            // .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events
10729            // that come from the document to fire beforehand. much more convenient this way.
10730            this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev));
10731        }
10732        stopDrag(ev) {
10733            this.isDragging = false;
10734            this.emitter.trigger('dragend', ev);
10735        }
10736        // fill in the implementations...
10737        setIgnoreMove(bool) {
10738            this.pointer.shouldIgnoreMove = bool;
10739        }
10740        setMirrorIsVisible(bool) {
10741            this.mirror.setIsVisible(bool);
10742        }
10743        setMirrorNeedsRevert(bool) {
10744            this.mirrorNeedsRevert = bool;
10745        }
10746        setAutoScrollEnabled(bool) {
10747            this.autoScroller.isEnabled = bool;
10748        }
10749    }
10750
10751    /*
10752    When this class is instantiated, it records the offset of an element (relative to the document topleft),
10753    and continues to monitor scrolling, updating the cached coordinates if it needs to.
10754    Does not access the DOM after instantiation, so highly performant.
10755
10756    Also keeps track of all scrolling/overflow:hidden containers that are parents of the given element
10757    and an determine if a given point is inside the combined clipping rectangle.
10758    */
10759    class OffsetTracker {
10760        constructor(el) {
10761            this.el = el;
10762            this.origRect = computeRect(el);
10763            // will work fine for divs that have overflow:hidden
10764            this.scrollCaches = getClippingParents(el).map((scrollEl) => new ElementScrollGeomCache(scrollEl, true));
10765        }
10766        destroy() {
10767            for (let scrollCache of this.scrollCaches) {
10768                scrollCache.destroy();
10769            }
10770        }
10771        computeLeft() {
10772            let left = this.origRect.left;
10773            for (let scrollCache of this.scrollCaches) {
10774                left += scrollCache.origScrollLeft - scrollCache.getScrollLeft();
10775            }
10776            return left;
10777        }
10778        computeTop() {
10779            let top = this.origRect.top;
10780            for (let scrollCache of this.scrollCaches) {
10781                top += scrollCache.origScrollTop - scrollCache.getScrollTop();
10782            }
10783            return top;
10784        }
10785        isWithinClipping(pageX, pageY) {
10786            let point = { left: pageX, top: pageY };
10787            for (let scrollCache of this.scrollCaches) {
10788                if (!isIgnoredClipping(scrollCache.getEventTarget()) &&
10789                    !
vendor: 3,268 bytes, lines 10789-10868
10789pointInsideRect(point, scrollCache.clientRect)) {
10790                    return false;
10791                }
10792            }
10793            return true;
10794        }
10795    }
10796    // certain clipping containers should never constrain interactions, like <html> and <body>
10797    // https://github.com/fullcalendar/fullcalendar/issues/3615
10798    function isIgnoredClipping(node) {
10799        let tagName = node.tagName;
10800        return tagName === 'HTML' || tagName === 'BODY';
10801    }
10802
10803    /*
10804    Tracks movement over multiple droppable areas (aka "hits")
10805    that exist in one or more DateComponents.
10806    Relies on an existing draggable.
10807
10808    emits:
10809    - pointerdown
10810    - dragstart
10811    - hitchange - fires initially, even if not over a hit
10812    - pointerup
10813    - (hitchange - again, to null, if ended over a hit)
10814    - dragend
10815    */
10816    class HitDragging {
10817        constructor(dragging, droppableStore) {
10818            // options that can be set by caller
10819            this.useSubjectCenter = false;
10820            this.requireInitial = true; // if doesn't start out on a hit, won't emit any events
10821            this.disablePointCheck = false;
10822            this.initialHit = null;
10823            this.movingHit = null;
10824            this.finalHit = null; // won't ever be populated if shouldIgnoreMove
10825            this.handlePointerDown = (ev) => {
10826                let { dragging } = this;
10827                this.initialHit = null;
10828                this.movingHit = null;
10829                this.finalHit = null;
10830                this.prepareHits();
10831                this.processFirstCoord(ev);
10832                if (this.initialHit || !this.requireInitial) {
10833                    dragging.setIgnoreMove(false);
10834                    // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :(
10835                    this.emitter.trigger('pointerdown', ev);
10836                }
10837                else {
10838                    dragging.setIgnoreMove(true);
10839                }
10840            };
10841            this.handleDragStart = (ev) => {
10842                this.emitter.trigger('dragstart', ev);
10843                this.handleMove(ev, true); // force = fire even if initially null
10844            };
10845            this.handleDragMove = (ev) => {
10846                this.emitter.trigger('dragmove', ev);
10847                this.handleMove(ev);
10848            };
10849            this.handlePointerUp = (ev) => {
10850                this.releaseHits();
10851                this.emitter.trigger('pointerup', ev);
10852            };
10853            this.handleDragEnd = (ev) => {
10854                if (this.movingHit) {
10855                    this.emitter.trigger('hitupdate', null, true, ev);
10856                }
10857                this.finalHit = this.movingHit;
10858                this.movingHit = null;
10859                this.emitter.trigger('dragend', ev);
10860            };
10861            this.droppableStore = droppableStore;
10862            dragging.emitter.on('pointerdown', this.handlePointerDown);
10863            dragging.emitter.on('dragstart', this.handleDragStart);
10864            dragging.emitter.on('dragmove', this.handleDragMove);
10865            dragging.emitter.on('pointerup', this.handlePointerUp);
10866            dragging.emitter.on('dragend', this.handleDragEnd);
10867            this.dragging = dragging;
10868            this.emitter = new 
vendor: 51,730 bytes, lines 10868-11909
10868Emitter();
10869        }
10870        // sets initialHit
10871        // sets coordAdjust
10872        processFirstCoord(ev) {
10873            let origPoint = { left: ev.pageX, top: ev.pageY };
10874            let adjustedPoint = origPoint;
10875            let subjectEl = ev.subjectEl;
10876            let subjectRect;
10877            if (subjectEl instanceof HTMLElement) { // i.e. not a Document/ShadowRoot
10878                subjectRect = computeRect(subjectEl);
10879                adjustedPoint = constrainPoint(adjustedPoint, subjectRect);
10880            }
10881            let initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top);
10882            if (initialHit) {
10883                if (this.useSubjectCenter && subjectRect) {
10884                    let slicedSubjectRect = intersectRects(subjectRect, initialHit.rect);
10885                    if (slicedSubjectRect) {
10886                        adjustedPoint = getRectCenter(slicedSubjectRect);
10887                    }
10888                }
10889                this.coordAdjust = diffPoints(adjustedPoint, origPoint);
10890            }
10891            else {
10892                this.coordAdjust = { left: 0, top: 0 };
10893            }
10894        }
10895        handleMove(ev, forceHandle) {
10896            let hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top);
10897            if (forceHandle || !isHitsEqual(this.movingHit, hit)) {
10898                this.movingHit = hit;
10899                this.emitter.trigger('hitupdate', hit, false, ev);
10900            }
10901        }
10902        prepareHits() {
10903            this.offsetTrackers = mapHash(this.droppableStore, (interactionSettings) => {
10904                interactionSettings.component.prepareHits();
10905                return new OffsetTracker(interactionSettings.el);
10906            });
10907        }
10908        releaseHits() {
10909            let { offsetTrackers } = this;
10910            for (let id in offsetTrackers) {
10911                offsetTrackers[id].destroy();
10912            }
10913            this.offsetTrackers = {};
10914        }
10915        queryHitForOffset(offsetLeft, offsetTop) {
10916            let { droppableStore, offsetTrackers } = this;
10917            let bestHit = null;
10918            for (let id in droppableStore) {
10919                let component = droppableStore[id].component;
10920                let offsetTracker = offsetTrackers[id];
10921                if (offsetTracker && // wasn't destroyed mid-drag
10922                    offsetTracker.isWithinClipping(offsetLeft, offsetTop)) {
10923                    let originLeft = offsetTracker.computeLeft();
10924                    let originTop = offsetTracker.computeTop();
10925                    let positionLeft = offsetLeft - originLeft;
10926                    let positionTop = offsetTop - originTop;
10927                    let { origRect } = offsetTracker;
10928                    let width = origRect.right - origRect.left;
10929                    let height = origRect.bottom - origRect.top;
10930                    if (
10931                    // must be within the element's bounds
10932                    positionLeft >= 0 && positionLeft < width &&
10933                        positionTop >= 0 && positionTop < height) {
10934                        let hit = component.queryHit(positionLeft, positionTop, width, height);
10935                        if (hit && (
10936                        // make sure the hit is within activeRange, meaning it's not a dead cell
10937                        rangeContainsRange(hit.dateProfile.activeRange, hit.dateSpan.range)) &&
10938                            // Ensure the component we are querying for the hit is accessibly my the pointer
10939                            // Prevents obscured calendars (ex: under a modal dialog) from accepting hit
10940                            // https://github.com/fullcalendar/fullcalendar/issues/5026
10941                            (this.disablePointCheck ||
10942                                offsetTracker.el.contains(offsetTracker.el.getRootNode().elementFromPoint(
10943                                // add-back origins to get coordinate relative to top-left of window viewport
10944                                positionLeft + originLeft - window.scrollX, positionTop + originTop - window.scrollY))) &&
10945                            (!bestHit || hit.layer > bestHit.layer)) {
10946                            hit.componentId = id;
10947                            hit.context = component.context;
10948                            // TODO: better way to re-orient rectangle
10949                            hit.rect.left += originLeft;
10950                            hit.rect.right += originLeft;
10951                            hit.rect.top += originTop;
10952                            hit.rect.bottom += originTop;
10953                            bestHit = hit;
10954                        }
10955                    }
10956                }
10957            }
10958            return bestHit;
10959        }
10960    }
10961    function isHitsEqual(hit0, hit1) {
10962        if (!hit0 && !hit1) {
10963            return true;
10964        }
10965        if (Boolean(hit0) !== Boolean(hit1)) {
10966            return false;
10967        }
10968        return isDateSpansEqual(hit0.dateSpan, hit1.dateSpan);
10969    }
10970
10971    function buildDatePointApiWithContext(dateSpan, context) {
10972        let props = {};
10973        for (let transform of context.pluginHooks.datePointTransforms) {
10974            Object.assign(props, transform(dateSpan, context));
10975        }
10976        Object.assign(props, buildDatePointApi(dateSpan, context.dateEnv));
10977        return props;
10978    }
10979    function buildDatePointApi(span, dateEnv) {
10980        return {
10981            date: dateEnv.toDate(span.range.start),
10982            dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }),
10983            allDay: span.allDay,
10984        };
10985    }
10986
10987    /*
10988    Monitors when the user clicks on a specific date/time of a component.
10989    A pointerdown+pointerup on the same "hit" constitutes a click.
10990    */
10991    class DateClicking extends Interaction {
10992        constructor(settings) {
10993            super(settings);
10994            this.handlePointerDown = (pev) => {
10995                let { dragging } = this;
10996                let downEl = pev.origEvent.target;
10997                // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired
10998                dragging.setIgnoreMove(!this.component.isValidDateDownEl(downEl));
10999            };
11000            // won't even fire if moving was ignored
11001            this.handleDragEnd = (ev) => {
11002                let { component } = this;
11003                let { pointer } = this.dragging;
11004                if (!pointer.wasTouchScroll) {
11005                    let { initialHit, finalHit } = this.hitDragging;
11006                    if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) {
11007                        let { context } = component;
11008                        let arg = Object.assign(Object.assign({}, buildDatePointApiWithContext(initialHit.dateSpan, context)), { dayEl: initialHit.dayEl, jsEvent: ev.origEvent, view: context.viewApi || context.calendarApi.view });
11009                        context.emitter.trigger('dateClick', arg);
11010                    }
11011                }
11012            };
11013            // we DO want to watch pointer moves because otherwise finalHit won't get populated
11014            this.dragging = new FeaturefulElementDragging(settings.el);
11015            this.dragging.autoScroller.isEnabled = false;
11016            let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
11017            hitDragging.emitter.on('pointerdown', this.handlePointerDown);
11018            hitDragging.emitter.on('dragend', this.handleDragEnd);
11019        }
11020        destroy() {
11021            this.dragging.destroy();
11022        }
11023    }
11024
11025    /*
11026    Tracks when the user selects a portion of time of a component,
11027    constituted by a drag over date cells, with a possible delay at the beginning of the drag.
11028    */
11029    class DateSelecting extends Interaction {
11030        constructor(settings) {
11031            super(settings);
11032            this.dragSelection = null;
11033            this.handlePointerDown = (ev) => {
11034                let { component, dragging } = this;
11035                let { options } = component.context;
11036                let canSelect = options.selectable &&
11037                    component.isValidDateDownEl(ev.origEvent.target);
11038                // don't bother to watch expensive moves if component won't do selection
11039                dragging.setIgnoreMove(!canSelect);
11040                // if touch, require user to hold down
11041                dragging.delay = ev.isTouch ? getComponentTouchDelay$1(component) : null;
11042            };
11043            this.handleDragStart = (ev) => {
11044                this.component.context.calendarApi.unselect(ev); // unselect previous selections
11045            };
11046            this.handleHitUpdate = (hit, isFinal) => {
11047                let { context } = this.component;
11048                let dragSelection = null;
11049                let isInvalid = false;
11050                if (hit) {
11051                    let initialHit = this.hitDragging.initialHit;
11052                    let disallowed = hit.componentId === initialHit.componentId
11053                        && this.isHitComboAllowed
11054                        && !this.isHitComboAllowed(initialHit, hit);
11055                    if (!disallowed) {
11056                        dragSelection = joinHitsIntoSelection(initialHit, hit, context.pluginHooks.dateSelectionTransformers);
11057                    }
11058                    if (!dragSelection || !isDateSelectionValid(dragSelection, hit.dateProfile, context)) {
11059                        isInvalid = true;
11060                        dragSelection = null;
11061                    }
11062                }
11063                if (dragSelection) {
11064                    context.dispatch({ type: 'SELECT_DATES', selection: dragSelection });
11065                }
11066                else if (!isFinal) { // only unselect if moved away while dragging
11067                    context.dispatch({ type: 'UNSELECT_DATES' });
11068                }
11069                if (!isInvalid) {
11070                    enableCursor();
11071                }
11072                else {
11073                    disableCursor();
11074                }
11075                if (!isFinal) {
11076                    this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging
11077                }
11078            };
11079            this.handlePointerUp = (pev) => {
11080                if (this.dragSelection) {
11081                    // selection is already rendered, so just need to report selection
11082                    triggerDateSelect(this.dragSelection, pev, this.component.context);
11083                    this.dragSelection = null;
11084                }
11085            };
11086            let { component } = settings;
11087            let { options } = component.context;
11088            let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
11089            dragging.touchScrollAllowed = false;
11090            dragging.minDistance = options.selectMinDistance || 0;
11091            dragging.autoScroller.isEnabled = options.dragScroll;
11092            let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
11093            hitDragging.emitter.on('pointerdown', this.handlePointerDown);
11094            hitDragging.emitter.on('dragstart', this.handleDragStart);
11095            hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
11096            hitDragging.emitter.on('pointerup', this.handlePointerUp);
11097        }
11098        destroy() {
11099            this.dragging.destroy();
11100        }
11101    }
11102    function getComponentTouchDelay$1(component) {
11103        let { options } = component.context;
11104        let delay = options.selectLongPressDelay;
11105        if (delay == null) {
11106            delay = options.longPressDelay;
11107        }
11108        return delay;
11109    }
11110    function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) {
11111        let dateSpan0 = hit0.dateSpan;
11112        let dateSpan1 = hit1.dateSpan;
11113        let ms = [
11114            dateSpan0.range.start,
11115            dateSpan0.range.end,
11116            dateSpan1.range.start,
11117            dateSpan1.range.end,
11118        ];
11119        ms.sort(compareNumbers);
11120        let props = {};
11121        for (let transformer of dateSelectionTransformers) {
11122            let res = transformer(hit0, hit1);
11123            if (res === false) {
11124                return null;
11125            }
11126            if (res) {
11127                Object.assign(props, res);
11128            }
11129        }
11130        props.range = { start: ms[0], end: ms[3] };
11131        props.allDay = dateSpan0.allDay;
11132        return props;
11133    }
11134
11135    class EventDragging extends Interaction {
11136        constructor(settings) {
11137            super(settings);
11138            // internal state
11139            this.subjectEl = null;
11140            this.subjectSeg = null; // the seg being selected/dragged
11141            this.isDragging = false;
11142            this.eventRange = null;
11143            this.relevantEvents = null; // the events being dragged
11144            this.receivingContext = null;
11145            this.validMutation = null;
11146            this.mutatedRelevantEvents = null;
11147            this.handlePointerDown = (ev) => {
11148                let origTarget = ev.origEvent.target;
11149                let { component, dragging } = this;
11150                let { mirror } = dragging;
11151                let { options } = component.context;
11152                let initialContext = component.context;
11153                this.subjectEl = ev.subjectEl;
11154                let subjectSeg = this.subjectSeg = getElSeg(ev.subjectEl);
11155                let eventRange = this.eventRange = subjectSeg.eventRange;
11156                let eventInstanceId = eventRange.instance.instanceId;
11157                this.relevantEvents = getRelevantEvents(initialContext.getCurrentData().eventStore, eventInstanceId);
11158                dragging.minDistance = ev.isTouch ? 0 : options.eventDragMinDistance;
11159                dragging.delay =
11160                    // only do a touch delay if touch and this event hasn't been selected yet
11161                    (ev.isTouch && eventInstanceId !== component.props.eventSelection) ?
11162                        getComponentTouchDelay(component) :
11163                        null;
11164                if (options.fixedMirrorParent) {
11165                    mirror.parentNode = options.fixedMirrorParent;
11166                }
11167                else {
11168                    mirror.parentNode = elementClosest(origTarget, '.fc');
11169                }
11170                mirror.revertDuration = options.dragRevertDuration;
11171                let isValid = component.isValidSegDownEl(origTarget) &&
11172                    !elementClosest(origTarget, '.fc-event-resizer'); // NOT on a resizer
11173                dragging.setIgnoreMove(!isValid);
11174                // disable dragging for elements that are resizable (ie, selectable)
11175                // but are not draggable
11176                this.isDragging = isValid &&
11177                    ev.subjectEl.classList.contains('fc-event-draggable');
11178            };
11179            this.handleDragStart = (ev) => {
11180                let initialContext = this.component.context;
11181                let eventRange = this.eventRange;
11182                let eventInstanceId = eventRange.instance.instanceId;
11183                if (ev.isTouch) {
11184                    // need to select a different event?
11185                    if (eventInstanceId !== this.component.props.eventSelection) {
11186                        initialContext.dispatch({ type: 'SELECT_EVENT', eventInstanceId });
11187                    }
11188                }
11189                else {
11190                    // if now using mouse, but was previous touch interaction, clear selected event
11191                    initialContext.dispatch({ type: 'UNSELECT_EVENT' });
11192                }
11193                if (this.isDragging) {
11194                    initialContext.calendarApi.unselect(ev); // unselect *date* selection
11195                    initialContext.emitter.trigger('eventDragStart', {
11196                        el: this.subjectEl,
11197                        event: new EventImpl(initialContext, eventRange.def, eventRange.instance),
11198                        jsEvent: ev.origEvent,
11199                        view: initialContext.viewApi,
11200                    });
11201                }
11202            };
11203            this.handleHitUpdate = (hit, isFinal) => {
11204                if (!this.isDragging) {
11205                    return;
11206                }
11207                let relevantEvents = this.relevantEvents;
11208                let initialHit = this.hitDragging.initialHit;
11209                let initialContext = this.component.context;
11210                // states based on new hit
11211                let receivingContext = null;
11212                let mutation = null;
11213                let mutatedRelevantEvents = null;
11214                let isInvalid = false;
11215                let interaction = {
11216                    affectedEvents: relevantEvents,
11217                    mutatedEvents: createEmptyEventStore(),
11218                    isEvent: true,
11219                };
11220                if (hit) {
11221                    receivingContext = hit.context;
11222                    let receivingOptions = receivingContext.options;
11223                    if (initialContext === receivingContext ||
11224                        (receivingOptions.editable && receivingOptions.droppable)) {
11225                        mutation = computeEventMutation(initialHit, hit, this.eventRange.instance.range.start, receivingContext.getCurrentData().pluginHooks.eventDragMutationMassagers);
11226                        if (mutation) {
11227                            mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, receivingContext.getCurrentData().eventUiBases, mutation, receivingContext);
11228                            interaction.mutatedEvents = mutatedRelevantEvents;
11229                            if (!isInteractionValid(interaction, hit.dateProfile, receivingContext)) {
11230                                isInvalid = true;
11231                                mutation = null;
11232                                mutatedRelevantEvents = null;
11233                                interaction.mutatedEvents = createEmptyEventStore();
11234                            }
11235                        }
11236                    }
11237                    else {
11238                        receivingContext = null;
11239                    }
11240                }
11241                this.displayDrag(receivingContext, interaction);
11242                if (!isInvalid) {
11243                    enableCursor();
11244                }
11245                else {
11246                    disableCursor();
11247                }
11248                if (!isFinal) {
11249                    if (initialContext === receivingContext && // TODO: write test for this
11250                        isHitsEqual(initialHit, hit)) {
11251                        mutation = null;
11252                    }
11253                    this.dragging.setMirrorNeedsRevert(!mutation);
11254                    // render the mirror if no already-rendered mirror
11255                    // TODO: wish we could somehow wait for dispatch to guarantee render
11256                    this.dragging.setMirrorIsVisible(!hit || !this.subjectEl.getRootNode().querySelector('.fc-event-mirror'));
11257                    // assign states based on new hit
11258                    this.receivingContext = receivingContext;
11259                    this.validMutation = mutation;
11260                    this.mutatedRelevantEvents = mutatedRelevantEvents;
11261                }
11262            };
11263            this.handlePointerUp = () => {
11264                if (!this.isDragging) {
11265                    this.cleanup(); // because handleDragEnd won't fire
11266                }
11267            };
11268            this.handleDragEnd = (ev) => {
11269                if (this.isDragging) {
11270                    let initialContext = this.component.context;
11271                    let initialView = initialContext.viewApi;
11272                    let { receivingContext, validMutation } = this;
11273                    let eventDef = this.eventRange.def;
11274                    let eventInstance = this.eventRange.instance;
11275                    let eventApi = new EventImpl(initialContext, eventDef, eventInstance);
11276                    let relevantEvents = this.relevantEvents;
11277                    let mutatedRelevantEvents = this.mutatedRelevantEvents;
11278                    let { finalHit } = this.hitDragging;
11279                    this.clearDrag(); // must happen after revert animation
11280                    initialContext.emitter.trigger('eventDragStop', {
11281                        el: this.subjectEl,
11282                        event: eventApi,
11283                        jsEvent: ev.origEvent,
11284                        view: initialView,
11285                    });
11286                    if (validMutation) {
11287                        // dropped within same calendar
11288                        if (receivingContext === initialContext) {
11289                            let updatedEventApi = new EventImpl(initialContext, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null);
11290                            initialContext.dispatch({
11291                                type: 'MERGE_EVENTS',
11292                                eventStore: mutatedRelevantEvents,
11293                            });
11294                            let eventChangeArg = {
11295                                oldEvent: eventApi,
11296                                event: updatedEventApi,
11297                                relatedEvents: buildEventApis(mutatedRelevantEvents, initialContext, eventInstance),
11298                                revert() {
11299                                    initialContext.dispatch({
11300                                        type: 'MERGE_EVENTS',
11301                                        eventStore: relevantEvents, // the pre-change data
11302                                    });
11303                                },
11304                            };
11305                            let transformed = {};
11306                            for (let transformer of initialContext.getCurrentData().pluginHooks.eventDropTransformers) {
11307                                Object.assign(transformed, transformer(validMutation, initialContext));
11308                            }
11309                            initialContext.emitter.trigger('eventDrop', Object.assign(Object.assign(Object.assign({}, eventChangeArg), transformed), { el: ev.subjectEl, delta: validMutation.datesDelta, jsEvent: ev.origEvent, view: initialView }));
11310                            initialContext.emitter.trigger('eventChange', eventChangeArg);
11311                            // dropped in different calendar
11312                        }
11313                        else if (receivingContext) {
11314                            let eventRemoveArg = {
11315                                event: eventApi,
11316                                relatedEvents: buildEventApis(relevantEvents, initialContext, eventInstance),
11317                                revert() {
11318                                    initialContext.dispatch({
11319                                        type: 'MERGE_EVENTS',
11320                                        eventStore: relevantEvents,
11321                                    });
11322                                },
11323                            };
11324                            initialContext.emitter.trigger('eventLeave', Object.assign(Object.assign({}, eventRemoveArg), { draggedEl: ev.subjectEl, view: initialView }));
11325                            initialContext.dispatch({
11326                                type: 'REMOVE_EVENTS',
11327                                eventStore: relevantEvents,
11328                            });
11329                            initialContext.emitter.trigger('eventRemove', eventRemoveArg);
11330                            let addedEventDef = mutatedRelevantEvents.defs[eventDef.defId];
11331                            let addedEventInstance = mutatedRelevantEvents.instances[eventInstance.instanceId];
11332                            let addedEventApi = new EventImpl(receivingContext, addedEventDef, addedEventInstance);
11333                            receivingContext.dispatch({
11334                                type: 'MERGE_EVENTS',
11335                                eventStore: mutatedRelevantEvents,
11336                            });
11337                            let eventAddArg = {
11338                                event: addedEventApi,
11339                                relatedEvents: buildEventApis(mutatedRelevantEvents, receivingContext, addedEventInstance),
11340                                revert() {
11341                                    receivingContext.dispatch({
11342                                        type: 'REMOVE_EVENTS',
11343                                        eventStore: mutatedRelevantEvents,
11344                                    });
11345                                },
11346                            };
11347                            receivingContext.emitter.trigger('eventAdd', eventAddArg);
11348                            if (ev.isTouch) {
11349                                receivingContext.dispatch({
11350                                    type: 'SELECT_EVENT',
11351                                    eventInstanceId: eventInstance.instanceId,
11352                                });
11353                            }
11354                            receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.context.viewApi }));
11355                            receivingContext.emitter.trigger('eventReceive', Object.assign(Object.assign({}, eventAddArg), { draggedEl: ev.subjectEl, view: finalHit.context.viewApi }));
11356                        }
11357                    }
11358                    else {
11359                        initialContext.emitter.trigger('_noEventDrop');
11360                    }
11361                }
11362                this.cleanup();
11363            };
11364            let { component } = this;
11365            let { options } = component.context;
11366            let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
11367            dragging.pointer.selector = EventDragging.SELECTOR;
11368            dragging.touchScrollAllowed = false;
11369            dragging.autoScroller.isEnabled = options.dragScroll;
11370            let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsStore);
11371            hitDragging.useSubjectCenter = settings.useEventCenter;
11372            hitDragging.emitter.on('pointerdown', this.handlePointerDown);
11373            hitDragging.emitter.on('dragstart', this.handleDragStart);
11374            hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
11375            hitDragging.emitter.on('pointerup', this.handlePointerUp);
11376            hitDragging.emitter.on('dragend', this.handleDragEnd);
11377        }
11378        destroy() {
11379            this.dragging.destroy();
11380        }
11381        // render a drag state on the next receivingCalendar
11382        displayDrag(nextContext, state) {
11383            let initialContext = this.component.context;
11384            let prevContext = this.receivingContext;
11385            // does the previous calendar need to be cleared?
11386            if (prevContext && prevContext !== nextContext) {
11387                // does the initial calendar need to be cleared?
11388                // if so, don't clear all the way. we still need to to hide the affectedEvents
11389                if (prevContext === initialContext) {
11390                    prevContext.dispatch({
11391                        type: 'SET_EVENT_DRAG',
11392                        state: {
11393                            affectedEvents: state.affectedEvents,
11394                            mutatedEvents: createEmptyEventStore(),
11395                            isEvent: true,
11396                        },
11397                    });
11398                    // completely clear the old calendar if it wasn't the initial
11399                }
11400                else {
11401                    prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
11402                }
11403            }
11404            if (nextContext) {
11405                nextContext.dispatch({ type: 'SET_EVENT_DRAG', state });
11406            }
11407        }
11408        clearDrag() {
11409            let initialCalendar = this.component.context;
11410            let { receivingContext } = this;
11411            if (receivingContext) {
11412                receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
11413            }
11414            // the initial calendar might have an dummy drag state from displayDrag
11415            if (initialCalendar !== receivingContext) {
11416                initialCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
11417            }
11418        }
11419        cleanup() {
11420            this.subjectSeg = null;
11421            this.isDragging = false;
11422            this.eventRange = null;
11423            this.relevantEvents = null;
11424            this.receivingContext = null;
11425            this.validMutation = null;
11426            this.mutatedRelevantEvents = null;
11427        }
11428    }
11429    // TODO: test this in IE11
11430    // QUESTION: why do we need it on the resizable???
11431    EventDragging.SELECTOR = '.fc-event-draggable, .fc-event-resizable';
11432    function computeEventMutation(hit0, hit1, eventInstanceStart, massagers) {
11433        let dateSpan0 = hit0.dateSpan;
11434        let dateSpan1 = hit1.dateSpan;
11435        let date0 = dateSpan0.range.start;
11436        let date1 = dateSpan1.range.start;
11437        let standardProps = {};
11438        if (dateSpan0.allDay !== dateSpan1.allDay) {
11439            standardProps.allDay = dateSpan1.allDay;
11440            standardProps.hasEnd = hit1.context.options.allDayMaintainDuration;
11441            if (dateSpan1.allDay) {
11442                // means date1 is already start-of-day,
11443                // but date0 needs to be converted
11444                date0 = startOfDay(eventInstanceStart);
11445            }
11446            else {
11447                // Moving from allDate->timed
11448                // Doesn't matter where on the event the drag began, mutate the event's start-date to date1
11449                date0 = eventInstanceStart;
11450            }
11451        }
11452        let delta = diffDates(date0, date1, hit0.context.dateEnv, hit0.componentId === hit1.componentId ?
11453            hit0.largeUnit :
11454            null);
11455        if (delta.milliseconds) { // has hours/minutes/seconds
11456            standardProps.allDay = false;
11457        }
11458        let mutation = {
11459            datesDelta: delta,
11460            standardProps,
11461        };
11462        for (let massager of massagers) {
11463            massager(mutation, hit0, hit1);
11464        }
11465        return mutation;
11466    }
11467    function getComponentTouchDelay(component) {
11468        let { options } = component.context;
11469        let delay = options.eventLongPressDelay;
11470        if (delay == null) {
11471            delay = options.longPressDelay;
11472        }
11473        return delay;
11474    }
11475
11476    class EventResizing extends Interaction {
11477        constructor(settings) {
11478            super(settings);
11479            // internal state
11480            this.draggingSegEl = null;
11481            this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg?
11482            this.eventRange = null;
11483            this.relevantEvents = null;
11484            this.validMutation = null;
11485            this.mutatedRelevantEvents = null;
11486            this.handlePointerDown = (ev) => {
11487                let { component } = this;
11488                let segEl = this.querySegEl(ev);
11489                let seg = getElSeg(segEl);
11490                let eventRange = this.eventRange = seg.eventRange;
11491                this.dragging.minDistance = component.context.options.eventDragMinDistance;
11492                // if touch, need to be working with a selected event
11493                this.dragging.setIgnoreMove(!this.component.isValidSegDownEl(ev.origEvent.target) ||
11494                    (ev.isTouch && this.component.props.eventSelection !== eventRange.instance.instanceId));
11495            };
11496            this.handleDragStart = (ev) => {
11497                let { context } = this.component;
11498                let eventRange = this.eventRange;
11499                this.relevantEvents = getRelevantEvents(context.getCurrentData().eventStore, this.eventRange.instance.instanceId);
11500                let segEl = this.querySegEl(ev);
11501                this.draggingSegEl = segEl;
11502                this.draggingSeg = getElSeg(segEl);
11503                context.calendarApi.unselect();
11504                context.emitter.trigger('eventResizeStart', {
11505                    el: segEl,
11506                    event: new EventImpl(context, eventRange.def, eventRange.instance),
11507                    jsEvent: ev.origEvent,
11508                    view: context.viewApi,
11509                });
11510            };
11511            this.handleHitUpdate = (hit, isFinal, ev) => {
11512                let { context } = this.component;
11513                let relevantEvents = this.relevantEvents;
11514                let initialHit = this.hitDragging.initialHit;
11515                let eventInstance = this.eventRange.instance;
11516                let mutation = null;
11517                let mutatedRelevantEvents = null;
11518                let isInvalid = false;
11519                let interaction = {
11520                    affectedEvents: relevantEvents,
11521                    mutatedEvents: createEmptyEventStore(),
11522                    isEvent: true,
11523                };
11524                if (hit) {
11525                    let disallowed = hit.componentId === initialHit.componentId
11526                        && this.isHitComboAllowed
11527                        && !this.isHitComboAllowed(initialHit, hit);
11528                    if (!disallowed) {
11529                        mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-event-resizer-start'), eventInstance.range);
11530                    }
11531                }
11532                if (mutation) {
11533                    mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, context.getCurrentData().eventUiBases, mutation, context);
11534                    interaction.mutatedEvents = mutatedRelevantEvents;
11535                    if (!isInteractionValid(interaction, hit.dateProfile, context)) {
11536                        isInvalid = true;
11537                        mutation = null;
11538                        mutatedRelevantEvents = null;
11539                        interaction.mutatedEvents = null;
11540                    }
11541                }
11542                if (mutatedRelevantEvents) {
11543                    context.dispatch({
11544                        type: 'SET_EVENT_RESIZE',
11545                        state: interaction,
11546                    });
11547                }
11548                else {
11549                    context.dispatch({ type: 'UNSET_EVENT_RESIZE' });
11550                }
11551                if (!isInvalid) {
11552                    enableCursor();
11553                }
11554                else {
11555                    disableCursor();
11556                }
11557                if (!isFinal) {
11558                    if (mutation && isHitsEqual(initialHit, hit)) {
11559                        mutation = null;
11560                    }
11561                    this.validMutation = mutation;
11562                    this.mutatedRelevantEvents = mutatedRelevantEvents;
11563                }
11564            };
11565            this.handleDragEnd = (ev) => {
11566                let { context } = this.component;
11567                let eventDef = this.eventRange.def;
11568                let eventInstance = this.eventRange.instance;
11569                let eventApi = new EventImpl(context, eventDef, eventInstance);
11570                let relevantEvents = this.relevantEvents;
11571                let mutatedRelevantEvents = this.mutatedRelevantEvents;
11572                context.emitter.trigger('eventResizeStop', {
11573                    el: this.draggingSegEl,
11574                    event: eventApi,
11575                    jsEvent: ev.origEvent,
11576                    view: context.viewApi,
11577                });
11578                if (this.validMutation) {
11579                    let updatedEventApi = new EventImpl(context, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null);
11580                    context.dispatch({
11581                        type: 'MERGE_EVENTS',
11582                        eventStore: mutatedRelevantEvents,
11583                    });
11584                    let eventChangeArg = {
11585                        oldEvent: eventApi,
11586                        event: updatedEventApi,
11587                        relatedEvents: buildEventApis(mutatedRelevantEvents, context, eventInstance),
11588                        revert() {
11589                            context.dispatch({
11590                                type: 'MERGE_EVENTS',
11591                                eventStore: relevantEvents, // the pre-change events
11592                            });
11593                        },
11594                    };
11595                    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 }));
11596                    context.emitter.trigger('eventChange', eventChangeArg);
11597                }
11598                else {
11599                    context.emitter.trigger('_noEventResize');
11600                }
11601                // reset all internal state
11602                this.draggingSeg = null;
11603                this.relevantEvents = null;
11604                this.validMutation = null;
11605                // okay to keep eventInstance around. useful to set it in handlePointerDown
11606            };
11607            let { component } = settings;
11608            let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
11609            dragging.pointer.selector = '.fc-event-resizer';
11610            dragging.touchScrollAllowed = false;
11611            dragging.autoScroller.isEnabled = component.context.options.dragScroll;
11612            let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
11613            hitDragging.emitter.on('pointerdown', this.handlePointerDown);
11614            hitDragging.emitter.on('dragstart', this.handleDragStart);
11615            hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
11616            hitDragging.emitter.on('dragend', this.handleDragEnd);
11617        }
11618        destroy() {
11619            this.dragging.destroy();
11620        }
11621        querySegEl(ev) {
11622            return elementClosest(ev.subjectEl, '.fc-event');
11623        }
11624    }
11625    function computeMutation(hit0, hit1, isFromStart, instanceRange) {
11626        let dateEnv = hit0.context.dateEnv;
11627        let date0 = hit0.dateSpan.range.start;
11628        let date1 = hit1.dateSpan.range.start;
11629        let delta = diffDates(date0, date1, dateEnv, hit0.largeUnit);
11630        if (isFromStart) {
11631            if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) {
11632                return { startDelta: delta };
11633            }
11634        }
11635        else if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) {
11636            return { endDelta: delta };
11637        }
11638        return null;
11639    }
11640
11641    class UnselectAuto {
11642        constructor(context) {
11643            this.context = context;
11644            this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system
11645            this.matchesCancel = false;
11646            this.matchesEvent = false;
11647            this.onSelect = (selectInfo) => {
11648                if (selectInfo.jsEvent) {
11649                    this.isRecentPointerDateSelect = true;
11650                }
11651            };
11652            this.onDocumentPointerDown = (pev) => {
11653                let unselectCancel = this.context.options.unselectCancel;
11654                let downEl = getEventTargetViaRoot(pev.origEvent);
11655                this.matchesCancel = !!elementClosest(downEl, unselectCancel);
11656                this.matchesEvent = !!elementClosest(downEl, EventDragging.SELECTOR); // interaction started on an event?
11657            };
11658            this.onDocumentPointerUp = (pev) => {
11659                let { context } = this;
11660                let { documentPointer } = this;
11661                let calendarState = context.getCurrentData();
11662                // touch-scrolling should never unfocus any type of selection
11663                if (!documentPointer.wasTouchScroll) {
11664                    if (calendarState.dateSelection && // an existing date selection?
11665                        !this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp?
11666                    ) {
11667                        let unselectAuto = context.options.unselectAuto;
11668                        if (unselectAuto && (!unselectAuto || !this.matchesCancel)) {
11669                            context.calendarApi.unselect(pev);
11670                        }
11671                    }
11672                    if (calendarState.eventSelection && // an existing event selected?
11673                        !this.matchesEvent // interaction DIDN'T start on an event
11674                    ) {
11675                        context.dispatch({ type: 'UNSELECT_EVENT' });
11676                    }
11677                }
11678                this.isRecentPointerDateSelect = false;
11679            };
11680            let documentPointer = this.documentPointer = new PointerDragging(document);
11681            documentPointer.shouldIgnoreMove = true;
11682            documentPointer.shouldWatchScroll = false;
11683            documentPointer.emitter.on('pointerdown', this.onDocumentPointerDown);
11684            documentPointer.emitter.on('pointerup', this.onDocumentPointerUp);
11685            /*
11686            TODO: better way to know about whether there was a selection with the pointer
11687            */
11688            context.emitter.on('select', this.onSelect);
11689        }
11690        destroy() {
11691            this.context.emitter.off('select', this.onSelect);
11692            this.documentPointer.destroy();
11693        }
11694    }
11695
11696    const OPTION_REFINERS$3 = {
11697        fixedMirrorParent: identity,
11698    };
11699    const LISTENER_REFINERS = {
11700        dateClick: identity,
11701        eventDragStart: identity,
11702        eventDragStop: identity,
11703        eventDrop: identity,
11704        eventResizeStart: identity,
11705        eventResizeStop: identity,
11706        eventResize: identity,
11707        drop: identity,
11708        eventReceive: identity,
11709        eventLeave: identity,
11710    };
11711
11712    /*
11713    Given an already instantiated draggable object for one-or-more elements,
11714    Interprets any dragging as an attempt to drag an events that lives outside
11715    of a calendar onto a calendar.
11716    */
11717    class ExternalElementDragging {
11718        constructor(dragging, suppliedDragMeta) {
11719            this.receivingContext = null;
11720            this.droppableEvent = null; // will exist for all drags, even if create:false
11721            this.suppliedDragMeta = null;
11722            this.dragMeta = null;
11723            this.handleDragStart = (ev) => {
11724                this.dragMeta = this.buildDragMeta(ev.subjectEl);
11725            };
11726            this.handleHitUpdate = (hit, isFinal, ev) => {
11727                let { dragging } = this.hitDragging;
11728                let receivingContext = null;
11729                let droppableEvent = null;
11730                let isInvalid = false;
11731                let interaction = {
11732                    affectedEvents: createEmptyEventStore(),
11733                    mutatedEvents: createEmptyEventStore(),
11734                    isEvent: this.dragMeta.create,
11735                };
11736                if (hit) {
11737                    receivingContext = hit.context;
11738                    if (this.canDropElOnCalendar(ev.subjectEl, receivingContext)) {
11739                        droppableEvent = computeEventForDateSpan(hit.dateSpan, this.dragMeta, receivingContext);
11740                        interaction.mutatedEvents = eventTupleToStore(droppableEvent);
11741                        isInvalid = !isInteractionValid(interaction, hit.dateProfile, receivingContext);
11742                        if (isInvalid) {
11743                            interaction.mutatedEvents = createEmptyEventStore();
11744                            droppableEvent = null;
11745                        }
11746                    }
11747                }
11748                this.displayDrag(receivingContext, interaction);
11749                // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?)
11750                // TODO: wish we could somehow wait for dispatch to guarantee render
11751                dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-event-mirror'));
11752                if (!isInvalid) {
11753                    enableCursor();
11754                }
11755                else {
11756                    disableCursor();
11757                }
11758                if (!isFinal) {
11759                    dragging.setMirrorNeedsRevert(!droppableEvent);
11760                    this.receivingContext = receivingContext;
11761                    this.droppableEvent = droppableEvent;
11762                }
11763            };
11764            this.handleDragEnd = (pev) => {
11765                let { receivingContext, droppableEvent } = this;
11766                this.clearDrag();
11767                if (receivingContext && droppableEvent) {
11768                    let finalHit = this.hitDragging.finalHit;
11769                    let finalView = finalHit.context.viewApi;
11770                    let dragMeta = this.dragMeta;
11771                    receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView }));
11772                    if (dragMeta.create) {
11773                        let addingEvents = eventTupleToStore(droppableEvent);
11774                        receivingContext.dispatch({
11775                            type: 'MERGE_EVENTS',
11776                            eventStore: addingEvents,
11777                        });
11778                        if (pev.isTouch) {
11779                            receivingContext.dispatch({
11780                                type: 'SELECT_EVENT',
11781                                eventInstanceId: droppableEvent.instance.instanceId,
11782                            });
11783                        }
11784                        // signal that an external event landed
11785                        receivingContext.emitter.trigger('eventReceive', {
11786                            event: new EventImpl(receivingContext, droppableEvent.def, droppableEvent.instance),
11787                            relatedEvents: [],
11788                            revert() {
11789                                receivingContext.dispatch({
11790                                    type: 'REMOVE_EVENTS',
11791                                    eventStore: addingEvents,
11792                                });
11793                            },
11794                            draggedEl: pev.subjectEl,
11795                            view: finalView,
11796                        });
11797                    }
11798                }
11799                this.receivingContext = null;
11800                this.droppableEvent = null;
11801            };
11802            let hitDragging = this.hitDragging = new HitDragging(dragging, interactionSettingsStore);
11803            hitDragging.requireInitial = false; // will start outside of a component
11804            hitDragging.emitter.on('dragstart', this.handleDragStart);
11805            hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
11806            hitDragging.emitter.on('dragend', this.handleDragEnd);
11807            this.suppliedDragMeta = suppliedDragMeta;
11808        }
11809        buildDragMeta(subjectEl) {
11810            if (typeof this.suppliedDragMeta === 'object') {
11811                return parseDragMeta(this.suppliedDragMeta);
11812            }
11813            if (typeof this.suppliedDragMeta === 'function') {
11814                return parseDragMeta(this.suppliedDragMeta(subjectEl));
11815            }
11816            return getDragMetaFromEl(subjectEl);
11817        }
11818        displayDrag(nextContext, state) {
11819            let prevContext = this.receivingContext;
11820            if (prevContext && prevContext !== nextContext) {
11821                prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
11822            }
11823            if (nextContext) {
11824                nextContext.dispatch({ type: 'SET_EVENT_DRAG', state });
11825            }
11826        }
11827        clearDrag() {
11828            if (this.receivingContext) {
11829                this.receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
11830            }
11831        }
11832        canDropElOnCalendar(el, receivingContext) {
11833            let dropAccept = receivingContext.options.dropAccept;
11834            if (typeof dropAccept === 'function') {
11835                return dropAccept.call(receivingContext.calendarApi, el);
11836            }
11837            if (typeof dropAccept === 'string' && dropAccept) {
11838                return Boolean(elementMatches(el, dropAccept));
11839            }
11840            return true;
11841        }
11842    }
11843    // Utils for computing event store from the DragMeta
11844    // ----------------------------------------------------------------------------------------------------
11845    function computeEventForDateSpan(dateSpan, dragMeta, context) {
11846        let defProps = Object.assign({}, dragMeta.leftoverProps);
11847        for (let transform of context.pluginHooks.externalDefTransforms) {
11848            Object.assign(defProps, transform(dateSpan, dragMeta));
11849        }
11850        let { refined, extra } = refineEventDef(defProps, context);
11851        let def = parseEventDef(refined, extra, dragMeta.sourceId, dateSpan.allDay, context.options.forceEventDuration || Boolean(dragMeta.duration), // hasEnd
11852        context);
11853        let start = dateSpan.range.start;
11854        // only rely on time info if drop zone is all-day,
11855        // otherwise, we already know the time
11856        if (dateSpan.allDay && dragMeta.startTime) {
11857            start = context.dateEnv.add(start, dragMeta.startTime);
11858        }
11859        let end = dragMeta.duration ?
11860            context.dateEnv.add(start, dragMeta.duration) :
11861            getDefaultEventEnd(dateSpan.allDay, start, context);
11862        let instance = createEventInstance(def.defId, { start, end });
11863        return { def, instance };
11864    }
11865    // Utils for extracting data from element
11866    // ----------------------------------------------------------------------------------------------------
11867    function getDragMetaFromEl(el) {
11868        let str = getEmbeddedElData(el, 'event');
11869        let obj = str ?
11870            JSON.parse(str) :
11871            { create: false }; // if no embedded data, assume no event creation
11872        return parseDragMeta(obj);
11873    }
11874    config.dataAttrPrefix = '';
11875    function getEmbeddedElData(el, name) {
11876        let prefix = config.dataAttrPrefix;
11877        let prefixedName = (prefix ? prefix + '-' : '') + name;
11878        return el.getAttribute('data-' + prefixedName) || '';
11879    }
11880
11881    /*
11882    Makes an element (that is *external* to any calendar) draggable.
11883    Can pass in data that determines how an event will be created when dropped onto a calendar.
11884    Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system.
11885    */
11886    class ExternalDraggable {
11887        constructor(el, settings = {}) {
11888            this.handlePointerDown = (ev) => {
11889                let { dragging } = this;
11890                let { minDistance, longPressDelay } = this.settings;
11891                dragging.minDistance =
11892                    minDistance != null ?
11893                        minDistance :
11894                        (ev.isTouch ? 0 : BASE_OPTION_DEFAULTS.eventDragMinDistance);
11895                dragging.delay =
11896                    ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv
11897                        (longPressDelay != null ? longPressDelay : BASE_OPTION_DEFAULTS.longPressDelay) :
11898                        0;
11899            };
11900            this.handleDragStart = (ev) => {
11901                if (ev.isTouch &&
11902                    this.dragging.delay &&
11903                    ev.subjectEl.classList.contains('fc-event')) {
11904                    this.dragging.mirror.getMirrorEl().classList.add('fc-event-selected');
11905                }
11906            };
11907            this.settings = settings;
11908            let dragging = this.dragging = new FeaturefulElementDragging(el);
11909            dragging.touchScrollAllowed = false;
11910            if (settings.itemSelector != null) {
11911                dragging.pointer.selector = settings.itemSelector;
11912            }
11913            if (settings.appendTo != null) {
11914                dragging.mirror.parentNode = settings.appendTo; // TODO: write tests
11915            }
11916            dragging.emitter.on('pointerdown', this.handlePointerDown);
11917            dragging.emitter.on('dragstart', this.handleDragStart);
11918            new ExternalElementDragging(dragging, settings.eventData); // eslint-disable-line no-new
11919        }
11920        destroy() {
11921            this.dragging.destroy();
11922        }
11923    }
11924
11925    /*
11926    Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements.
11927    The third-party system is responsible for drawing the visuals effects of the drag.
11928    This class simply monitors for pointer movements and fires events.
11929    It also has the ability to hide the moving element (the "mirror") during the drag.
11930    */
11931    class InferredElementDragging extends ElementDragging {
11932        constructor(containerEl) {
11933            super(containerEl);
11934            this.shouldIgnoreMove = false;
11935            this.mirrorSelector = '';
11936            this.currentMirrorEl = null;
11937            this.handlePointerDown = (ev) => {
11938                this.emitter.trigger('pointerdown', ev);
11939                if (!this.shouldIgnoreMove) {
11940                    // fire dragstart right away. does not support delay or min-distance
11941                    this.emitter.trigger('dragstart', ev);
11942                }
11943            };
11944            this.handlePointerMove = (ev) => {
11945                if (!this.shouldIgnoreMove) {
11946                    this.emitter.trigger('dragmove', ev);
11947                }
11948            };
11949            this.handlePointerUp = (ev) => {
11950                this.emitter.trigger('pointerup', ev);
11951                if (!this.shouldIgnoreMove) {
11952                    // fire dragend right away. does not support a revert animation
11953                    this.emitter.trigger('dragend', ev);
11954                }
11955            };
11956            let pointer = this.pointer = new PointerDragging(containerEl);
11957            pointer.emitter.on('pointerdown', this.handlePointerDown);
11958            pointer.emitter.on('pointermove', this.handlePointerMove);
11959            pointer.emitter.on('pointerup', this.handlePointerUp);
11960        }
11961        destroy() {
11962            this.pointer.destroy();
11963        }
11964        setIgnoreMove(bool) {
11965            this.shouldIgnoreMove = bool;
11966        }
11967        setMirrorIsVisible(bool) {
11968            if (bool) {
11969                // restore a previously hidden element.
11970                // use the reference in case the selector class has already been removed.
11971                if (this.currentMirrorEl) {
11972                    this.currentMirrorEl.style.visibility = '';
11973                    this.currentMirrorEl = null;
11974                }
11975            }
11976            else {
11977                let mirrorEl = this.mirrorSelector
11978                    // TODO: somehow query FullCalendars WITHIN shadow-roots
11979                    ? document.querySelector(this.mirrorSelector)
11980                    : null;
11981                if (mirrorEl) {
11982                    this.currentMirrorEl = mirrorEl;
11983                    mirrorEl.style.visibility = 'hidden';
11984                }
11985            }
11986        }
11987    }
11988
11989    /*
11990    Bridges third-party drag-n-drop systems with FullCalendar.
11991    Must be instantiated and destroyed by caller.
11992    */
11993    class ThirdPartyDraggable {
11994        constructor(containerOrSettings, settings) {
11995            let containerEl = document;
11996            if (
11997            // wish we could just test instanceof EventTarget, but doesn't work in IE11
11998            containerOrSettings === document ||
11999                containerOrSettings instanceof Element) {
12000                containerEl = containerOrSettings;
12001                settings = settings || {};
12002            }
12003            else {
12004                settings = (containerOrSettings || {});
12005            }
12006            let dragging = this.dragging = new InferredElementDragging(containerEl);
12007            if (typeof settings.itemSelector === 'string') {
12008                dragging.pointer.selector = settings.itemSelector;
12009            }
12010            else if (containerEl === document) {
12011                dragging.pointer.selector = '[data-event]';
12012            }
12013            if (typeof settings.mirrorSelector === 'string') {
12014                dragging.mirrorSelector = settings.mirrorSelector;
12015            }
12016            let externalDragging = new ExternalElementDragging(dragging, settings.eventData);
12017            // The hit-detection system requires that the dnd-mirror-element be pointer-events:none,
12018            // but this can't be guaranteed for third-party draggables, so disable
12019            externalDragging.hitDragging.disablePointCheck = true;
12020        }
12021        destroy() {
12022            this.dragging.destroy();
12023        }
12024    }
12025
12026    var index$4 = createPlugin({
12027        name: '@fullcalendar/interaction',
12028        componentInteractions: [DateClicking, DateSelecting, EventDragging, EventResizing],
12029        calendarInteractions: [UnselectAuto],
12030        elementDraggingImpl: FeaturefulElementDragging,
12031        optionRefiners: OPTION_REFINERS$3,
12032        listenerRefiners: LISTENER_REFINERS,
12033    });
12034
12035    /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.
12036    ----------------------------------------------------------------------------------------------------------------------*/
12037    // It is a manager for a Table subcomponent, which does most of the heavy lifting.
12038    // It is responsible for managing width/height.
12039    class TableView extends DateComponent {
12040        constructor() {
12041            super(...arguments);
12042            this.headerElRef = d();
12043        }
12044        renderSimpleLayout(headerRowContent, bodyContent) {
12045            let { props, context } = this;
12046            let sections = [];
12047            let stickyHeaderDates = getStickyHeaderDates(context.options);
12048            if (headerRowContent) {
12049                sections.push({
12050                    type: 'header',
12051                    key: 'header',
12052                    isSticky: stickyHeaderDates,
12053                    chunk: {
12054                        elRef: this.headerElRef,
12055                        tableClassName: 'fc-col-header',
12056                        rowContent: headerRowContent,
12057                    },
12058                });
12059            }
12060            sections.push({
12061                type: 'body',
12062                key: 'body',
12063                liquid: true,
12064                chunk: { content: bodyContent },
12065            });
vendor: 28,331 bytes, lines 12066-12619
12066            return (y(ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
12067                y(SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [] /* TODO: make optional? */, sections: sections })));
12068        }
12069        renderHScrollLayout(headerRowContent, bodyContent, colCnt, dayMinWidth) {
12070            let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
12071            if (!ScrollGrid) {
12072                throw new Error('No ScrollGrid implementation');
12073            }
12074            let { props, context } = this;
12075            let stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options);
12076            let stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options);
12077            let sections = [];
12078            if (headerRowContent) {
12079                sections.push({
12080                    type: 'header',
12081                    key: 'header',
12082                    isSticky: stickyHeaderDates,
12083                    chunks: [{
12084                            key: 'main',
12085                            elRef: this.headerElRef,
12086                            tableClassName: 'fc-col-header',
12087                            rowContent: headerRowContent,
12088                        }],
12089                });
12090            }
12091            sections.push({
12092                type: 'body',
12093                key: 'body',
12094                liquid: true,
12095                chunks: [{
12096                        key: 'main',
12097                        content: bodyContent,
12098                    }],
12099            });
12100            if (stickyFooterScrollbar) {
12101                sections.push({
12102                    type: 'footer',
12103                    key: 'footer',
12104                    isSticky: true,
12105                    chunks: [{
12106                            key: 'main',
12107                            content: renderScrollShim,
12108                        }],
12109                });
12110            }
12111            return (y(ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
12112                y(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: props.forPrint, colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }], sections: sections })));
12113        }
12114    }
12115
12116    function splitSegsByRow(segs, rowCnt) {
12117        let byRow = [];
12118        for (let i = 0; i < rowCnt; i += 1) {
12119            byRow[i] = [];
12120        }
12121        for (let seg of segs) {
12122            byRow[seg.row].push(seg);
12123        }
12124        return byRow;
12125    }
12126    function splitSegsByFirstCol(segs, colCnt) {
12127        let byCol = [];
12128        for (let i = 0; i < colCnt; i += 1) {
12129            byCol[i] = [];
12130        }
12131        for (let seg of segs) {
12132            byCol[seg.firstCol].push(seg);
12133        }
12134        return byCol;
12135    }
12136    function splitInteractionByRow(ui, rowCnt) {
12137        let byRow = [];
12138        if (!ui) {
12139            for (let i = 0; i < rowCnt; i += 1) {
12140                byRow[i] = null;
12141            }
12142        }
12143        else {
12144            for (let i = 0; i < rowCnt; i += 1) {
12145                byRow[i] = {
12146                    affectedInstances: ui.affectedInstances,
12147                    isEvent: ui.isEvent,
12148                    segs: [],
12149                };
12150            }
12151            for (let seg of ui.segs) {
12152                byRow[seg.row].segs.push(seg);
12153            }
12154        }
12155        return byRow;
12156    }
12157
12158    const DEFAULT_TABLE_EVENT_TIME_FORMAT = createFormatter({
12159        hour: 'numeric',
12160        minute: '2-digit',
12161        omitZeroMinute: true,
12162        meridiem: 'narrow',
12163    });
12164    function hasListItemDisplay(seg) {
12165        let { display } = seg.eventRange.ui;
12166        return display === 'list-item' || (display === 'auto' &&
12167            !seg.eventRange.def.allDay &&
12168            seg.firstCol === seg.lastCol && // can't be multi-day
12169            seg.isStart && // "
12170            seg.isEnd // "
12171        );
12172    }
12173
12174    class TableBlockEvent extends BaseComponent {
12175        render() {
12176            let { props } = this;
12177            return (y(StandardEvent, Object.assign({}, props, { elClasses: ['fc-daygrid-event', 'fc-daygrid-block-event', 'fc-h-event'], defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: props.defaultDisplayEventEnd, disableResizing: !props.seg.eventRange.def.allDay })));
12178        }
12179    }
12180
12181    class TableListItemEvent extends BaseComponent {
12182        render() {
12183            let { props, context } = this;
12184            let { options } = context;
12185            let { seg } = props;
12186            let timeFormat = options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT;
12187            let timeText = buildSegTimeText(seg, timeFormat, context, true, props.defaultDisplayEventEnd);
12188            return (y(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 })));
12189        }
12190    }
12191    function renderInnerContent$2(renderProps) {
12192        return (y(_, null,
12193            y("div", { className: "fc-daygrid-event-dot", style: { borderColor: renderProps.borderColor || renderProps.backgroundColor } }),
12194            renderProps.timeText && (y("div", { className: "fc-event-time" }, renderProps.timeText)),
12195            y("div", { className: "fc-event-title" }, renderProps.event.title || y(_, null, "\u00A0"))));
12196    }
12197
12198    class TableCellMoreLink extends BaseComponent {
12199        constructor() {
12200            super(...arguments);
12201            this.compileSegs = memoize(compileSegs);
12202        }
12203        render() {
12204            let { props } = this;
12205            let { allSegs, invisibleSegs } = this.compileSegs(props.singlePlacements);
12206            return (y(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: () => {
12207                    let isForcedInvisible = (props.eventDrag ? props.eventDrag.affectedInstances : null) ||
12208                        (props.eventResize ? props.eventResize.affectedInstances : null) ||
12209                        {};
12210                    return (y(_, null, allSegs.map((seg) => {
12211                        let instanceId = seg.eventRange.instance.instanceId;
12212                        return (y("div", { className: "fc-daygrid-event-harness", key: instanceId, style: {
12213                                visibility: isForcedInvisible[instanceId] ? 'hidden' : '',
12214                            } }, hasListItemDisplay(seg) ? (y(TableListItemEvent, Object.assign({ seg: seg, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, getSegMeta(seg, props.todayRange)))) : (y(TableBlockEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, getSegMeta(seg, props.todayRange))))));
12215                    })));
12216                } }));
12217        }
12218    }
12219    function compileSegs(singlePlacements) {
12220        let allSegs = [];
12221        let invisibleSegs = [];
12222        for (let placement of singlePlacements) {
12223            allSegs.push(placement.seg);
12224            if (!placement.isVisible) {
12225                invisibleSegs.push(placement.seg);
12226            }
12227        }
12228        return { allSegs, invisibleSegs };
12229    }
12230
12231    const DEFAULT_WEEK_NUM_FORMAT$1 = createFormatter({ week: 'narrow' });
12232    class TableCell extends DateComponent {
12233        constructor() {
12234            super(...arguments);
12235            this.rootElRef = d();
12236            this.state = {
12237                dayNumberId: getUniqueDomId(),
12238            };
12239            this.handleRootEl = (el) => {
12240                setRef(this.rootElRef, el);
12241                setRef(this.props.elRef, el);
12242            };
12243        }
12244        render() {
12245            let { context, props, state, rootElRef } = this;
12246            let { options, dateEnv } = context;
12247            let { date, dateProfile } = props;
12248            // TODO: memoize this?
12249            const isMonthStart = props.showDayNumber &&
12250                shouldDisplayMonthStart(date, dateProfile.currentRange, dateEnv);
12251            return (y(DayCellContainer, { elTag: "td", elRef: this.handleRootEl, elClasses: [
12252                    'fc-daygrid-day',
12253                    ...(props.extraClassNames || []),
12254                ], elAttrs: Object.assign(Object.assign(Object.assign({}, props.extraDataAttrs), (props.showDayNumber ? { 'aria-labelledby': state.dayNumberId } : {})), { role: 'gridcell' }), defaultGenerator: renderTopInner, date: date, dateProfile: dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, isMonthStart: isMonthStart, extraRenderProps: props.extraRenderProps }, (InnerContent, renderProps) => (y("div", { ref: props.innerElRef, className: "fc-daygrid-day-frame fc-scrollgrid-sync-inner", style: { minHeight: props.minHeight } },
12255                props.showWeekNumber && (y(WeekNumberContainer, { elTag: "a", elClasses: ['fc-daygrid-week-number'], elAttrs: buildNavLinkAttrs(context, date, 'week'), date: date, defaultFormat: DEFAULT_WEEK_NUM_FORMAT$1 })),
12256                !renderProps.isDisabled &&
12257                    (props.showDayNumber || hasCustomDayCellContent(options) || props.forceDayTop) ? (y("div", { className: "fc-daygrid-day-top" },
12258                    y(InnerContent, { elTag: "a", elClasses: [
12259                            'fc-daygrid-day-number',
12260                            isMonthStart && 'fc-daygrid-month-start',
12261                        ], elAttrs: Object.assign(Object.assign({}, buildNavLinkAttrs(context, date)), { id: state.dayNumberId }) }))) : props.showDayNumber ? (
12262                // for creating correct amount of space (see issue #7162)
12263                y("div", { className: "fc-daygrid-day-top", style: { visibility: 'hidden' } },
12264                    y("a", { className: "fc-daygrid-day-number" }, "\u00A0"))) : undefined,
12265                y("div", { className: "fc-daygrid-day-events", ref: props.fgContentElRef },
12266                    props.fgContent,
12267                    y("div", { className: "fc-daygrid-day-bottom", style: { marginTop: props.moreMarginTop } },
12268                        y(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 }))),
12269                y("div", { className: "fc-daygrid-day-bg" }, props.bgContent)))));
12270        }
12271    }
12272    function renderTopInner(props) {
12273        return props.dayNumberText || y(_, null, "\u00A0");
12274    }
12275    function shouldDisplayMonthStart(date, currentRange, dateEnv) {
12276        const { start: currentStart, end: currentEnd } = currentRange;
12277        const currentEndIncl = addMs(currentEnd, -1);
12278        const currentFirstYear = dateEnv.getYear(currentStart);
12279        const currentFirstMonth = dateEnv.getMonth(currentStart);
12280        const currentLastYear = dateEnv.getYear(currentEndIncl);
12281        const currentLastMonth = dateEnv.getMonth(currentEndIncl);
12282        // spans more than one month?
12283        return !(currentFirstYear === currentLastYear && currentFirstMonth === currentLastMonth) &&
12284            Boolean(
12285            // first date in current view?
12286            date.valueOf() === currentStart.valueOf() ||
12287                // a month-start that's within the current range?
12288                (dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf()));
12289    }
12290
12291    function generateSegKey(seg) {
12292        return seg.eventRange.instance.instanceId + ':' + seg.firstCol;
12293    }
12294    function generateSegUid(seg) {
12295        return generateSegKey(seg) + ':' + seg.lastCol;
12296    }
12297    function computeFgSegPlacement(segs, // assumed already sorted
12298    dayMaxEvents, dayMaxEventRows, strictOrder, segHeights, maxContentHeight, cells) {
12299        let hierarchy = new DayGridSegHierarchy((segEntry) => {
12300            // TODO: more DRY with generateSegUid
12301            let segUid = segs[segEntry.index].eventRange.instance.instanceId +
12302                ':' + segEntry.span.start +
12303                ':' + (segEntry.span.end - 1);
12304            // if no thickness known, assume 1 (if 0, so small it always fits)
12305            return segHeights[segUid] || 1;
12306        });
12307        hierarchy.allowReslicing = true;
12308        hierarchy.strictOrder = strictOrder;
12309        if (dayMaxEvents === true || dayMaxEventRows === true) {
12310            hierarchy.maxCoord = maxContentHeight;
12311            hierarchy.hiddenConsumes = true;
12312        }
12313        else if (typeof dayMaxEvents === 'number') {
12314            hierarchy.maxStackCnt = dayMaxEvents;
12315        }
12316        else if (typeof dayMaxEventRows === 'number') {
12317            hierarchy.maxStackCnt = dayMaxEventRows;
12318            hierarchy.hiddenConsumes = true;
12319        }
12320        // create segInputs only for segs with known heights
12321        let segInputs = [];
12322        let unknownHeightSegs = [];
12323        for (let i = 0; i < segs.length; i += 1) {
12324            let seg = segs[i];
12325            let segUid = generateSegUid(seg);
12326            let eventHeight = segHeights[segUid];
12327            if (eventHeight != null) {
12328                segInputs.push({
12329                    index: i,
12330                    span: {
12331                        start: seg.firstCol,
12332                        end: seg.lastCol + 1,
12333                    },
12334                });
12335            }
12336            else {
12337                unknownHeightSegs.push(seg);
12338            }
12339        }
12340        let hiddenEntries = hierarchy.addSegs(segInputs);
12341        let segRects = hierarchy.toRects();
12342        let { singleColPlacements, multiColPlacements, leftoverMargins } = placeRects(segRects, segs, cells);
12343        let moreCnts = [];
12344        let moreMarginTops = [];
12345        // add segs with unknown heights
12346        for (let seg of unknownHeightSegs) {
12347            multiColPlacements[seg.firstCol].push({
12348                seg,
12349                isVisible: false,
12350                isAbsolute: true,
12351                absoluteTop: 0,
12352                marginTop: 0,
12353            });
12354            for (let col = seg.firstCol; col <= seg.lastCol; col += 1) {
12355                singleColPlacements[col].push({
12356                    seg: resliceSeg(seg, col, col + 1, cells),
12357                    isVisible: false,
12358                    isAbsolute: false,
12359                    absoluteTop: 0,
12360                    marginTop: 0,
12361                });
12362            }
12363        }
12364        // add the hidden entries
12365        for (let col = 0; col < cells.length; col += 1) {
12366            moreCnts.push(0);
12367        }
12368        for (let hiddenEntry of hiddenEntries) {
12369            let seg = segs[hiddenEntry.index];
12370            let hiddenSpan = hiddenEntry.span;
12371            multiColPlacements[hiddenSpan.start].push({
12372                seg: resliceSeg(seg, hiddenSpan.start, hiddenSpan.end, cells),
12373                isVisible: false,
12374                isAbsolute: true,
12375                absoluteTop: 0,
12376                marginTop: 0,
12377            });
12378            for (let col = hiddenSpan.start; col < hiddenSpan.end; col += 1) {
12379                moreCnts[col] += 1;
12380                singleColPlacements[col].push({
12381                    seg: resliceSeg(seg, col, col + 1, cells),
12382                    isVisible: false,
12383                    isAbsolute: false,
12384                    absoluteTop: 0,
12385                    marginTop: 0,
12386                });
12387            }
12388        }
12389        // deal with leftover margins
12390        for (let col = 0; col < cells.length; col += 1) {
12391            moreMarginTops.push(leftoverMargins[col]);
12392        }
12393        return { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops };
12394    }
12395    // rects ordered by top coord, then left
12396    function placeRects(allRects, segs, cells) {
12397        let rectsByEachCol = groupRectsByEachCol(allRects, cells.length);
12398        let singleColPlacements = [];
12399        let multiColPlacements = [];
12400        let leftoverMargins = [];
12401        for (let col = 0; col < cells.length; col += 1) {
12402            let rects = rectsByEachCol[col];
12403            // compute all static segs in singlePlacements
12404            let singlePlacements = [];
12405            let currentHeight = 0;
12406            let currentMarginTop = 0;
12407            for (let rect of rects) {
12408                let seg = segs[rect.index];
12409                singlePlacements.push({
12410                    seg: resliceSeg(seg, col, col + 1, cells),
12411                    isVisible: true,
12412                    isAbsolute: false,
12413                    absoluteTop: rect.levelCoord,
12414                    marginTop: rect.levelCoord - currentHeight,
12415                });
12416                currentHeight = rect.levelCoord + rect.thickness;
12417            }
12418            // compute mixed static/absolute segs in multiPlacements
12419            let multiPlacements = [];
12420            currentHeight = 0;
12421            currentMarginTop = 0;
12422            for (let rect of rects) {
12423                let seg = segs[rect.index];
12424                let isAbsolute = rect.span.end - rect.span.start > 1; // multi-column?
12425                let isFirstCol = rect.span.start === col;
12426                currentMarginTop += rect.levelCoord - currentHeight; // amount of space since bottom of previous seg
12427                currentHeight = rect.levelCoord + rect.thickness; // height will now be bottom of current seg
12428                if (isAbsolute) {
12429                    currentMarginTop += rect.thickness;
12430                    if (isFirstCol) {
12431                        multiPlacements.push({
12432                            seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
12433                            isVisible: true,
12434                            isAbsolute: true,
12435                            absoluteTop: rect.levelCoord,
12436                            marginTop: 0,
12437                        });
12438                    }
12439                }
12440                else if (isFirstCol) {
12441                    multiPlacements.push({
12442                        seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
12443                        isVisible: true,
12444                        isAbsolute: false,
12445                        absoluteTop: rect.levelCoord,
12446                        marginTop: currentMarginTop, // claim the margin
12447                    });
12448                    currentMarginTop = 0;
12449                }
12450            }
12451            singleColPlacements.push(singlePlacements);
12452            multiColPlacements.push(multiPlacements);
12453            leftoverMargins.push(currentMarginTop);
12454        }
12455        return { singleColPlacements, multiColPlacements, leftoverMargins };
12456    }
12457    function groupRectsByEachCol(rects, colCnt) {
12458        let rectsByEachCol = [];
12459        for (let col = 0; col < colCnt; col += 1) {
12460            rectsByEachCol.push([]);
12461        }
12462        for (let rect of rects) {
12463            for (let col = rect.span.start; col < rect.span.end; col += 1) {
12464                rectsByEachCol[col].push(rect);
12465            }
12466        }
12467        return rectsByEachCol;
12468    }
12469    function resliceSeg(seg, spanStart, spanEnd, cells) {
12470        if (seg.firstCol === spanStart && seg.lastCol === spanEnd - 1) {
12471            return seg;
12472        }
12473        let eventRange = seg.eventRange;
12474        let origRange = eventRange.range;
12475        let slicedRange = intersectRanges(origRange, {
12476            start: cells[spanStart].date,
12477            end: addDays(cells[spanEnd - 1].date, 1),
12478        });
12479        return Object.assign(Object.assign({}, seg), { firstCol: spanStart, lastCol: spanEnd - 1, eventRange: {
12480                def: eventRange.def,
12481                ui: Object.assign(Object.assign({}, eventRange.ui), { durationEditable: false }),
12482                instance: eventRange.instance,
12483                range: slicedRange,
12484            }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() });
12485    }
12486    class DayGridSegHierarchy extends SegHierarchy {
12487        constructor() {
12488            super(...arguments);
12489            // config
12490            this.hiddenConsumes = false;
12491            // allows us to keep hidden entries in the hierarchy so they take up space
12492            this.forceHidden = {};
12493        }
12494        addSegs(segInputs) {
12495            const hiddenSegs = super.addSegs(segInputs);
12496            const { entriesByLevel } = this;
12497            const excludeHidden = (entry) => !this.forceHidden[buildEntryKey(entry)];
12498            // remove the forced-hidden segs
12499            for (let level = 0; level < entriesByLevel.length; level += 1) {
12500                entriesByLevel[level] = entriesByLevel[level].filter(excludeHidden);
12501            }
12502            return hiddenSegs;
12503        }
12504        handleInvalidInsertion(insertion, entry, hiddenEntries) {
12505            const { entriesByLevel, forceHidden } = this;
12506            const { touchingEntry, touchingLevel, touchingLateral } = insertion;
12507            // the entry that the new insertion is touching must be hidden
12508            if (this.hiddenConsumes && touchingEntry) {
12509                const touchingEntryId = buildEntryKey(touchingEntry);
12510                if (!forceHidden[touchingEntryId]) {
12511                    if (this.allowReslicing) {
12512                        // split up the touchingEntry, reinsert it
12513                        const hiddenEntry = Object.assign(Object.assign({}, touchingEntry), { span: intersectSpans(touchingEntry.span, entry.span) });
12514                        // reinsert the area that turned into a "more" link (so no other entries try to
12515                        // occupy the space) but mark it forced-hidden
12516                        const hiddenEntryId = buildEntryKey(hiddenEntry);
12517                        forceHidden[hiddenEntryId] = true;
12518                        entriesByLevel[touchingLevel][touchingLateral] = hiddenEntry;
12519                        hiddenEntries.push(hiddenEntry);
12520                        this.splitEntry(touchingEntry, entry, hiddenEntries);
12521                    }
12522                    else {
12523                        forceHidden[touchingEntryId] = true;
12524                        hiddenEntries.push(touchingEntry);
12525                    }
12526                }
12527            }
12528            // will try to reslice...
12529            super.handleInvalidInsertion(insertion, entry, hiddenEntries);
12530        }
12531    }
12532
12533    class TableRow extends DateComponent {
12534        constructor() {
12535            super(...arguments);
12536            this.cellElRefs = new RefMap(); // the <td>
12537            this.frameElRefs = new RefMap(); // the fc-daygrid-day-frame
12538            this.fgElRefs = new RefMap(); // the fc-daygrid-day-events
12539            this.segHarnessRefs = new RefMap(); // indexed by "instanceId:firstCol"
12540            this.rootElRef = d();
12541            this.state = {
12542                framePositions: null,
12543                maxContentHeight: null,
12544                segHeights: {},
12545            };
12546            this.handleResize = (isForced) => {
12547                if (isForced) {
12548                    this.updateSizing(true); // isExternal=true
12549                }
12550            };
12551        }
12552        render() {
12553            let { props, state, context } = this;
12554            let { options } = context;
12555            let colCnt = props.cells.length;
12556            let businessHoursByCol = splitSegsByFirstCol(props.businessHourSegs, colCnt);
12557            let bgEventSegsByCol = splitSegsByFirstCol(props.bgEventSegs, colCnt);
12558            let highlightSegsByCol = splitSegsByFirstCol(this.getHighlightSegs(), colCnt);
12559            let mirrorSegsByCol = splitSegsByFirstCol(this.getMirrorSegs(), colCnt);
12560            let { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops } = computeFgSegPlacement(sortEventSegs(props.fgEventSegs, options.eventOrder), props.dayMaxEvents, props.dayMaxEventRows, options.eventOrderStrict, state.segHeights, state.maxContentHeight, props.cells);
12561            let isForcedInvisible = // TODO: messy way to compute this
12562             (props.eventDrag && props.eventDrag.affectedInstances) ||
12563                (props.eventResize && props.eventResize.affectedInstances) ||
12564                {};
12565            return (y("tr", { ref: this.rootElRef, role: "row" },
12566                props.renderIntro && props.renderIntro(),
12567                props.cells.map((cell, col) => {
12568                    let normalFgNodes = this.renderFgSegs(col, props.forPrint ? singleColPlacements[col] : multiColPlacements[col], props.todayRange, isForcedInvisible);
12569                    let mirrorFgNodes = this.renderFgSegs(col, buildMirrorPlacements(mirrorSegsByCol[col], multiColPlacements), props.todayRange, {}, Boolean(props.eventDrag), Boolean(props.eventResize), false);
12570                    return (y(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
12571                        y(_, null,
12572                            y(_, null, normalFgNodes),
12573                            y(_, null, mirrorFgNodes))), bgContent: ( // Fragment scopes the keys
12574                        y(_, null,
12575                            this.renderFillSegs(highlightSegsByCol[col], 'highlight'),
12576                            this.renderFillSegs(businessHoursByCol[col], 'non-business'),
12577                            this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))), minHeight: props.cellMinHeight }));
12578                })));
12579        }
12580        componentDidMount() {
12581            this.updateSizing(true);
12582            this.context.addResizeHandler(this.handleResize);
12583        }
12584        componentDidUpdate(prevProps, prevState) {
12585            let currentProps = this.props;
12586            this.updateSizing(!isPropsEqual(prevProps, currentProps));
12587        }
12588        componentWillUnmount() {
12589            this.context.removeResizeHandler(this.handleResize);
12590        }
12591        getHighlightSegs() {
12592            let { props } = this;
12593            if (props.eventDrag && props.eventDrag.segs.length) { // messy check
12594                return props.eventDrag.segs;
12595            }
12596            if (props.eventResize && props.eventResize.segs.length) { // messy check
12597                return props.eventResize.segs;
12598            }
12599            return props.dateSelectionSegs;
12600        }
12601        getMirrorSegs() {
12602            let { props } = this;
12603            if (props.eventResize && props.eventResize.segs.length) { // messy check
12604                return props.eventResize.segs;
12605            }
12606            return [];
12607        }
12608        renderFgSegs(col, segPlacements, todayRange, isForcedInvisible, isDragging, isResizing, isDateSelecting) {
12609            let { context } = this;
12610            let { eventSelection } = this.props;
12611            let { framePositions } = this.state;
12612            let defaultDisplayEventEnd = this.props.cells.length === 1; // colCnt === 1
12613            let isMirror = isDragging || isResizing || isDateSelecting;
12614            let nodes = [];
12615            if (framePositions) {
12616                for (let placement of segPlacements) {
12617                    let { seg } = placement;
12618                    let { instanceId } = seg.eventRange.instance;
12619                    let isVisible = placement.isVisible && !isForcedInvisible[instanceId];
vendor: 14,006 bytes, lines 12620-12880
12620                    let isAbsolute = placement.isAbsolute;
12621                    let left = '';
12622                    let right = '';
12623                    if (isAbsolute) {
12624                        if (context.isRtl) {
12625                            right = 0;
12626                            left = framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol];
12627                        }
12628                        else {
12629                            left = 0;
12630                            right = framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol];
12631                        }
12632                    }
12633                    /*
12634                    known bug: events that are force to be list-item but span multiple days still take up space in later columns
12635                    todo: in print view, for multi-day events, don't display title within non-start/end segs
12636                    */
12637                    nodes.push(y("div", { className: 'fc-daygrid-event-harness' + (isAbsolute ? ' fc-daygrid-event-harness-abs' : ''), key: generateSegKey(seg), ref: isMirror ? null : this.segHarnessRefs.createRef(generateSegUid(seg)), style: {
12638                            visibility: isVisible ? '' : 'hidden',
12639                            marginTop: isAbsolute ? '' : placement.marginTop,
12640                            top: isAbsolute ? placement.absoluteTop : '',
12641                            left,
12642                            right,
12643                        } }, hasListItemDisplay(seg) ? (y(TableListItemEvent, Object.assign({ seg: seg, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getSegMeta(seg, todayRange)))) : (y(TableBlockEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getSegMeta(seg, todayRange))))));
12644                }
12645            }
12646            return nodes;
12647        }
12648        renderFillSegs(segs, fillType) {
12649            let { isRtl } = this.context;
12650            let { todayRange } = this.props;
12651            let { framePositions } = this.state;
12652            let nodes = [];
12653            if (framePositions) {
12654                for (let seg of segs) {
12655                    let leftRightCss = isRtl ? {
12656                        right: 0,
12657                        left: framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol],
12658                    } : {
12659                        left: 0,
12660                        right: framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol],
12661                    };
12662                    nodes.push(y("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-daygrid-bg-harness", style: leftRightCss }, fillType === 'bg-event' ?
12663                        y(BgEvent, Object.assign({ seg: seg }, getSegMeta(seg, todayRange))) :
12664                        renderFill(fillType)));
12665                }
12666            }
12667            return y(_, {}, ...nodes);
12668        }
12669        updateSizing(isExternalSizingChange) {
12670            let { props, state, frameElRefs } = this;
12671            if (!props.forPrint &&
12672                props.clientWidth !== null // positioning ready?
12673            ) {
12674                if (isExternalSizingChange) {
12675                    let frameEls = props.cells.map((cell) => frameElRefs.currentMap[cell.key]);
12676                    if (frameEls.length) {
12677                        let originEl = this.rootElRef.current;
12678                        let newPositionCache = new PositionCache(originEl, frameEls, true, // isHorizontal
12679                        false);
12680                        if (!state.framePositions || !state.framePositions.similarTo(newPositionCache)) {
12681                            this.setState({
12682                                framePositions: new PositionCache(originEl, frameEls, true, // isHorizontal
12683                                false),
12684                            });
12685                        }
12686                    }
12687                }
12688                const oldSegHeights = this.state.segHeights;
12689                const newSegHeights = this.querySegHeights();
12690                const limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
12691                this.safeSetState({
12692                    // HACK to prevent oscillations of events being shown/hidden from max-event-rows
12693                    // Essentially, once you compute an element's height, never null-out.
12694                    // TODO: always display all events, as visibility:hidden?
12695                    segHeights: Object.assign(Object.assign({}, oldSegHeights), newSegHeights),
12696                    maxContentHeight: limitByContentHeight ? this.computeMaxContentHeight() : null,
12697                });
12698            }
12699        }
12700        querySegHeights() {
12701            let segElMap = this.segHarnessRefs.currentMap;
12702            let segHeights = {};
12703            // get the max height amongst instance segs
12704            for (let segUid in segElMap) {
12705                let height = Math.round(segElMap[segUid].getBoundingClientRect().height);
12706                segHeights[segUid] = Math.max(segHeights[segUid] || 0, height);
12707            }
12708            return segHeights;
12709        }
12710        computeMaxContentHeight() {
12711            let firstKey = this.props.cells[0].key;
12712            let cellEl = this.cellElRefs.currentMap[firstKey];
12713            let fcContainerEl = this.fgElRefs.currentMap[firstKey];
12714            return cellEl.getBoundingClientRect().bottom - fcContainerEl.getBoundingClientRect().top;
12715        }
12716        getCellEls() {
12717            let elMap = this.cellElRefs.currentMap;
12718            return this.props.cells.map((cell) => elMap[cell.key]);
12719        }
12720    }
12721    TableRow.addStateEquality({
12722        segHeights: isPropsEqual,
12723    });
12724    function buildMirrorPlacements(mirrorSegs, colPlacements) {
12725        if (!mirrorSegs.length) {
12726            return [];
12727        }
12728        let topsByInstanceId = buildAbsoluteTopHash(colPlacements); // TODO: cache this at first render?
12729        return mirrorSegs.map((seg) => ({
12730            seg,
12731            isVisible: true,
12732            isAbsolute: true,
12733            absoluteTop: topsByInstanceId[seg.eventRange.instance.instanceId],
12734            marginTop: 0,
12735        }));
12736    }
12737    function buildAbsoluteTopHash(colPlacements) {
12738        let topsByInstanceId = {};
12739        for (let placements of colPlacements) {
12740            for (let placement of placements) {
12741                topsByInstanceId[placement.seg.eventRange.instance.instanceId] = placement.absoluteTop;
12742            }
12743        }
12744        return topsByInstanceId;
12745    }
12746
12747    class TableRows extends DateComponent {
12748        constructor() {
12749            super(...arguments);
12750            this.splitBusinessHourSegs = memoize(splitSegsByRow);
12751            this.splitBgEventSegs = memoize(splitSegsByRow);
12752            this.splitFgEventSegs = memoize(splitSegsByRow);
12753            this.splitDateSelectionSegs = memoize(splitSegsByRow);
12754            this.splitEventDrag = memoize(splitInteractionByRow);
12755            this.splitEventResize = memoize(splitInteractionByRow);
12756            this.rowRefs = new RefMap();
12757        }
12758        render() {
12759            let { props, context } = this;
12760            let rowCnt = props.cells.length;
12761            let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt);
12762            let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);
12763            let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt);
12764            let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt);
12765            let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt);
12766            let eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt);
12767            // for DayGrid view with many rows, force a min-height on cells so doesn't appear squished
12768            // choose 7 because a month view will have max 6 rows
12769            let cellMinHeight = (rowCnt >= 7 && props.clientWidth) ?
12770                props.clientWidth / context.options.aspectRatio / 6 :
12771                null;
12772            return (y(NowTimer, { unit: "day" }, (nowDate, todayRange) => (y(_, null, props.cells.map((cells, row) => (y(TableRow, { ref: this.rowRefs.createRef(row), key: cells.length
12773                    ? cells[0].date.toISOString() /* best? or put key on cell? or use diff formatter? */
12774                    : row // in case there are no cells (like when resource view is loading)
12775                , showDayNumbers: rowCnt > 1, showWeekNumbers: props.showWeekNumbers, todayRange: todayRange, dateProfile: props.dateProfile, cells: cells, renderIntro: props.renderRowIntro, businessHourSegs: businessHourSegsByRow[row], eventSelection: props.eventSelection, bgEventSegs: bgEventSegsByRow[row].filter(isSegAllDay) /* hack */, fgEventSegs: fgEventSegsByRow[row], dateSelectionSegs: dateSelectionSegsByRow[row], eventDrag: eventDragByRow[row], eventResize: eventResizeByRow[row], dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, clientWidth: props.clientWidth, clientHeight: props.clientHeight, cellMinHeight: cellMinHeight, forPrint: props.forPrint })))))));
12776        }
12777        componentDidMount() {
12778            this.registerInteractiveComponent();
12779        }
12780        componentDidUpdate() {
12781            // for if started with zero cells
12782            this.registerInteractiveComponent();
12783        }
12784        registerInteractiveComponent() {
12785            if (!this.rootEl) {
12786                // HACK: need a daygrid wrapper parent to do positioning
12787                // NOTE: a daygrid resource view w/o resources can have zero cells
12788                const firstCellEl = this.rowRefs.currentMap[0].getCellEls()[0];
12789                const rootEl = firstCellEl ? firstCellEl.closest('.fc-daygrid-body') : null;
12790                if (rootEl) {
12791                    this.rootEl = rootEl;
12792                    this.context.registerInteractiveComponent(this, {
12793                        el: rootEl,
12794                        isHitComboAllowed: this.props.isHitComboAllowed,
12795                    });
12796                }
12797            }
12798        }
12799        componentWillUnmount() {
12800            if (this.rootEl) {
12801                this.context.unregisterInteractiveComponent(this);
12802                this.rootEl = null;
12803            }
12804        }
12805        // Hit System
12806        // ----------------------------------------------------------------------------------------------------
12807        prepareHits() {
12808            this.rowPositions = new PositionCache(this.rootEl, this.rowRefs.collect().map((rowObj) => rowObj.getCellEls()[0]), // first cell el in each row. TODO: not optimal
12809            false, true);
12810            this.colPositions = new PositionCache(this.rootEl, this.rowRefs.currentMap[0].getCellEls(), // cell els in first row
12811            true, // horizontal
12812            false);
12813        }
12814        queryHit(positionLeft, positionTop) {
12815            let { colPositions, rowPositions } = this;
12816            let col = colPositions.leftToIndex(positionLeft);
12817            let row = rowPositions.topToIndex(positionTop);
12818            if (row != null && col != null) {
12819                let cell = this.props.cells[row][col];
12820                return {
12821                    dateProfile: this.props.dateProfile,
12822                    dateSpan: Object.assign({ range: this.getCellRange(row, col), allDay: true }, cell.extraDateSpan),
12823                    dayEl: this.getCellEl(row, col),
12824                    rect: {
12825                        left: colPositions.lefts[col],
12826                        right: colPositions.rights[col],
12827                        top: rowPositions.tops[row],
12828                        bottom: rowPositions.bottoms[row],
12829                    },
12830                    layer: 0,
12831                };
12832            }
12833            return null;
12834        }
12835        getCellEl(row, col) {
12836            return this.rowRefs.currentMap[row].getCellEls()[col]; // TODO: not optimal
12837        }
12838        getCellRange(row, col) {
12839            let start = this.props.cells[row][col].date;
12840            let end = addDays(start, 1);
12841            return { start, end };
12842        }
12843    }
12844    function isSegAllDay(seg) {
12845        return seg.eventRange.def.allDay;
12846    }
12847
12848    class Table extends DateComponent {
12849        constructor() {
12850            super(...arguments);
12851            this.elRef = d();
12852            this.needsScrollReset = false;
12853        }
12854        render() {
12855            let { props } = this;
12856            let { dayMaxEventRows, dayMaxEvents, expandRows } = props;
12857            let limitViaBalanced = dayMaxEvents === true || dayMaxEventRows === true;
12858            // if rows can't expand to fill fixed height, can't do balanced-height event limit
12859            // TODO: best place to normalize these options?
12860            if (limitViaBalanced && !expandRows) {
12861                limitViaBalanced = false;
12862                dayMaxEventRows = null;
12863                dayMaxEvents = null;
12864            }
12865            let classNames = [
12866                'fc-daygrid-body',
12867                limitViaBalanced ? 'fc-daygrid-body-balanced' : 'fc-daygrid-body-unbalanced',
12868                expandRows ? '' : 'fc-daygrid-body-natural', // will height of one row depend on the others?
12869            ];
12870            return (y("div", { ref: this.elRef, className: classNames.join(' '), style: {
12871                    // these props are important to give this wrapper correct dimensions for interactions
12872                    // TODO: if we set it here, can we avoid giving to inner tables?
12873                    width: props.clientWidth,
12874                    minWidth: props.tableMinWidth,
12875                } },
12876                y("table", { role: "presentation", className: "fc-scrollgrid-sync-table", style: {
12877                        width: props.clientWidth,
12878                        minWidth: props.tableMinWidth,
12879                        height: expandRows ? props.clientHeight : '',
12880                    } },
vendor: 7,468 bytes, lines 12881-13013
12881                    props.colGroupNode,
12882                    y("tbody", { role: "presentation" },
12883                        y(TableRows, { dateProfile: props.dateProfile, cells: props.cells, renderRowIntro: props.renderRowIntro, showWeekNumbers: props.showWeekNumbers, clientWidth: props.clientWidth, clientHeight: props.clientHeight, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, dayMaxEvents: dayMaxEvents, dayMaxEventRows: dayMaxEventRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed })))));
12884        }
12885        componentDidMount() {
12886            this.requestScrollReset();
12887        }
12888        componentDidUpdate(prevProps) {
12889            if (prevProps.dateProfile !== this.props.dateProfile) {
12890                this.requestScrollReset();
12891            }
12892            else {
12893                this.flushScrollReset();
12894            }
12895        }
12896        requestScrollReset() {
12897            this.needsScrollReset = true;
12898            this.flushScrollReset();
12899        }
12900        flushScrollReset() {
12901            if (this.needsScrollReset &&
12902                this.props.clientWidth // sizes computed?
12903            ) {
12904                const subjectEl = getScrollSubjectEl(this.elRef.current, this.props.dateProfile);
12905                if (subjectEl) {
12906                    const originEl = subjectEl.closest('.fc-daygrid-body');
12907                    const scrollEl = originEl.closest('.fc-scroller');
12908                    const scrollTop = subjectEl.getBoundingClientRect().top -
12909                        originEl.getBoundingClientRect().top;
12910                    scrollEl.scrollTop = scrollTop ? (scrollTop + 1) : 0; // overcome border
12911                }
12912                this.needsScrollReset = false;
12913            }
12914        }
12915    }
12916    function getScrollSubjectEl(containerEl, dateProfile) {
12917        let el;
12918        if (dateProfile.currentRangeUnit.match(/year|month/)) {
12919            el = containerEl.querySelector(`[data-date="${formatIsoMonthStr(dateProfile.currentDate)}-01"]`);
12920            // even if view is month-based, first-of-month might be hidden...
12921        }
12922        if (!el) {
12923            el = containerEl.querySelector(`[data-date="${formatDayString(dateProfile.currentDate)}"]`);
12924            // could still be hidden if an interior-view hidden day
12925        }
12926        return el;
12927    }
12928
12929    class DayTableSlicer extends Slicer {
12930        constructor() {
12931            super(...arguments);
12932            this.forceDayIfListItem = true;
12933        }
12934        sliceRange(dateRange, dayTableModel) {
12935            return dayTableModel.sliceRange(dateRange);
12936        }
12937    }
12938
12939    class DayTable extends DateComponent {
12940        constructor() {
12941            super(...arguments);
12942            this.slicer = new DayTableSlicer();
12943            this.tableRef = d();
12944        }
12945        render() {
12946            let { props, context } = this;
12947            return (y(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 })));
12948        }
12949    }
12950
12951    class DayTableView extends TableView {
12952        constructor() {
12953            super(...arguments);
12954            this.buildDayTableModel = memoize(buildDayTableModel);
12955            this.headerRef = d();
12956            this.tableRef = d();
12957            // can't override any lifecycle methods from parent
12958        }
12959        render() {
12960            let { options, dateProfileGenerator } = this.context;
12961            let { props } = this;
12962            let dayTableModel = this.buildDayTableModel(props.dateProfile, dateProfileGenerator);
12963            let headerContent = options.dayHeaders && (y(DayHeader, { ref: this.headerRef, dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: dayTableModel.rowCnt === 1 }));
12964            let bodyContent = (contentArg) => (y(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 }));
12965            return options.dayMinWidth
12966                ? this.renderHScrollLayout(headerContent, bodyContent, dayTableModel.colCnt, options.dayMinWidth)
12967                : this.renderSimpleLayout(headerContent, bodyContent);
12968        }
12969    }
12970    function buildDayTableModel(dateProfile, dateProfileGenerator) {
12971        let daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
12972        return new DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
12973    }
12974
12975    class TableDateProfileGenerator extends DateProfileGenerator {
12976        // Computes the date range that will be rendered
12977        buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
12978            let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay);
12979            let { props } = this;
12980            return buildDayTableRenderRange({
12981                currentRange: renderRange,
12982                snapToWeek: /^(year|month)$/.test(currentRangeUnit),
12983                fixedWeekCount: props.fixedWeekCount,
12984                dateEnv: props.dateEnv,
12985            });
12986        }
12987    }
12988    function buildDayTableRenderRange(props) {
12989        let { dateEnv, currentRange } = props;
12990        let { start, end } = currentRange;
12991        let endOfWeek;
12992        // year and month views should be aligned with weeks. this is already done for week
12993        if (props.snapToWeek) {
12994            start = dateEnv.startOfWeek(start);
12995            // make end-of-week if not already
12996            endOfWeek = dateEnv.startOfWeek(end);
12997            if (endOfWeek.valueOf() !== end.valueOf()) {
12998                end = addWeeks(endOfWeek, 1);
12999            }
13000        }
13001        // ensure 6 weeks
13002        if (props.fixedWeekCount) {
13003            // TODO: instead of these date-math gymnastics (for multimonth view),
13004            // compute dateprofiles of all months, then use start of first and end of last.
13005            let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth(addDays(currentRange.end, -1)));
13006            let rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
13007            diffWeeks(lastMonthRenderStart, end));
13008            end = addWeeks(end, 6 - rowCnt);
13009        }
13010        return { start, end };
13011    }
13012
13013    var css_248z$3
vendor: 3,531 bytes, line 13013
13013 = ":root{--fc-daygrid-event-dot-width:8px}.fc-daygrid-day-events:after,.fc-daygrid-day-events:before,.fc-daygrid-day-frame:after,.fc-daygrid-day-frame:before,.fc-daygrid-event-harness:after,.fc-daygrid-event-harness:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-body{position:relative;z-index:1}.fc .fc-daygrid-day.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-daygrid-day-frame{min-height:100%;position:relative}.fc .fc-daygrid-day-top{display:flex;flex-direction:row-reverse}.fc .fc-day-other .fc-daygrid-day-top{opacity:.3}.fc .fc-daygrid-day-number{padding:4px;position:relative;z-index:4}.fc .fc-daygrid-month-start{font-size:1.1em;font-weight:700}.fc .fc-daygrid-day-events{margin-top:1px}.fc .fc-daygrid-body-balanced .fc-daygrid-day-events{left:0;position:absolute;right:0}.fc .fc-daygrid-body-unbalanced .fc-daygrid-day-events{min-height:2em;position:relative}.fc .fc-daygrid-body-natural .fc-daygrid-day-events{margin-bottom:1em}.fc .fc-daygrid-event-harness{position:relative}.fc .fc-daygrid-event-harness-abs{left:0;position:absolute;right:0;top:0}.fc .fc-daygrid-bg-harness{bottom:0;position:absolute;top:0}.fc .fc-daygrid-day-bg .fc-non-business{z-index:1}.fc .fc-daygrid-day-bg .fc-bg-event{z-index:2}.fc .fc-daygrid-day-bg .fc-highlight{z-index:3}.fc .fc-daygrid-event{margin-top:1px;z-index:6}.fc .fc-daygrid-event.fc-event-mirror{z-index:7}.fc .fc-daygrid-day-bottom{font-size:.85em;margin:0 2px}.fc .fc-daygrid-day-bottom:after,.fc .fc-daygrid-day-bottom:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-more-link{border-radius:3px;cursor:pointer;line-height:1;margin-top:1px;max-width:100%;overflow:hidden;padding:2px;position:relative;white-space:nowrap;z-index:4}.fc .fc-daygrid-more-link:hover{background-color:rgba(0,0,0,.1)}.fc .fc-daygrid-week-number{background-color:var(--fc-neutral-bg-color);color:var(--fc-neutral-text-color);min-width:1.5em;padding:2px;position:absolute;text-align:center;top:0;z-index:5}.fc .fc-more-popover .fc-popover-body{min-width:220px;padding:10px}.fc-direction-ltr .fc-daygrid-event.fc-event-start,.fc-direction-rtl .fc-daygrid-event.fc-event-end{margin-left:2px}.fc-direction-ltr .fc-daygrid-event.fc-event-end,.fc-direction-rtl .fc-daygrid-event.fc-event-start{margin-right:2px}.fc-direction-ltr .fc-daygrid-more-link{float:left}.fc-direction-ltr .fc-daygrid-week-number{border-radius:0 0 3px 0;left:0}.fc-direction-rtl .fc-daygrid-more-link{float:right}.fc-direction-rtl .fc-daygrid-week-number{border-radius:0 0 0 3px;right:0}.fc-liquid-hack .fc-daygrid-day-frame{position:static}.fc-daygrid-event{border-radius:3px;font-size:var(--fc-small-font-size);position:relative;white-space:nowrap}.fc-daygrid-block-event .fc-event-time{font-weight:700}.fc-daygrid-block-event .fc-event-time,.fc-daygrid-block-event .fc-event-title{padding:1px}.fc-daygrid-dot-event{align-items:center;display:flex;padding:2px 0}.fc-daygrid-dot-event .fc-event-title{flex-grow:1;flex-shrink:1;font-weight:700;min-width:0;overflow:hidden}.fc-daygrid-dot-event.fc-event-mirror,.fc-daygrid-dot-event:hover{background:rgba(0,0,0,.1)}.fc-daygrid-dot-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-daygrid-event-dot{border:calc(var(--fc-daygrid-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-daygrid-event-dot-width)/2);box-sizing:content-box;height:0;margin:0 4px;width:0}.fc-direction-ltr .fc-daygrid-event .fc-event-time{margin-right:3px}.fc-direction-rtl .fc-daygrid-event .fc-event-time{margin-left:3px}";
13014    injectStyles(css_248z$3);
13015
13016    var index$3 = createPlugin({
13017        name: '@fullcalendar/daygrid',
13018        initialView: 'dayGridMonth',
13019        views: {
13020            dayGrid: {
13021                component: DayTableView,
13022                dateProfileGeneratorClass: TableDateProfileGenerator,
13023            },
13024            dayGridDay: {
13025                type: 'dayGrid',
13026                duration: { days: 1 },
13027            },
13028            dayGridWeek: {
13029                type: 'dayGrid',
13030                duration: { weeks: 1 },
13031            },
13032            dayGridMonth: {
13033                type: 'dayGrid',
13034                duration: { months: 1 },
13035                fixedWeekCount: true,
13036            },
13037            dayGridYear: {
13038                type: 'dayGrid',
13039                duration: { years: 1 },
13040            },
13041        },
13042    });
13043
13044    class AllDaySplitter extends Splitter {
13045        getKeyInfo() {
13046            return {
13047                allDay: {},
13048                timed: {},
13049            };
13050        }
13051        getKeysForDateSpan(dateSpan) {
13052            if (dateSpan.allDay) {
13053                return ['allDay'];
13054            }
13055            return ['timed'];
13056        }
13057        getKeysForEventDef(eventDef) {
13058            if (!eventDef.allDay) {
13059                return ['timed'];
13060            }
13061            if (hasBgRendering(eventDef)) {
13062                return ['timed', 'allDay'];
13063            }
13064            return ['allDay'];
13065        }
13066    }
13067
13068    const DEFAULT_SLAT_LABEL_FORMAT = createFormatter({
13069        hour: 'numeric',
13070        minute: '2-digit',
13071        omitZeroMinute: true,
13072        meridiem: 'short',
13073    });
13074    function TimeColsAxisCell(props) {
13075        let classNames = [
13076            'fc-timegrid-slot',
13077            'fc-timegrid-slot-label',
13078            props.isLabeled ? 'fc-scrollgrid-shrink' : 'fc-timegrid-slot-minor',
13079        ];
13080        return (y(ViewContextType.Consumer, null, (context) => {
13081            if (!props.isLabeled) {
13082                return (y("td", { className: classNames.join(' '), "data-time": props.isoTimeStr }));
13083            }
13084            let { dateEnv, options, viewApi } = context;
13085            let labelFormat = // TODO: fully pre-parse
13086             options.slotLabelFormat == null ? DEFAULT_SLAT_LABEL_FORMAT :
13087                Array.isArray(options.slotLabelFormat) ? createFormatter(options.slotLabelFormat[0]) :
13088                    createFormatter(options.slotLabelFormat);
13089            let renderProps = {
13090                level: 0,
13091                time: props.time,
13092                date: dateEnv.toDate(props.date),
13093                view: viewApi,
13094                text: dateEnv.format(props.date, labelFormat),
13095            };
13096            return (y(ContentContainer, { elTag: "td", elClasses: classNames, elAttrs: {
13097                    'data-time': props.isoTimeStr,
13098                }, renderProps: renderProps, generatorName: "slotLabelContent", customGenerator: options.slotLabelContent, defaultGenerator: renderInnerContent$1, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (y("div", { className: "fc-timegrid-slot-label-frame fc-scrollgrid-shrink-frame" },
13099                y(InnerContent, { elTag: "div", elClasses: [
13100                        'fc-timegrid-slot-label-cushion',
13101                        'fc-scrollgrid-shrink-cushion',
13102                    ] })))));
13103        }));
13104    }
13105    function renderInnerContent$1(props) {
13106        return props.text;
13107    }
13108
13109    class TimeBodyAxis extends BaseComponent {
13110        render() {
13111            return this.props.slatMetas.map((slatMeta) => (y("tr", { key: slatMeta.key },
vendor: 55,589 bytes, lines 13112-14175
13112                y(TimeColsAxisCell, Object.assign({}, slatMeta)))));
13113        }
13114    }
13115
13116    const DEFAULT_WEEK_NUM_FORMAT = createFormatter({ week: 'short' });
13117    const AUTO_ALL_DAY_MAX_EVENT_ROWS = 5;
13118    class TimeColsView extends DateComponent {
13119        constructor() {
13120            super(...arguments);
13121            this.allDaySplitter = new AllDaySplitter(); // for use by subclasses
13122            this.headerElRef = d();
13123            this.rootElRef = d();
13124            this.scrollerElRef = d();
13125            this.state = {
13126                slatCoords: null,
13127            };
13128            this.handleScrollTopRequest = (scrollTop) => {
13129                let scrollerEl = this.scrollerElRef.current;
13130                if (scrollerEl) { // TODO: not sure how this could ever be null. weirdness with the reducer
13131                    scrollerEl.scrollTop = scrollTop;
13132                }
13133            };
13134            /* Header Render Methods
13135            ------------------------------------------------------------------------------------------------------------------*/
13136            this.renderHeadAxis = (rowKey, frameHeight = '') => {
13137                let { options } = this.context;
13138                let { dateProfile } = this.props;
13139                let range = dateProfile.renderRange;
13140                let dayCnt = diffDays(range.start, range.end);
13141                // only do in day views (to avoid doing in week views that dont need it)
13142                let navLinkAttrs = (dayCnt === 1)
13143                    ? buildNavLinkAttrs(this.context, range.start, 'week')
13144                    : {};
13145                if (options.weekNumbers && rowKey === 'day') {
13146                    return (y(WeekNumberContainer, { elTag: "th", elClasses: [
13147                            'fc-timegrid-axis',
13148                            'fc-scrollgrid-shrink',
13149                        ], elAttrs: {
13150                            'aria-hidden': true,
13151                        }, date: range.start, defaultFormat: DEFAULT_WEEK_NUM_FORMAT }, (InnerContent) => (y("div", { className: [
13152                            'fc-timegrid-axis-frame',
13153                            'fc-scrollgrid-shrink-frame',
13154                            'fc-timegrid-axis-frame-liquid',
13155                        ].join(' '), style: { height: frameHeight } },
13156                        y(InnerContent, { elTag: "a", elClasses: [
13157                                'fc-timegrid-axis-cushion',
13158                                'fc-scrollgrid-shrink-cushion',
13159                                'fc-scrollgrid-sync-inner',
13160                            ], elAttrs: navLinkAttrs })))));
13161                }
13162                return (y("th", { "aria-hidden": true, className: "fc-timegrid-axis" },
13163                    y("div", { className: "fc-timegrid-axis-frame", style: { height: frameHeight } })));
13164            };
13165            /* Table Component Render Methods
13166            ------------------------------------------------------------------------------------------------------------------*/
13167            // only a one-way height sync. we don't send the axis inner-content height to the DayGrid,
13168            // but DayGrid still needs to have classNames on inner elements in order to measure.
13169            this.renderTableRowAxis = (rowHeight) => {
13170                let { options, viewApi } = this.context;
13171                let renderProps = {
13172                    text: options.allDayText,
13173                    view: viewApi,
13174                };
13175                return (
13176                // TODO: make reusable hook. used in list view too
13177                y(ContentContainer, { elTag: "td", elClasses: [
13178                        'fc-timegrid-axis',
13179                        'fc-scrollgrid-shrink',
13180                    ], elAttrs: {
13181                        'aria-hidden': true,
13182                    }, renderProps: renderProps, generatorName: "allDayContent", customGenerator: options.allDayContent, defaultGenerator: renderAllDayInner$1, classNameGenerator: options.allDayClassNames, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }, (InnerContent) => (y("div", { className: [
13183                        'fc-timegrid-axis-frame',
13184                        'fc-scrollgrid-shrink-frame',
13185                        rowHeight == null ? ' fc-timegrid-axis-frame-liquid' : '',
13186                    ].join(' '), style: { height: rowHeight } },
13187                    y(InnerContent, { elTag: "span", elClasses: [
13188                            'fc-timegrid-axis-cushion',
13189                            'fc-scrollgrid-shrink-cushion',
13190                            'fc-scrollgrid-sync-inner',
13191                        ] })))));
13192            };
13193            this.handleSlatCoords = (slatCoords) => {
13194                this.setState({ slatCoords });
13195            };
13196        }
13197        // rendering
13198        // ----------------------------------------------------------------------------------------------------
13199        renderSimpleLayout(headerRowContent, allDayContent, timeContent) {
13200            let { context, props } = this;
13201            let sections = [];
13202            let stickyHeaderDates = getStickyHeaderDates(context.options);
13203            if (headerRowContent) {
13204                sections.push({
13205                    type: 'header',
13206                    key: 'header',
13207                    isSticky: stickyHeaderDates,
13208                    chunk: {
13209                        elRef: this.headerElRef,
13210                        tableClassName: 'fc-col-header',
13211                        rowContent: headerRowContent,
13212                    },
13213                });
13214            }
13215            if (allDayContent) {
13216                sections.push({
13217                    type: 'body',
13218                    key: 'all-day',
13219                    chunk: { content: allDayContent },
13220                });
13221                sections.push({
13222                    type: 'body',
13223                    key: 'all-day-divider',
13224                    outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?
13225                    y("tr", { role: "presentation", className: "fc-scrollgrid-section" },
13226                        y("td", { className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),
13227                });
13228            }
13229            sections.push({
13230                type: 'body',
13231                key: 'body',
13232                liquid: true,
13233                expandRows: Boolean(context.options.expandRows),
13234                chunk: {
13235                    scrollerElRef: this.scrollerElRef,
13236                    content: timeContent,
13237                },
13238            });
13239            return (y(ViewContainer, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },
13240                y(SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [{ width: 'shrink' }], sections: sections })));
13241        }
13242        renderHScrollLayout(headerRowContent, allDayContent, timeContent, colCnt, dayMinWidth, slatMetas, slatCoords) {
13243            let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
13244            if (!ScrollGrid) {
13245                throw new Error('No ScrollGrid implementation');
13246            }
13247            let { context, props } = this;
13248            let stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options);
13249            let stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options);
13250            let sections = [];
13251            if (headerRowContent) {
13252                sections.push({
13253                    type: 'header',
13254                    key: 'header',
13255                    isSticky: stickyHeaderDates,
13256                    syncRowHeights: true,
13257                    chunks: [
13258                        {
13259                            key: 'axis',
13260                            rowContent: (arg) => (y("tr", { role: "presentation" }, this.renderHeadAxis('day', arg.rowSyncHeights[0]))),
13261                        },
13262                        {
13263                            key: 'cols',
13264                            elRef: this.headerElRef,
13265                            tableClassName: 'fc-col-header',
13266                            rowContent: headerRowContent,
13267                        },
13268                    ],
13269                });
13270            }
13271            if (allDayContent) {
13272                sections.push({
13273                    type: 'body',
13274                    key: 'all-day',
13275                    syncRowHeights: true,
13276                    chunks: [
13277                        {
13278                            key: 'axis',
13279                            rowContent: (contentArg) => (y("tr", { role: "presentation" }, this.renderTableRowAxis(contentArg.rowSyncHeights[0]))),
13280                        },
13281                        {
13282                            key: 'cols',
13283                            content: allDayContent,
13284                        },
13285                    ],
13286                });
13287                sections.push({
13288                    key: 'all-day-divider',
13289                    type: 'body',
13290                    outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?
13291                    y("tr", { role: "presentation", className: "fc-scrollgrid-section" },
13292                        y("td", { colSpan: 2, className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),
13293                });
13294            }
13295            let isNowIndicator = context.options.nowIndicator;
13296            sections.push({
13297                type: 'body',
13298                key: 'body',
13299                liquid: true,
13300                expandRows: Boolean(context.options.expandRows),
13301                chunks: [
13302                    {
13303                        key: 'axis',
13304                        content: (arg) => (
13305                        // TODO: make this now-indicator arrow more DRY with TimeColsContent
13306                        y("div", { className: "fc-timegrid-axis-chunk" },
13307                            y("table", { "aria-hidden": true, style: { height: arg.expandRows ? arg.clientHeight : '' } },
13308                                arg.tableColGroupNode,
13309                                y("tbody", null,
13310                                    y(TimeBodyAxis, { slatMetas: slatMetas }))),
13311                            y("div", { className: "fc-timegrid-now-indicator-container" },
13312                                y(NowTimer, { unit: isNowIndicator ? 'minute' : 'day' /* hacky */ }, (nowDate) => {
13313                                    let nowIndicatorTop = isNowIndicator &&
13314                                        slatCoords &&
13315                                        slatCoords.safeComputeTop(nowDate); // might return void
13316                                    if (typeof nowIndicatorTop === 'number') {
13317                                        return (y(NowIndicatorContainer, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: nowDate }));
13318                                    }
13319                                    return null;
13320                                })))),
13321                    },
13322                    {
13323                        key: 'cols',
13324                        scrollerElRef: this.scrollerElRef,
13325                        content: timeContent,
13326                    },
13327                ],
13328            });
13329            if (stickyFooterScrollbar) {
13330                sections.push({
13331                    key: 'footer',
13332                    type: 'footer',
13333                    isSticky: true,
13334                    chunks: [
13335                        {
13336                            key: 'axis',
13337                            content: renderScrollShim,
13338                        },
13339                        {
13340                            key: 'cols',
13341                            content: renderScrollShim,
13342                        },
13343                    ],
13344                });
13345            }
13346            return (y(ViewContainer, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },
13347                y(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: false, colGroups: [
13348                        { width: 'shrink', cols: [{ width: 'shrink' }] },
13349                        { cols: [{ span: colCnt, minWidth: dayMinWidth }] },
13350                    ], sections: sections })));
13351        }
13352        /* Dimensions
13353        ------------------------------------------------------------------------------------------------------------------*/
13354        getAllDayMaxEventProps() {
13355            let { dayMaxEvents, dayMaxEventRows } = this.context.options;
13356            if (dayMaxEvents === true || dayMaxEventRows === true) { // is auto?
13357                dayMaxEvents = undefined;
13358                dayMaxEventRows = AUTO_ALL_DAY_MAX_EVENT_ROWS; // make sure "auto" goes to a real number
13359            }
13360            return { dayMaxEvents, dayMaxEventRows };
13361        }
13362    }
13363    function renderAllDayInner$1(renderProps) {
13364        return renderProps.text;
13365    }
13366
13367    class TimeColsSlatsCoords {
13368        constructor(positions, dateProfile, slotDuration) {
13369            this.positions = positions;
13370            this.dateProfile = dateProfile;
13371            this.slotDuration = slotDuration;
13372        }
13373        safeComputeTop(date) {
13374            let { dateProfile } = this;
13375            if (rangeContainsMarker(dateProfile.currentRange, date)) {
13376                let startOfDayDate = startOfDay(date);
13377                let timeMs = date.valueOf() - startOfDayDate.valueOf();
13378                if (timeMs >= asRoughMs(dateProfile.slotMinTime) &&
13379                    timeMs < asRoughMs(dateProfile.slotMaxTime)) {
13380                    return this.computeTimeTop(createDuration(timeMs));
13381                }
13382            }
13383            return null;
13384        }
13385        // Computes the top coordinate, relative to the bounds of the grid, of the given date.
13386        // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.
13387        computeDateTop(when, startOfDayDate) {
13388            if (!startOfDayDate) {
13389                startOfDayDate = startOfDay(when);
13390            }
13391            return this.computeTimeTop(createDuration(when.valueOf() - startOfDayDate.valueOf()));
13392        }
13393        // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).
13394        // This is a makeshify way to compute the time-top. Assumes all slatMetas dates are uniform.
13395        // Eventually allow computation with arbirary slat dates.
13396        computeTimeTop(duration) {
13397            let { positions, dateProfile } = this;
13398            let len = positions.els.length;
13399            // floating-point value of # of slots covered
13400            let slatCoverage = (duration.milliseconds - asRoughMs(dateProfile.slotMinTime)) / asRoughMs(this.slotDuration);
13401            let slatIndex;
13402            let slatRemainder;
13403            // compute a floating-point number for how many slats should be progressed through.
13404            // from 0 to number of slats (inclusive)
13405            // constrained because slotMinTime/slotMaxTime might be customized.
13406            slatCoverage = Math.max(0, slatCoverage);
13407            slatCoverage = Math.min(len, slatCoverage);
13408            // an integer index of the furthest whole slat
13409            // from 0 to number slats (*exclusive*, so len-1)
13410            slatIndex = Math.floor(slatCoverage);
13411            slatIndex = Math.min(slatIndex, len - 1);
13412            // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.
13413            // could be 1.0 if slatCoverage is covering *all* the slots
13414            slatRemainder = slatCoverage - slatIndex;
13415            return positions.tops[slatIndex] +
13416                positions.getHeight(slatIndex) * slatRemainder;
13417        }
13418    }
13419
13420    class TimeColsSlatsBody extends BaseComponent {
13421        render() {
13422            let { props, context } = this;
13423            let { options } = context;
13424            let { slatElRefs } = props;
13425            return (y("tbody", null, props.slatMetas.map((slatMeta, i) => {
13426                let renderProps = {
13427                    time: slatMeta.time,
13428                    date: context.dateEnv.toDate(slatMeta.date),
13429                    view: context.viewApi,
13430                };
13431                return (y("tr", { key: slatMeta.key, ref: slatElRefs.createRef(slatMeta.key) },
13432                    props.axis && (y(TimeColsAxisCell, Object.assign({}, slatMeta))),
13433                    y(ContentContainer, { elTag: "td", elClasses: [
13434                            'fc-timegrid-slot',
13435                            'fc-timegrid-slot-lane',
13436                            !slatMeta.isLabeled && 'fc-timegrid-slot-minor',
13437                        ], elAttrs: {
13438                            'data-time': slatMeta.isoTimeStr,
13439                        }, renderProps: renderProps, generatorName: "slotLaneContent", customGenerator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount })));
13440            })));
13441        }
13442    }
13443
13444    /*
13445    for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL.
13446    */
13447    class TimeColsSlats extends BaseComponent {
13448        constructor() {
13449            super(...arguments);
13450            this.rootElRef = d();
13451            this.slatElRefs = new RefMap();
13452        }
13453        render() {
13454            let { props, context } = this;
13455            return (y("div", { ref: this.rootElRef, className: "fc-timegrid-slots" },
13456                y("table", { "aria-hidden": true, className: context.theme.getClass('table'), style: {
13457                        minWidth: props.tableMinWidth,
13458                        width: props.clientWidth,
13459                        height: props.minHeight,
13460                    } },
13461                    props.tableColGroupNode /* relies on there only being a single <col> for the axis */,
13462                    y(TimeColsSlatsBody, { slatElRefs: this.slatElRefs, axis: props.axis, slatMetas: props.slatMetas }))));
13463        }
13464        componentDidMount() {
13465            this.updateSizing();
13466        }
13467        componentDidUpdate() {
13468            this.updateSizing();
13469        }
13470        componentWillUnmount() {
13471            if (this.props.onCoords) {
13472                this.props.onCoords(null);
13473            }
13474        }
13475        updateSizing() {
13476            let { context, props } = this;
13477            if (props.onCoords &&
13478                props.clientWidth !== null // means sizing has stabilized
13479            ) {
13480                let rootEl = this.rootElRef.current;
13481                if (rootEl.offsetHeight) { // not hidden by css
13482                    props.onCoords(new TimeColsSlatsCoords(new PositionCache(this.rootElRef.current, collectSlatEls(this.slatElRefs.currentMap, props.slatMetas), false, true), this.props.dateProfile, context.options.slotDuration));
13483                }
13484            }
13485        }
13486    }
13487    function collectSlatEls(elMap, slatMetas) {
13488        return slatMetas.map((slatMeta) => elMap[slatMeta.key]);
13489    }
13490
13491    function splitSegsByCol(segs, colCnt) {
13492        let segsByCol = [];
13493        let i;
13494        for (i = 0; i < colCnt; i += 1) {
13495            segsByCol.push([]);
13496        }
13497        if (segs) {
13498            for (i = 0; i < segs.length; i += 1) {
13499                segsByCol[segs[i].col].push(segs[i]);
13500            }
13501        }
13502        return segsByCol;
13503    }
13504    function splitInteractionByCol(ui, colCnt) {
13505        let byRow = [];
13506        if (!ui) {
13507            for (let i = 0; i < colCnt; i += 1) {
13508                byRow[i] = null;
13509            }
13510        }
13511        else {
13512            for (let i = 0; i < colCnt; i += 1) {
13513                byRow[i] = {
13514                    affectedInstances: ui.affectedInstances,
13515                    isEvent: ui.isEvent,
13516                    segs: [],
13517                };
13518            }
13519            for (let seg of ui.segs) {
13520                byRow[seg.col].segs.push(seg);
13521            }
13522        }
13523        return byRow;
13524    }
13525
13526    class TimeColMoreLink extends BaseComponent {
13527        render() {
13528            let { props } = this;
13529            return (y(MoreLinkContainer, { elClasses: ['fc-timegrid-more-link'], elStyle: {
13530                    top: props.top,
13531                    bottom: props.bottom,
13532                }, 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, forceTimed: true }, (InnerContent) => (y(InnerContent, { elTag: "div", elClasses: ['fc-timegrid-more-link-inner', 'fc-sticky'] }))));
13533        }
13534    }
13535    function renderMoreLinkInner(props) {
13536        return props.shortText;
13537    }
13538
13539    // segInputs assumed sorted
13540    function buildPositioning(segInputs, strictOrder, maxStackCnt) {
13541        let hierarchy = new SegHierarchy();
13542        if (strictOrder != null) {
13543            hierarchy.strictOrder = strictOrder;
13544        }
13545        if (maxStackCnt != null) {
13546            hierarchy.maxStackCnt = maxStackCnt;
13547        }
13548        let hiddenEntries = hierarchy.addSegs(segInputs);
13549        let hiddenGroups = groupIntersectingEntries(hiddenEntries);
13550        let web = buildWeb(hierarchy);
13551        web = stretchWeb(web, 1); // all levelCoords/thickness will have 0.0-1.0
13552        let segRects = webToRects(web);
13553        return { segRects, hiddenGroups };
13554    }
13555    function buildWeb(hierarchy) {
13556        const { entriesByLevel } = hierarchy;
13557        const buildNode = cacheable((level, lateral) => level + ':' + lateral, (level, lateral) => {
13558            let siblingRange = findNextLevelSegs(hierarchy, level, lateral);
13559            let nextLevelRes = buildNodes(siblingRange, buildNode);
13560            let entry = entriesByLevel[level][lateral];
13561            return [
13562                Object.assign(Object.assign({}, entry), { nextLevelNodes: nextLevelRes[0] }),
13563                entry.thickness + nextLevelRes[1], // the pressure builds
13564            ];
13565        });
13566        return buildNodes(entriesByLevel.length
13567            ? { level: 0, lateralStart: 0, lateralEnd: entriesByLevel[0].length }
13568            : null, buildNode)[0];
13569    }
13570    function buildNodes(siblingRange, buildNode) {
13571        if (!siblingRange) {
13572            return [[], 0];
13573        }
13574        let { level, lateralStart, lateralEnd } = siblingRange;
13575        let lateral = lateralStart;
13576        let pairs = [];
13577        while (lateral < lateralEnd) {
13578            pairs.push(buildNode(level, lateral));
13579            lateral += 1;
13580        }
13581        pairs.sort(cmpDescPressures);
13582        return [
13583            pairs.map(extractNode),
13584            pairs[0][1], // first item's pressure
13585        ];
13586    }
13587    function cmpDescPressures(a, b) {
13588        return b[1] - a[1];
13589    }
13590    function extractNode(a) {
13591        return a[0];
13592    }
13593    function findNextLevelSegs(hierarchy, subjectLevel, subjectLateral) {
13594        let { levelCoords, entriesByLevel } = hierarchy;
13595        let subjectEntry = entriesByLevel[subjectLevel][subjectLateral];
13596        let afterSubject = levelCoords[subjectLevel] + subjectEntry.thickness;
13597        let levelCnt = levelCoords.length;
13598        let level = subjectLevel;
13599        // skip past levels that are too high up
13600        for (; level < levelCnt && levelCoords[level] < afterSubject; level += 1)
13601            ; // do nothing
13602        for (; level < levelCnt; level += 1) {
13603            let entries = entriesByLevel[level];
13604            let entry;
13605            let searchIndex = binarySearch(entries, subjectEntry.span.start, getEntrySpanEnd);
13606            let lateralStart = searchIndex[0] + searchIndex[1]; // if exact match (which doesn't collide), go to next one
13607            let lateralEnd = lateralStart;
13608            while ( // loop through entries that horizontally intersect
13609            (entry = entries[lateralEnd]) && // but not past the whole seg list
13610                entry.span.start < subjectEntry.span.end) {
13611                lateralEnd += 1;
13612            }
13613            if (lateralStart < lateralEnd) {
13614                return { level, lateralStart, lateralEnd };
13615            }
13616        }
13617        return null;
13618    }
13619    function stretchWeb(topLevelNodes, totalThickness) {
13620        const stretchNode = cacheable((node, startCoord, prevThickness) => buildEntryKey(node), (node, startCoord, prevThickness) => {
13621            let { nextLevelNodes, thickness } = node;
13622            let allThickness = thickness + prevThickness;
13623            let thicknessFraction = thickness / allThickness;
13624            let endCoord;
13625            let newChildren = [];
13626            if (!nextLevelNodes.length) {
13627                endCoord = totalThickness;
13628            }
13629            else {
13630                for (let childNode of nextLevelNodes) {
13631                    if (endCoord === undefined) {
13632                        let res = stretchNode(childNode, startCoord, allThickness);
13633                        endCoord = res[0];
13634                        newChildren.push(res[1]);
13635                    }
13636                    else {
13637                        let res = stretchNode(childNode, endCoord, 0);
13638                        newChildren.push(res[1]);
13639                    }
13640                }
13641            }
13642            let newThickness = (endCoord - startCoord) * thicknessFraction;
13643            return [endCoord - newThickness, Object.assign(Object.assign({}, node), { thickness: newThickness, nextLevelNodes: newChildren })];
13644        });
13645        return topLevelNodes.map((node) => stretchNode(node, 0, 0)[1]);
13646    }
13647    // not sorted in any particular order
13648    function webToRects(topLevelNodes) {
13649        let rects = [];
13650        const processNode = cacheable((node, levelCoord, stackDepth) => buildEntryKey(node), (node, levelCoord, stackDepth) => {
13651            let rect = Object.assign(Object.assign({}, node), { levelCoord,
13652                stackDepth, stackForward: 0 });
13653            rects.push(rect);
13654            return (rect.stackForward = processNodes(node.nextLevelNodes, levelCoord + node.thickness, stackDepth + 1) + 1);
13655        });
13656        function processNodes(nodes, levelCoord, stackDepth) {
13657            let stackForward = 0;
13658            for (let node of nodes) {
13659                stackForward = Math.max(processNode(node, levelCoord, stackDepth), stackForward);
13660            }
13661            return stackForward;
13662        }
13663        processNodes(topLevelNodes, 0, 0);
13664        return rects; // TODO: sort rects by levelCoord to be consistent with toRects?
13665    }
13666    // TODO: move to general util
13667    function cacheable(keyFunc, workFunc) {
13668        const cache = {};
13669        return (...args) => {
13670            let key = keyFunc(...args);
13671            return (key in cache)
13672                ? cache[key]
13673                : (cache[key] = workFunc(...args));
13674        };
13675    }
13676
13677    function computeSegVCoords(segs, colDate, slatCoords = null, eventMinHeight = 0) {
13678        let vcoords = [];
13679        if (slatCoords) {
13680            for (let i = 0; i < segs.length; i += 1) {
13681                let seg = segs[i];
13682                let spanStart = slatCoords.computeDateTop(seg.start, colDate);
13683                let spanEnd = Math.max(spanStart + (eventMinHeight || 0), // :(
13684                slatCoords.computeDateTop(seg.end, colDate));
13685                vcoords.push({
13686                    start: Math.round(spanStart),
13687                    end: Math.round(spanEnd), //
13688                });
13689            }
13690        }
13691        return vcoords;
13692    }
13693    function computeFgSegPlacements(segs, segVCoords, // might not have for every seg
13694    eventOrderStrict, eventMaxStack) {
13695        let segInputs = [];
13696        let dumbSegs = []; // segs without coords
13697        for (let i = 0; i < segs.length; i += 1) {
13698            let vcoords = segVCoords[i];
13699            if (vcoords) {
13700                segInputs.push({
13701                    index: i,
13702                    thickness: 1,
13703                    span: vcoords,
13704                });
13705            }
13706            else {
13707                dumbSegs.push(segs[i]);
13708            }
13709        }
13710        let { segRects, hiddenGroups } = buildPositioning(segInputs, eventOrderStrict, eventMaxStack);
13711        let segPlacements = [];
13712        for (let segRect of segRects) {
13713            segPlacements.push({
13714                seg: segs[segRect.index],
13715                rect: segRect,
13716            });
13717        }
13718        for (let dumbSeg of dumbSegs) {
13719            segPlacements.push({ seg: dumbSeg, rect: null });
13720        }
13721        return { segPlacements, hiddenGroups };
13722    }
13723
13724    const DEFAULT_TIME_FORMAT$1 = createFormatter({
13725        hour: 'numeric',
13726        minute: '2-digit',
13727        meridiem: false,
13728    });
13729    class TimeColEvent extends BaseComponent {
13730        render() {
13731            return (y(StandardEvent, Object.assign({}, this.props, { elClasses: [
13732                    'fc-timegrid-event',
13733                    'fc-v-event',
13734                    this.props.isShort && 'fc-timegrid-event-short',
13735                ], defaultTimeFormat: DEFAULT_TIME_FORMAT$1 })));
13736        }
13737    }
13738
13739    class TimeCol extends BaseComponent {
13740        constructor() {
13741            super(...arguments);
13742            this.sortEventSegs = memoize(sortEventSegs);
13743        }
13744        // TODO: memoize event-placement?
13745        render() {
13746            let { props, context } = this;
13747            let { options } = context;
13748            let isSelectMirror = options.selectMirror;
13749            let mirrorSegs = // yuck
13750             (props.eventDrag && props.eventDrag.segs) ||
13751                (props.eventResize && props.eventResize.segs) ||
13752                (isSelectMirror && props.dateSelectionSegs) ||
13753                [];
13754            let interactionAffectedInstances = // TODO: messy way to compute this
13755             (props.eventDrag && props.eventDrag.affectedInstances) ||
13756                (props.eventResize && props.eventResize.affectedInstances) ||
13757                {};
13758            let sortedFgSegs = this.sortEventSegs(props.fgEventSegs, options.eventOrder);
13759            return (y(DayCellContainer, { elTag: "td", elRef: props.elRef, elClasses: [
13760                    'fc-timegrid-col',
13761                    ...(props.extraClassNames || []),
13762                ], elAttrs: Object.assign({ role: 'gridcell' }, props.extraDataAttrs), date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, extraRenderProps: props.extraRenderProps }, (InnerContent) => (y("div", { className: "fc-timegrid-col-frame" },
13763                y("div", { className: "fc-timegrid-col-bg" },
13764                    this.renderFillSegs(props.businessHourSegs, 'non-business'),
13765                    this.renderFillSegs(props.bgEventSegs, 'bg-event'),
13766                    this.renderFillSegs(props.dateSelectionSegs, 'highlight')),
13767                y("div", { className: "fc-timegrid-col-events" }, this.renderFgSegs(sortedFgSegs, interactionAffectedInstances, false, false, false)),
13768                y("div", { className: "fc-timegrid-col-events" }, this.renderFgSegs(mirrorSegs, {}, Boolean(props.eventDrag), Boolean(props.eventResize), Boolean(isSelectMirror), 'mirror')),
13769                y("div", { className: "fc-timegrid-now-indicator-container" }, this.renderNowIndicator(props.nowIndicatorSegs)),
13770                hasCustomDayCellContent(options) && (y(InnerContent, { elTag: "div", elClasses: ['fc-timegrid-col-misc'] }))))));
13771        }
13772        renderFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey) {
13773            let { props } = this;
13774            if (props.forPrint) {
13775                return renderPlainFgSegs(sortedFgSegs, props);
13776            }
13777            return this.renderPositionedFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey);
13778        }
13779        renderPositionedFgSegs(segs, // if not mirror, needs to be sorted
13780        segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey) {
13781            let { eventMaxStack, eventShortHeight, eventOrderStrict, eventMinHeight } = this.context.options;
13782            let { date, slatCoords, eventSelection, todayRange, nowDate } = this.props;
13783            let isMirror = isDragging || isResizing || isDateSelecting;
13784            let segVCoords = computeSegVCoords(segs, date, slatCoords, eventMinHeight);
13785            let { segPlacements, hiddenGroups } = computeFgSegPlacements(segs, segVCoords, eventOrderStrict, eventMaxStack);
13786            return (y(_, null,
13787                this.renderHiddenGroups(hiddenGroups, segs),
13788                segPlacements.map((segPlacement) => {
13789                    let { seg, rect } = segPlacement;
13790                    let instanceId = seg.eventRange.instance.instanceId;
13791                    let isVisible = isMirror || Boolean(!segIsInvisible[instanceId] && rect);
13792                    let vStyle = computeSegVStyle(rect && rect.span);
13793                    let hStyle = (!isMirror && rect) ? this.computeSegHStyle(rect) : { left: 0, right: 0 };
13794                    let isInset = Boolean(rect) && rect.stackForward > 0;
13795                    let isShort = Boolean(rect) && (rect.span.end - rect.span.start) < eventShortHeight; // look at other places for this problem
13796                    return (y("div", { className: 'fc-timegrid-event-harness' +
13797                            (isInset ? ' fc-timegrid-event-harness-inset' : ''), key: forcedKey || instanceId, style: Object.assign(Object.assign({ visibility: isVisible ? '' : 'hidden' }, vStyle), hStyle) },
13798                        y(TimeColEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, isShort: isShort }, getSegMeta(seg, todayRange, nowDate)))));
13799                })));
13800        }
13801        // will already have eventMinHeight applied because segInputs already had it
13802        renderHiddenGroups(hiddenGroups, segs) {
13803            let { extraDateSpan, dateProfile, todayRange, nowDate, eventSelection, eventDrag, eventResize } = this.props;
13804            return (y(_, null, hiddenGroups.map((hiddenGroup) => {
13805                let positionCss = computeSegVStyle(hiddenGroup.span);
13806                let hiddenSegs = compileSegsFromEntries(hiddenGroup.entries, segs);
13807                return (y(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 }));
13808            })));
13809        }
13810        renderFillSegs(segs, fillType) {
13811            let { props, context } = this;
13812            let segVCoords = computeSegVCoords(segs, props.date, props.slatCoords, context.options.eventMinHeight); // don't assume all populated
13813            let children = segVCoords.map((vcoords, i) => {
13814                let seg = segs[i];
13815                return (y("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-timegrid-bg-harness", style: computeSegVStyle(vcoords) }, fillType === 'bg-event' ?
13816                    y(BgEvent, Object.assign({ seg: seg }, getSegMeta(seg, props.todayRange, props.nowDate))) :
13817                    renderFill(fillType)));
13818            });
13819            return y(_, null, children);
13820        }
13821        renderNowIndicator(segs) {
13822            let { slatCoords, date } = this.props;
13823            if (!slatCoords) {
13824                return null;
13825            }
13826            return segs.map((seg, i) => (y(NowIndicatorContainer
13827            // key doesn't matter. will only ever be one
13828            , { 
13829                // key doesn't matter. will only ever be one
13830                key: i, elClasses: ['fc-timegrid-now-indicator-line'], elStyle: {
13831                    top: slatCoords.computeDateTop(seg.start, date),
13832                }, isAxis: false, date: date })));
13833        }
13834        computeSegHStyle(segHCoords) {
13835            let { isRtl, options } = this.context;
13836            let shouldOverlap = options.slotEventOverlap;
13837            let nearCoord = segHCoords.levelCoord; // the left side if LTR. the right side if RTL. floating-point
13838            let farCoord = segHCoords.levelCoord + segHCoords.thickness; // the right side if LTR. the left side if RTL. floating-point
13839            let left; // amount of space from left edge, a fraction of the total width
13840            let right; // amount of space from right edge, a fraction of the total width
13841            if (shouldOverlap) {
13842                // double the width, but don't go beyond the maximum forward coordinate (1.0)
13843                farCoord = Math.min(1, nearCoord + (farCoord - nearCoord) * 2);
13844            }
13845            if (isRtl) {
13846                left = 1 - farCoord;
13847                right = nearCoord;
13848            }
13849            else {
13850                left = nearCoord;
13851                right = 1 - farCoord;
13852            }
13853            let props = {
13854                zIndex: segHCoords.stackDepth + 1,
13855                left: left * 100 + '%',
13856                right: right * 100 + '%',
13857            };
13858            if (shouldOverlap && !segHCoords.stackForward) {
13859                // add padding to the edge so that forward stacked events don't cover the resizer's icon
13860                props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
13861            }
13862            return props;
13863        }
13864    }
13865    function renderPlainFgSegs(sortedFgSegs, { todayRange, nowDate, eventSelection, eventDrag, eventResize }) {
13866        let hiddenInstances = (eventDrag ? eventDrag.affectedInstances : null) ||
13867            (eventResize ? eventResize.affectedInstances : null) ||
13868            {};
13869        return (y(_, null, sortedFgSegs.map((seg) => {
13870            let instanceId = seg.eventRange.instance.instanceId;
13871            return (y("div", { key: instanceId, style: { visibility: hiddenInstances[instanceId] ? 'hidden' : '' } },
13872                y(TimeColEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === eventSelection, isShort: false }, getSegMeta(seg, todayRange, nowDate)))));
13873        })));
13874    }
13875    function computeSegVStyle(segVCoords) {
13876        if (!segVCoords) {
13877            return { top: '', bottom: '' };
13878        }
13879        return {
13880            top: segVCoords.start,
13881            bottom: -segVCoords.end,
13882        };
13883    }
13884    function compileSegsFromEntries(segEntries, allSegs) {
13885        return segEntries.map((segEntry) => allSegs[segEntry.index]);
13886    }
13887
13888    class TimeColsContent extends BaseComponent {
13889        constructor() {
13890            super(...arguments);
13891            this.splitFgEventSegs = memoize(splitSegsByCol);
13892            this.splitBgEventSegs = memoize(splitSegsByCol);
13893            this.splitBusinessHourSegs = memoize(splitSegsByCol);
13894            this.splitNowIndicatorSegs = memoize(splitSegsByCol);
13895            this.splitDateSelectionSegs = memoize(splitSegsByCol);
13896            this.splitEventDrag = memoize(splitInteractionByCol);
13897            this.splitEventResize = memoize(splitInteractionByCol);
13898            this.rootElRef = d();
13899            this.cellElRefs = new RefMap();
13900        }
13901        render() {
13902            let { props, context } = this;
13903            let nowIndicatorTop = context.options.nowIndicator &&
13904                props.slatCoords &&
13905                props.slatCoords.safeComputeTop(props.nowDate); // might return void
13906            let colCnt = props.cells.length;
13907            let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, colCnt);
13908            let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, colCnt);
13909            let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, colCnt);
13910            let nowIndicatorSegsByRow = this.splitNowIndicatorSegs(props.nowIndicatorSegs, colCnt);
13911            let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, colCnt);
13912            let eventDragByRow = this.splitEventDrag(props.eventDrag, colCnt);
13913            let eventResizeByRow = this.splitEventResize(props.eventResize, colCnt);
13914            return (y("div", { className: "fc-timegrid-cols", ref: this.rootElRef },
13915                y("table", { role: "presentation", style: {
13916                        minWidth: props.tableMinWidth,
13917                        width: props.clientWidth,
13918                    } },
13919                    props.tableColGroupNode,
13920                    y("tbody", { role: "presentation" },
13921                        y("tr", { role: "row" },
13922                            props.axis && (y("td", { "aria-hidden": true, className: "fc-timegrid-col fc-timegrid-axis" },
13923                                y("div", { className: "fc-timegrid-col-frame" },
13924                                    y("div", { className: "fc-timegrid-now-indicator-container" }, typeof nowIndicatorTop === 'number' && (y(NowIndicatorContainer, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: props.nowDate })))))),
13925                            props.cells.map((cell, i) => (y(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 }))))))));
13926        }
13927        componentDidMount() {
13928            this.updateCoords();
13929        }
13930        componentDidUpdate() {
13931            this.updateCoords();
13932        }
13933        updateCoords() {
13934            let { props } = this;
13935            if (props.onColCoords &&
13936                props.clientWidth !== null // means sizing has stabilized
13937            ) {
13938                props.onColCoords(new PositionCache(this.rootElRef.current, collectCellEls(this.cellElRefs.currentMap, props.cells), true, // horizontal
13939                false));
13940            }
13941        }
13942    }
13943    function collectCellEls(elMap, cells) {
13944        return cells.map((cell) => elMap[cell.key]);
13945    }
13946
13947    /* A component that renders one or more columns of vertical time slots
13948    ----------------------------------------------------------------------------------------------------------------------*/
13949    class TimeCols extends DateComponent {
13950        constructor() {
13951            super(...arguments);
13952            this.processSlotOptions = memoize(processSlotOptions);
13953            this.state = {
13954                slatCoords: null,
13955            };
13956            this.handleRootEl = (el) => {
13957                if (el) {
13958                    this.context.registerInteractiveComponent(this, {
13959                        el,
13960                        isHitComboAllowed: this.props.isHitComboAllowed,
13961                    });
13962                }
13963                else {
13964                    this.context.unregisterInteractiveComponent(this);
13965                }
13966            };
13967            this.handleScrollRequest = (request) => {
13968                let { onScrollTopRequest } = this.props;
13969                let { slatCoords } = this.state;
13970                if (onScrollTopRequest && slatCoords) {
13971                    if (request.time) {
13972                        let top = slatCoords.computeTimeTop(request.time);
13973                        top = Math.ceil(top); // zoom can give weird floating-point values. rather scroll a little bit further
13974                        if (top) {
13975                            top += 1; // to overcome top border that slots beyond the first have. looks better
13976                        }
13977                        onScrollTopRequest(top);
13978                    }
13979                    return true;
13980                }
13981                return false;
13982            };
13983            this.handleColCoords = (colCoords) => {
13984                this.colCoords = colCoords;
13985            };
13986            this.handleSlatCoords = (slatCoords) => {
13987                this.setState({ slatCoords });
13988                if (this.props.onSlatCoords) {
13989                    this.props.onSlatCoords(slatCoords);
13990                }
13991            };
13992        }
13993        render() {
13994            let { props, state } = this;
13995            return (y("div", { className: "fc-timegrid-body", ref: this.handleRootEl, style: {
13996                    // these props are important to give this wrapper correct dimensions for interactions
13997                    // TODO: if we set it here, can we avoid giving to inner tables?
13998                    width: props.clientWidth,
13999                    minWidth: props.tableMinWidth,
14000                } },
14001                y(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 }),
14002                y(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 })));
14003        }
14004        componentDidMount() {
14005            this.scrollResponder = this.context.createScrollResponder(this.handleScrollRequest);
14006        }
14007        componentDidUpdate(prevProps) {
14008            this.scrollResponder.update(prevProps.dateProfile !== this.props.dateProfile);
14009        }
14010        componentWillUnmount() {
14011            this.scrollResponder.detach();
14012        }
14013        queryHit(positionLeft, positionTop) {
14014            let { dateEnv, options } = this.context;
14015            let { colCoords } = this;
14016            let { dateProfile } = this.props;
14017            let { slatCoords } = this.state;
14018            let { snapDuration, snapsPerSlot } = this.processSlotOptions(this.props.slotDuration, options.snapDuration);
14019            let colIndex = colCoords.leftToIndex(positionLeft);
14020            let slatIndex = slatCoords.positions.topToIndex(positionTop);
14021            if (colIndex != null && slatIndex != null) {
14022                let cell = this.props.cells[colIndex];
14023                let slatTop = slatCoords.positions.tops[slatIndex];
14024                let slatHeight = slatCoords.positions.getHeight(slatIndex);
14025                let partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1
14026                let localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat
14027                let snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
14028                let dayDate = this.props.cells[colIndex].date;
14029                let time = addDurations(dateProfile.slotMinTime, multiplyDuration(snapDuration, snapIndex));
14030                let start = dateEnv.add(dayDate, time);
14031                let end = dateEnv.add(start, snapDuration);
14032                return {
14033                    dateProfile,
14034                    dateSpan: Object.assign({ range: { start, end }, allDay: false }, cell.extraDateSpan),
14035                    dayEl: colCoords.els[colIndex],
14036                    rect: {
14037                        left: colCoords.lefts[colIndex],
14038                        right: colCoords.rights[colIndex],
14039                        top: slatTop,
14040                        bottom: slatTop + slatHeight,
14041                    },
14042                    layer: 0,
14043                };
14044            }
14045            return null;
14046        }
14047    }
14048    function processSlotOptions(slotDuration, snapDurationOverride) {
14049        let snapDuration = snapDurationOverride || slotDuration;
14050        let snapsPerSlot = wholeDivideDurations(slotDuration, snapDuration);
14051        if (snapsPerSlot === null) {
14052            snapDuration = slotDuration;
14053            snapsPerSlot = 1;
14054            // TODO: say warning?
14055        }
14056        return { snapDuration, snapsPerSlot };
14057    }
14058
14059    class DayTimeColsSlicer extends Slicer {
14060        sliceRange(range, dayRanges) {
14061            let segs = [];
14062            for (let col = 0; col < dayRanges.length; col += 1) {
14063                let segRange = intersectRanges(range, dayRanges[col]);
14064                if (segRange) {
14065                    segs.push({
14066                        start: segRange.start,
14067                        end: segRange.end,
14068                        isStart: segRange.start.valueOf() === range.start.valueOf(),
14069                        isEnd: segRange.end.valueOf() === range.end.valueOf(),
14070                        col,
14071                    });
14072                }
14073            }
14074            return segs;
14075        }
14076    }
14077
14078    class DayTimeCols extends DateComponent {
14079        constructor() {
14080            super(...arguments);
14081            this.buildDayRanges = memoize(buildDayRanges);
14082            this.slicer = new DayTimeColsSlicer();
14083            this.timeColsRef = d();
14084        }
14085        render() {
14086            let { props, context } = this;
14087            let { dateProfile, dayTableModel } = props;
14088            let { nowIndicator, nextDayThreshold } = context.options;
14089            let dayRanges = this.buildDayRanges(dayTableModel, dateProfile, context.dateEnv);
14090            // give it the first row of cells
14091            // TODO: would move this further down hierarchy, but sliceNowDate needs it
14092            return (y(NowTimer, { unit: nowIndicator ? 'minute' : 'day' }, (nowDate, todayRange) => (y(TimeCols, Object.assign({ ref: this.timeColsRef }, this.slicer.sliceProps(props, dateProfile, null, context, dayRanges), { forPrint: props.forPrint, axis: props.axis, dateProfile: dateProfile, slatMetas: props.slatMetas, slotDuration: props.slotDuration, cells: dayTableModel.cells[0], tableColGroupNode: props.tableColGroupNode, tableMinWidth: props.tableMinWidth, clientWidth: props.clientWidth, clientHeight: props.clientHeight, expandRows: props.expandRows, nowDate: nowDate, nowIndicatorSegs: nowIndicator && this.slicer.sliceNowDate(nowDate, dateProfile, nextDayThreshold, context, dayRanges), todayRange: todayRange, onScrollTopRequest: props.onScrollTopRequest, onSlatCoords: props.onSlatCoords })))));
14093        }
14094    }
14095    function buildDayRanges(dayTableModel, dateProfile, dateEnv) {
14096        let ranges = [];
14097        for (let date of dayTableModel.headerDates) {
14098            ranges.push({
14099                start: dateEnv.add(date, dateProfile.slotMinTime),
14100                end: dateEnv.add(date, dateProfile.slotMaxTime),
14101            });
14102        }
14103        return ranges;
14104    }
14105
14106    // potential nice values for the slot-duration and interval-duration
14107    // from largest to smallest
14108    const STOCK_SUB_DURATIONS = [
14109        { hours: 1 },
14110        { minutes: 30 },
14111        { minutes: 15 },
14112        { seconds: 30 },
14113        { seconds: 15 },
14114    ];
14115    function buildSlatMetas(slotMinTime, slotMaxTime, explicitLabelInterval, slotDuration, dateEnv) {
14116        let dayStart = new Date(0);
14117        let slatTime = slotMinTime;
14118        let slatIterator = createDuration(0);
14119        let labelInterval = explicitLabelInterval || computeLabelInterval(slotDuration);
14120        let metas = [];
14121        while (asRoughMs(slatTime) < asRoughMs(slotMaxTime)) {
14122            let date = dateEnv.add(dayStart, slatTime);
14123            let isLabeled = wholeDivideDurations(slatIterator, labelInterval) !== null;
14124            metas.push({
14125                date,
14126                time: slatTime,
14127                key: date.toISOString(),
14128                isoTimeStr: formatIsoTimeString(date),
14129                isLabeled,
14130            });
14131            slatTime = addDurations(slatTime, slotDuration);
14132            slatIterator = addDurations(slatIterator, slotDuration);
14133        }
14134        return metas;
14135    }
14136    // Computes an automatic value for slotLabelInterval
14137    function computeLabelInterval(slotDuration) {
14138        let i;
14139        let labelInterval;
14140        let slotsPerLabel;
14141        // find the smallest stock label interval that results in more than one slots-per-label
14142        for (i = STOCK_SUB_DURATIONS.length - 1; i >= 0; i -= 1) {
14143            labelInterval = createDuration(STOCK_SUB_DURATIONS[i]);
14144            slotsPerLabel = wholeDivideDurations(labelInterval, slotDuration);
14145            if (slotsPerLabel !== null && slotsPerLabel > 1) {
14146                return labelInterval;
14147            }
14148        }
14149        return slotDuration; // fall back
14150    }
14151
14152    class DayTimeColsView extends TimeColsView {
14153        constructor() {
14154            super(...arguments);
14155            this.buildTimeColsModel = memoize(buildTimeColsModel);
14156            this.buildSlatMetas = memoize(buildSlatMetas);
14157        }
14158        render() {
14159            let { options, dateEnv, dateProfileGenerator } = this.context;
14160            let { props } = this;
14161            let { dateProfile } = props;
14162            let dayTableModel = this.buildTimeColsModel(dateProfile, dateProfileGenerator);
14163            let splitProps = this.allDaySplitter.splitProps(props);
14164            let slatMetas = this.buildSlatMetas(dateProfile.slotMinTime, dateProfile.slotMaxTime, options.slotLabelInterval, options.slotDuration, dateEnv);
14165            let { dayMinWidth } = options;
14166            let hasAttachedAxis = !dayMinWidth;
14167            let hasDetachedAxis = dayMinWidth;
14168            let headerContent = options.dayHeaders && (y(DayHeader, { dates: dayTableModel.headerDates, dateProfile: dateProfile, datesRepDistinctDays: true, renderIntro: hasAttachedAxis ? this.renderHeadAxis : null }));
14169            let allDayContent = (options.allDaySlot !== false) && ((contentArg) => (y(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()))));
14170            let timeGridContent = (contentArg) => (y(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 })));
14171            return hasDetachedAxis
14172                ? this.renderHScrollLayout(headerContent, allDayContent, timeGridContent, dayTableModel.colCnt, dayMinWidth, slatMetas, this.state.slatCoords)
14173                : this.renderSimpleLayout(headerContent, allDayContent, timeGridContent);
14174        }
14175    }
14176    function buildTimeColsModel(dateProfile, dateProfileGenerator) {
14177        let daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
14178        return new DayTableModel(daySeries, false);
14179    }
14180
14181    var css_248z$2 = ".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-arrow,.fc .fc-timegrid-now-indicator-line{pointer-events:none}.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}";
14182    injectStyles(css_248z$2);
14183
14184    const OPTION_REFINERS$2 = {
14185        allDaySlot: Boolean,
14186    };
14187
14188    var index$2 = createPlugin({
14189        name: '@fullcalendar/timegrid',
14190        initialView: 'timeGridWeek',
14191        optionRefiners: OPTION_REFINERS$2,
14192        views: {
14193            timeGrid: {
14194                component: DayTimeColsView,
14195                usesMinMaxTime: true,
14196                allDaySlot: true,
14197                slotDuration: '00:30:00',
14198                slotEventOverlap: true, // a bad name. confused with overlap/constraint system
14199            },
14200            timeGridDay: {
14201                type: 'timeGrid',
14202                duration: { days: 1 },
14203            },
14204            timeGridWeek: {
14205                type: 'timeGrid',
14206                duration: { weeks: 1 },
14207            },
14208        },
14209    });
14210
14211    class ListViewHeaderRow extends BaseComponent {
14212        constructor() {
14213            super(...arguments);
14214            this.state = {
14215                textId: getUniqueDomId(),
14216            };
14217        }
14218        render() {
14219            let { theme, dateEnv, options, viewApi } = this.context;
14220            let { cellId, dayDate, todayRange } = this.props;
14221            let { textId } = this.state;
vendor: 8,357 bytes, lines 14222-14369
14222            let dayMeta = getDateMeta(dayDate, todayRange);
14223            // will ever be falsy?
14224            let text = options.listDayFormat ? dateEnv.format(dayDate, options.listDayFormat) : '';
14225            // will ever be falsy? also, BAD NAME "alt"
14226            let sideText = options.listDaySideFormat ? dateEnv.format(dayDate, options.listDaySideFormat) : '';
14227            let renderProps = Object.assign({ date: dateEnv.toDate(dayDate), view: viewApi, textId,
14228                text,
14229                sideText, navLinkAttrs: buildNavLinkAttrs(this.context, dayDate), sideNavLinkAttrs: buildNavLinkAttrs(this.context, dayDate, 'day', false) }, dayMeta);
14230            // TODO: make a reusable HOC for dayHeader (used in daygrid/timegrid too)
14231            return (y(ContentContainer, { elTag: "tr", elClasses: [
14232                    'fc-list-day',
14233                    ...getDayClassNames(dayMeta, theme),
14234                ], elAttrs: {
14235                    'data-date': formatDayString(dayDate),
14236                }, renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInnerContent, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => ( // TODO: force-hide top border based on :first-child
14237            y("th", { scope: "colgroup", colSpan: 3, id: cellId, "aria-labelledby": textId },
14238                y(InnerContent, { elTag: "div", elClasses: [
14239                        'fc-list-day-cushion',
14240                        theme.getClass('tableCellShaded'),
14241                    ] })))));
14242        }
14243    }
14244    function renderInnerContent(props) {
14245        return (y(_, null,
14246            props.text && (y("a", Object.assign({ id: props.textId, className: "fc-list-day-text" }, props.navLinkAttrs), props.text)),
14247            props.sideText && ( /* not keyboard tabbable */y("a", Object.assign({ "aria-hidden": true, className: "fc-list-day-side-text" }, props.sideNavLinkAttrs), props.sideText))));
14248    }
14249
14250    const DEFAULT_TIME_FORMAT = createFormatter({
14251        hour: 'numeric',
14252        minute: '2-digit',
14253        meridiem: 'short',
14254    });
14255    class ListViewEventRow extends BaseComponent {
14256        render() {
14257            let { props, context } = this;
14258            let { options } = context;
14259            let { seg, timeHeaderId, eventHeaderId, dateHeaderId } = props;
14260            let timeFormat = options.eventTimeFormat || DEFAULT_TIME_FORMAT;
14261            return (y(EventContainer, Object.assign({}, props, { elTag: "tr", elClasses: [
14262                    'fc-list-event',
14263                    seg.eventRange.def.url && 'fc-event-forced-url',
14264                ], defaultGenerator: () => renderEventInnerContent(seg, context) /* weird */, seg: seg, timeText: "", disableDragging: true, disableResizing: true }), (InnerContent, eventContentArg) => (y(_, null,
14265                buildTimeContent(seg, timeFormat, context, timeHeaderId, dateHeaderId),
14266                y("td", { "aria-hidden": true, className: "fc-list-event-graphic" },
14267                    y("span", { className: "fc-list-event-dot", style: {
14268                            borderColor: eventContentArg.borderColor || eventContentArg.backgroundColor,
14269                        } })),
14270                y(InnerContent, { elTag: "td", elClasses: ['fc-list-event-title'], elAttrs: { headers: `${eventHeaderId} ${dateHeaderId}` } })))));
14271        }
14272    }
14273    function renderEventInnerContent(seg, context) {
14274        let interactiveAttrs = getSegAnchorAttrs(seg, context);
14275        return (y("a", Object.assign({}, interactiveAttrs), seg.eventRange.def.title));
14276    }
14277    function buildTimeContent(seg, timeFormat, context, timeHeaderId, dateHeaderId) {
14278        let { options } = context;
14279        if (options.displayEventTime !== false) {
14280            let eventDef = seg.eventRange.def;
14281            let eventInstance = seg.eventRange.instance;
14282            let doAllDay = false;
14283            let timeText;
14284            if (eventDef.allDay) {
14285                doAllDay = true;
14286            }
14287            else if (isMultiDayRange(seg.eventRange.range)) { // TODO: use (!isStart || !isEnd) instead?
14288                if (seg.isStart) {
14289                    timeText = buildSegTimeText(seg, timeFormat, context, null, null, eventInstance.range.start, seg.end);
14290                }
14291                else if (seg.isEnd) {
14292                    timeText = buildSegTimeText(seg, timeFormat, context, null, null, seg.start, eventInstance.range.end);
14293                }
14294                else {
14295                    doAllDay = true;
14296                }
14297            }
14298            else {
14299                timeText = buildSegTimeText(seg, timeFormat, context);
14300            }
14301            if (doAllDay) {
14302                let renderProps = {
14303                    text: context.options.allDayText,
14304                    view: context.viewApi,
14305                };
14306                return (y(ContentContainer, { elTag: "td", elClasses: ['fc-list-event-time'], elAttrs: {
14307                        headers: `${timeHeaderId} ${dateHeaderId}`,
14308                    }, renderProps: renderProps, generatorName: "allDayContent", customGenerator: options.allDayContent, defaultGenerator: renderAllDayInner, classNameGenerator: options.allDayClassNames, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }));
14309            }
14310            return (y("td", { className: "fc-list-event-time" }, timeText));
14311        }
14312        return null;
14313    }
14314    function renderAllDayInner(renderProps) {
14315        return renderProps.text;
14316    }
14317
14318    /*
14319    Responsible for the scroller, and forwarding event-related actions into the "grid".
14320    */
14321    class ListView extends DateComponent {
14322        constructor() {
14323            super(...arguments);
14324            this.computeDateVars = memoize(computeDateVars);
14325            this.eventStoreToSegs = memoize(this._eventStoreToSegs);
14326            this.state = {
14327                timeHeaderId: getUniqueDomId(),
14328                eventHeaderId: getUniqueDomId(),
14329                dateHeaderIdRoot: getUniqueDomId(),
14330            };
14331            this.setRootEl = (rootEl) => {
14332                if (rootEl) {
14333                    this.context.registerInteractiveComponent(this, {
14334                        el: rootEl,
14335                    });
14336                }
14337                else {
14338                    this.context.unregisterInteractiveComponent(this);
14339                }
14340            };
14341        }
14342        render() {
14343            let { props, context } = this;
14344            let { dayDates, dayRanges } = this.computeDateVars(props.dateProfile);
14345            let eventSegs = this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges);
14346            return (y(ViewContainer, { elRef: this.setRootEl, elClasses: [
14347                    'fc-list',
14348                    context.theme.getClass('table'),
14349                    context.options.stickyHeaderDates !== false ?
14350                        'fc-list-sticky' :
14351                        '',
14352                ], viewSpec: context.viewSpec },
14353                y(Scroller, { liquid: !props.isHeightAuto, overflowX: props.isHeightAuto ? 'visible' : 'hidden', overflowY: props.isHeightAuto ? 'visible' : 'auto' }, eventSegs.length > 0 ?
14354                    this.renderSegList(eventSegs, dayDates) :
14355                    this.renderEmptyMessage())));
14356        }
14357        renderEmptyMessage() {
14358            let { options, viewApi } = this.context;
14359            let renderProps = {
14360                text: options.noEventsText,
14361                view: viewApi,
14362            };
14363            return (y(ContentContainer, { elTag: "div", elClasses: ['fc-list-empty'], renderProps: renderProps, generatorName: "noEventsContent", customGenerator: options.noEventsContent, defaultGenerator: renderNoEventsInner, classNameGenerator: options.noEventsClassNames, didMount: options.noEventsDidMount, willUnmount: options.noEventsWillUnmount }, (InnerContent) => (y(InnerContent, { elTag: "div", elClasses: ['fc-list-empty-cushion'] }))));
14364        }
14365        renderSegList(allSegs, dayDates) {
14366            let { theme, options } = this.context;
14367            let { timeHeaderId, eventHeaderId, dateHeaderIdRoot } = this.state;
14368            let segsByDay = groupSegsByDay(allSegs); // sparse array
14369            return (y(NowTimer, { unit: "day" }, (nowDate, todayRange) => {
14370                let innerNodes = [];
14371                for (let dayIndex = 0; dayIndex < segsByDay.length; dayIndex += 1) {
14372                    let daySegs = segsByDay[dayIndex];
14373                    if (daySegs) { // sparse array, so might be undefined
14374                        let dayStr = formatDayString(dayDates[dayIndex]);
14375                        let dateHeaderId = dateHeaderIdRoot + '-' + dayStr;
14376                        // append a day header
14377                        innerNodes.push(y(ListViewHeaderRow, { key: dayStr, cellId: dateHeaderId, dayDate: dayDates[dayIndex], todayRange: todayRange }));
14378                        daySegs = sortEventSegs(daySegs, options.eventOrder);
14379                        for (let seg of daySegs) {
14380                            innerNodes.push(y(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))));
14381                        }
14382                    }
14383                }
14384                return (y("table", { className: 'fc-list-table ' + theme.getClass('table') },
14385                    y("thead", null,
14386                        y("tr", null,
14387                            y("th", { scope: "col", id: timeHeaderId }, options.timeHint),
14388                            y("th", { scope: "col", "aria-hidden": true }),
14389                            y("th", { scope: "col", id: eventHeaderId }, options.eventHint))),
14390                    y("tbody", null, innerNodes)));
14391            }));
14392        }
14393        _eventStoreToSegs(eventStore, eventUiBases, dayRanges) {
14394            return this.eventRangesToSegs(sliceEventStore(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.context.options.nextDayThreshold).fg, dayRanges);
14395        }
14396        eventRangesToSegs(eventRanges, dayRanges) {
14397            let segs = [];
14398            for (let eventRange of eventRanges) {
14399                segs.push(...this.eventRangeToSegs(eventRange, dayRanges));
14400            }
14401            return segs;
14402        }
14403        eventRangeToSegs(eventRange, dayRanges) {
14404            let { dateEnv } = this.context;
14405            let { nextDayThreshold } = this.context.options;
14406            let range = eventRange.range;
14407            let allDay = eventRange.def.allDay;
14408            let dayIndex;
14409            let segRange;
14410            let seg;
14411            let segs = [];
14412            for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex += 1) {
14413                segRange = intersectRanges(range, dayRanges[dayIndex]);
14414                if (segRange) {
14415                    seg = {
14416                        component: this,
14417                        eventRange,
14418                        start: segRange.start,
14419                        end: segRange.end,
14420                        isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(),
14421                        isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(),
14422                        dayIndex,
14423                    };
14424                    segs.push(seg);
14425                    // detect when range won't go fully into the next day,
14426                    // and mutate the latest seg to the be the end.
14427                    if (!seg.isEnd && !allDay &&
14428                        dayIndex + 1 < dayRanges.length &&
14429                        range.end <
14430                            dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) {
14431                        seg.end = range.end;
14432                        seg.isEnd = true;
14433                        break;
14434                    }
14435                }
14436            }
14437            return segs;
14438        }
14439    }
14440    function renderNoEventsInner(renderProps) {
14441        return renderProps.text;
14442    }
14443    function computeDateVars(dateProfile) {
14444        let dayStart = startOfDay(dateProfile.renderRange.start);
14445        let viewEnd = dateProfile.renderRange.end;
14446        let dayDates = [];
14447        let dayRanges = [];
14448        while (dayStart < viewEnd) {
14449            dayDates.push(dayStart);
14450            dayRanges.push({
14451                start: dayStart,
14452                end: addDays(dayStart, 1),
14453            });
14454            dayStart = addDays(dayStart, 1);
14455        }
14456        return { dayDates, dayRanges };
14457    }
14458    // Returns a sparse array of arrays, segs grouped by their dayIndex
14459    function groupSegsByDay(segs) {
14460        let segsByDay = []; // sparse array
14461        let i;
14462        let seg;
14463        for (i = 0; i < segs.length; i += 1) {
14464            seg = segs[i];
14465            (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = []))
14466                .push(seg);
14467        }
14468        return segsByDay;
14469    }
14470
14471    var css_248z$1 = ":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}";
14472    injectStyles(css_248z$1);
14473
14474    const OPTION_REFINERS$1 = {
14475        listDayFormat: createFalsableFormatter,
14476        listDaySideFormat: createFalsableFormatter,
14477        noEventsClassNames: identity,
14478        noEventsContent: identity,
14479        noEventsDidMount: identity,
14480        noEventsWillUnmount: identity,
14481        // noEventsText is defined in base options
14482    };
14483    function createFalsableFormatter(input) {
14484        return input === false ? null : createFormatter(input);
14485    }
14486
14487    var index$1 = createPlugin({
14488        name: '@fullcalendar/list',
14489        optionRefiners: OPTION_REFINERS$1,
14490        views: {
14491            list: {
14492                component: ListView,
14493                buttonTextKey: 'list',
14494                listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' }, // like "January 1, 2016"
14495            },
14496            listDay: {
14497                type: 'list',
14498                duration: { days: 1 },
14499                listDayFormat: { weekday: 'long' }, // day-of-week is all we need. full date is probably in headerToolbar
14500            },
14501            listWeek: {
14502                type: 'list',
14503                duration: { weeks: 1 },
14504                listDayFormat: { weekday: 'long' },
14505                listDaySideFormat: { month: 'long', day: 'numeric', year: 'numeric' },
14506            },
14507            listMonth: {
14508                type: 'list',
14509                duration: { month: 1 },
14510                listDaySideFormat: { weekday: 'long' }, // day-of-week is nice-to-have
14511            },
14512            listYear: {
14513                type: 'list',
14514                duration: { year: 1 },
14515                listDaySideFormat: { weekday: 'long' }, // day-of-week is nice-to-have
14516            },
14517        },
14518    });
14519
14520    class SingleMonth extends DateComponent {
14521        constructor() {
14522            super(...arguments);
14523            this.buildDayTableModel = memoize(buildDayTableModel);
14524            this.slicer = new DayTableSlicer();
14525            this.state = {
14526                labelId: getUniqueDomId(),
14527            };
14528        }
14529        render() {
14530            const { props, state, context } = this;
14531            const { dateProfile, forPrint } = props;
14532            const { options } = context;
14533            const dayTableModel = this.buildDayTableModel(dateProfile, context.dateProfileGenerator);
14534            const slicedProps = this.slicer.sliceProps(props, dateProfile, options.nextDayThreshold, context, dayTableModel);
14535            // ensure single-month has aspect ratio
14536            const tableHeight = props.tableWidth != null ? props.tableWidth / options.aspectRatio : null;
14537            const rowCnt = dayTableModel.cells.length;
14538            const rowHeight = tableHeight != null ? tableHeight / rowCnt : null;
14539            return (y("div", { ref: props.elRef, "data-date": props.isoDateStr, className: "fc-multimonth-month", style: { width: props.width }, role: "grid", "aria-labelledby": state.labelId },
14540                y("div", { className: "fc-multimonth-header", style: { marginBottom: rowHeight }, role: "presentation" },
14541                    y("div", { className: "fc-multimonth-title", id: state.labelId }, context.dateEnv.format(props.dateProfile.currentRange.start, props.titleFormat)),
14542                    y("table", { className: [
14543                            'fc-multimonth-header-table',
14544                            context.theme.getClass('table'),
14545                        ].join(' '), role: "presentation" },
14546                        y("thead", { role: "rowgroup" },
14547                            y(DayHeader, { dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: false })))),
14548                y("div", { className: [
14549                        'fc-multimonth-daygrid',
vendor: 9,988 bytes, lines 14550-14732
14550                        'fc-daygrid',
14551                        'fc-daygrid-body',
14552                        !forPrint && 'fc-daygrid-body-balanced',
14553                        forPrint && 'fc-daygrid-body-unbalanced',
14554                        forPrint && 'fc-daygrid-body-natural',
14555                    ].join(' '), style: { marginTop: -rowHeight } },
14556                    y("table", { className: [
14557                            'fc-multimonth-daygrid-table',
14558                            context.theme.getClass('table'),
14559                        ].join(' '), style: { height: forPrint ? '' : tableHeight }, role: "presentation" },
14560                        y("tbody", { role: "rowgroup" },
14561                            y(TableRows, Object.assign({}, slicedProps, { dateProfile: dateProfile, cells: dayTableModel.cells, eventSelection: props.eventSelection, dayMaxEvents: !forPrint, dayMaxEventRows: !forPrint, showWeekNumbers: options.weekNumbers, clientWidth: props.clientWidth, clientHeight: props.clientHeight, forPrint: forPrint })))))));
14562        }
14563    }
14564
14565    class MultiMonthView extends DateComponent {
14566        constructor() {
14567            super(...arguments);
14568            this.splitDateProfileByMonth = memoize(splitDateProfileByMonth);
14569            this.buildMonthFormat = memoize(buildMonthFormat);
14570            this.scrollElRef = d();
14571            this.firstMonthElRef = d();
14572            this.needsScrollReset = false;
14573            this.handleSizing = (isForced) => {
14574                if (isForced) {
14575                    this.updateSize();
14576                }
14577            };
14578        }
14579        render() {
14580            const { context, props, state } = this;
14581            const { options } = context;
14582            const { clientWidth, clientHeight } = state;
14583            const monthHPadding = state.monthHPadding || 0;
14584            const colCount = Math.min(clientWidth != null ?
14585                Math.floor(clientWidth / (options.multiMonthMinWidth + monthHPadding)) :
14586                1, options.multiMonthMaxColumns) || 1;
14587            const monthWidthPct = (100 / colCount) + '%';
14588            const monthTableWidth = clientWidth == null ? null :
14589                (clientWidth / colCount) - monthHPadding;
14590            const isLegitSingleCol = clientWidth != null && colCount === 1;
14591            const monthDateProfiles = this.splitDateProfileByMonth(context.dateProfileGenerator, props.dateProfile, context.dateEnv, isLegitSingleCol ? false : options.fixedWeekCount, options.showNonCurrentDates);
14592            const monthTitleFormat = this.buildMonthFormat(options.multiMonthTitleFormat, monthDateProfiles);
14593            const rootClassNames = [
14594                'fc-multimonth',
14595                isLegitSingleCol ?
14596                    'fc-multimonth-singlecol' :
14597                    'fc-multimonth-multicol',
14598                (monthTableWidth != null && monthTableWidth < 400) ?
14599                    'fc-multimonth-compact' :
14600                    '',
14601                props.isHeightAuto ?
14602                    '' :
14603                    'fc-scroller', // for AutoScroller
14604            ];
14605            return (y(ViewContainer, { elRef: this.scrollElRef, elClasses: rootClassNames, viewSpec: context.viewSpec }, monthDateProfiles.map((monthDateProfile, i) => {
14606                const monthStr = formatIsoMonthStr(monthDateProfile.currentRange.start);
14607                return (y(SingleMonth, Object.assign({}, props, { key: monthStr, isoDateStr: monthStr, elRef: i === 0 ? this.firstMonthElRef : undefined, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width: monthWidthPct, tableWidth: monthTableWidth, clientWidth: clientWidth, clientHeight: clientHeight })));
14608            })));
14609        }
14610        componentDidMount() {
14611            this.updateSize();
14612            this.context.addResizeHandler(this.handleSizing);
14613            this.requestScrollReset();
14614        }
14615        componentDidUpdate(prevProps) {
14616            if (!isPropsEqual(prevProps, this.props)) { // an external change?
14617                this.handleSizing(false);
14618            }
14619            if (prevProps.dateProfile !== this.props.dateProfile) {
14620                this.requestScrollReset();
14621            }
14622            else {
14623                this.flushScrollReset();
14624            }
14625        }
14626        componentWillUnmount() {
14627            this.context.removeResizeHandler(this.handleSizing);
14628        }
14629        updateSize() {
14630            const scrollEl = this.scrollElRef.current;
14631            const firstMonthEl = this.firstMonthElRef.current;
14632            if (scrollEl) {
14633                this.setState({
14634                    clientWidth: scrollEl.clientWidth,
14635                    clientHeight: scrollEl.clientHeight,
14636                });
14637            }
14638            if (firstMonthEl && scrollEl) {
14639                if (this.state.monthHPadding == null) { // always remember initial non-zero value
14640                    this.setState({
14641                        monthHPadding: scrollEl.clientWidth - // go within padding
14642                            firstMonthEl.firstChild.offsetWidth,
14643                    });
14644                }
14645            }
14646        }
14647        requestScrollReset() {
14648            this.needsScrollReset = true;
14649            this.flushScrollReset();
14650        }
14651        flushScrollReset() {
14652            if (this.needsScrollReset &&
14653                this.state.monthHPadding != null // indicates sizing already happened
14654            ) {
14655                const { currentDate } = this.props.dateProfile;
14656                const scrollEl = this.scrollElRef.current;
14657                const monthEl = scrollEl.querySelector(`[data-date="${formatIsoMonthStr(currentDate)}"]`);
14658                scrollEl.scrollTop = monthEl.getBoundingClientRect().top -
14659                    this.firstMonthElRef.current.getBoundingClientRect().top;
14660                this.needsScrollReset = false;
14661            }
14662        }
14663        // workaround for when queued setState render (w/ clientWidth) gets cancelled because
14664        // subsequent update and shouldComponentUpdate says not to render :(
14665        shouldComponentUpdate() {
14666            return true;
14667        }
14668    }
14669    // date profile
14670    // -------------------------------------------------------------------------------------------------
14671    const oneMonthDuration = createDuration(1, 'month');
14672    function splitDateProfileByMonth(dateProfileGenerator, dateProfile, dateEnv, fixedWeekCount, showNonCurrentDates) {
14673        const { start, end } = dateProfile.currentRange;
14674        let monthStart = start;
14675        const monthDateProfiles = [];
14676        while (monthStart.valueOf() < end.valueOf()) {
14677            const monthEnd = dateEnv.add(monthStart, oneMonthDuration);
14678            const currentRange = {
14679                // yuck
14680                start: dateProfileGenerator.skipHiddenDays(monthStart),
14681                end: dateProfileGenerator.skipHiddenDays(monthEnd, -1, true),
14682            };
14683            let renderRange = buildDayTableRenderRange({
14684                currentRange,
14685                snapToWeek: true,
14686                fixedWeekCount,
14687                dateEnv,
14688            });
14689            renderRange = {
14690                // yuck
14691                start: dateProfileGenerator.skipHiddenDays(renderRange.start),
14692                end: dateProfileGenerator.skipHiddenDays(renderRange.end, -1, true),
14693            };
14694            const activeRange = dateProfile.activeRange ?
14695                intersectRanges(dateProfile.activeRange, showNonCurrentDates ? renderRange : currentRange) :
14696                null;
14697            monthDateProfiles.push({
14698                currentDate: dateProfile.currentDate,
14699                isValid: dateProfile.isValid,
14700                validRange: dateProfile.validRange,
14701                renderRange,
14702                activeRange,
14703                currentRange,
14704                currentRangeUnit: 'month',
14705                isRangeAllDay: true,
14706                dateIncrement: dateProfile.dateIncrement,
14707                slotMinTime: dateProfile.slotMaxTime,
14708                slotMaxTime: dateProfile.slotMinTime,
14709            });
14710            monthStart = monthEnd;
14711        }
14712        return monthDateProfiles;
14713    }
14714    // date formatting
14715    // -------------------------------------------------------------------------------------------------
14716    const YEAR_MONTH_FORMATTER = createFormatter({ year: 'numeric', month: 'long' });
14717    const YEAR_FORMATTER = createFormatter({ month: 'long' });
14718    function buildMonthFormat(formatOverride, monthDateProfiles) {
14719        return formatOverride ||
14720            ((monthDateProfiles[0].currentRange.start.getUTCFullYear() !==
14721                monthDateProfiles[monthDateProfiles.length - 1].currentRange.start.getUTCFullYear())
14722                ? YEAR_MONTH_FORMATTER
14723                : YEAR_FORMATTER);
14724    }
14725
14726    const OPTION_REFINERS = {
14727        multiMonthTitleFormat: createFormatter,
14728        multiMonthMaxColumns: Number,
14729        multiMonthMinWidth: Number,
14730    };
14731
14732    var css_248z = ".fc .fc-multimonth{border:1px solid var(--fc-border-color);display:flex;flex-wrap:wrap;overflow-x:hidden;overflow-y:auto}.fc .fc-multimonth-title{font-size:1.2em;font-weight:700;padding:1em 0;text-align:center}.fc .fc-multimonth-daygrid{background:var(--fc-page-bg-color)}.fc .fc-multimonth-daygrid-table,.fc .fc-multimonth-header-table{table-layout:fixed;width:100%}.fc .fc-multimonth-daygrid-table{border-top-style:hidden!important}.fc .fc-multimonth-singlecol .fc-multimonth{position:relative}.fc .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:relative;top:0;z-index:2}.fc .fc-multimonth-singlecol .fc-multimonth-daygrid{position:relative;z-index:1}.fc .fc-multimonth-singlecol .fc-multimonth-daygrid-table,.fc .fc-multimonth-singlecol .fc-multimonth-header-table{border-left-style:hidden;border-right-style:hidden}.fc .fc-multimonth-singlecol .fc-multimonth-month:last-child .fc-multimonth-daygrid-table{border-bottom-style:hidden}.fc .fc-multimonth-multicol{line-height:1}.fc .fc-multimonth-multicol .fc-multimonth-month{padding:0 1.2em 1.2em}
14732.fc .fc-multimonth-multicol .fc-daygrid-more-link{border:1px solid var(--fc-event-border-color);display:block;float:none;padding:1px}.fc .fc-multimonth-compact{line-height:1}.fc .fc-multimonth-compact .fc-multimonth-daygrid-table,.fc .fc-multimonth-compact .fc-multimonth-header-table{font-size:.9em}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{position:sticky}.fc-media-print .fc-multimonth{overflow:visible}";
14733    injectStyles(css_248z);
14734
14735    var index = createPlugin({
14736        name: '@fullcalendar/multimonth',
14737        initialView: 'multiMonthYear',
14738        optionRefiners: OPTION_REFINERS,
14739        views: {
14740            multiMonth: {
14741                component: MultiMonthView,
14742                dateProfileGeneratorClass: TableDateProfileGenerator,
14743                multiMonthMinWidth: 350,
14744                multiMonthMaxColumns: 3,
14745            },
14746            multiMonthYear: {
14747                type: 'multiMonth',
14748                duration: { years: 1 },
14749                fixedWeekCount: true,
14750                showNonCurrentDates: false,
14751            },
14752        },
14753    });
14754
14755    globalPlugins.push(index$4, index$3, index$2, index$1, index);
14756
14757    exports.Calendar = Calendar;
14758    exports.Draggable = ExternalDraggable;
14759    exports.Internal = internal;
14760    exports.JsonRequestError = JsonRequestError;
14761    exports.Preact = preact;
14762    exports.ThirdPartyDraggable = ThirdPartyDraggable;
14763    exports.createPlugin = createPlugin;
14764    exports.formatDate = formatDate;
14765    exports.formatRange = formatRange;
14766    exports.globalLocales = globalLocales;
14767    exports.globalPlugins = globalPlugins;
14768    exports.sliceEvents = sliceEvents;
14769    exports.version = version;
14770
14771    Object.defineProperty(exports, '__esModule', { value: true });
14772
14773    return exports;
14774
14775})({});

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.