aboutsummaryrefslogtreecommitdiffstats
path: root/library/fullcalendar/dist
diff options
context:
space:
mode:
authorMario <mario@mariovavti.com>2023-01-25 13:09:00 +0000
committerMario <mario@mariovavti.com>2023-01-25 13:09:00 +0000
commita9ae17036d30a676c833a6ddb98409f19cbbd963 (patch)
tree66d29806350386a585dcbf4aa20f51cda4da6c49 /library/fullcalendar/dist
parent08e925758e920b898ac2d08710eab2f9638fe276 (diff)
downloadvolse-hubzilla-a9ae17036d30a676c833a6ddb98409f19cbbd963.tar.gz
volse-hubzilla-a9ae17036d30a676c833a6ddb98409f19cbbd963.tar.bz2
volse-hubzilla-a9ae17036d30a676c833a6ddb98409f19cbbd963.zip
update fullcalendar
Diffstat (limited to 'library/fullcalendar/dist')
-rw-r--r--library/fullcalendar/dist/index.global.js14083
-rw-r--r--library/fullcalendar/dist/index.global.min.js6
2 files changed, 14089 insertions, 0 deletions
diff --git a/library/fullcalendar/dist/index.global.js b/library/fullcalendar/dist/index.global.js
new file mode 100644
index 000000000..d2a252f78
--- /dev/null
+++ b/library/fullcalendar/dist/index.global.js
@@ -0,0 +1,14083 @@
+/*!
+FullCalendar Standard Bundle v6.0.3
+Docs & License: https://fullcalendar.io/docs/initialize-globals
+(c) 2022 Adam Shaw
+*/
+var FullCalendar = (function (exports) {
+ 'use strict';
+
+ var n,l$1,u$1,i$1,t,o,r$1,f$1={},e$1=[],c$1=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function s(n,l){for(var u in l)n[u]=l[u];return n}function a$1(n){var l=n.parentNode;l&&l.removeChild(n);}function h(l,u,i){var t,o,r,f={};for(r in u)"key"==r?t=u[r]:"ref"==r?o=u[r]:f[r]=u[r];if(arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),"function"==typeof l&&null!=l.defaultProps)for(r in l.defaultProps)void 0===f[r]&&(f[r]=l.defaultProps[r]);return v$1(l,f,t,o,null)}function v$1(n,i,t,o,r){var f={type:n,props:i,key:t,ref:o,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==r?++u$1:r};return null==r&&null!=l$1.vnode&&l$1.vnode(f),f}function y(){return {current:null}}function p(n){return n.children}function d(n,l){this.props=n,this.context=l;}function _(n,l){if(null==l)return n.__?_(n.__,n.__.__k.indexOf(n)+1):null;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e;return "function"==typeof n.type?_(n):null}function k$1(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return k$1(n)}}function b$1(n){(!n.__d&&(n.__d=!0)&&t.push(n)&&!g$2.__r++||o!==l$1.debounceRendering)&&((o=l$1.debounceRendering)||setTimeout)(g$2);}function g$2(){for(var n;g$2.__r=t.length;)n=t.sort(function(n,l){return n.__v.__b-l.__v.__b}),t=[],n.some(function(n){var l,u,i,t,o,r;n.__d&&(o=(t=(l=n).__v).__e,(r=l.__P)&&(u=[],(i=s({},t)).__v=t.__v+1,j$2(r,t,i,l.__n,void 0!==r.ownerSVGElement,null!=t.__h?[o]:null,u,null==o?_(t):o,t.__h),z$1(u,t),t.__e!=o&&k$1(t)));});}function w$2(n,l,u,i,t,o,r,c,s,a){var h,y,d,k,b,g,w,x=i&&i.__k||e$1,C=x.length;for(u.__k=[],h=0;h<l.length;h++)if(null!=(k=u.__k[h]=null==(k=l[h])||"boolean"==typeof k?null:"string"==typeof k||"number"==typeof k||"bigint"==typeof k?v$1(null,k,null,null,k):Array.isArray(k)?v$1(p,{children:k},null,null,null):k.__b>0?v$1(k.type,k.props,k.key,k.ref?k.ref:null,k.__v):k)){if(k.__=u,k.__b=u.__b+1,null===(d=x[h])||d&&k.key==d.key&&k.type===d.type)x[h]=void 0;else for(y=0;y<C;y++){if((d=x[y])&&k.key==d.key&&k.type===d.type){x[y]=void 0;break}d=null;}j$2(n,k,d=d||f$1,t,o,r,c,s,a),b=k.__e,(y=k.ref)&&d.ref!=y&&(w||(w=[]),d.ref&&w.push(d.ref,null,k),w.push(y,k.__c||b,k)),null!=b?(null==g&&(g=b),"function"==typeof k.type&&k.__k===d.__k?k.__d=s=m$1(k,s,n):s=A(n,k,d,x,b,s),"function"==typeof u.type&&(u.__d=s)):s&&d.__e==s&&s.parentNode!=n&&(s=_(d));}for(u.__e=g,h=C;h--;)null!=x[h]&&N(x[h],x[h]);if(w)for(h=0;h<w.length;h++)M(w[h],w[++h],w[++h]);}function m$1(n,l,u){for(var i,t=n.__k,o=0;t&&o<t.length;o++)(i=t[o])&&(i.__=n,l="function"==typeof i.type?m$1(i,l,u):A(u,i,i,t,i.__e,l));return l}function x$1(n,l){return l=l||[],null==n||"boolean"==typeof n||(Array.isArray(n)?n.some(function(n){x$1(n,l);}):l.push(n)),l}function A(n,l,u,i,t,o){var r,f,e;if(void 0!==l.__d)r=l.__d,l.__d=void 0;else if(null==u||t!=o||null==t.parentNode)n:if(null==o||o.parentNode!==n)n.appendChild(t),r=null;else {for(f=o,e=0;(f=f.nextSibling)&&e<i.length;e+=1)if(f==t)break n;n.insertBefore(t,o),r=o;}return void 0!==r?r:t.nextSibling}function C$1(n,l,u,i,t){var o;for(o in u)"children"===o||"key"===o||o in l||H$1(n,o,null,u[o],i);for(o in l)t&&"function"!=typeof l[o]||"children"===o||"key"===o||"value"===o||"checked"===o||u[o]===l[o]||H$1(n,o,l[o],u[o],i);}function $$1(n,l,u){"-"===l[0]?n.setProperty(l,u):n[l]=null==u?"":"number"!=typeof u||c$1.test(l)?u:u+"px";}function H$1(n,l,u,i,t){var o;n:if("style"===l)if("string"==typeof u)n.style.cssText=u;else {if("string"==typeof i&&(n.style.cssText=i=""),i)for(l in i)u&&l in u||$$1(n.style,l,"");if(u)for(l in u)i&&u[l]===i[l]||$$1(n.style,l,u[l]);}else if("o"===l[0]&&"n"===l[1])o=l!==(l=l.replace(/Capture$/,"")),l=l.toLowerCase()in n?l.toLowerCase().slice(2):l.slice(2),n.l||(n.l={}),n.l[l+o]=u,u?i||n.addEventListener(l,o?T$1:I$1,o):n.removeEventListener(l,o?T$1:I$1,o);else if("dangerouslySetInnerHTML"!==l){if(t)l=l.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("href"!==l&&"list"!==l&&"form"!==l&&"tabIndex"!==l&&"download"!==l&&l in n)try{n[l]=null==u?"":u;break n}catch(n){}"function"==typeof u||(null==u||!1===u&&-1==l.indexOf("-")?n.removeAttribute(l):n.setAttribute(l,u));}}function I$1(n){this.l[n.type+!1](l$1.event?l$1.event(n):n);}function T$1(n){this.l[n.type+!0](l$1.event?l$1.event(n):n);}function j$2(n,u,i,t,o,r,f,e,c){var a,h,v,y,_,k,b,g,m,x,A,C,$,H,I,T=u.type;if(void 0!==u.constructor)return null;null!=i.__h&&(c=i.__h,e=u.__e=i.__e,u.__h=null,r=[e]),(a=l$1.__b)&&a(u);try{n:if("function"==typeof T){if(g=u.props,m=(a=T.contextType)&&t[a.__c],x=a?m?m.props.value:a.__:t,i.__c?b=(h=u.__c=i.__c).__=h.__E:("prototype"in T&&T.prototype.render?u.__c=h=new T(g,x):(u.__c=h=new d(g,x),h.constructor=T,h.render=O),m&&m.sub(h),h.props=g,h.state||(h.state={}),h.context=x,h.__n=t,v=h.__d=!0,h.__h=[],h._sb=[]),null==h.__s&&(h.__s=h.state),null!=T.getDerivedStateFromProps&&(h.__s==h.state&&(h.__s=s({},h.__s)),s(h.__s,T.getDerivedStateFromProps(g,h.__s))),y=h.props,_=h.state,v)null==T.getDerivedStateFromProps&&null!=h.componentWillMount&&h.componentWillMount(),null!=h.componentDidMount&&h.__h.push(h.componentDidMount);else {if(null==T.getDerivedStateFromProps&&g!==y&&null!=h.componentWillReceiveProps&&h.componentWillReceiveProps(g,x),!h.__e&&null!=h.shouldComponentUpdate&&!1===h.shouldComponentUpdate(g,h.__s,x)||u.__v===i.__v){for(h.props=g,h.state=h.__s,u.__v!==i.__v&&(h.__d=!1),h.__v=u,u.__e=i.__e,u.__k=i.__k,u.__k.forEach(function(n){n&&(n.__=u);}),A=0;A<h._sb.length;A++)h.__h.push(h._sb[A]);h._sb=[],h.__h.length&&f.push(h);break n}null!=h.componentWillUpdate&&h.componentWillUpdate(g,h.__s,x),null!=h.componentDidUpdate&&h.__h.push(function(){h.componentDidUpdate(y,_,k);});}if(h.context=x,h.props=g,h.__v=u,h.__P=n,C=l$1.__r,$=0,"prototype"in T&&T.prototype.render){for(h.state=h.__s,h.__d=!1,C&&C(u),a=h.render(h.props,h.state,h.context),H=0;H<h._sb.length;H++)h.__h.push(h._sb[H]);h._sb=[];}else do{h.__d=!1,C&&C(u),a=h.render(h.props,h.state,h.context),h.state=h.__s;}while(h.__d&&++$<25);h.state=h.__s,null!=h.getChildContext&&(t=s(s({},t),h.getChildContext())),v||null==h.getSnapshotBeforeUpdate||(k=h.getSnapshotBeforeUpdate(y,_)),I=null!=a&&a.type===p&&null==a.key?a.props.children:a,w$2(n,Array.isArray(I)?I:[I],u,i,t,o,r,f,e,c),h.base=u.__e,u.__h=null,h.__h.length&&f.push(h),b&&(h.__E=h.__=null),h.__e=!1;}else null==r&&u.__v===i.__v?(u.__k=i.__k,u.__e=i.__e):u.__e=L$1(i.__e,u,i,t,o,r,f,c);(a=l$1.diffed)&&a(u);}catch(n){u.__v=null,(c||null!=r)&&(u.__e=e,u.__h=!!c,r[r.indexOf(e)]=null),l$1.__e(n,u,i);}}function z$1(n,u){l$1.__c&&l$1.__c(u,n),n.some(function(u){try{n=u.__h,u.__h=[],n.some(function(n){n.call(u);});}catch(n){l$1.__e(n,u.__v);}});}function L$1(l,u,i,t,o,r,e,c){var s,h,v,y=i.props,p=u.props,d=u.type,k=0;if("svg"===d&&(o=!0),null!=r)for(;k<r.length;k++)if((s=r[k])&&"setAttribute"in s==!!d&&(d?s.localName===d:3===s.nodeType)){l=s,r[k]=null;break}if(null==l){if(null===d)return document.createTextNode(p);l=o?document.createElementNS("http://www.w3.org/2000/svg",d):document.createElement(d,p.is&&p),r=null,c=!1;}if(null===d)y===p||c&&l.data===p||(l.data=p);else {if(r=r&&n.call(l.childNodes),h=(y=i.props||f$1).dangerouslySetInnerHTML,v=p.dangerouslySetInnerHTML,!c){if(null!=r)for(y={},k=0;k<l.attributes.length;k++)y[l.attributes[k].name]=l.attributes[k].value;(v||h)&&(v&&(h&&v.__html==h.__html||v.__html===l.innerHTML)||(l.innerHTML=v&&v.__html||""));}if(C$1(l,p,y,o,c),v)u.__k=[];else if(k=u.props.children,w$2(l,Array.isArray(k)?k:[k],u,i,t,o&&"foreignObject"!==d,r,e,r?r[0]:i.__k&&_(i,0),c),null!=r)for(k=r.length;k--;)null!=r[k]&&a$1(r[k]);c||("value"in p&&void 0!==(k=p.value)&&(k!==l.value||"progress"===d&&!k||"option"===d&&k!==y.value)&&H$1(l,"value",k,y.value,!1),"checked"in p&&void 0!==(k=p.checked)&&k!==l.checked&&H$1(l,"checked",k,y.checked,!1));}return l}function M(n,u,i){try{"function"==typeof n?n(u):n.current=u;}catch(n){l$1.__e(n,i);}}function N(n,u,i){var t,o;if(l$1.unmount&&l$1.unmount(n),(t=n.ref)&&(t.current&&t.current!==n.__e||M(t,null,u)),null!=(t=n.__c)){if(t.componentWillUnmount)try{t.componentWillUnmount();}catch(n){l$1.__e(n,u);}t.base=t.__P=null,n.__c=void 0;}if(t=n.__k)for(o=0;o<t.length;o++)t[o]&&N(t[o],u,i||"function"!=typeof n.type);i||null==n.__e||a$1(n.__e),n.__=n.__e=n.__d=void 0;}function O(n,l,u){return this.constructor(n,u)}function P$1(u,i,t){var o,r,e;l$1.__&&l$1.__(u,i),r=(o="function"==typeof t)?null:t&&t.__k||i.__k,e=[],j$2(i,u=(!o&&t||i).__k=h(p,null,[u]),r||f$1,f$1,void 0!==i.ownerSVGElement,!o&&t?[t]:r?null:i.firstChild?n.call(i.childNodes):null,e,!o&&t?t:r?r.__e:i.firstChild,o),z$1(e,u);}function B$1(n,l){var u={__c:l="__cC"+r$1++,__:n,Consumer:function(n,l){return n.children(l)},Provider:function(n){var u,i;return this.getChildContext||(u=[],(i={})[l]=this,this.getChildContext=function(){return i},this.shouldComponentUpdate=function(n){this.props.value!==n.value&&u.some(b$1);},this.sub=function(n){u.push(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){u.splice(u.indexOf(n),1),l&&l.call(n);};}),n.children}};return u.Provider.__=u.Consumer.contextType=u}n=e$1.slice,l$1={__e:function(n,l,u,i){for(var t,o,r;l=l.__;)if((t=l.__c)&&!t.__)try{if((o=t.constructor)&&null!=o.getDerivedStateFromError&&(t.setState(o.getDerivedStateFromError(n)),r=t.__d),null!=t.componentDidCatch&&(t.componentDidCatch(n,i||{}),r=t.__d),r)return t.__E=t}catch(l){n=l;}throw n}},u$1=0,i$1=function(n){return null!=n&&void 0===n.constructor},d.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=s({},this.state),"function"==typeof n&&(n=n(s({},u),this.props)),n&&s(u,n),null!=n&&this.__v&&(l&&this._sb.push(l),b$1(this));},d.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),b$1(this));},d.prototype.render=p,t=[],g$2.__r=0,r$1=0;
+
+ 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;}
+
+ function g(n,t){for(var e in t)n[e]=t[e];return n}function C(n,t){for(var e in n)if("__source"!==e&&!(e in t))return !0;for(var r in t)if("__source"!==r&&n[r]!==t[r])return !0;return !1}function w(n){this.props=n;}(w.prototype=new d).isPureReactComponent=!0,w.prototype.shouldComponentUpdate=function(n,t){return C(this.props,n)||C(this.state,t)};var x=l$1.__b;l$1.__b=function(n){n.type&&n.type.__f&&n.ref&&(n.props.ref=n.ref,n.ref=null),x&&x(n);};var T=l$1.__e;l$1.__e=function(n,t,e,r){if(n.then)for(var u,o=t;o=o.__;)if((u=o.__c)&&u.__c)return null==t.__e&&(t.__e=e.__e,t.__k=e.__k),u.__c(n,t);T(n,t,e,r);};var I=l$1.unmount;function L(n,t,e){return n&&(n.__c&&n.__c.__H&&(n.__c.__H.__.forEach(function(n){"function"==typeof n.__c&&n.__c();}),n.__c.__H=null),null!=(n=g({},n)).__c&&(n.__c.__P===e&&(n.__c.__P=t),n.__c=null),n.__k=n.__k&&n.__k.map(function(n){return L(n,t,e)})),n}function U(n,t,e){return n&&(n.__v=null,n.__k=n.__k&&n.__k.map(function(n){return U(n,t,e)}),n.__c&&n.__c.__P===t&&(n.__e&&e.insertBefore(n.__e,n.__d),n.__c.__e=!0,n.__c.__P=e)),n}function D(){this.__u=0,this.t=null,this.__b=null;}function F(n){var t=n.__.__c;return t&&t.__a&&t.__a(n)}function V(){this.u=null,this.o=null;}l$1.unmount=function(n){var t=n.__c;t&&t.__R&&t.__R(),t&&!0===n.__h&&(n.type=null),I&&I(n);},(D.prototype=new d).__c=function(n,t){var e=t.__c,r=this;null==r.t&&(r.t=[]),r.t.push(e);var u=F(r.__v),o=!1,i=function(){o||(o=!0,e.__R=null,u?u(l):l());};e.__R=i;var l=function(){if(!--r.__u){if(r.state.__a){var n=r.state.__a;r.__v.__k[0]=U(n,n.__c.__P,n.__c.__O);}var t;for(r.setState({__a:r.__b=null});t=r.t.pop();)t.forceUpdate();}},c=!0===t.__h;r.__u++||c||r.setState({__a:r.__b=r.__v.__k[0]}),n.then(i,i);},D.prototype.componentWillUnmount=function(){this.t=[];},D.prototype.render=function(n,e){if(this.__b){if(this.__v.__k){var r=document.createElement("div"),o=this.__v.__k[0].__c;this.__v.__k[0]=L(this.__b,r,o.__O=o.__P);}this.__b=null;}var i=e.__a&&h(p,null,n.fallback);return i&&(i.__h=null),[h(p,null,e.__a?null:n.children),i]};var W=function(n,t,e){if(++e[1]===e[0]&&n.o.delete(t),n.props.revealOrder&&("t"!==n.props.revealOrder[0]||!n.o.size))for(e=n.u;e;){for(;e.length>3;)e.pop()();if(e[1]<e[0])break;n.u=e=e[2];}};function P(n){return this.getChildContext=function(){return n.context},n.children}function $(n){var e=this,r=n.i;e.componentWillUnmount=function(){P$1(null,e.l),e.l=null,e.i=null;},e.i&&e.i!==r&&e.componentWillUnmount(),n.__v?(e.l||(e.i=r,e.l={nodeType:1,parentNode:r,childNodes:[],appendChild:function(n){this.childNodes.push(n),e.i.appendChild(n);},insertBefore:function(n,t){this.childNodes.push(n),e.i.appendChild(n);},removeChild:function(n){this.childNodes.splice(this.childNodes.indexOf(n)>>>1,1),e.i.removeChild(n);}}),P$1(h(P,{context:e.context},n.__v),e.l)):e.l&&e.componentWillUnmount();}function j(n,e){var r=h($,{__v:n,i:e});return r.containerInfo=e,r}(V.prototype=new d).__a=function(n){var t=this,e=F(t.__v),r=t.o.get(n);return r[0]++,function(u){var o=function(){t.props.revealOrder?(r.push(u),W(t,n,r)):u();};e?e(o):o();}},V.prototype.render=function(n){this.u=null,this.o=new Map;var t=x$1(n.children);n.revealOrder&&"b"===n.revealOrder[0]&&t.reverse();for(var e=t.length;e--;)this.o.set(t[e],this.u=[1,0,this.u]);return n.children},V.prototype.componentDidUpdate=V.prototype.componentDidMount=function(){var n=this;this.o.forEach(function(t,e){W(n,e,t);});};var z="undefined"!=typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103,B=/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|image|letter|lighting|marker(?!H|W|U)|overline|paint|pointer|shape|stop|strikethrough|stroke|text(?!L)|transform|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,H="undefined"!=typeof document,Z=function(n){return ("undefined"!=typeof Symbol&&"symbol"==typeof Symbol()?/fil|che|rad/i:/fil|che|ra/i).test(n)};d.prototype.isReactComponent={},["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach(function(t){Object.defineProperty(d.prototype,t,{configurable:!0,get:function(){return this["UNSAFE_"+t]},set:function(n){Object.defineProperty(this,t,{configurable:!0,writable:!0,value:n});}});});var G=l$1.event;function J(){}function K(){return this.cancelBubble}function Q(){return this.defaultPrevented}l$1.event=function(n){return G&&(n=G(n)),n.persist=J,n.isPropagationStopped=K,n.isDefaultPrevented=Q,n.nativeEvent=n};var nn={configurable:!0,get:function(){return this.class}},tn=l$1.vnode;l$1.vnode=function(n){var t=n.type,e=n.props,u=e;if("string"==typeof t){var o=-1===t.indexOf("-");for(var i in u={},e){var l=e[i];H&&"children"===i&&"noscript"===t||"value"===i&&"defaultValue"in e&&null==l||("defaultValue"===i&&"value"in e&&null==e.value?i="value":"download"===i&&!0===l?l="":/ondoubleclick/i.test(i)?i="ondblclick":/^onchange(textarea|input)/i.test(i+t)&&!Z(e.type)?i="oninput":/^onfocus$/i.test(i)?i="onfocusin":/^onblur$/i.test(i)?i="onfocusout":/^on(Ani|Tra|Tou|BeforeInp|Compo)/.test(i)?i=i.toLowerCase():o&&B.test(i)?i=i.replace(/[A-Z0-9]/g,"-$&").toLowerCase():null===l&&(l=void 0),/^oninput$/i.test(i)&&(i=i.toLowerCase(),u[i]&&(i="oninputCapture")),u[i]=l);}"select"==t&&u.multiple&&Array.isArray(u.value)&&(u.value=x$1(e.children).forEach(function(n){n.props.selected=-1!=u.value.indexOf(n.props.value);})),"select"==t&&null!=u.defaultValue&&(u.value=x$1(e.children).forEach(function(n){n.props.selected=u.multiple?-1!=u.defaultValue.indexOf(n.props.value):u.defaultValue==n.props.value;})),n.props=u,e.class!=e.className&&(nn.enumerable="className"in e,null!=e.className&&(u.class=e.className),Object.defineProperty(u,"className",nn));}n.$$typeof=z,tn&&tn(n);};var en=l$1.__r;l$1.__r=function(n){en&&en(n),n.__c;};
+
+ function removeElement(el) {
+ if (el.parentNode) {
+ el.parentNode.removeChild(el);
+ }
+ }
+ // Querying
+ // ----------------------------------------------------------------------------------------------------------------
+ function elementClosest(el, selector) {
+ if (el.closest) {
+ return el.closest(selector);
+ // really bad fallback for IE
+ // from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
+ }
+ if (!document.documentElement.contains(el)) {
+ return null;
+ }
+ do {
+ if (elementMatches(el, selector)) {
+ return el;
+ }
+ el = (el.parentElement || el.parentNode);
+ } while (el !== null && el.nodeType === 1);
+ return null;
+ }
+ function elementMatches(el, selector) {
+ let method = el.matches || el.matchesSelector || el.msMatchesSelector;
+ return method.call(el, selector);
+ }
+ // accepts multiple subject els
+ // returns a real array. good for methods like forEach
+ // TODO: accept the document
+ function findElements(container, selector) {
+ let containers = container instanceof HTMLElement ? [container] : container;
+ let allMatches = [];
+ for (let i = 0; i < containers.length; i += 1) {
+ let matches = containers[i].querySelectorAll(selector);
+ for (let j = 0; j < matches.length; j += 1) {
+ allMatches.push(matches[j]);
+ }
+ }
+ return allMatches;
+ }
+ // accepts multiple subject els
+ // only queries direct child elements // TODO: rename to findDirectChildren!
+ function findDirectChildren(parent, selector) {
+ let parents = parent instanceof HTMLElement ? [parent] : parent;
+ let allMatches = [];
+ for (let i = 0; i < parents.length; i += 1) {
+ let childNodes = parents[i].children; // only ever elements
+ for (let j = 0; j < childNodes.length; j += 1) {
+ let childNode = childNodes[j];
+ if (!selector || elementMatches(childNode, selector)) {
+ allMatches.push(childNode);
+ }
+ }
+ }
+ return allMatches;
+ }
+ // Style
+ // ----------------------------------------------------------------------------------------------------------------
+ const PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i;
+ function applyStyle(el, props) {
+ for (let propName in props) {
+ applyStyleProp(el, propName, props[propName]);
+ }
+ }
+ function applyStyleProp(el, name, val) {
+ if (val == null) {
+ el.style[name] = '';
+ }
+ else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) {
+ el.style[name] = `${val}px`;
+ }
+ else {
+ el.style[name] = val;
+ }
+ }
+ // Event Handling
+ // ----------------------------------------------------------------------------------------------------------------
+ // if intercepting bubbled events at the document/window/body level,
+ // and want to see originating element (the 'target'), use this util instead
+ // of `ev.target` because it goes within web-component boundaries.
+ function getEventTargetViaRoot(ev) {
+ var _a, _b;
+ return (_b = (_a = ev.composedPath) === null || _a === void 0 ? void 0 : _a.call(ev)[0]) !== null && _b !== void 0 ? _b : ev.target;
+ }
+ // Shadow DOM consuderations
+ // ----------------------------------------------------------------------------------------------------------------
+ function getElRoot(el) {
+ return el.getRootNode ? el.getRootNode() : document;
+ }
+ // Unique ID for DOM attribute
+ let guid$1 = 0;
+ function getUniqueDomId() {
+ guid$1 += 1;
+ return 'fc-dom-' + guid$1;
+ }
+
+ // Stops a mouse/touch event from doing it's native browser action
+ function preventDefault(ev) {
+ ev.preventDefault();
+ }
+ // Event Delegation
+ // ----------------------------------------------------------------------------------------------------------------
+ function buildDelegationHandler(selector, handler) {
+ return (ev) => {
+ let matchedChild = elementClosest(ev.target, selector);
+ if (matchedChild) {
+ handler.call(matchedChild, ev, matchedChild);
+ }
+ };
+ }
+ function listenBySelector(container, eventType, selector, handler) {
+ let attachedHandler = buildDelegationHandler(selector, handler);
+ container.addEventListener(eventType, attachedHandler);
+ return () => {
+ container.removeEventListener(eventType, attachedHandler);
+ };
+ }
+ function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) {
+ let currentMatchedChild;
+ return listenBySelector(container, 'mouseover', selector, (mouseOverEv, matchedChild) => {
+ if (matchedChild !== currentMatchedChild) {
+ currentMatchedChild = matchedChild;
+ onMouseEnter(mouseOverEv, matchedChild);
+ let realOnMouseLeave = (mouseLeaveEv) => {
+ currentMatchedChild = null;
+ onMouseLeave(mouseLeaveEv, matchedChild);
+ matchedChild.removeEventListener('mouseleave', realOnMouseLeave);
+ };
+ // listen to the next mouseleave, and then unattach
+ matchedChild.addEventListener('mouseleave', realOnMouseLeave);
+ }
+ });
+ }
+ // Animation
+ // ----------------------------------------------------------------------------------------------------------------
+ const transitionEventNames = [
+ 'webkitTransitionEnd',
+ 'otransitionend',
+ 'oTransitionEnd',
+ 'msTransitionEnd',
+ 'transitionend',
+ ];
+ // triggered only when the next single subsequent transition finishes
+ function whenTransitionDone(el, callback) {
+ let realCallback = (ev) => {
+ callback(ev);
+ transitionEventNames.forEach((eventName) => {
+ el.removeEventListener(eventName, realCallback);
+ });
+ };
+ transitionEventNames.forEach((eventName) => {
+ el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes
+ });
+ }
+ // ARIA workarounds
+ // ----------------------------------------------------------------------------------------------------------------
+ function createAriaClickAttrs(handler) {
+ return Object.assign({ onClick: handler }, createAriaKeyboardAttrs(handler));
+ }
+ function createAriaKeyboardAttrs(handler) {
+ return {
+ tabIndex: 0,
+ onKeyDown(ev) {
+ if (ev.key === 'Enter' || ev.key === ' ') {
+ handler(ev);
+ ev.preventDefault(); // if space, don't scroll down page
+ }
+ },
+ };
+ }
+
+ let guidNumber = 0;
+ function guid() {
+ guidNumber += 1;
+ return String(guidNumber);
+ }
+ /* FullCalendar-specific DOM Utilities
+ ----------------------------------------------------------------------------------------------------------------------*/
+ // Make the mouse cursor express that an event is not allowed in the current area
+ function disableCursor() {
+ document.body.classList.add('fc-not-allowed');
+ }
+ // Returns the mouse cursor to its original look
+ function enableCursor() {
+ document.body.classList.remove('fc-not-allowed');
+ }
+ /* Selection
+ ----------------------------------------------------------------------------------------------------------------------*/
+ function preventSelection(el) {
+ el.classList.add('fc-unselectable');
+ el.addEventListener('selectstart', preventDefault);
+ }
+ function allowSelection(el) {
+ el.classList.remove('fc-unselectable');
+ el.removeEventListener('selectstart', preventDefault);
+ }
+ /* Context Menu
+ ----------------------------------------------------------------------------------------------------------------------*/
+ function preventContextMenu(el) {
+ el.addEventListener('contextmenu', preventDefault);
+ }
+ function allowContextMenu(el) {
+ el.removeEventListener('contextmenu', preventDefault);
+ }
+ function parseFieldSpecs(input) {
+ let specs = [];
+ let tokens = [];
+ let i;
+ let token;
+ if (typeof input === 'string') {
+ tokens = input.split(/\s*,\s*/);
+ }
+ else if (typeof input === 'function') {
+ tokens = [input];
+ }
+ else if (Array.isArray(input)) {
+ tokens = input;
+ }
+ for (i = 0; i < tokens.length; i += 1) {
+ token = tokens[i];
+ if (typeof token === 'string') {
+ specs.push(token.charAt(0) === '-' ?
+ { field: token.substring(1), order: -1 } :
+ { field: token, order: 1 });
+ }
+ else if (typeof token === 'function') {
+ specs.push({ func: token });
+ }
+ }
+ return specs;
+ }
+ function compareByFieldSpecs(obj0, obj1, fieldSpecs) {
+ let i;
+ let cmp;
+ for (i = 0; i < fieldSpecs.length; i += 1) {
+ cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]);
+ if (cmp) {
+ return cmp;
+ }
+ }
+ return 0;
+ }
+ function compareByFieldSpec(obj0, obj1, fieldSpec) {
+ if (fieldSpec.func) {
+ return fieldSpec.func(obj0, obj1);
+ }
+ return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field])
+ * (fieldSpec.order || 1);
+ }
+ function flexibleCompare(a, b) {
+ if (!a && !b) {
+ return 0;
+ }
+ if (b == null) {
+ return -1;
+ }
+ if (a == null) {
+ return 1;
+ }
+ if (typeof a === 'string' || typeof b === 'string') {
+ return String(a).localeCompare(String(b));
+ }
+ return a - b;
+ }
+ /* String Utilities
+ ----------------------------------------------------------------------------------------------------------------------*/
+ function padStart(val, len) {
+ let s = String(val);
+ return '000'.substr(0, len - s.length) + s;
+ }
+ function formatWithOrdinals(formatter, args, fallbackText) {
+ if (typeof formatter === 'function') {
+ return formatter(...args);
+ }
+ if (typeof formatter === 'string') { // non-blank string
+ return args.reduce((str, arg, index) => (str.replace('$' + index, arg || '')), formatter);
+ }
+ return fallbackText;
+ }
+ /* Number Utilities
+ ----------------------------------------------------------------------------------------------------------------------*/
+ function compareNumbers(a, b) {
+ return a - b;
+ }
+ function isInt(n) {
+ return n % 1 === 0;
+ }
+ /* FC-specific DOM dimension stuff
+ ----------------------------------------------------------------------------------------------------------------------*/
+ function computeSmallestCellWidth(cellEl) {
+ let allWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-frame');
+ let contentWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-cushion');
+ if (!allWidthEl) {
+ throw new Error('needs fc-scrollgrid-shrink-frame className'); // TODO: use const
+ }
+ if (!contentWidthEl) {
+ throw new Error('needs fc-scrollgrid-shrink-cushion className');
+ }
+ return cellEl.getBoundingClientRect().width - allWidthEl.getBoundingClientRect().width + // the cell padding+border
+ contentWidthEl.getBoundingClientRect().width;
+ }
+
+ const INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];
+ const PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/;
+ // Parsing and Creation
+ function createDuration(input, unit) {
+ if (typeof input === 'string') {
+ return parseString(input);
+ }
+ if (typeof input === 'object' && input) { // non-null object
+ return parseObject(input);
+ }
+ if (typeof input === 'number') {
+ return parseObject({ [unit || 'milliseconds']: input });
+ }
+ return null;
+ }
+ function parseString(s) {
+ let m = PARSE_RE.exec(s);
+ if (m) {
+ let sign = m[1] ? -1 : 1;
+ return {
+ years: 0,
+ months: 0,
+ days: sign * (m[2] ? parseInt(m[2], 10) : 0),
+ milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours
+ (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes
+ (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds
+ (m[6] ? parseInt(m[6], 10) : 0) // ms
+ ),
+ };
+ }
+ return null;
+ }
+ function parseObject(obj) {
+ let duration = {
+ years: obj.years || obj.year || 0,
+ months: obj.months || obj.month || 0,
+ days: obj.days || obj.day || 0,
+ milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours
+ (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes
+ (obj.seconds || obj.second || 0) * 1000 + // seconds
+ (obj.milliseconds || obj.millisecond || obj.ms || 0), // ms
+ };
+ let weeks = obj.weeks || obj.week;
+ if (weeks) {
+ duration.days += weeks * 7;
+ duration.specifiedWeeks = true;
+ }
+ return duration;
+ }
+ // Equality
+ function durationsEqual(d0, d1) {
+ return d0.years === d1.years &&
+ d0.months === d1.months &&
+ d0.days === d1.days &&
+ d0.milliseconds === d1.milliseconds;
+ }
+ function asCleanDays(dur) {
+ if (!dur.years && !dur.months && !dur.milliseconds) {
+ return dur.days;
+ }
+ return 0;
+ }
+ // Simple Math
+ function addDurations(d0, d1) {
+ return {
+ years: d0.years + d1.years,
+ months: d0.months + d1.months,
+ days: d0.days + d1.days,
+ milliseconds: d0.milliseconds + d1.milliseconds,
+ };
+ }
+ function subtractDurations(d1, d0) {
+ return {
+ years: d1.years - d0.years,
+ months: d1.months - d0.months,
+ days: d1.days - d0.days,
+ milliseconds: d1.milliseconds - d0.milliseconds,
+ };
+ }
+ function multiplyDuration(d, n) {
+ return {
+ years: d.years * n,
+ months: d.months * n,
+ days: d.days * n,
+ milliseconds: d.milliseconds * n,
+ };
+ }
+ // Conversions
+ // "Rough" because they are based on average-case Gregorian months/years
+ function asRoughYears(dur) {
+ return asRoughDays(dur) / 365;
+ }
+ function asRoughMonths(dur) {
+ return asRoughDays(dur) / 30;
+ }
+ function asRoughDays(dur) {
+ return asRoughMs(dur) / 864e5;
+ }
+ function asRoughMinutes(dur) {
+ return asRoughMs(dur) / (1000 * 60);
+ }
+ function asRoughSeconds(dur) {
+ return asRoughMs(dur) / 1000;
+ }
+ function asRoughMs(dur) {
+ return dur.years * (365 * 864e5) +
+ dur.months * (30 * 864e5) +
+ dur.days * 864e5 +
+ dur.milliseconds;
+ }
+ // Advanced Math
+ function wholeDivideDurations(numerator, denominator) {
+ let res = null;
+ for (let i = 0; i < INTERNAL_UNITS.length; i += 1) {
+ let unit = INTERNAL_UNITS[i];
+ if (denominator[unit]) {
+ let localRes = numerator[unit] / denominator[unit];
+ if (!isInt(localRes) || (res !== null && res !== localRes)) {
+ return null;
+ }
+ res = localRes;
+ }
+ else if (numerator[unit]) {
+ // needs to divide by something but can't!
+ return null;
+ }
+ }
+ return res;
+ }
+ function greatestDurationDenominator(dur) {
+ let ms = dur.milliseconds;
+ if (ms) {
+ if (ms % 1000 !== 0) {
+ return { unit: 'millisecond', value: ms };
+ }
+ if (ms % (1000 * 60) !== 0) {
+ return { unit: 'second', value: ms / 1000 };
+ }
+ if (ms % (1000 * 60 * 60) !== 0) {
+ return { unit: 'minute', value: ms / (1000 * 60) };
+ }
+ if (ms) {
+ return { unit: 'hour', value: ms / (1000 * 60 * 60) };
+ }
+ }
+ if (dur.days) {
+ if (dur.specifiedWeeks && dur.days % 7 === 0) {
+ return { unit: 'week', value: dur.days / 7 };
+ }
+ return { unit: 'day', value: dur.days };
+ }
+ if (dur.months) {
+ return { unit: 'month', value: dur.months };
+ }
+ if (dur.years) {
+ return { unit: 'year', value: dur.years };
+ }
+ return { unit: 'millisecond', value: 0 };
+ }
+
+ const { hasOwnProperty } = Object.prototype;
+ // Merges an array of objects into a single object.
+ // The second argument allows for an array of property names who's object values will be merged together.
+ function mergeProps(propObjs, complexPropsMap) {
+ let dest = {};
+ if (complexPropsMap) {
+ for (let name in complexPropsMap) {
+ let complexObjs = [];
+ // collect the trailing object values, stopping when a non-object is discovered
+ for (let i = propObjs.length - 1; i >= 0; i -= 1) {
+ let val = propObjs[i][name];
+ if (typeof val === 'object' && val) { // non-null object
+ complexObjs.unshift(val);
+ }
+ else if (val !== undefined) {
+ dest[name] = val; // if there were no objects, this value will be used
+ break;
+ }
+ }
+ // if the trailing values were objects, use the merged value
+ if (complexObjs.length) {
+ dest[name] = mergeProps(complexObjs);
+ }
+ }
+ }
+ // copy values into the destination, going from last to first
+ for (let i = propObjs.length - 1; i >= 0; i -= 1) {
+ let props = propObjs[i];
+ for (let name in props) {
+ if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign
+ dest[name] = props[name];
+ }
+ }
+ }
+ return dest;
+ }
+ function filterHash(hash, func) {
+ let filtered = {};
+ for (let key in hash) {
+ if (func(hash[key], key)) {
+ filtered[key] = hash[key];
+ }
+ }
+ return filtered;
+ }
+ function mapHash(hash, func) {
+ let newHash = {};
+ for (let key in hash) {
+ newHash[key] = func(hash[key], key);
+ }
+ return newHash;
+ }
+ function arrayToHash(a) {
+ let hash = {};
+ for (let item of a) {
+ hash[item] = true;
+ }
+ return hash;
+ }
+ // TODO: reassess browser support
+ // https://caniuse.com/?search=object.values
+ function hashValuesToArray(obj) {
+ let a = [];
+ for (let key in obj) {
+ a.push(obj[key]);
+ }
+ return a;
+ }
+ function isPropsEqual(obj0, obj1) {
+ if (obj0 === obj1) {
+ return true;
+ }
+ for (let key in obj0) {
+ if (hasOwnProperty.call(obj0, key)) {
+ if (!(key in obj1)) {
+ return false;
+ }
+ }
+ }
+ for (let key in obj1) {
+ if (hasOwnProperty.call(obj1, key)) {
+ if (obj0[key] !== obj1[key]) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ const HANDLER_RE = /^on[A-Z]/;
+ function isNonHandlerPropsEqual(obj0, obj1) {
+ const keys = getUnequalProps(obj0, obj1);
+ for (let key of keys) {
+ if (!HANDLER_RE.test(key)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ function getUnequalProps(obj0, obj1) {
+ let keys = [];
+ for (let key in obj0) {
+ if (hasOwnProperty.call(obj0, key)) {
+ if (!(key in obj1)) {
+ keys.push(key);
+ }
+ }
+ }
+ for (let key in obj1) {
+ if (hasOwnProperty.call(obj1, key)) {
+ if (obj0[key] !== obj1[key]) {
+ keys.push(key);
+ }
+ }
+ }
+ return keys;
+ }
+ function compareObjs(oldProps, newProps, equalityFuncs = {}) {
+ if (oldProps === newProps) {
+ return true;
+ }
+ for (let key in newProps) {
+ if (key in oldProps && isObjValsEqual(oldProps[key], newProps[key], equalityFuncs[key])) ;
+ else {
+ return false;
+ }
+ }
+ // check for props that were omitted in the new
+ for (let key in oldProps) {
+ if (!(key in newProps)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ /*
+ assumed "true" equality for handler names like "onReceiveSomething"
+ */
+ function isObjValsEqual(val0, val1, comparator) {
+ if (val0 === val1 || comparator === true) {
+ return true;
+ }
+ if (comparator) {
+ return comparator(val0, val1);
+ }
+ return false;
+ }
+ function collectFromHash(hash, startIndex = 0, endIndex, step = 1) {
+ let res = [];
+ if (endIndex == null) {
+ endIndex = Object.keys(hash).length;
+ }
+ for (let i = startIndex; i < endIndex; i += step) {
+ let val = hash[i];
+ if (val !== undefined) { // will disregard undefined for sparse arrays
+ res.push(val);
+ }
+ }
+ return res;
+ }
+
+ const DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
+ // Adding
+ function addWeeks(m, n) {
+ let a = dateToUtcArray(m);
+ a[2] += n * 7;
+ return arrayToUtcDate(a);
+ }
+ function addDays(m, n) {
+ let a = dateToUtcArray(m);
+ a[2] += n;
+ return arrayToUtcDate(a);
+ }
+ function addMs(m, n) {
+ let a = dateToUtcArray(m);
+ a[6] += n;
+ return arrayToUtcDate(a);
+ }
+ // Diffing (all return floats)
+ // TODO: why not use ranges?
+ function diffWeeks(m0, m1) {
+ return diffDays(m0, m1) / 7;
+ }
+ function diffDays(m0, m1) {
+ return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24);
+ }
+ function diffHours(m0, m1) {
+ return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60);
+ }
+ function diffMinutes(m0, m1) {
+ return (m1.valueOf() - m0.valueOf()) / (1000 * 60);
+ }
+ function diffSeconds(m0, m1) {
+ return (m1.valueOf() - m0.valueOf()) / 1000;
+ }
+ function diffDayAndTime(m0, m1) {
+ let m0day = startOfDay(m0);
+ let m1day = startOfDay(m1);
+ return {
+ years: 0,
+ months: 0,
+ days: Math.round(diffDays(m0day, m1day)),
+ milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()),
+ };
+ }
+ // Diffing Whole Units
+ function diffWholeWeeks(m0, m1) {
+ let d = diffWholeDays(m0, m1);
+ if (d !== null && d % 7 === 0) {
+ return d / 7;
+ }
+ return null;
+ }
+ function diffWholeDays(m0, m1) {
+ if (timeAsMs(m0) === timeAsMs(m1)) {
+ return Math.round(diffDays(m0, m1));
+ }
+ return null;
+ }
+ // Start-Of
+ function startOfDay(m) {
+ return arrayToUtcDate([
+ m.getUTCFullYear(),
+ m.getUTCMonth(),
+ m.getUTCDate(),
+ ]);
+ }
+ function startOfHour(m) {
+ return arrayToUtcDate([
+ m.getUTCFullYear(),
+ m.getUTCMonth(),
+ m.getUTCDate(),
+ m.getUTCHours(),
+ ]);
+ }
+ function startOfMinute(m) {
+ return arrayToUtcDate([
+ m.getUTCFullYear(),
+ m.getUTCMonth(),
+ m.getUTCDate(),
+ m.getUTCHours(),
+ m.getUTCMinutes(),
+ ]);
+ }
+ function startOfSecond(m) {
+ return arrayToUtcDate([
+ m.getUTCFullYear(),
+ m.getUTCMonth(),
+ m.getUTCDate(),
+ m.getUTCHours(),
+ m.getUTCMinutes(),
+ m.getUTCSeconds(),
+ ]);
+ }
+ // Week Computation
+ function weekOfYear(marker, dow, doy) {
+ let y = marker.getUTCFullYear();
+ let w = weekOfGivenYear(marker, y, dow, doy);
+ if (w < 1) {
+ return weekOfGivenYear(marker, y - 1, dow, doy);
+ }
+ let nextW = weekOfGivenYear(marker, y + 1, dow, doy);
+ if (nextW >= 1) {
+ return Math.min(w, nextW);
+ }
+ return w;
+ }
+ function weekOfGivenYear(marker, year, dow, doy) {
+ let firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]);
+ let dayStart = startOfDay(marker);
+ let days = Math.round(diffDays(firstWeekStart, dayStart));
+ return Math.floor(days / 7) + 1; // zero-indexed
+ }
+ // start-of-first-week - start-of-year
+ function firstWeekOffset(year, dow, doy) {
+ // first-week day -- which january is always in the first week (4 for iso, 1 for other)
+ let fwd = 7 + dow - doy;
+ // first-week day local weekday -- which local weekday is fwd
+ let fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7;
+ return -fwdlw + fwd - 1;
+ }
+ // Array Conversion
+ function dateToLocalArray(date) {
+ return [
+ date.getFullYear(),
+ date.getMonth(),
+ date.getDate(),
+ date.getHours(),
+ date.getMinutes(),
+ date.getSeconds(),
+ date.getMilliseconds(),
+ ];
+ }
+ function arrayToLocalDate(a) {
+ return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month
+ a[3] || 0, a[4] || 0, a[5] || 0);
+ }
+ function dateToUtcArray(date) {
+ return [
+ date.getUTCFullYear(),
+ date.getUTCMonth(),
+ date.getUTCDate(),
+ date.getUTCHours(),
+ date.getUTCMinutes(),
+ date.getUTCSeconds(),
+ date.getUTCMilliseconds(),
+ ];
+ }
+ function arrayToUtcDate(a) {
+ // according to web standards (and Safari), a month index is required.
+ // massage if only given a year.
+ if (a.length === 1) {
+ a = a.concat([0]);
+ }
+ return new Date(Date.UTC(...a));
+ }
+ // Other Utils
+ function isValidDate(m) {
+ return !isNaN(m.valueOf());
+ }
+ function timeAsMs(m) {
+ return m.getUTCHours() * 1000 * 60 * 60 +
+ m.getUTCMinutes() * 1000 * 60 +
+ m.getUTCSeconds() * 1000 +
+ m.getUTCMilliseconds();
+ }
+
+ // timeZoneOffset is in minutes
+ function buildIsoString(marker, timeZoneOffset, stripZeroTime = false) {
+ let s = marker.toISOString();
+ s = s.replace('.000', '');
+ if (stripZeroTime) {
+ s = s.replace('T00:00:00Z', '');
+ }
+ if (s.length > 10) { // time part wasn't stripped, can add timezone info
+ if (timeZoneOffset == null) {
+ s = s.replace('Z', '');
+ }
+ else if (timeZoneOffset !== 0) {
+ s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true));
+ }
+ // otherwise, its UTC-0 and we want to keep the Z
+ }
+ return s;
+ }
+ // formats the date, but with no time part
+ // TODO: somehow merge with buildIsoString and stripZeroTime
+ // TODO: rename. omit "string"
+ function formatDayString(marker) {
+ return marker.toISOString().replace(/T.*$/, '');
+ }
+ // TODO: use Date::toISOString and use everything after the T?
+ function formatIsoTimeString(marker) {
+ return padStart(marker.getUTCHours(), 2) + ':' +
+ padStart(marker.getUTCMinutes(), 2) + ':' +
+ padStart(marker.getUTCSeconds(), 2);
+ }
+ function formatTimeZoneOffset(minutes, doIso = false) {
+ let sign = minutes < 0 ? '-' : '+';
+ let abs = Math.abs(minutes);
+ let hours = Math.floor(abs / 60);
+ let mins = Math.round(abs % 60);
+ if (doIso) {
+ return `${sign + padStart(hours, 2)}:${padStart(mins, 2)}`;
+ }
+ return `GMT${sign}${hours}${mins ? `:${padStart(mins, 2)}` : ''}`;
+ }
+
+ // TODO: new util arrayify?
+ function removeExact(array, exactVal) {
+ let removeCnt = 0;
+ let i = 0;
+ while (i < array.length) {
+ if (array[i] === exactVal) {
+ array.splice(i, 1);
+ removeCnt += 1;
+ }
+ else {
+ i += 1;
+ }
+ }
+ return removeCnt;
+ }
+ function isArraysEqual(a0, a1, equalityFunc) {
+ if (a0 === a1) {
+ return true;
+ }
+ let len = a0.length;
+ let i;
+ if (len !== a1.length) { // not array? or not same length?
+ return false;
+ }
+ for (i = 0; i < len; i += 1) {
+ if (!(equalityFunc ? equalityFunc(a0[i], a1[i]) : a0[i] === a1[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function memoize(workerFunc, resEquality, teardownFunc) {
+ let currentArgs;
+ let currentRes;
+ return function (...newArgs) {
+ if (!currentArgs) {
+ currentRes = workerFunc.apply(this, newArgs);
+ }
+ else if (!isArraysEqual(currentArgs, newArgs)) {
+ if (teardownFunc) {
+ teardownFunc(currentRes);
+ }
+ let res = workerFunc.apply(this, newArgs);
+ if (!resEquality || !resEquality(res, currentRes)) {
+ currentRes = res;
+ }
+ }
+ currentArgs = newArgs;
+ return currentRes;
+ };
+ }
+ function memoizeObjArg(workerFunc, resEquality, teardownFunc) {
+ let currentArg;
+ let currentRes;
+ return (newArg) => {
+ if (!currentArg) {
+ currentRes = workerFunc.call(this, newArg);
+ }
+ else if (!isPropsEqual(currentArg, newArg)) {
+ if (teardownFunc) {
+ teardownFunc(currentRes);
+ }
+ let res = workerFunc.call(this, newArg);
+ if (!resEquality || !resEquality(res, currentRes)) {
+ currentRes = res;
+ }
+ }
+ currentArg = newArg;
+ return currentRes;
+ };
+ }
+ function memoizeArraylike(// used at all?
+ workerFunc, resEquality, teardownFunc) {
+ let currentArgSets = [];
+ let currentResults = [];
+ return (newArgSets) => {
+ let currentLen = currentArgSets.length;
+ let newLen = newArgSets.length;
+ let i = 0;
+ for (; i < currentLen; i += 1) {
+ if (!newArgSets[i]) { // one of the old sets no longer exists
+ if (teardownFunc) {
+ teardownFunc(currentResults[i]);
+ }
+ }
+ else if (!isArraysEqual(currentArgSets[i], newArgSets[i])) {
+ if (teardownFunc) {
+ teardownFunc(currentResults[i]);
+ }
+ let res = workerFunc.apply(this, newArgSets[i]);
+ if (!resEquality || !resEquality(res, currentResults[i])) {
+ currentResults[i] = res;
+ }
+ }
+ }
+ for (; i < newLen; i += 1) {
+ currentResults[i] = workerFunc.apply(this, newArgSets[i]);
+ }
+ currentArgSets = newArgSets;
+ currentResults.splice(newLen); // remove excess
+ return currentResults;
+ };
+ }
+ function memoizeHashlike(workerFunc, resEquality, teardownFunc) {
+ let currentArgHash = {};
+ let currentResHash = {};
+ return (newArgHash) => {
+ let newResHash = {};
+ for (let key in newArgHash) {
+ if (!currentResHash[key]) {
+ newResHash[key] = workerFunc.apply(this, newArgHash[key]);
+ }
+ else if (!isArraysEqual(currentArgHash[key], newArgHash[key])) {
+ if (teardownFunc) {
+ teardownFunc(currentResHash[key]);
+ }
+ let res = workerFunc.apply(this, newArgHash[key]);
+ newResHash[key] = (resEquality && resEquality(res, currentResHash[key]))
+ ? currentResHash[key]
+ : res;
+ }
+ else {
+ newResHash[key] = currentResHash[key];
+ }
+ }
+ currentArgHash = newArgHash;
+ currentResHash = newResHash;
+ return newResHash;
+ };
+ }
+
+ const EXTENDED_SETTINGS_AND_SEVERITIES = {
+ week: 3,
+ separator: 0,
+ omitZeroMinute: 0,
+ meridiem: 0,
+ omitCommas: 0,
+ };
+ const STANDARD_DATE_PROP_SEVERITIES = {
+ timeZoneName: 7,
+ era: 6,
+ year: 5,
+ month: 4,
+ day: 2,
+ weekday: 2,
+ hour: 1,
+ minute: 1,
+ second: 1,
+ };
+ const MERIDIEM_RE = /\s*([ap])\.?m\.?/i; // eats up leading spaces too
+ const COMMA_RE = /,/g; // we need re for globalness
+ const MULTI_SPACE_RE = /\s+/g;
+ const LTR_RE = /\u200e/g; // control character
+ const UTC_RE = /UTC|GMT/;
+ class NativeFormatter {
+ constructor(formatSettings) {
+ let standardDateProps = {};
+ let extendedSettings = {};
+ let severity = 0;
+ for (let name in formatSettings) {
+ if (name in EXTENDED_SETTINGS_AND_SEVERITIES) {
+ extendedSettings[name] = formatSettings[name];
+ severity = Math.max(EXTENDED_SETTINGS_AND_SEVERITIES[name], severity);
+ }
+ else {
+ standardDateProps[name] = formatSettings[name];
+ if (name in STANDARD_DATE_PROP_SEVERITIES) { // TODO: what about hour12? no severity
+ severity = Math.max(STANDARD_DATE_PROP_SEVERITIES[name], severity);
+ }
+ }
+ }
+ this.standardDateProps = standardDateProps;
+ this.extendedSettings = extendedSettings;
+ this.severity = severity;
+ this.buildFormattingFunc = memoize(buildFormattingFunc);
+ }
+ format(date, context) {
+ return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date);
+ }
+ formatRange(start, end, context, betterDefaultSeparator) {
+ let { standardDateProps, extendedSettings } = this;
+ let diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem);
+ if (!diffSeverity) {
+ return this.format(start, context);
+ }
+ let biggestUnitForPartial = diffSeverity;
+ if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time
+ (standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') &&
+ (standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') &&
+ (standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) {
+ biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time
+ }
+ let full0 = this.format(start, context);
+ let full1 = this.format(end, context);
+ if (full0 === full1) {
+ return full0;
+ }
+ let partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForPartial);
+ let partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context);
+ let partial0 = partialFormattingFunc(start);
+ let partial1 = partialFormattingFunc(end);
+ let insertion = findCommonInsertion(full0, partial0, full1, partial1);
+ let separator = extendedSettings.separator || betterDefaultSeparator || context.defaultSeparator || '';
+ if (insertion) {
+ return insertion.before + partial0 + separator + partial1 + insertion.after;
+ }
+ return full0 + separator + full1;
+ }
+ getLargestUnit() {
+ switch (this.severity) {
+ case 7:
+ case 6:
+ case 5:
+ return 'year';
+ case 4:
+ return 'month';
+ case 3:
+ return 'week';
+ case 2:
+ return 'day';
+ default:
+ return 'time'; // really?
+ }
+ }
+ }
+ function buildFormattingFunc(standardDateProps, extendedSettings, context) {
+ let standardDatePropCnt = Object.keys(standardDateProps).length;
+ if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') {
+ return (date) => (formatTimeZoneOffset(date.timeZoneOffset));
+ }
+ if (standardDatePropCnt === 0 && extendedSettings.week) {
+ return (date) => (formatWeekNumber(context.computeWeekNumber(date.marker), context.weekText, context.weekTextLong, context.locale, extendedSettings.week));
+ }
+ return buildNativeFormattingFunc(standardDateProps, extendedSettings, context);
+ }
+ function buildNativeFormattingFunc(standardDateProps, extendedSettings, context) {
+ standardDateProps = Object.assign({}, standardDateProps); // copy
+ extendedSettings = Object.assign({}, extendedSettings); // copy
+ sanitizeSettings(standardDateProps, extendedSettings);
+ standardDateProps.timeZone = 'UTC'; // we leverage the only guaranteed timeZone for our UTC markers
+ let normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps);
+ let zeroFormat; // needed?
+ if (extendedSettings.omitZeroMinute) {
+ let zeroProps = Object.assign({}, standardDateProps);
+ delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings
+ zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps);
+ }
+ return (date) => {
+ let { marker } = date;
+ let format;
+ if (zeroFormat && !marker.getUTCMinutes()) {
+ format = zeroFormat;
+ }
+ else {
+ format = normalFormat;
+ }
+ let s = format.format(marker);
+ return postProcess(s, date, standardDateProps, extendedSettings, context);
+ };
+ }
+ function sanitizeSettings(standardDateProps, extendedSettings) {
+ // deal with a browser inconsistency where formatting the timezone
+ // requires that the hour/minute be present.
+ if (standardDateProps.timeZoneName) {
+ if (!standardDateProps.hour) {
+ standardDateProps.hour = '2-digit';
+ }
+ if (!standardDateProps.minute) {
+ standardDateProps.minute = '2-digit';
+ }
+ }
+ // only support short timezone names
+ if (standardDateProps.timeZoneName === 'long') {
+ standardDateProps.timeZoneName = 'short';
+ }
+ // if requesting to display seconds, MUST display minutes
+ if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) {
+ delete extendedSettings.omitZeroMinute;
+ }
+ }
+ function postProcess(s, date, standardDateProps, extendedSettings, context) {
+ s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes
+ if (standardDateProps.timeZoneName === 'short') {
+ s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ?
+ 'UTC' : // important to normalize for IE, which does "GMT"
+ formatTimeZoneOffset(date.timeZoneOffset));
+ }
+ if (extendedSettings.omitCommas) {
+ s = s.replace(COMMA_RE, '').trim();
+ }
+ if (extendedSettings.omitZeroMinute) {
+ s = s.replace(':00', ''); // zeroFormat doesn't always achieve this
+ }
+ // ^ do anything that might create adjacent spaces before this point,
+ // because MERIDIEM_RE likes to eat up loading spaces
+ if (extendedSettings.meridiem === false) {
+ s = s.replace(MERIDIEM_RE, '').trim();
+ }
+ else if (extendedSettings.meridiem === 'narrow') { // a/p
+ s = s.replace(MERIDIEM_RE, (m0, m1) => m1.toLocaleLowerCase());
+ }
+ else if (extendedSettings.meridiem === 'short') { // am/pm
+ s = s.replace(MERIDIEM_RE, (m0, m1) => `${m1.toLocaleLowerCase()}m`);
+ }
+ else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase
+ s = s.replace(MERIDIEM_RE, (m0) => m0.toLocaleLowerCase());
+ }
+ s = s.replace(MULTI_SPACE_RE, ' ');
+ s = s.trim();
+ return s;
+ }
+ function injectTzoStr(s, tzoStr) {
+ let replaced = false;
+ s = s.replace(UTC_RE, () => {
+ replaced = true;
+ return tzoStr;
+ });
+ // IE11 doesn't include UTC/GMT in the original string, so append to end
+ if (!replaced) {
+ s += ` ${tzoStr}`;
+ }
+ return s;
+ }
+ function formatWeekNumber(num, weekText, weekTextLong, locale, display) {
+ let parts = [];
+ if (display === 'long') {
+ parts.push(weekTextLong);
+ }
+ else if (display === 'short' || display === 'narrow') {
+ parts.push(weekText);
+ }
+ if (display === 'long' || display === 'short') {
+ parts.push(' ');
+ }
+ parts.push(locale.simpleNumberFormat.format(num));
+ if (locale.options.direction === 'rtl') { // TODO: use control characters instead?
+ parts.reverse();
+ }
+ return parts.join('');
+ }
+ // Range Formatting Utils
+ // 0 = exactly the same
+ // 1 = different by time
+ // and bigger
+ function computeMarkerDiffSeverity(d0, d1, ca) {
+ if (ca.getMarkerYear(d0) !== ca.getMarkerYear(d1)) {
+ return 5;
+ }
+ if (ca.getMarkerMonth(d0) !== ca.getMarkerMonth(d1)) {
+ return 4;
+ }
+ if (ca.getMarkerDay(d0) !== ca.getMarkerDay(d1)) {
+ return 2;
+ }
+ if (timeAsMs(d0) !== timeAsMs(d1)) {
+ return 1;
+ }
+ return 0;
+ }
+ function computePartialFormattingOptions(options, biggestUnit) {
+ let partialOptions = {};
+ for (let name in options) {
+ if (!(name in STANDARD_DATE_PROP_SEVERITIES) || // not a date part prop (like timeZone)
+ STANDARD_DATE_PROP_SEVERITIES[name] <= biggestUnit) {
+ partialOptions[name] = options[name];
+ }
+ }
+ return partialOptions;
+ }
+ function findCommonInsertion(full0, partial0, full1, partial1) {
+ let i0 = 0;
+ while (i0 < full0.length) {
+ let found0 = full0.indexOf(partial0, i0);
+ if (found0 === -1) {
+ break;
+ }
+ let before0 = full0.substr(0, found0);
+ i0 = found0 + partial0.length;
+ let after0 = full0.substr(i0);
+ let i1 = 0;
+ while (i1 < full1.length) {
+ let found1 = full1.indexOf(partial1, i1);
+ if (found1 === -1) {
+ break;
+ }
+ let before1 = full1.substr(0, found1);
+ i1 = found1 + partial1.length;
+ let after1 = full1.substr(i1);
+ if (before0 === before1 && after0 === after1) {
+ return {
+ before: before0,
+ after: after0,
+ };
+ }
+ }
+ }
+ return null;
+ }
+
+ function expandZonedMarker(dateInfo, calendarSystem) {
+ let a = calendarSystem.markerToArray(dateInfo.marker);
+ return {
+ marker: dateInfo.marker,
+ timeZoneOffset: dateInfo.timeZoneOffset,
+ array: a,
+ year: a[0],
+ month: a[1],
+ day: a[2],
+ hour: a[3],
+ minute: a[4],
+ second: a[5],
+ millisecond: a[6],
+ };
+ }
+
+ function createVerboseFormattingArg(start, end, context, betterDefaultSeparator) {
+ let startInfo = expandZonedMarker(start, context.calendarSystem);
+ let endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null;
+ return {
+ date: startInfo,
+ start: startInfo,
+ end: endInfo,
+ timeZone: context.timeZone,
+ localeCodes: context.locale.codes,
+ defaultSeparator: betterDefaultSeparator || context.defaultSeparator,
+ };
+ }
+
+ /*
+ TODO: fix the terminology of "formatter" vs "formatting func"
+ */
+ /*
+ At the time of instantiation, this object does not know which cmd-formatting system it will use.
+ It receives this at the time of formatting, as a setting.
+ */
+ class CmdFormatter {
+ constructor(cmdStr) {
+ this.cmdStr = cmdStr;
+ }
+ format(date, context, betterDefaultSeparator) {
+ return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, betterDefaultSeparator));
+ }
+ formatRange(start, end, context, betterDefaultSeparator) {
+ return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, betterDefaultSeparator));
+ }
+ }
+
+ class FuncFormatter {
+ constructor(func) {
+ this.func = func;
+ }
+ format(date, context, betterDefaultSeparator) {
+ return this.func(createVerboseFormattingArg(date, null, context, betterDefaultSeparator));
+ }
+ formatRange(start, end, context, betterDefaultSeparator) {
+ return this.func(createVerboseFormattingArg(start, end, context, betterDefaultSeparator));
+ }
+ }
+
+ function createFormatter(input) {
+ if (typeof input === 'object' && input) { // non-null object
+ return new NativeFormatter(input);
+ }
+ if (typeof input === 'string') {
+ return new CmdFormatter(input);
+ }
+ if (typeof input === 'function') {
+ return new FuncFormatter(input);
+ }
+ return null;
+ }
+
+ // base options
+ // ------------
+ const BASE_OPTION_REFINERS = {
+ navLinkDayClick: identity,
+ navLinkWeekClick: identity,
+ duration: createDuration,
+ bootstrapFontAwesome: identity,
+ buttonIcons: identity,
+ customButtons: identity,
+ defaultAllDayEventDuration: createDuration,
+ defaultTimedEventDuration: createDuration,
+ nextDayThreshold: createDuration,
+ scrollTime: createDuration,
+ scrollTimeReset: Boolean,
+ slotMinTime: createDuration,
+ slotMaxTime: createDuration,
+ dayPopoverFormat: createFormatter,
+ slotDuration: createDuration,
+ snapDuration: createDuration,
+ headerToolbar: identity,
+ footerToolbar: identity,
+ defaultRangeSeparator: String,
+ titleRangeSeparator: String,
+ forceEventDuration: Boolean,
+ dayHeaders: Boolean,
+ dayHeaderFormat: createFormatter,
+ dayHeaderClassNames: identity,
+ dayHeaderContent: identity,
+ dayHeaderDidMount: identity,
+ dayHeaderWillUnmount: identity,
+ dayCellClassNames: identity,
+ dayCellContent: identity,
+ dayCellDidMount: identity,
+ dayCellWillUnmount: identity,
+ initialView: String,
+ aspectRatio: Number,
+ weekends: Boolean,
+ weekNumberCalculation: identity,
+ weekNumbers: Boolean,
+ weekNumberClassNames: identity,
+ weekNumberContent: identity,
+ weekNumberDidMount: identity,
+ weekNumberWillUnmount: identity,
+ editable: Boolean,
+ viewClassNames: identity,
+ viewDidMount: identity,
+ viewWillUnmount: identity,
+ nowIndicator: Boolean,
+ nowIndicatorClassNames: identity,
+ nowIndicatorContent: identity,
+ nowIndicatorDidMount: identity,
+ nowIndicatorWillUnmount: identity,
+ showNonCurrentDates: Boolean,
+ lazyFetching: Boolean,
+ startParam: String,
+ endParam: String,
+ timeZoneParam: String,
+ timeZone: String,
+ locales: identity,
+ locale: identity,
+ themeSystem: String,
+ dragRevertDuration: Number,
+ dragScroll: Boolean,
+ allDayMaintainDuration: Boolean,
+ unselectAuto: Boolean,
+ dropAccept: identity,
+ eventOrder: parseFieldSpecs,
+ eventOrderStrict: Boolean,
+ handleWindowResize: Boolean,
+ windowResizeDelay: Number,
+ longPressDelay: Number,
+ eventDragMinDistance: Number,
+ expandRows: Boolean,
+ height: identity,
+ contentHeight: identity,
+ direction: String,
+ weekNumberFormat: createFormatter,
+ eventResizableFromStart: Boolean,
+ displayEventTime: Boolean,
+ displayEventEnd: Boolean,
+ weekText: String,
+ weekTextLong: String,
+ progressiveEventRendering: Boolean,
+ businessHours: identity,
+ initialDate: identity,
+ now: identity,
+ eventDataTransform: identity,
+ stickyHeaderDates: identity,
+ stickyFooterScrollbar: identity,
+ viewHeight: identity,
+ defaultAllDay: Boolean,
+ eventSourceFailure: identity,
+ eventSourceSuccess: identity,
+ eventDisplay: String,
+ eventStartEditable: Boolean,
+ eventDurationEditable: Boolean,
+ eventOverlap: identity,
+ eventConstraint: identity,
+ eventAllow: identity,
+ eventBackgroundColor: String,
+ eventBorderColor: String,
+ eventTextColor: String,
+ eventColor: String,
+ eventClassNames: identity,
+ eventContent: identity,
+ eventDidMount: identity,
+ eventWillUnmount: identity,
+ selectConstraint: identity,
+ selectOverlap: identity,
+ selectAllow: identity,
+ droppable: Boolean,
+ unselectCancel: String,
+ slotLabelFormat: identity,
+ slotLaneClassNames: identity,
+ slotLaneContent: identity,
+ slotLaneDidMount: identity,
+ slotLaneWillUnmount: identity,
+ slotLabelClassNames: identity,
+ slotLabelContent: identity,
+ slotLabelDidMount: identity,
+ slotLabelWillUnmount: identity,
+ dayMaxEvents: identity,
+ dayMaxEventRows: identity,
+ dayMinWidth: Number,
+ slotLabelInterval: createDuration,
+ allDayText: String,
+ allDayClassNames: identity,
+ allDayContent: identity,
+ allDayDidMount: identity,
+ allDayWillUnmount: identity,
+ slotMinWidth: Number,
+ navLinks: Boolean,
+ eventTimeFormat: createFormatter,
+ rerenderDelay: Number,
+ moreLinkText: identity,
+ moreLinkHint: identity,
+ selectMinDistance: Number,
+ selectable: Boolean,
+ selectLongPressDelay: Number,
+ eventLongPressDelay: Number,
+ selectMirror: Boolean,
+ eventMaxStack: Number,
+ eventMinHeight: Number,
+ eventMinWidth: Number,
+ eventShortHeight: Number,
+ slotEventOverlap: Boolean,
+ plugins: identity,
+ firstDay: Number,
+ dayCount: Number,
+ dateAlignment: String,
+ dateIncrement: createDuration,
+ hiddenDays: identity,
+ monthMode: Boolean,
+ fixedWeekCount: Boolean,
+ validRange: identity,
+ visibleRange: identity,
+ titleFormat: identity,
+ eventInteractive: Boolean,
+ // only used by list-view, but languages define the value, so we need it in base options
+ noEventsText: String,
+ viewHint: identity,
+ navLinkHint: identity,
+ closeHint: String,
+ timeHint: String,
+ eventHint: String,
+ moreLinkClick: identity,
+ moreLinkClassNames: identity,
+ moreLinkContent: identity,
+ moreLinkDidMount: identity,
+ moreLinkWillUnmount: identity,
+ // for connectors
+ // (can't be part of plugin system b/c must be provided at runtime)
+ handleCustomRendering: identity,
+ customRenderingMetaMap: identity,
+ customRenderingReplacesEl: Boolean,
+ };
+ // do NOT give a type here. need `typeof BASE_OPTION_DEFAULTS` to give real results.
+ // raw values.
+ const BASE_OPTION_DEFAULTS = {
+ eventDisplay: 'auto',
+ defaultRangeSeparator: ' - ',
+ titleRangeSeparator: ' \u2013 ',
+ defaultTimedEventDuration: '01:00:00',
+ defaultAllDayEventDuration: { day: 1 },
+ forceEventDuration: false,
+ nextDayThreshold: '00:00:00',
+ dayHeaders: true,
+ initialView: '',
+ aspectRatio: 1.35,
+ headerToolbar: {
+ start: 'title',
+ center: '',
+ end: 'today prev,next',
+ },
+ weekends: true,
+ weekNumbers: false,
+ weekNumberCalculation: 'local',
+ editable: false,
+ nowIndicator: false,
+ scrollTime: '06:00:00',
+ scrollTimeReset: true,
+ slotMinTime: '00:00:00',
+ slotMaxTime: '24:00:00',
+ showNonCurrentDates: true,
+ lazyFetching: true,
+ startParam: 'start',
+ endParam: 'end',
+ timeZoneParam: 'timeZone',
+ timeZone: 'local',
+ locales: [],
+ locale: '',
+ themeSystem: 'standard',
+ dragRevertDuration: 500,
+ dragScroll: true,
+ allDayMaintainDuration: false,
+ unselectAuto: true,
+ dropAccept: '*',
+ eventOrder: 'start,-duration,allDay,title',
+ dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' },
+ handleWindowResize: true,
+ windowResizeDelay: 100,
+ longPressDelay: 1000,
+ eventDragMinDistance: 5,
+ expandRows: false,
+ navLinks: false,
+ selectable: false,
+ eventMinHeight: 15,
+ eventMinWidth: 30,
+ eventShortHeight: 30,
+ };
+ // calendar listeners
+ // ------------------
+ const CALENDAR_LISTENER_REFINERS = {
+ datesSet: identity,
+ eventsSet: identity,
+ eventAdd: identity,
+ eventChange: identity,
+ eventRemove: identity,
+ windowResize: identity,
+ eventClick: identity,
+ eventMouseEnter: identity,
+ eventMouseLeave: identity,
+ select: identity,
+ unselect: identity,
+ loading: identity,
+ // internal
+ _unmount: identity,
+ _beforeprint: identity,
+ _afterprint: identity,
+ _noEventDrop: identity,
+ _noEventResize: identity,
+ _resize: identity,
+ _scrollRequest: identity,
+ };
+ // calendar-specific options
+ // -------------------------
+ const CALENDAR_OPTION_REFINERS = {
+ buttonText: identity,
+ buttonHints: identity,
+ views: identity,
+ plugins: identity,
+ initialEvents: identity,
+ events: identity,
+ eventSources: identity,
+ };
+ const COMPLEX_OPTION_COMPARATORS = {
+ headerToolbar: isMaybeObjectsEqual,
+ footerToolbar: isMaybeObjectsEqual,
+ buttonText: isMaybeObjectsEqual,
+ buttonHints: isMaybeObjectsEqual,
+ buttonIcons: isMaybeObjectsEqual,
+ dateIncrement: isMaybeObjectsEqual,
+ };
+ function isMaybeObjectsEqual(a, b) {
+ if (typeof a === 'object' && typeof b === 'object' && a && b) { // both non-null objects
+ return isPropsEqual(a, b);
+ }
+ return a === b;
+ }
+ // view-specific options
+ // ---------------------
+ const VIEW_OPTION_REFINERS = {
+ type: String,
+ component: identity,
+ buttonText: String,
+ buttonTextKey: String,
+ dateProfileGeneratorClass: identity,
+ usesMinMaxTime: Boolean,
+ classNames: identity,
+ content: identity,
+ didMount: identity,
+ willUnmount: identity,
+ };
+ // util funcs
+ // ----------------------------------------------------------------------------------------------------
+ function mergeRawOptions(optionSets) {
+ return mergeProps(optionSets, COMPLEX_OPTION_COMPARATORS);
+ }
+ function refineProps(input, refiners) {
+ let refined = {};
+ let extra = {};
+ for (let propName in refiners) {
+ if (propName in input) {
+ refined[propName] = refiners[propName](input[propName]);
+ }
+ }
+ for (let propName in input) {
+ if (!(propName in refiners)) {
+ extra[propName] = input[propName];
+ }
+ }
+ return { refined, extra };
+ }
+ function identity(raw) {
+ return raw;
+ }
+
+ function createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) {
+ return {
+ instanceId: guid(),
+ defId,
+ range,
+ forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo,
+ forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo,
+ };
+ }
+
+ function parseRecurring(refined, defaultAllDay, dateEnv, recurringTypes) {
+ for (let i = 0; i < recurringTypes.length; i += 1) {
+ let parsed = recurringTypes[i].parse(refined, dateEnv);
+ if (parsed) {
+ let { allDay } = refined;
+ if (allDay == null) {
+ allDay = defaultAllDay;
+ if (allDay == null) {
+ allDay = parsed.allDayGuess;
+ if (allDay == null) {
+ allDay = false;
+ }
+ }
+ }
+ return {
+ allDay,
+ duration: parsed.duration,
+ typeData: parsed.typeData,
+ typeId: i,
+ };
+ }
+ }
+ return null;
+ }
+ function expandRecurring(eventStore, framingRange, context) {
+ let { dateEnv, pluginHooks, options } = context;
+ let { defs, instances } = eventStore;
+ // remove existing recurring instances
+ // TODO: bad. always expand events as a second step
+ instances = filterHash(instances, (instance) => !defs[instance.defId].recurringDef);
+ for (let defId in defs) {
+ let def = defs[defId];
+ if (def.recurringDef) {
+ let { duration } = def.recurringDef;
+ if (!duration) {
+ duration = def.allDay ?
+ options.defaultAllDayEventDuration :
+ options.defaultTimedEventDuration;
+ }
+ let starts = expandRecurringRanges(def, duration, framingRange, dateEnv, pluginHooks.recurringTypes);
+ for (let start of starts) {
+ let instance = createEventInstance(defId, {
+ start,
+ end: dateEnv.add(start, duration),
+ });
+ instances[instance.instanceId] = instance;
+ }
+ }
+ }
+ return { defs, instances };
+ }
+ /*
+ Event MUST have a recurringDef
+ */
+ function expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) {
+ let typeDef = recurringTypes[eventDef.recurringDef.typeId];
+ let markers = typeDef.expand(eventDef.recurringDef.typeData, {
+ start: dateEnv.subtract(framingRange.start, duration),
+ end: framingRange.end,
+ }, dateEnv);
+ // the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to
+ if (eventDef.allDay) {
+ markers = markers.map(startOfDay);
+ }
+ return markers;
+ }
+
+ function parseEvents(rawEvents, eventSource, context, allowOpenRange) {
+ let eventStore = createEmptyEventStore();
+ let eventRefiners = buildEventRefiners(context);
+ for (let rawEvent of rawEvents) {
+ let tuple = parseEvent(rawEvent, eventSource, context, allowOpenRange, eventRefiners);
+ if (tuple) {
+ eventTupleToStore(tuple, eventStore);
+ }
+ }
+ return eventStore;
+ }
+ function eventTupleToStore(tuple, eventStore = createEmptyEventStore()) {
+ eventStore.defs[tuple.def.defId] = tuple.def;
+ if (tuple.instance) {
+ eventStore.instances[tuple.instance.instanceId] = tuple.instance;
+ }
+ return eventStore;
+ }
+ // retrieves events that have the same groupId as the instance specified by `instanceId`
+ // or they are the same as the instance.
+ // why might instanceId not be in the store? an event from another calendar?
+ function getRelevantEvents(eventStore, instanceId) {
+ let instance = eventStore.instances[instanceId];
+ if (instance) {
+ let def = eventStore.defs[instance.defId];
+ // get events/instances with same group
+ let newStore = filterEventStoreDefs(eventStore, (lookDef) => isEventDefsGrouped(def, lookDef));
+ // add the original
+ // TODO: wish we could use eventTupleToStore or something like it
+ newStore.defs[def.defId] = def;
+ newStore.instances[instance.instanceId] = instance;
+ return newStore;
+ }
+ return createEmptyEventStore();
+ }
+ function isEventDefsGrouped(def0, def1) {
+ return Boolean(def0.groupId && def0.groupId === def1.groupId);
+ }
+ function createEmptyEventStore() {
+ return { defs: {}, instances: {} };
+ }
+ function mergeEventStores(store0, store1) {
+ return {
+ defs: Object.assign(Object.assign({}, store0.defs), store1.defs),
+ instances: Object.assign(Object.assign({}, store0.instances), store1.instances),
+ };
+ }
+ function filterEventStoreDefs(eventStore, filterFunc) {
+ let defs = filterHash(eventStore.defs, filterFunc);
+ let instances = filterHash(eventStore.instances, (instance) => (defs[instance.defId] // still exists?
+ ));
+ return { defs, instances };
+ }
+ function excludeSubEventStore(master, sub) {
+ let { defs, instances } = master;
+ let filteredDefs = {};
+ let filteredInstances = {};
+ for (let defId in defs) {
+ if (!sub.defs[defId]) { // not explicitly excluded
+ filteredDefs[defId] = defs[defId];
+ }
+ }
+ for (let instanceId in instances) {
+ if (!sub.instances[instanceId] && // not explicitly excluded
+ filteredDefs[instances[instanceId].defId] // def wasn't filtered away
+ ) {
+ filteredInstances[instanceId] = instances[instanceId];
+ }
+ }
+ return {
+ defs: filteredDefs,
+ instances: filteredInstances,
+ };
+ }
+
+ function normalizeConstraint(input, context) {
+ if (Array.isArray(input)) {
+ return parseEvents(input, null, context, true); // allowOpenRange=true
+ }
+ if (typeof input === 'object' && input) { // non-null object
+ return parseEvents([input], null, context, true); // allowOpenRange=true
+ }
+ if (input != null) {
+ return String(input);
+ }
+ return null;
+ }
+
+ function parseClassNames(raw) {
+ if (Array.isArray(raw)) {
+ return raw;
+ }
+ if (typeof raw === 'string') {
+ return raw.split(/\s+/);
+ }
+ return [];
+ }
+
+ // TODO: better called "EventSettings" or "EventConfig"
+ // TODO: move this file into structs
+ // TODO: separate constraint/overlap/allow, because selection uses only that, not other props
+ const EVENT_UI_REFINERS = {
+ display: String,
+ editable: Boolean,
+ startEditable: Boolean,
+ durationEditable: Boolean,
+ constraint: identity,
+ overlap: identity,
+ allow: identity,
+ className: parseClassNames,
+ classNames: parseClassNames,
+ color: String,
+ backgroundColor: String,
+ borderColor: String,
+ textColor: String,
+ };
+ const EMPTY_EVENT_UI = {
+ display: null,
+ startEditable: null,
+ durationEditable: null,
+ constraints: [],
+ overlap: null,
+ allows: [],
+ backgroundColor: '',
+ borderColor: '',
+ textColor: '',
+ classNames: [],
+ };
+ function createEventUi(refined, context) {
+ let constraint = normalizeConstraint(refined.constraint, context);
+ return {
+ display: refined.display || null,
+ startEditable: refined.startEditable != null ? refined.startEditable : refined.editable,
+ durationEditable: refined.durationEditable != null ? refined.durationEditable : refined.editable,
+ constraints: constraint != null ? [constraint] : [],
+ overlap: refined.overlap != null ? refined.overlap : null,
+ allows: refined.allow != null ? [refined.allow] : [],
+ backgroundColor: refined.backgroundColor || refined.color || '',
+ borderColor: refined.borderColor || refined.color || '',
+ textColor: refined.textColor || '',
+ classNames: (refined.className || []).concat(refined.classNames || []), // join singular and plural
+ };
+ }
+ // TODO: prevent against problems with <2 args!
+ function combineEventUis(uis) {
+ return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI);
+ }
+ function combineTwoEventUis(item0, item1) {
+ return {
+ display: item1.display != null ? item1.display : item0.display,
+ startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable,
+ durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable,
+ constraints: item0.constraints.concat(item1.constraints),
+ overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap,
+ allows: item0.allows.concat(item1.allows),
+ backgroundColor: item1.backgroundColor || item0.backgroundColor,
+ borderColor: item1.borderColor || item0.borderColor,
+ textColor: item1.textColor || item0.textColor,
+ classNames: item0.classNames.concat(item1.classNames),
+ };
+ }
+
+ const EVENT_NON_DATE_REFINERS = {
+ id: String,
+ groupId: String,
+ title: String,
+ url: String,
+ interactive: Boolean,
+ };
+ const EVENT_DATE_REFINERS = {
+ start: identity,
+ end: identity,
+ date: identity,
+ allDay: Boolean,
+ };
+ const EVENT_REFINERS = Object.assign(Object.assign(Object.assign({}, EVENT_NON_DATE_REFINERS), EVENT_DATE_REFINERS), { extendedProps: identity });
+ function parseEvent(raw, eventSource, context, allowOpenRange, refiners = buildEventRefiners(context)) {
+ let { refined, extra } = refineEventDef(raw, context, refiners);
+ let defaultAllDay = computeIsDefaultAllDay(eventSource, context);
+ let recurringRes = parseRecurring(refined, defaultAllDay, context.dateEnv, context.pluginHooks.recurringTypes);
+ if (recurringRes) {
+ let def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', recurringRes.allDay, Boolean(recurringRes.duration), context);
+ def.recurringDef = {
+ typeId: recurringRes.typeId,
+ typeData: recurringRes.typeData,
+ duration: recurringRes.duration,
+ };
+ return { def, instance: null };
+ }
+ let singleRes = parseSingle(refined, defaultAllDay, context, allowOpenRange);
+ if (singleRes) {
+ let def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', singleRes.allDay, singleRes.hasEnd, context);
+ let instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo);
+ return { def, instance };
+ }
+ return null;
+ }
+ function refineEventDef(raw, context, refiners = buildEventRefiners(context)) {
+ return refineProps(raw, refiners);
+ }
+ function buildEventRefiners(context) {
+ return Object.assign(Object.assign(Object.assign({}, EVENT_UI_REFINERS), EVENT_REFINERS), context.pluginHooks.eventRefiners);
+ }
+ /*
+ Will NOT populate extendedProps with the leftover properties.
+ Will NOT populate date-related props.
+ */
+ function parseEventDef(refined, extra, sourceId, allDay, hasEnd, context) {
+ let def = {
+ title: refined.title || '',
+ groupId: refined.groupId || '',
+ publicId: refined.id || '',
+ url: refined.url || '',
+ recurringDef: null,
+ defId: guid(),
+ sourceId,
+ allDay,
+ hasEnd,
+ interactive: refined.interactive,
+ ui: createEventUi(refined, context),
+ extendedProps: Object.assign(Object.assign({}, (refined.extendedProps || {})), extra),
+ };
+ for (let memberAdder of context.pluginHooks.eventDefMemberAdders) {
+ Object.assign(def, memberAdder(refined));
+ }
+ // help out EventImpl from having user modify props
+ Object.freeze(def.ui.classNames);
+ Object.freeze(def.extendedProps);
+ return def;
+ }
+ function parseSingle(refined, defaultAllDay, context, allowOpenRange) {
+ let { allDay } = refined;
+ let startMeta;
+ let startMarker = null;
+ let hasEnd = false;
+ let endMeta;
+ let endMarker = null;
+ let startInput = refined.start != null ? refined.start : refined.date;
+ startMeta = context.dateEnv.createMarkerMeta(startInput);
+ if (startMeta) {
+ startMarker = startMeta.marker;
+ }
+ else if (!allowOpenRange) {
+ return null;
+ }
+ if (refined.end != null) {
+ endMeta = context.dateEnv.createMarkerMeta(refined.end);
+ }
+ if (allDay == null) {
+ if (defaultAllDay != null) {
+ allDay = defaultAllDay;
+ }
+ else {
+ // fall back to the date props LAST
+ allDay = (!startMeta || startMeta.isTimeUnspecified) &&
+ (!endMeta || endMeta.isTimeUnspecified);
+ }
+ }
+ if (allDay && startMarker) {
+ startMarker = startOfDay(startMarker);
+ }
+ if (endMeta) {
+ endMarker = endMeta.marker;
+ if (allDay) {
+ endMarker = startOfDay(endMarker);
+ }
+ if (startMarker && endMarker <= startMarker) {
+ endMarker = null;
+ }
+ }
+ if (endMarker) {
+ hasEnd = true;
+ }
+ else if (!allowOpenRange) {
+ hasEnd = context.options.forceEventDuration || false;
+ endMarker = context.dateEnv.add(startMarker, allDay ?
+ context.options.defaultAllDayEventDuration :
+ context.options.defaultTimedEventDuration);
+ }
+ return {
+ allDay,
+ hasEnd,
+ range: { start: startMarker, end: endMarker },
+ forcedStartTzo: startMeta ? startMeta.forcedTzo : null,
+ forcedEndTzo: endMeta ? endMeta.forcedTzo : null,
+ };
+ }
+ function computeIsDefaultAllDay(eventSource, context) {
+ let res = null;
+ if (eventSource) {
+ res = eventSource.defaultAllDay;
+ }
+ if (res == null) {
+ res = context.options.defaultAllDay;
+ }
+ return res;
+ }
+
+ const DEF_DEFAULTS = {
+ startTime: '09:00',
+ endTime: '17:00',
+ daysOfWeek: [1, 2, 3, 4, 5],
+ display: 'inverse-background',
+ classNames: 'fc-non-business',
+ groupId: '_businessHours', // so multiple defs get grouped
+ };
+ /*
+ TODO: pass around as EventDefHash!!!
+ */
+ function parseBusinessHours(input, context) {
+ return parseEvents(refineInputs(input), null, context);
+ }
+ function refineInputs(input) {
+ let rawDefs;
+ if (input === true) {
+ rawDefs = [{}]; // will get DEF_DEFAULTS verbatim
+ }
+ else if (Array.isArray(input)) {
+ // if specifying an array, every sub-definition NEEDS a day-of-week
+ rawDefs = input.filter((rawDef) => rawDef.daysOfWeek);
+ }
+ else if (typeof input === 'object' && input) { // non-null object
+ rawDefs = [input];
+ }
+ else { // is probably false
+ rawDefs = [];
+ }
+ rawDefs = rawDefs.map((rawDef) => (Object.assign(Object.assign({}, DEF_DEFAULTS), rawDef)));
+ return rawDefs;
+ }
+
+ /* Date stuff that doesn't belong in datelib core
+ ----------------------------------------------------------------------------------------------------------------------*/
+ // given a timed range, computes an all-day range that has the same exact duration,
+ // but whose start time is aligned with the start of the day.
+ function computeAlignedDayRange(timedRange) {
+ let dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1;
+ let start = startOfDay(timedRange.start);
+ let end = addDays(start, dayCnt);
+ return { start, end };
+ }
+ // given a timed range, computes an all-day range based on how for the end date bleeds into the next day
+ // TODO: give nextDayThreshold a default arg
+ function computeVisibleDayRange(timedRange, nextDayThreshold = createDuration(0)) {
+ let startDay = null;
+ let endDay = null;
+ if (timedRange.end) {
+ endDay = startOfDay(timedRange.end);
+ let endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay`
+ // If the end time is actually inclusively part of the next day and is equal to or
+ // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.
+ // Otherwise, leaving it as inclusive will cause it to exclude `endDay`.
+ if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) {
+ endDay = addDays(endDay, 1);
+ }
+ }
+ if (timedRange.start) {
+ startDay = startOfDay(timedRange.start); // the beginning of the day the range starts
+ // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day.
+ if (endDay && endDay <= startDay) {
+ endDay = addDays(startDay, 1);
+ }
+ }
+ return { start: startDay, end: endDay };
+ }
+ // spans from one day into another?
+ function isMultiDayRange(range) {
+ let visibleRange = computeVisibleDayRange(range);
+ return diffDays(visibleRange.start, visibleRange.end) > 1;
+ }
+ function diffDates(date0, date1, dateEnv, largeUnit) {
+ if (largeUnit === 'year') {
+ return createDuration(dateEnv.diffWholeYears(date0, date1), 'year');
+ }
+ if (largeUnit === 'month') {
+ return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month');
+ }
+ return diffDayAndTime(date0, date1); // returns a duration
+ }
+
+ function pointInsideRect(point, rect) {
+ return point.left >= rect.left &&
+ point.left < rect.right &&
+ point.top >= rect.top &&
+ point.top < rect.bottom;
+ }
+ // Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false
+ function intersectRects(rect1, rect2) {
+ let res = {
+ left: Math.max(rect1.left, rect2.left),
+ right: Math.min(rect1.right, rect2.right),
+ top: Math.max(rect1.top, rect2.top),
+ bottom: Math.min(rect1.bottom, rect2.bottom),
+ };
+ if (res.left < res.right && res.top < res.bottom) {
+ return res;
+ }
+ return false;
+ }
+ function translateRect(rect, deltaX, deltaY) {
+ return {
+ left: rect.left + deltaX,
+ right: rect.right + deltaX,
+ top: rect.top + deltaY,
+ bottom: rect.bottom + deltaY,
+ };
+ }
+ // Returns a new point that will have been moved to reside within the given rectangle
+ function constrainPoint(point, rect) {
+ return {
+ left: Math.min(Math.max(point.left, rect.left), rect.right),
+ top: Math.min(Math.max(point.top, rect.top), rect.bottom),
+ };
+ }
+ // Returns a point that is the center of the given rectangle
+ function getRectCenter(rect) {
+ return {
+ left: (rect.left + rect.right) / 2,
+ top: (rect.top + rect.bottom) / 2,
+ };
+ }
+ // Subtracts point2's coordinates from point1's coordinates, returning a delta
+ function diffPoints(point1, point2) {
+ return {
+ left: point1.left - point2.left,
+ top: point1.top - point2.top,
+ };
+ }
+
+ let canVGrowWithinCell;
+ function getCanVGrowWithinCell() {
+ if (canVGrowWithinCell == null) {
+ canVGrowWithinCell = computeCanVGrowWithinCell();
+ }
+ return canVGrowWithinCell;
+ }
+ function computeCanVGrowWithinCell() {
+ // for SSR, because this function is call immediately at top-level
+ // TODO: just make this logic execute top-level, immediately, instead of doing lazily
+ if (typeof document === 'undefined') {
+ return true;
+ }
+ let el = document.createElement('div');
+ el.style.position = 'absolute';
+ el.style.top = '0px';
+ el.style.left = '0px';
+ el.innerHTML = '<table><tr><td><div></div></td></tr></table>';
+ el.querySelector('table').style.height = '100px';
+ el.querySelector('div').style.height = '100%';
+ document.body.appendChild(el);
+ let div = el.querySelector('div');
+ let possible = div.offsetHeight > 0;
+ document.body.removeChild(el);
+ return possible;
+ }
+
+ const EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere
+ class Splitter {
+ constructor() {
+ this.getKeysForEventDefs = memoize(this._getKeysForEventDefs);
+ this.splitDateSelection = memoize(this._splitDateSpan);
+ this.splitEventStore = memoize(this._splitEventStore);
+ this.splitIndividualUi = memoize(this._splitIndividualUi);
+ this.splitEventDrag = memoize(this._splitInteraction);
+ this.splitEventResize = memoize(this._splitInteraction);
+ this.eventUiBuilders = {}; // TODO: typescript protection
+ }
+ splitProps(props) {
+ let keyInfos = this.getKeyInfo(props);
+ let defKeys = this.getKeysForEventDefs(props.eventStore);
+ let dateSelections = this.splitDateSelection(props.dateSelection);
+ let individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases*
+ let eventStores = this.splitEventStore(props.eventStore, defKeys);
+ let eventDrags = this.splitEventDrag(props.eventDrag);
+ let eventResizes = this.splitEventResize(props.eventResize);
+ let splitProps = {};
+ this.eventUiBuilders = mapHash(keyInfos, (info, key) => this.eventUiBuilders[key] || memoize(buildEventUiForKey));
+ for (let key in keyInfos) {
+ let keyInfo = keyInfos[key];
+ let eventStore = eventStores[key] || EMPTY_EVENT_STORE;
+ let buildEventUi = this.eventUiBuilders[key];
+ splitProps[key] = {
+ businessHours: keyInfo.businessHours || props.businessHours,
+ dateSelection: dateSelections[key] || null,
+ eventStore,
+ eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]),
+ eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '',
+ eventDrag: eventDrags[key] || null,
+ eventResize: eventResizes[key] || null,
+ };
+ }
+ return splitProps;
+ }
+ _splitDateSpan(dateSpan) {
+ let dateSpans = {};
+ if (dateSpan) {
+ let keys = this.getKeysForDateSpan(dateSpan);
+ for (let key of keys) {
+ dateSpans[key] = dateSpan;
+ }
+ }
+ return dateSpans;
+ }
+ _getKeysForEventDefs(eventStore) {
+ return mapHash(eventStore.defs, (eventDef) => this.getKeysForEventDef(eventDef));
+ }
+ _splitEventStore(eventStore, defKeys) {
+ let { defs, instances } = eventStore;
+ let splitStores = {};
+ for (let defId in defs) {
+ for (let key of defKeys[defId]) {
+ if (!splitStores[key]) {
+ splitStores[key] = createEmptyEventStore();
+ }
+ splitStores[key].defs[defId] = defs[defId];
+ }
+ }
+ for (let instanceId in instances) {
+ let instance = instances[instanceId];
+ for (let key of defKeys[instance.defId]) {
+ if (splitStores[key]) { // must have already been created
+ splitStores[key].instances[instanceId] = instance;
+ }
+ }
+ }
+ return splitStores;
+ }
+ _splitIndividualUi(eventUiBases, defKeys) {
+ let splitHashes = {};
+ for (let defId in eventUiBases) {
+ if (defId) { // not the '' key
+ for (let key of defKeys[defId]) {
+ if (!splitHashes[key]) {
+ splitHashes[key] = {};
+ }
+ splitHashes[key][defId] = eventUiBases[defId];
+ }
+ }
+ }
+ return splitHashes;
+ }
+ _splitInteraction(interaction) {
+ let splitStates = {};
+ if (interaction) {
+ let affectedStores = this._splitEventStore(interaction.affectedEvents, this._getKeysForEventDefs(interaction.affectedEvents));
+ // can't rely on defKeys because event data is mutated
+ let mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents);
+ let mutatedStores = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId);
+ let populate = (key) => {
+ if (!splitStates[key]) {
+ splitStates[key] = {
+ affectedEvents: affectedStores[key] || EMPTY_EVENT_STORE,
+ mutatedEvents: mutatedStores[key] || EMPTY_EVENT_STORE,
+ isEvent: interaction.isEvent,
+ };
+ }
+ };
+ for (let key in affectedStores) {
+ populate(key);
+ }
+ for (let key in mutatedStores) {
+ populate(key);
+ }
+ }
+ return splitStates;
+ }
+ }
+ function buildEventUiForKey(allUi, eventUiForKey, individualUi) {
+ let baseParts = [];
+ if (allUi) {
+ baseParts.push(allUi);
+ }
+ if (eventUiForKey) {
+ baseParts.push(eventUiForKey);
+ }
+ let stuff = {
+ '': combineEventUis(baseParts),
+ };
+ if (individualUi) {
+ Object.assign(stuff, individualUi);
+ }
+ return stuff;
+ }
+
+ function parseRange(input, dateEnv) {
+ let start = null;
+ let end = null;
+ if (input.start) {
+ start = dateEnv.createMarker(input.start);
+ }
+ if (input.end) {
+ end = dateEnv.createMarker(input.end);
+ }
+ if (!start && !end) {
+ return null;
+ }
+ if (start && end && end < start) {
+ return null;
+ }
+ return { start, end };
+ }
+ // SIDE-EFFECT: will mutate ranges.
+ // Will return a new array result.
+ function invertRanges(ranges, constraintRange) {
+ let invertedRanges = [];
+ let { start } = constraintRange; // the end of the previous range. the start of the new range
+ let i;
+ let dateRange;
+ // ranges need to be in order. required for our date-walking algorithm
+ ranges.sort(compareRanges);
+ for (i = 0; i < ranges.length; i += 1) {
+ dateRange = ranges[i];
+ // add the span of time before the event (if there is any)
+ if (dateRange.start > start) { // compare millisecond time (skip any ambig logic)
+ invertedRanges.push({ start, end: dateRange.start });
+ }
+ if (dateRange.end > start) {
+ start = dateRange.end;
+ }
+ }
+ // add the span of time after the last event (if there is any)
+ if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic)
+ invertedRanges.push({ start, end: constraintRange.end });
+ }
+ return invertedRanges;
+ }
+ function compareRanges(range0, range1) {
+ return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first
+ }
+ function intersectRanges(range0, range1) {
+ let { start, end } = range0;
+ let newRange = null;
+ if (range1.start !== null) {
+ if (start === null) {
+ start = range1.start;
+ }
+ else {
+ start = new Date(Math.max(start.valueOf(), range1.start.valueOf()));
+ }
+ }
+ if (range1.end != null) {
+ if (end === null) {
+ end = range1.end;
+ }
+ else {
+ end = new Date(Math.min(end.valueOf(), range1.end.valueOf()));
+ }
+ }
+ if (start === null || end === null || start < end) {
+ newRange = { start, end };
+ }
+ return newRange;
+ }
+ function rangesEqual(range0, range1) {
+ return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) &&
+ (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf());
+ }
+ function rangesIntersect(range0, range1) {
+ return (range0.end === null || range1.start === null || range0.end > range1.start) &&
+ (range0.start === null || range1.end === null || range0.start < range1.end);
+ }
+ function rangeContainsRange(outerRange, innerRange) {
+ return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) &&
+ (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end));
+ }
+ function rangeContainsMarker(range, date) {
+ return (range.start === null || date >= range.start) &&
+ (range.end === null || date < range.end);
+ }
+ // If the given date is not within the given range, move it inside.
+ // (If it's past the end, make it one millisecond before the end).
+ function constrainMarkerToRange(date, range) {
+ if (range.start != null && date < range.start) {
+ return range.start;
+ }
+ if (range.end != null && date >= range.end) {
+ return new Date(range.end.valueOf() - 1);
+ }
+ return date;
+ }
+
+ function getDateMeta(date, todayRange, nowDate, dateProfile) {
+ return {
+ dow: date.getUTCDay(),
+ isDisabled: Boolean(dateProfile && !rangeContainsMarker(dateProfile.activeRange, date)),
+ isOther: Boolean(dateProfile && !rangeContainsMarker(dateProfile.currentRange, date)),
+ isToday: Boolean(todayRange && rangeContainsMarker(todayRange, date)),
+ isPast: Boolean(nowDate ? (date < nowDate) : todayRange ? (date < todayRange.start) : false),
+ isFuture: Boolean(nowDate ? (date > nowDate) : todayRange ? (date >= todayRange.end) : false),
+ };
+ }
+ function getDayClassNames(meta, theme) {
+ let classNames = [
+ 'fc-day',
+ `fc-day-${DAY_IDS[meta.dow]}`,
+ ];
+ if (meta.isDisabled) {
+ classNames.push('fc-day-disabled');
+ }
+ else {
+ if (meta.isToday) {
+ classNames.push('fc-day-today');
+ classNames.push(theme.getClass('today'));
+ }
+ if (meta.isPast) {
+ classNames.push('fc-day-past');
+ }
+ if (meta.isFuture) {
+ classNames.push('fc-day-future');
+ }
+ if (meta.isOther) {
+ classNames.push('fc-day-other');
+ }
+ }
+ return classNames;
+ }
+ function getSlotClassNames(meta, theme) {
+ let classNames = [
+ 'fc-slot',
+ `fc-slot-${DAY_IDS[meta.dow]}`,
+ ];
+ if (meta.isDisabled) {
+ classNames.push('fc-slot-disabled');
+ }
+ else {
+ if (meta.isToday) {
+ classNames.push('fc-slot-today');
+ classNames.push(theme.getClass('today'));
+ }
+ if (meta.isPast) {
+ classNames.push('fc-slot-past');
+ }
+ if (meta.isFuture) {
+ classNames.push('fc-slot-future');
+ }
+ }
+ return classNames;
+ }
+
+ const DAY_FORMAT = createFormatter({ year: 'numeric', month: 'long', day: 'numeric' });
+ const WEEK_FORMAT = createFormatter({ week: 'long' });
+ function buildNavLinkAttrs(context, dateMarker, viewType = 'day', isTabbable = true) {
+ const { dateEnv, options, calendarApi } = context;
+ let dateStr = dateEnv.format(dateMarker, viewType === 'week' ? WEEK_FORMAT : DAY_FORMAT);
+ if (options.navLinks) {
+ let zonedDate = dateEnv.toDate(dateMarker);
+ const handleInteraction = (ev) => {
+ let customAction = viewType === 'day' ? options.navLinkDayClick :
+ viewType === 'week' ? options.navLinkWeekClick : null;
+ if (typeof customAction === 'function') {
+ customAction.call(calendarApi, dateEnv.toDate(dateMarker), ev);
+ }
+ else {
+ if (typeof customAction === 'string') {
+ viewType = customAction;
+ }
+ calendarApi.zoomTo(dateMarker, viewType);
+ }
+ };
+ return Object.assign({ title: formatWithOrdinals(options.navLinkHint, [dateStr, zonedDate], dateStr), 'data-navlink': '' }, (isTabbable
+ ? createAriaClickAttrs(handleInteraction)
+ : { onClick: handleInteraction }));
+ }
+ return { 'aria-label': dateStr };
+ }
+
+ let _isRtlScrollbarOnLeft = null;
+ function getIsRtlScrollbarOnLeft() {
+ if (_isRtlScrollbarOnLeft === null) {
+ _isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft();
+ }
+ return _isRtlScrollbarOnLeft;
+ }
+ function computeIsRtlScrollbarOnLeft() {
+ let outerEl = document.createElement('div');
+ applyStyle(outerEl, {
+ position: 'absolute',
+ top: -1000,
+ left: 0,
+ border: 0,
+ padding: 0,
+ overflow: 'scroll',
+ direction: 'rtl',
+ });
+ outerEl.innerHTML = '<div></div>';
+ document.body.appendChild(outerEl);
+ let innerEl = outerEl.firstChild;
+ let res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left;
+ removeElement(outerEl);
+ return res;
+ }
+
+ let _scrollbarWidths;
+ function getScrollbarWidths() {
+ if (!_scrollbarWidths) {
+ _scrollbarWidths = computeScrollbarWidths();
+ }
+ return _scrollbarWidths;
+ }
+ function computeScrollbarWidths() {
+ let el = document.createElement('div');
+ el.style.overflow = 'scroll';
+ el.style.position = 'absolute';
+ el.style.top = '-9999px';
+ el.style.left = '-9999px';
+ document.body.appendChild(el);
+ let res = computeScrollbarWidthsForEl(el);
+ document.body.removeChild(el);
+ return res;
+ }
+ // WARNING: will include border
+ function computeScrollbarWidthsForEl(el) {
+ return {
+ x: el.offsetHeight - el.clientHeight,
+ y: el.offsetWidth - el.clientWidth,
+ };
+ }
+
+ function computeEdges(el, getPadding = false) {
+ let computedStyle = window.getComputedStyle(el);
+ let borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0;
+ let borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0;
+ let borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0;
+ let borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
+ let badScrollbarWidths = computeScrollbarWidthsForEl(el); // includes border!
+ let scrollbarLeftRight = badScrollbarWidths.y - borderLeft - borderRight;
+ let scrollbarBottom = badScrollbarWidths.x - borderTop - borderBottom;
+ let res = {
+ borderLeft,
+ borderRight,
+ borderTop,
+ borderBottom,
+ scrollbarBottom,
+ scrollbarLeft: 0,
+ scrollbarRight: 0,
+ };
+ if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side?
+ res.scrollbarLeft = scrollbarLeftRight;
+ }
+ else {
+ res.scrollbarRight = scrollbarLeftRight;
+ }
+ if (getPadding) {
+ res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0;
+ res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0;
+ res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0;
+ res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0;
+ }
+ return res;
+ }
+ function computeInnerRect(el, goWithinPadding = false, doFromWindowViewport) {
+ let outerRect = doFromWindowViewport ? el.getBoundingClientRect() : computeRect(el);
+ let edges = computeEdges(el, goWithinPadding);
+ let res = {
+ left: outerRect.left + edges.borderLeft + edges.scrollbarLeft,
+ right: outerRect.right - edges.borderRight - edges.scrollbarRight,
+ top: outerRect.top + edges.borderTop,
+ bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom,
+ };
+ if (goWithinPadding) {
+ res.left += edges.paddingLeft;
+ res.right -= edges.paddingRight;
+ res.top += edges.paddingTop;
+ res.bottom -= edges.paddingBottom;
+ }
+ return res;
+ }
+ function computeRect(el) {
+ let rect = el.getBoundingClientRect();
+ return {
+ left: rect.left + window.pageXOffset,
+ top: rect.top + window.pageYOffset,
+ right: rect.right + window.pageXOffset,
+ bottom: rect.bottom + window.pageYOffset,
+ };
+ }
+ function computeClippedClientRect(el) {
+ let clippingParents = getClippingParents(el);
+ let rect = el.getBoundingClientRect();
+ for (let clippingParent of clippingParents) {
+ let intersection = intersectRects(rect, clippingParent.getBoundingClientRect());
+ if (intersection) {
+ rect = intersection;
+ }
+ else {
+ return null;
+ }
+ }
+ return rect;
+ }
+ // does not return window
+ function getClippingParents(el) {
+ let parents = [];
+ while (el instanceof HTMLElement) { // will stop when gets to document or null
+ let computedStyle = window.getComputedStyle(el);
+ if (computedStyle.position === 'fixed') {
+ break;
+ }
+ if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) {
+ parents.push(el);
+ }
+ el = el.parentNode;
+ }
+ return parents;
+ }
+
+ /*
+ given a function that resolves a result asynchronously.
+ the function can either call passed-in success and failure callbacks,
+ or it can return a promise.
+ if you need to pass additional params to func, bind them first.
+ */
+ function unpromisify(func, normalizedSuccessCallback, normalizedFailureCallback) {
+ // guard against success/failure callbacks being called more than once
+ // and guard against a promise AND callback being used together.
+ let isResolved = false;
+ let wrappedSuccess = function (res) {
+ if (!isResolved) {
+ isResolved = true;
+ normalizedSuccessCallback(res);
+ }
+ };
+ let wrappedFailure = function (error) {
+ if (!isResolved) {
+ isResolved = true;
+ normalizedFailureCallback(error);
+ }
+ };
+ let res = func(wrappedSuccess, wrappedFailure);
+ if (res && typeof res.then === 'function') {
+ res.then(wrappedSuccess, wrappedFailure);
+ }
+ }
+
+ class Emitter {
+ constructor() {
+ this.handlers = {};
+ this.thisContext = null;
+ }
+ setThisContext(thisContext) {
+ this.thisContext = thisContext;
+ }
+ setOptions(options) {
+ this.options = options;
+ }
+ on(type, handler) {
+ addToHash(this.handlers, type, handler);
+ }
+ off(type, handler) {
+ removeFromHash(this.handlers, type, handler);
+ }
+ trigger(type, ...args) {
+ let attachedHandlers = this.handlers[type] || [];
+ let optionHandler = this.options && this.options[type];
+ let handlers = [].concat(optionHandler || [], attachedHandlers);
+ for (let handler of handlers) {
+ handler.apply(this.thisContext, args);
+ }
+ }
+ hasHandlers(type) {
+ return Boolean((this.handlers[type] && this.handlers[type].length) ||
+ (this.options && this.options[type]));
+ }
+ }
+ function addToHash(hash, type, handler) {
+ (hash[type] || (hash[type] = []))
+ .push(handler);
+ }
+ function removeFromHash(hash, type, handler) {
+ if (handler) {
+ if (hash[type]) {
+ hash[type] = hash[type].filter((func) => func !== handler);
+ }
+ }
+ else {
+ delete hash[type]; // remove all handler funcs for this type
+ }
+ }
+
+ /*
+ Records offset information for a set of elements, relative to an origin element.
+ Can record the left/right OR the top/bottom OR both.
+ Provides methods for querying the cache by position.
+ */
+ class PositionCache {
+ constructor(originEl, els, isHorizontal, isVertical) {
+ this.els = els;
+ let originClientRect = this.originClientRect = originEl.getBoundingClientRect(); // relative to viewport top-left
+ if (isHorizontal) {
+ this.buildElHorizontals(originClientRect.left);
+ }
+ if (isVertical) {
+ this.buildElVerticals(originClientRect.top);
+ }
+ }
+ // Populates the left/right internal coordinate arrays
+ buildElHorizontals(originClientLeft) {
+ let lefts = [];
+ let rights = [];
+ for (let el of this.els) {
+ let rect = el.getBoundingClientRect();
+ lefts.push(rect.left - originClientLeft);
+ rights.push(rect.right - originClientLeft);
+ }
+ this.lefts = lefts;
+ this.rights = rights;
+ }
+ // Populates the top/bottom internal coordinate arrays
+ buildElVerticals(originClientTop) {
+ let tops = [];
+ let bottoms = [];
+ for (let el of this.els) {
+ let rect = el.getBoundingClientRect();
+ tops.push(rect.top - originClientTop);
+ bottoms.push(rect.bottom - originClientTop);
+ }
+ this.tops = tops;
+ this.bottoms = bottoms;
+ }
+ // Given a left offset (from document left), returns the index of the el that it horizontally intersects.
+ // If no intersection is made, returns undefined.
+ leftToIndex(leftPosition) {
+ let { lefts, rights } = this;
+ let len = lefts.length;
+ let i;
+ for (i = 0; i < len; i += 1) {
+ if (leftPosition >= lefts[i] && leftPosition < rights[i]) {
+ return i;
+ }
+ }
+ return undefined; // TODO: better
+ }
+ // Given a top offset (from document top), returns the index of the el that it vertically intersects.
+ // If no intersection is made, returns undefined.
+ topToIndex(topPosition) {
+ let { tops, bottoms } = this;
+ let len = tops.length;
+ let i;
+ for (i = 0; i < len; i += 1) {
+ if (topPosition >= tops[i] && topPosition < bottoms[i]) {
+ return i;
+ }
+ }
+ return undefined; // TODO: better
+ }
+ // Gets the width of the element at the given index
+ getWidth(leftIndex) {
+ return this.rights[leftIndex] - this.lefts[leftIndex];
+ }
+ // Gets the height of the element at the given index
+ getHeight(topIndex) {
+ return this.bottoms[topIndex] - this.tops[topIndex];
+ }
+ similarTo(otherCache) {
+ return similarNumArrays(this.tops || [], otherCache.tops || []) &&
+ similarNumArrays(this.bottoms || [], otherCache.bottoms || []) &&
+ similarNumArrays(this.lefts || [], otherCache.lefts || []) &&
+ similarNumArrays(this.rights || [], otherCache.rights || []);
+ }
+ }
+ function similarNumArrays(a, b) {
+ const len = a.length;
+ if (len !== b.length) {
+ return false;
+ }
+ for (let i = 0; i < len; i++) {
+ if (Math.round(a[i]) !== Math.round(b[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /* eslint max-classes-per-file: "off" */
+ /*
+ An object for getting/setting scroll-related information for an element.
+ Internally, this is done very differently for window versus DOM element,
+ so this object serves as a common interface.
+ */
+ class ScrollController {
+ getMaxScrollTop() {
+ return this.getScrollHeight() - this.getClientHeight();
+ }
+ getMaxScrollLeft() {
+ return this.getScrollWidth() - this.getClientWidth();
+ }
+ canScrollVertically() {
+ return this.getMaxScrollTop() > 0;
+ }
+ canScrollHorizontally() {
+ return this.getMaxScrollLeft() > 0;
+ }
+ canScrollUp() {
+ return this.getScrollTop() > 0;
+ }
+ canScrollDown() {
+ return this.getScrollTop() < this.getMaxScrollTop();
+ }
+ canScrollLeft() {
+ return this.getScrollLeft() > 0;
+ }
+ canScrollRight() {
+ return this.getScrollLeft() < this.getMaxScrollLeft();
+ }
+ }
+ class ElementScrollController extends ScrollController {
+ constructor(el) {
+ super();
+ this.el = el;
+ }
+ getScrollTop() {
+ return this.el.scrollTop;
+ }
+ getScrollLeft() {
+ return this.el.scrollLeft;
+ }
+ setScrollTop(top) {
+ this.el.scrollTop = top;
+ }
+ setScrollLeft(left) {
+ this.el.scrollLeft = left;
+ }
+ getScrollWidth() {
+ return this.el.scrollWidth;
+ }
+ getScrollHeight() {
+ return this.el.scrollHeight;
+ }
+ getClientHeight() {
+ return this.el.clientHeight;
+ }
+ getClientWidth() {
+ return this.el.clientWidth;
+ }
+ }
+ class WindowScrollController extends ScrollController {
+ getScrollTop() {
+ return window.pageYOffset;
+ }
+ getScrollLeft() {
+ return window.pageXOffset;
+ }
+ setScrollTop(n) {
+ window.scroll(window.pageXOffset, n);
+ }
+ setScrollLeft(n) {
+ window.scroll(n, window.pageYOffset);
+ }
+ getScrollWidth() {
+ return document.documentElement.scrollWidth;
+ }
+ getScrollHeight() {
+ return document.documentElement.scrollHeight;
+ }
+ getClientHeight() {
+ return document.documentElement.clientHeight;
+ }
+ getClientWidth() {
+ return document.documentElement.clientWidth;
+ }
+ }
+
+ class Theme {
+ constructor(calendarOptions) {
+ if (this.iconOverrideOption) {
+ this.setIconOverride(calendarOptions[this.iconOverrideOption]);
+ }
+ }
+ setIconOverride(iconOverrideHash) {
+ let iconClassesCopy;
+ let buttonName;
+ if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object
+ iconClassesCopy = Object.assign({}, this.iconClasses);
+ for (buttonName in iconOverrideHash) {
+ iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]);
+ }
+ this.iconClasses = iconClassesCopy;
+ }
+ else if (iconOverrideHash === false) {
+ this.iconClasses = {};
+ }
+ }
+ applyIconOverridePrefix(className) {
+ let prefix = this.iconOverridePrefix;
+ if (prefix && className.indexOf(prefix) !== 0) { // if not already present
+ className = prefix + className;
+ }
+ return className;
+ }
+ getClass(key) {
+ return this.classes[key] || '';
+ }
+ getIconClass(buttonName, isRtl) {
+ let className;
+ if (isRtl && this.rtlIconClasses) {
+ className = this.rtlIconClasses[buttonName] || this.iconClasses[buttonName];
+ }
+ else {
+ className = this.iconClasses[buttonName];
+ }
+ if (className) {
+ return `${this.baseIconClass} ${className}`;
+ }
+ return '';
+ }
+ getCustomButtonIconClass(customButtonProps) {
+ let className;
+ if (this.iconOverrideCustomButtonOption) {
+ className = customButtonProps[this.iconOverrideCustomButtonOption];
+ if (className) {
+ return `${this.baseIconClass} ${this.applyIconOverridePrefix(className)}`;
+ }
+ }
+ return '';
+ }
+ }
+ Theme.prototype.classes = {};
+ Theme.prototype.iconClasses = {};
+ Theme.prototype.baseIconClass = '';
+ Theme.prototype.iconOverridePrefix = '';
+
+ /*
+ NOTE: this can be a public API, especially createElement for hooks.
+ See examples/typescript-scheduler/src/index.ts
+ */
+ function flushSync(runBeforeFlush) {
+ runBeforeFlush();
+ let oldDebounceRendering = l$1.debounceRendering; // orig
+ let callbackQ = [];
+ function execCallbackSync(callback) {
+ callbackQ.push(callback);
+ }
+ l$1.debounceRendering = execCallbackSync;
+ P$1(h(FakeComponent, {}), document.createElement('div'));
+ while (callbackQ.length) {
+ callbackQ.shift()();
+ }
+ l$1.debounceRendering = oldDebounceRendering;
+ }
+ class FakeComponent extends d {
+ render() { return h('div', {}); }
+ componentDidMount() { this.setState({}); }
+ }
+ // TODO: use preact/compat instead?
+ function createContext(defaultValue) {
+ let ContextType = B$1(defaultValue);
+ let origProvider = ContextType.Provider;
+ ContextType.Provider = function () {
+ let isNew = !this.getChildContext;
+ let children = origProvider.apply(this, arguments); // eslint-disable-line prefer-rest-params
+ if (isNew) {
+ let subs = [];
+ this.shouldComponentUpdate = (_props) => {
+ if (this.props.value !== _props.value) {
+ subs.forEach((c) => {
+ c.context = _props.value;
+ c.forceUpdate();
+ });
+ }
+ };
+ this.sub = (c) => {
+ subs.push(c);
+ let old = c.componentWillUnmount;
+ c.componentWillUnmount = () => {
+ subs.splice(subs.indexOf(c), 1);
+ old && old.call(c);
+ };
+ };
+ }
+ return children;
+ };
+ return ContextType;
+ }
+
+ class ScrollResponder {
+ constructor(execFunc, emitter, scrollTime, scrollTimeReset) {
+ this.execFunc = execFunc;
+ this.emitter = emitter;
+ this.scrollTime = scrollTime;
+ this.scrollTimeReset = scrollTimeReset;
+ this.handleScrollRequest = (request) => {
+ this.queuedRequest = Object.assign({}, this.queuedRequest || {}, request);
+ this.drain();
+ };
+ emitter.on('_scrollRequest', this.handleScrollRequest);
+ this.fireInitialScroll();
+ }
+ detach() {
+ this.emitter.off('_scrollRequest', this.handleScrollRequest);
+ }
+ update(isDatesNew) {
+ if (isDatesNew && this.scrollTimeReset) {
+ this.fireInitialScroll(); // will drain
+ }
+ else {
+ this.drain();
+ }
+ }
+ fireInitialScroll() {
+ this.handleScrollRequest({
+ time: this.scrollTime,
+ });
+ }
+ drain() {
+ if (this.queuedRequest && this.execFunc(this.queuedRequest)) {
+ this.queuedRequest = null;
+ }
+ }
+ }
+
+ const ViewContextType = createContext({}); // for Components
+ function buildViewContext(viewSpec, viewApi, viewOptions, dateProfileGenerator, dateEnv, theme, pluginHooks, dispatch, getCurrentData, emitter, calendarApi, registerInteractiveComponent, unregisterInteractiveComponent) {
+ return {
+ dateEnv,
+ options: viewOptions,
+ pluginHooks,
+ emitter,
+ dispatch,
+ getCurrentData,
+ calendarApi,
+ viewSpec,
+ viewApi,
+ dateProfileGenerator,
+ theme,
+ isRtl: viewOptions.direction === 'rtl',
+ addResizeHandler(handler) {
+ emitter.on('_resize', handler);
+ },
+ removeResizeHandler(handler) {
+ emitter.off('_resize', handler);
+ },
+ createScrollResponder(execFunc) {
+ return new ScrollResponder(execFunc, emitter, createDuration(viewOptions.scrollTime), viewOptions.scrollTimeReset);
+ },
+ registerInteractiveComponent,
+ unregisterInteractiveComponent,
+ };
+ }
+
+ /* eslint max-classes-per-file: off */
+ class PureComponent extends d {
+ shouldComponentUpdate(nextProps, nextState) {
+ if (this.debug) {
+ // eslint-disable-next-line no-console
+ console.log(getUnequalProps(nextProps, this.props), getUnequalProps(nextState, this.state));
+ }
+ return !compareObjs(this.props, nextProps, this.propEquality) ||
+ !compareObjs(this.state, nextState, this.stateEquality);
+ }
+ // HACK for freakin' React StrictMode
+ safeSetState(newState) {
+ if (!compareObjs(this.state, Object.assign(Object.assign({}, this.state), newState), this.stateEquality)) {
+ this.setState(newState);
+ }
+ }
+ }
+ PureComponent.addPropsEquality = addPropsEquality;
+ PureComponent.addStateEquality = addStateEquality;
+ PureComponent.contextType = ViewContextType;
+ PureComponent.prototype.propEquality = {};
+ PureComponent.prototype.stateEquality = {};
+ class BaseComponent extends PureComponent {
+ }
+ BaseComponent.contextType = ViewContextType;
+ function addPropsEquality(propEquality) {
+ let hash = Object.create(this.prototype.propEquality);
+ Object.assign(hash, propEquality);
+ this.prototype.propEquality = hash;
+ }
+ function addStateEquality(stateEquality) {
+ let hash = Object.create(this.prototype.stateEquality);
+ Object.assign(hash, stateEquality);
+ this.prototype.stateEquality = hash;
+ }
+ // use other one
+ function setRef(ref, current) {
+ if (typeof ref === 'function') {
+ ref(current);
+ }
+ else if (ref) {
+ // see https://github.com/facebook/react/issues/13029
+ ref.current = current;
+ }
+ }
+
+ /*
+ an INTERACTABLE date component
+
+ PURPOSES:
+ - hook up to fg, fill, and mirror renderers
+ - interface for dragging and hits
+ */
+ class DateComponent extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.uid = guid();
+ }
+ // Hit System
+ // -----------------------------------------------------------------------------------------------------------------
+ prepareHits() {
+ }
+ queryHit(positionLeft, positionTop, elWidth, elHeight) {
+ return null; // this should be abstract
+ }
+ // Pointer Interaction Utils
+ // -----------------------------------------------------------------------------------------------------------------
+ isValidSegDownEl(el) {
+ return !this.props.eventDrag && // HACK
+ !this.props.eventResize && // HACK
+ !elementClosest(el, '.fc-event-mirror');
+ }
+ isValidDateDownEl(el) {
+ return !elementClosest(el, '.fc-event:not(.fc-bg-event)') &&
+ !elementClosest(el, '.fc-more-link') && // a "more.." link
+ !elementClosest(el, 'a[data-navlink]') && // a clickable nav link
+ !elementClosest(el, '.fc-popover'); // hack
+ }
+ }
+
+ function reduceCurrentDate(currentDate, action) {
+ switch (action.type) {
+ case 'CHANGE_DATE':
+ return action.dateMarker;
+ default:
+ return currentDate;
+ }
+ }
+ function getInitialDate(options, dateEnv) {
+ let initialDateInput = options.initialDate;
+ // compute the initial ambig-timezone date
+ if (initialDateInput != null) {
+ return dateEnv.createMarker(initialDateInput);
+ }
+ return getNow(options.now, dateEnv); // getNow already returns unzoned
+ }
+ function getNow(nowInput, dateEnv) {
+ if (typeof nowInput === 'function') {
+ nowInput = nowInput();
+ }
+ if (nowInput == null) {
+ return dateEnv.createNowMarker();
+ }
+ return dateEnv.createMarker(nowInput);
+ }
+
+ class DateProfileGenerator {
+ constructor(props) {
+ this.props = props;
+ this.nowDate = getNow(props.nowInput, props.dateEnv);
+ this.initHiddenDays();
+ }
+ /* Date Range Computation
+ ------------------------------------------------------------------------------------------------------------------*/
+ // Builds a structure with info about what the dates/ranges will be for the "prev" view.
+ buildPrev(currentDateProfile, currentDate, forceToValid) {
+ let { dateEnv } = this.props;
+ let prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
+ currentDateProfile.dateIncrement);
+ return this.build(prevDate, -1, forceToValid);
+ }
+ // Builds a structure with info about what the dates/ranges will be for the "next" view.
+ buildNext(currentDateProfile, currentDate, forceToValid) {
+ let { dateEnv } = this.props;
+ let nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
+ currentDateProfile.dateIncrement);
+ return this.build(nextDate, 1, forceToValid);
+ }
+ // Builds a structure holding dates/ranges for rendering around the given date.
+ // Optional direction param indicates whether the date is being incremented/decremented
+ // from its previous value. decremented = -1, incremented = 1 (default).
+ build(currentDate, direction, forceToValid = true) {
+ let { props } = this;
+ let validRange;
+ let currentInfo;
+ let isRangeAllDay;
+ let renderRange;
+ let activeRange;
+ let isValid;
+ validRange = this.buildValidRange();
+ validRange = this.trimHiddenDays(validRange);
+ if (forceToValid) {
+ currentDate = constrainMarkerToRange(currentDate, validRange);
+ }
+ currentInfo = this.buildCurrentRangeInfo(currentDate, direction);
+ isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit);
+ renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay);
+ renderRange = this.trimHiddenDays(renderRange);
+ activeRange = renderRange;
+ if (!props.showNonCurrentDates) {
+ activeRange = intersectRanges(activeRange, currentInfo.range);
+ }
+ activeRange = this.adjustActiveRange(activeRange);
+ activeRange = intersectRanges(activeRange, validRange); // might return null
+ // it's invalid if the originally requested date is not contained,
+ // or if the range is completely outside of the valid range.
+ isValid = rangesIntersect(currentInfo.range, validRange);
+ return {
+ // constraint for where prev/next operations can go and where events can be dragged/resized to.
+ // an object with optional start and end properties.
+ validRange,
+ // range the view is formally responsible for.
+ // for example, a month view might have 1st-31st, excluding padded dates
+ currentRange: currentInfo.range,
+ // name of largest unit being displayed, like "month" or "week"
+ currentRangeUnit: currentInfo.unit,
+ isRangeAllDay,
+ // dates that display events and accept drag-n-drop
+ // will be `null` if no dates accept events
+ activeRange,
+ // date range with a rendered skeleton
+ // includes not-active days that need some sort of DOM
+ renderRange,
+ // Duration object that denotes the first visible time of any given day
+ slotMinTime: props.slotMinTime,
+ // Duration object that denotes the exclusive visible end time of any given day
+ slotMaxTime: props.slotMaxTime,
+ isValid,
+ // how far the current date will move for a prev/next operation
+ dateIncrement: this.buildDateIncrement(currentInfo.duration),
+ // pass a fallback (might be null) ^
+ };
+ }
+ // Builds an object with optional start/end properties.
+ // Indicates the minimum/maximum dates to display.
+ // not responsible for trimming hidden days.
+ buildValidRange() {
+ let input = this.props.validRangeInput;
+ let simpleInput = typeof input === 'function'
+ ? input.call(this.props.calendarApi, this.nowDate)
+ : input;
+ return this.refineRange(simpleInput) ||
+ { start: null, end: null }; // completely open-ended
+ }
+ // Builds a structure with info about the "current" range, the range that is
+ // highlighted as being the current month for example.
+ // See build() for a description of `direction`.
+ // Guaranteed to have `range` and `unit` properties. `duration` is optional.
+ buildCurrentRangeInfo(date, direction) {
+ let { props } = this;
+ let duration = null;
+ let unit = null;
+ let range = null;
+ let dayCount;
+ if (props.duration) {
+ duration = props.duration;
+ unit = props.durationUnit;
+ range = this.buildRangeFromDuration(date, direction, duration, unit);
+ }
+ else if ((dayCount = this.props.dayCount)) {
+ unit = 'day';
+ range = this.buildRangeFromDayCount(date, direction, dayCount);
+ }
+ else if ((range = this.buildCustomVisibleRange(date))) {
+ unit = props.dateEnv.greatestWholeUnit(range.start, range.end).unit;
+ }
+ else {
+ duration = this.getFallbackDuration();
+ unit = greatestDurationDenominator(duration).unit;
+ range = this.buildRangeFromDuration(date, direction, duration, unit);
+ }
+ return { duration, unit, range };
+ }
+ getFallbackDuration() {
+ return createDuration({ day: 1 });
+ }
+ // Returns a new activeRange to have time values (un-ambiguate)
+ // slotMinTime or slotMaxTime causes the range to expand.
+ adjustActiveRange(range) {
+ let { dateEnv, usesMinMaxTime, slotMinTime, slotMaxTime } = this.props;
+ let { start, end } = range;
+ if (usesMinMaxTime) {
+ // expand active range if slotMinTime is negative (why not when positive?)
+ if (asRoughDays(slotMinTime) < 0) {
+ start = startOfDay(start); // necessary?
+ start = dateEnv.add(start, slotMinTime);
+ }
+ // expand active range if slotMaxTime is beyond one day (why not when negative?)
+ if (asRoughDays(slotMaxTime) > 1) {
+ end = startOfDay(end); // necessary?
+ end = addDays(end, -1);
+ end = dateEnv.add(end, slotMaxTime);
+ }
+ }
+ return { start, end };
+ }
+ // Builds the "current" range when it is specified as an explicit duration.
+ // `unit` is the already-computed greatestDurationDenominator unit of duration.
+ buildRangeFromDuration(date, direction, duration, unit) {
+ let { dateEnv, dateAlignment } = this.props;
+ let start;
+ let end;
+ let res;
+ // compute what the alignment should be
+ if (!dateAlignment) {
+ let { dateIncrement } = this.props;
+ if (dateIncrement) {
+ // use the smaller of the two units
+ if (asRoughMs(dateIncrement) < asRoughMs(duration)) {
+ dateAlignment = greatestDurationDenominator(dateIncrement).unit;
+ }
+ else {
+ dateAlignment = unit;
+ }
+ }
+ else {
+ dateAlignment = unit;
+ }
+ }
+ // if the view displays a single day or smaller
+ if (asRoughDays(duration) <= 1) {
+ if (this.isHiddenDay(start)) {
+ start = this.skipHiddenDays(start, direction);
+ start = startOfDay(start);
+ }
+ }
+ function computeRes() {
+ start = dateEnv.startOf(date, dateAlignment);
+ end = dateEnv.add(start, duration);
+ res = { start, end };
+ }
+ computeRes();
+ // if range is completely enveloped by hidden days, go past the hidden days
+ if (!this.trimHiddenDays(res)) {
+ date = this.skipHiddenDays(date, direction);
+ computeRes();
+ }
+ return res;
+ }
+ // Builds the "current" range when a dayCount is specified.
+ buildRangeFromDayCount(date, direction, dayCount) {
+ let { dateEnv, dateAlignment } = this.props;
+ let runningCount = 0;
+ let start = date;
+ let end;
+ if (dateAlignment) {
+ start = dateEnv.startOf(start, dateAlignment);
+ }
+ start = startOfDay(start);
+ start = this.skipHiddenDays(start, direction);
+ end = start;
+ do {
+ end = addDays(end, 1);
+ if (!this.isHiddenDay(end)) {
+ runningCount += 1;
+ }
+ } while (runningCount < dayCount);
+ return { start, end };
+ }
+ // Builds a normalized range object for the "visible" range,
+ // which is a way to define the currentRange and activeRange at the same time.
+ buildCustomVisibleRange(date) {
+ let { props } = this;
+ let input = props.visibleRangeInput;
+ let simpleInput = typeof input === 'function'
+ ? input.call(props.calendarApi, props.dateEnv.toDate(date))
+ : input;
+ let range = this.refineRange(simpleInput);
+ if (range && (range.start == null || range.end == null)) {
+ return null;
+ }
+ return range;
+ }
+ // Computes the range that will represent the element/cells for *rendering*,
+ // but which may have voided days/times.
+ // not responsible for trimming hidden days.
+ buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
+ return currentRange;
+ }
+ // Compute the duration value that should be added/substracted to the current date
+ // when a prev/next operation happens.
+ buildDateIncrement(fallback) {
+ let { dateIncrement } = this.props;
+ let customAlignment;
+ if (dateIncrement) {
+ return dateIncrement;
+ }
+ if ((customAlignment = this.props.dateAlignment)) {
+ return createDuration(1, customAlignment);
+ }
+ if (fallback) {
+ return fallback;
+ }
+ return createDuration({ days: 1 });
+ }
+ refineRange(rangeInput) {
+ if (rangeInput) {
+ let range = parseRange(rangeInput, this.props.dateEnv);
+ if (range) {
+ range = computeVisibleDayRange(range);
+ }
+ return range;
+ }
+ return null;
+ }
+ /* Hidden Days
+ ------------------------------------------------------------------------------------------------------------------*/
+ // Initializes internal variables related to calculating hidden days-of-week
+ initHiddenDays() {
+ let hiddenDays = this.props.hiddenDays || []; // array of day-of-week indices that are hidden
+ let isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool)
+ let dayCnt = 0;
+ let i;
+ if (this.props.weekends === false) {
+ hiddenDays.push(0, 6); // 0=sunday, 6=saturday
+ }
+ for (i = 0; i < 7; i += 1) {
+ if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) {
+ dayCnt += 1;
+ }
+ }
+ if (!dayCnt) {
+ throw new Error('invalid hiddenDays'); // all days were hidden? bad.
+ }
+ this.isHiddenDayHash = isHiddenDayHash;
+ }
+ // Remove days from the beginning and end of the range that are computed as hidden.
+ // If the whole range is trimmed off, returns null
+ trimHiddenDays(range) {
+ let { start, end } = range;
+ if (start) {
+ start = this.skipHiddenDays(start);
+ }
+ if (end) {
+ end = this.skipHiddenDays(end, -1, true);
+ }
+ if (start == null || end == null || start < end) {
+ return { start, end };
+ }
+ return null;
+ }
+ // Is the current day hidden?
+ // `day` is a day-of-week index (0-6), or a Date (used for UTC)
+ isHiddenDay(day) {
+ if (day instanceof Date) {
+ day = day.getUTCDay();
+ }
+ return this.isHiddenDayHash[day];
+ }
+ // Incrementing the current day until it is no longer a hidden day, returning a copy.
+ // DOES NOT CONSIDER validRange!
+ // If the initial value of `date` is not a hidden day, don't do anything.
+ // Pass `isExclusive` as `true` if you are dealing with an end date.
+ // `inc` defaults to `1` (increment one day forward each time)
+ skipHiddenDays(date, inc = 1, isExclusive = false) {
+ while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) {
+ date = addDays(date, inc);
+ }
+ return date;
+ }
+ }
+
+ function triggerDateSelect(selection, pev, context) {
+ context.emitter.trigger('select', Object.assign(Object.assign({}, buildDateSpanApiWithContext(selection, context)), { jsEvent: pev ? pev.origEvent : null, view: context.viewApi || context.calendarApi.view }));
+ }
+ function triggerDateUnselect(pev, context) {
+ context.emitter.trigger('unselect', {
+ jsEvent: pev ? pev.origEvent : null,
+ view: context.viewApi || context.calendarApi.view,
+ });
+ }
+ function buildDateSpanApiWithContext(dateSpan, context) {
+ let props = {};
+ for (let transform of context.pluginHooks.dateSpanTransforms) {
+ Object.assign(props, transform(dateSpan, context));
+ }
+ Object.assign(props, buildDateSpanApi(dateSpan, context.dateEnv));
+ return props;
+ }
+ // Given an event's allDay status and start date, return what its fallback end date should be.
+ // TODO: rename to computeDefaultEventEnd
+ function getDefaultEventEnd(allDay, marker, context) {
+ let { dateEnv, options } = context;
+ let end = marker;
+ if (allDay) {
+ end = startOfDay(end);
+ end = dateEnv.add(end, options.defaultAllDayEventDuration);
+ }
+ else {
+ end = dateEnv.add(end, options.defaultTimedEventDuration);
+ }
+ return end;
+ }
+
+ // applies the mutation to ALL defs/instances within the event store
+ function applyMutationToEventStore(eventStore, eventConfigBase, mutation, context) {
+ let eventConfigs = compileEventUis(eventStore.defs, eventConfigBase);
+ let dest = createEmptyEventStore();
+ for (let defId in eventStore.defs) {
+ let def = eventStore.defs[defId];
+ dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, context);
+ }
+ for (let instanceId in eventStore.instances) {
+ let instance = eventStore.instances[instanceId];
+ let def = dest.defs[instance.defId]; // important to grab the newly modified def
+ dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, context);
+ }
+ return dest;
+ }
+ function applyMutationToEventDef(eventDef, eventConfig, mutation, context) {
+ let standardProps = mutation.standardProps || {};
+ // if hasEnd has not been specified, guess a good value based on deltas.
+ // if duration will change, there's no way the default duration will persist,
+ // and thus, we need to mark the event as having a real end
+ if (standardProps.hasEnd == null &&
+ eventConfig.durationEditable &&
+ (mutation.startDelta || mutation.endDelta)) {
+ standardProps.hasEnd = true; // TODO: is this mutation okay?
+ }
+ let copy = Object.assign(Object.assign(Object.assign({}, eventDef), standardProps), { ui: Object.assign(Object.assign({}, eventDef.ui), standardProps.ui) });
+ if (mutation.extendedProps) {
+ copy.extendedProps = Object.assign(Object.assign({}, copy.extendedProps), mutation.extendedProps);
+ }
+ for (let applier of context.pluginHooks.eventDefMutationAppliers) {
+ applier(copy, mutation, context);
+ }
+ if (!copy.hasEnd && context.options.forceEventDuration) {
+ copy.hasEnd = true;
+ }
+ return copy;
+ }
+ function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef
+ eventConfig, mutation, context) {
+ let { dateEnv } = context;
+ let forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true;
+ let clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false;
+ let copy = Object.assign({}, eventInstance);
+ if (forceAllDay) {
+ copy.range = computeAlignedDayRange(copy.range);
+ }
+ if (mutation.datesDelta && eventConfig.startEditable) {
+ copy.range = {
+ start: dateEnv.add(copy.range.start, mutation.datesDelta),
+ end: dateEnv.add(copy.range.end, mutation.datesDelta),
+ };
+ }
+ if (mutation.startDelta && eventConfig.durationEditable) {
+ copy.range = {
+ start: dateEnv.add(copy.range.start, mutation.startDelta),
+ end: copy.range.end,
+ };
+ }
+ if (mutation.endDelta && eventConfig.durationEditable) {
+ copy.range = {
+ start: copy.range.start,
+ end: dateEnv.add(copy.range.end, mutation.endDelta),
+ };
+ }
+ if (clearEnd) {
+ copy.range = {
+ start: copy.range.start,
+ end: getDefaultEventEnd(eventDef.allDay, copy.range.start, context),
+ };
+ }
+ // in case event was all-day but the supplied deltas were not
+ // better util for this?
+ if (eventDef.allDay) {
+ copy.range = {
+ start: startOfDay(copy.range.start),
+ end: startOfDay(copy.range.end),
+ };
+ }
+ // handle invalid durations
+ if (copy.range.end < copy.range.start) {
+ copy.range.end = getDefaultEventEnd(eventDef.allDay, copy.range.start, context);
+ }
+ return copy;
+ }
+
+ class EventSourceImpl {
+ constructor(context, internalEventSource) {
+ this.context = context;
+ this.internalEventSource = internalEventSource;
+ }
+ remove() {
+ this.context.dispatch({
+ type: 'REMOVE_EVENT_SOURCE',
+ sourceId: this.internalEventSource.sourceId,
+ });
+ }
+ refetch() {
+ this.context.dispatch({
+ type: 'FETCH_EVENT_SOURCES',
+ sourceIds: [this.internalEventSource.sourceId],
+ isRefetch: true,
+ });
+ }
+ get id() {
+ return this.internalEventSource.publicId;
+ }
+ get url() {
+ return this.internalEventSource.meta.url;
+ }
+ get format() {
+ return this.internalEventSource.meta.format; // TODO: bad. not guaranteed
+ }
+ }
+
+ class EventImpl {
+ // instance will be null if expressing a recurring event that has no current instances,
+ // OR if trying to validate an incoming external event that has no dates assigned
+ constructor(context, def, instance) {
+ this._context = context;
+ this._def = def;
+ this._instance = instance || null;
+ }
+ /*
+ TODO: make event struct more responsible for this
+ */
+ setProp(name, val) {
+ if (name in EVENT_DATE_REFINERS) {
+ console.warn('Could not set date-related prop \'name\'. Use one of the date-related methods instead.');
+ // TODO: make proper aliasing system?
+ }
+ else if (name === 'id') {
+ val = EVENT_NON_DATE_REFINERS[name](val);
+ this.mutate({
+ standardProps: { publicId: val }, // hardcoded internal name
+ });
+ }
+ else if (name in EVENT_NON_DATE_REFINERS) {
+ val = EVENT_NON_DATE_REFINERS[name](val);
+ this.mutate({
+ standardProps: { [name]: val },
+ });
+ }
+ else if (name in EVENT_UI_REFINERS) {
+ let ui = EVENT_UI_REFINERS[name](val);
+ if (name === 'color') {
+ ui = { backgroundColor: val, borderColor: val };
+ }
+ else if (name === 'editable') {
+ ui = { startEditable: val, durationEditable: val };
+ }
+ else {
+ ui = { [name]: val };
+ }
+ this.mutate({
+ standardProps: { ui },
+ });
+ }
+ else {
+ console.warn(`Could not set prop '${name}'. Use setExtendedProp instead.`);
+ }
+ }
+ setExtendedProp(name, val) {
+ this.mutate({
+ extendedProps: { [name]: val },
+ });
+ }
+ setStart(startInput, options = {}) {
+ let { dateEnv } = this._context;
+ let start = dateEnv.createMarker(startInput);
+ if (start && this._instance) { // TODO: warning if parsed bad
+ let instanceRange = this._instance.range;
+ let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!?
+ if (options.maintainDuration) {
+ this.mutate({ datesDelta: startDelta });
+ }
+ else {
+ this.mutate({ startDelta });
+ }
+ }
+ }
+ setEnd(endInput, options = {}) {
+ let { dateEnv } = this._context;
+ let end;
+ if (endInput != null) {
+ end = dateEnv.createMarker(endInput);
+ if (!end) {
+ return; // TODO: warning if parsed bad
+ }
+ }
+ if (this._instance) {
+ if (end) {
+ let endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity);
+ this.mutate({ endDelta });
+ }
+ else {
+ this.mutate({ standardProps: { hasEnd: false } });
+ }
+ }
+ }
+ setDates(startInput, endInput, options = {}) {
+ let { dateEnv } = this._context;
+ let standardProps = { allDay: options.allDay };
+ let start = dateEnv.createMarker(startInput);
+ let end;
+ if (!start) {
+ return; // TODO: warning if parsed bad
+ }
+ if (endInput != null) {
+ end = dateEnv.createMarker(endInput);
+ if (!end) { // TODO: warning if parsed bad
+ return;
+ }
+ }
+ if (this._instance) {
+ let instanceRange = this._instance.range;
+ // when computing the diff for an event being converted to all-day,
+ // compute diff off of the all-day values the way event-mutation does.
+ if (options.allDay === true) {
+ instanceRange = computeAlignedDayRange(instanceRange);
+ }
+ let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity);
+ if (end) {
+ let endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity);
+ if (durationsEqual(startDelta, endDelta)) {
+ this.mutate({ datesDelta: startDelta, standardProps });
+ }
+ else {
+ this.mutate({ startDelta, endDelta, standardProps });
+ }
+ }
+ else { // means "clear the end"
+ standardProps.hasEnd = false;
+ this.mutate({ datesDelta: startDelta, standardProps });
+ }
+ }
+ }
+ moveStart(deltaInput) {
+ let delta = createDuration(deltaInput);
+ if (delta) { // TODO: warning if parsed bad
+ this.mutate({ startDelta: delta });
+ }
+ }
+ moveEnd(deltaInput) {
+ let delta = createDuration(deltaInput);
+ if (delta) { // TODO: warning if parsed bad
+ this.mutate({ endDelta: delta });
+ }
+ }
+ moveDates(deltaInput) {
+ let delta = createDuration(deltaInput);
+ if (delta) { // TODO: warning if parsed bad
+ this.mutate({ datesDelta: delta });
+ }
+ }
+ setAllDay(allDay, options = {}) {
+ let standardProps = { allDay };
+ let { maintainDuration } = options;
+ if (maintainDuration == null) {
+ maintainDuration = this._context.options.allDayMaintainDuration;
+ }
+ if (this._def.allDay !== allDay) {
+ standardProps.hasEnd = maintainDuration;
+ }
+ this.mutate({ standardProps });
+ }
+ formatRange(formatInput) {
+ let { dateEnv } = this._context;
+ let instance = this._instance;
+ let formatter = createFormatter(formatInput);
+ if (this._def.hasEnd) {
+ return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, {
+ forcedStartTzo: instance.forcedStartTzo,
+ forcedEndTzo: instance.forcedEndTzo,
+ });
+ }
+ return dateEnv.format(instance.range.start, formatter, {
+ forcedTzo: instance.forcedStartTzo,
+ });
+ }
+ mutate(mutation) {
+ let instance = this._instance;
+ if (instance) {
+ let def = this._def;
+ let context = this._context;
+ let { eventStore } = context.getCurrentData();
+ let relevantEvents = getRelevantEvents(eventStore, instance.instanceId);
+ let eventConfigBase = {
+ '': {
+ display: '',
+ startEditable: true,
+ durationEditable: true,
+ constraints: [],
+ overlap: null,
+ allows: [],
+ backgroundColor: '',
+ borderColor: '',
+ textColor: '',
+ classNames: [],
+ },
+ };
+ relevantEvents = applyMutationToEventStore(relevantEvents, eventConfigBase, mutation, context);
+ let oldEvent = new EventImpl(context, def, instance); // snapshot
+ this._def = relevantEvents.defs[def.defId];
+ this._instance = relevantEvents.instances[instance.instanceId];
+ context.dispatch({
+ type: 'MERGE_EVENTS',
+ eventStore: relevantEvents,
+ });
+ context.emitter.trigger('eventChange', {
+ oldEvent,
+ event: this,
+ relatedEvents: buildEventApis(relevantEvents, context, instance),
+ revert() {
+ context.dispatch({
+ type: 'RESET_EVENTS',
+ eventStore, // the ORIGINAL store
+ });
+ },
+ });
+ }
+ }
+ remove() {
+ let context = this._context;
+ let asStore = eventApiToStore(this);
+ context.dispatch({
+ type: 'REMOVE_EVENTS',
+ eventStore: asStore,
+ });
+ context.emitter.trigger('eventRemove', {
+ event: this,
+ relatedEvents: [],
+ revert() {
+ context.dispatch({
+ type: 'MERGE_EVENTS',
+ eventStore: asStore,
+ });
+ },
+ });
+ }
+ get source() {
+ let { sourceId } = this._def;
+ if (sourceId) {
+ return new EventSourceImpl(this._context, this._context.getCurrentData().eventSources[sourceId]);
+ }
+ return null;
+ }
+ get start() {
+ return this._instance ?
+ this._context.dateEnv.toDate(this._instance.range.start) :
+ null;
+ }
+ get end() {
+ return (this._instance && this._def.hasEnd) ?
+ this._context.dateEnv.toDate(this._instance.range.end) :
+ null;
+ }
+ get startStr() {
+ let instance = this._instance;
+ if (instance) {
+ return this._context.dateEnv.formatIso(instance.range.start, {
+ omitTime: this._def.allDay,
+ forcedTzo: instance.forcedStartTzo,
+ });
+ }
+ return '';
+ }
+ get endStr() {
+ let instance = this._instance;
+ if (instance && this._def.hasEnd) {
+ return this._context.dateEnv.formatIso(instance.range.end, {
+ omitTime: this._def.allDay,
+ forcedTzo: instance.forcedEndTzo,
+ });
+ }
+ return '';
+ }
+ // computable props that all access the def
+ // TODO: find a TypeScript-compatible way to do this at scale
+ get id() { return this._def.publicId; }
+ get groupId() { return this._def.groupId; }
+ get allDay() { return this._def.allDay; }
+ get title() { return this._def.title; }
+ get url() { return this._def.url; }
+ get display() { return this._def.ui.display || 'auto'; } // bad. just normalize the type earlier
+ get startEditable() { return this._def.ui.startEditable; }
+ get durationEditable() { return this._def.ui.durationEditable; }
+ get constraint() { return this._def.ui.constraints[0] || null; }
+ get overlap() { return this._def.ui.overlap; }
+ get allow() { return this._def.ui.allows[0] || null; }
+ get backgroundColor() { return this._def.ui.backgroundColor; }
+ get borderColor() { return this._def.ui.borderColor; }
+ get textColor() { return this._def.ui.textColor; }
+ // NOTE: user can't modify these because Object.freeze was called in event-def parsing
+ get classNames() { return this._def.ui.classNames; }
+ get extendedProps() { return this._def.extendedProps; }
+ toPlainObject(settings = {}) {
+ let def = this._def;
+ let { ui } = def;
+ let { startStr, endStr } = this;
+ let res = {};
+ if (def.title) {
+ res.title = def.title;
+ }
+ if (startStr) {
+ res.start = startStr;
+ }
+ if (endStr) {
+ res.end = endStr;
+ }
+ if (def.publicId) {
+ res.id = def.publicId;
+ }
+ if (def.groupId) {
+ res.groupId = def.groupId;
+ }
+ if (def.url) {
+ res.url = def.url;
+ }
+ if (ui.display && ui.display !== 'auto') {
+ res.display = ui.display;
+ }
+ // TODO: what about recurring-event properties???
+ // TODO: include startEditable/durationEditable/constraint/overlap/allow
+ if (settings.collapseColor && ui.backgroundColor && ui.backgroundColor === ui.borderColor) {
+ res.color = ui.backgroundColor;
+ }
+ else {
+ if (ui.backgroundColor) {
+ res.backgroundColor = ui.backgroundColor;
+ }
+ if (ui.borderColor) {
+ res.borderColor = ui.borderColor;
+ }
+ }
+ if (ui.textColor) {
+ res.textColor = ui.textColor;
+ }
+ if (ui.classNames.length) {
+ res.classNames = ui.classNames;
+ }
+ if (Object.keys(def.extendedProps).length) {
+ if (settings.collapseExtendedProps) {
+ Object.assign(res, def.extendedProps);
+ }
+ else {
+ res.extendedProps = def.extendedProps;
+ }
+ }
+ return res;
+ }
+ toJSON() {
+ return this.toPlainObject();
+ }
+ }
+ function eventApiToStore(eventApi) {
+ let def = eventApi._def;
+ let instance = eventApi._instance;
+ return {
+ defs: { [def.defId]: def },
+ instances: instance
+ ? { [instance.instanceId]: instance }
+ : {},
+ };
+ }
+ function buildEventApis(eventStore, context, excludeInstance) {
+ let { defs, instances } = eventStore;
+ let eventApis = [];
+ let excludeInstanceId = excludeInstance ? excludeInstance.instanceId : '';
+ for (let id in instances) {
+ let instance = instances[id];
+ let def = defs[instance.defId];
+ if (instance.instanceId !== excludeInstanceId) {
+ eventApis.push(new EventImpl(context, def, instance));
+ }
+ }
+ return eventApis;
+ }
+
+ /*
+ Specifying nextDayThreshold signals that all-day ranges should be sliced.
+ */
+ function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) {
+ let inverseBgByGroupId = {};
+ let inverseBgByDefId = {};
+ let defByGroupId = {};
+ let bgRanges = [];
+ let fgRanges = [];
+ let eventUis = compileEventUis(eventStore.defs, eventUiBases);
+ for (let defId in eventStore.defs) {
+ let def = eventStore.defs[defId];
+ let ui = eventUis[def.defId];
+ if (ui.display === 'inverse-background') {
+ if (def.groupId) {
+ inverseBgByGroupId[def.groupId] = [];
+ if (!defByGroupId[def.groupId]) {
+ defByGroupId[def.groupId] = def;
+ }
+ }
+ else {
+ inverseBgByDefId[defId] = [];
+ }
+ }
+ }
+ for (let instanceId in eventStore.instances) {
+ let instance = eventStore.instances[instanceId];
+ let def = eventStore.defs[instance.defId];
+ let ui = eventUis[def.defId];
+ let origRange = instance.range;
+ let normalRange = (!def.allDay && nextDayThreshold) ?
+ computeVisibleDayRange(origRange, nextDayThreshold) :
+ origRange;
+ let slicedRange = intersectRanges(normalRange, framingRange);
+ if (slicedRange) {
+ if (ui.display === 'inverse-background') {
+ if (def.groupId) {
+ inverseBgByGroupId[def.groupId].push(slicedRange);
+ }
+ else {
+ inverseBgByDefId[instance.defId].push(slicedRange);
+ }
+ }
+ else if (ui.display !== 'none') {
+ (ui.display === 'background' ? bgRanges : fgRanges).push({
+ def,
+ ui,
+ instance,
+ range: slicedRange,
+ isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(),
+ isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf(),
+ });
+ }
+ }
+ }
+ for (let groupId in inverseBgByGroupId) { // BY GROUP
+ let ranges = inverseBgByGroupId[groupId];
+ let invertedRanges = invertRanges(ranges, framingRange);
+ for (let invertedRange of invertedRanges) {
+ let def = defByGroupId[groupId];
+ let ui = eventUis[def.defId];
+ bgRanges.push({
+ def,
+ ui,
+ instance: null,
+ range: invertedRange,
+ isStart: false,
+ isEnd: false,
+ });
+ }
+ }
+ for (let defId in inverseBgByDefId) {
+ let ranges = inverseBgByDefId[defId];
+ let invertedRanges = invertRanges(ranges, framingRange);
+ for (let invertedRange of invertedRanges) {
+ bgRanges.push({
+ def: eventStore.defs[defId],
+ ui: eventUis[defId],
+ instance: null,
+ range: invertedRange,
+ isStart: false,
+ isEnd: false,
+ });
+ }
+ }
+ return { bg: bgRanges, fg: fgRanges };
+ }
+ function hasBgRendering(def) {
+ return def.ui.display === 'background' || def.ui.display === 'inverse-background';
+ }
+ function setElSeg(el, seg) {
+ el.fcSeg = seg;
+ }
+ function getElSeg(el) {
+ return el.fcSeg ||
+ el.parentNode.fcSeg || // for the harness
+ null;
+ }
+ // event ui computation
+ function compileEventUis(eventDefs, eventUiBases) {
+ return mapHash(eventDefs, (eventDef) => compileEventUi(eventDef, eventUiBases));
+ }
+ function compileEventUi(eventDef, eventUiBases) {
+ let uis = [];
+ if (eventUiBases['']) {
+ uis.push(eventUiBases['']);
+ }
+ if (eventUiBases[eventDef.defId]) {
+ uis.push(eventUiBases[eventDef.defId]);
+ }
+ uis.push(eventDef.ui);
+ return combineEventUis(uis);
+ }
+ function sortEventSegs(segs, eventOrderSpecs) {
+ let objs = segs.map(buildSegCompareObj);
+ objs.sort((obj0, obj1) => compareByFieldSpecs(obj0, obj1, eventOrderSpecs));
+ return objs.map((c) => c._seg);
+ }
+ // returns a object with all primitive props that can be compared
+ function buildSegCompareObj(seg) {
+ let { eventRange } = seg;
+ let eventDef = eventRange.def;
+ let range = eventRange.instance ? eventRange.instance.range : eventRange.range;
+ let start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events
+ let end = range.end ? range.end.valueOf() : 0; // "
+ return Object.assign(Object.assign(Object.assign({}, eventDef.extendedProps), eventDef), { id: eventDef.publicId, start,
+ end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg });
+ }
+ function computeSegDraggable(seg, context) {
+ let { pluginHooks } = context;
+ let transformers = pluginHooks.isDraggableTransformers;
+ let { def, ui } = seg.eventRange;
+ let val = ui.startEditable;
+ for (let transformer of transformers) {
+ val = transformer(val, def, ui, context);
+ }
+ return val;
+ }
+ function computeSegStartResizable(seg, context) {
+ return seg.isStart && seg.eventRange.ui.durationEditable && context.options.eventResizableFromStart;
+ }
+ function computeSegEndResizable(seg, context) {
+ return seg.isEnd && seg.eventRange.ui.durationEditable;
+ }
+ function buildSegTimeText(seg, timeFormat, context, defaultDisplayEventTime, // defaults to true
+ defaultDisplayEventEnd, // defaults to true
+ startOverride, endOverride) {
+ let { dateEnv, options } = context;
+ let { displayEventTime, displayEventEnd } = options;
+ let eventDef = seg.eventRange.def;
+ let eventInstance = seg.eventRange.instance;
+ if (displayEventTime == null) {
+ displayEventTime = defaultDisplayEventTime !== false;
+ }
+ if (displayEventEnd == null) {
+ displayEventEnd = defaultDisplayEventEnd !== false;
+ }
+ let wholeEventStart = eventInstance.range.start;
+ let wholeEventEnd = eventInstance.range.end;
+ let segStart = startOverride || seg.start || seg.eventRange.range.start;
+ let segEnd = endOverride || seg.end || seg.eventRange.range.end;
+ let isStartDay = startOfDay(wholeEventStart).valueOf() === startOfDay(segStart).valueOf();
+ let isEndDay = startOfDay(addMs(wholeEventEnd, -1)).valueOf() === startOfDay(addMs(segEnd, -1)).valueOf();
+ if (displayEventTime && !eventDef.allDay && (isStartDay || isEndDay)) {
+ segStart = isStartDay ? wholeEventStart : segStart;
+ segEnd = isEndDay ? wholeEventEnd : segEnd;
+ if (displayEventEnd && eventDef.hasEnd) {
+ return dateEnv.formatRange(segStart, segEnd, timeFormat, {
+ forcedStartTzo: startOverride ? null : eventInstance.forcedStartTzo,
+ forcedEndTzo: endOverride ? null : eventInstance.forcedEndTzo,
+ });
+ }
+ return dateEnv.format(segStart, timeFormat, {
+ forcedTzo: startOverride ? null : eventInstance.forcedStartTzo, // nooooo, same
+ });
+ }
+ return '';
+ }
+ function getSegMeta(seg, todayRange, nowDate) {
+ let segRange = seg.eventRange.range;
+ return {
+ isPast: segRange.end < (nowDate || todayRange.start),
+ isFuture: segRange.start >= (nowDate || todayRange.end),
+ isToday: todayRange && rangeContainsMarker(todayRange, segRange.start),
+ };
+ }
+ function getEventClassNames(props) {
+ let classNames = ['fc-event'];
+ if (props.isMirror) {
+ classNames.push('fc-event-mirror');
+ }
+ if (props.isDraggable) {
+ classNames.push('fc-event-draggable');
+ }
+ if (props.isStartResizable || props.isEndResizable) {
+ classNames.push('fc-event-resizable');
+ }
+ if (props.isDragging) {
+ classNames.push('fc-event-dragging');
+ }
+ if (props.isResizing) {
+ classNames.push('fc-event-resizing');
+ }
+ if (props.isSelected) {
+ classNames.push('fc-event-selected');
+ }
+ if (props.isStart) {
+ classNames.push('fc-event-start');
+ }
+ if (props.isEnd) {
+ classNames.push('fc-event-end');
+ }
+ if (props.isPast) {
+ classNames.push('fc-event-past');
+ }
+ if (props.isToday) {
+ classNames.push('fc-event-today');
+ }
+ if (props.isFuture) {
+ classNames.push('fc-event-future');
+ }
+ return classNames;
+ }
+ function buildEventRangeKey(eventRange) {
+ return eventRange.instance
+ ? eventRange.instance.instanceId
+ : `${eventRange.def.defId}:${eventRange.range.start.toISOString()}`;
+ // inverse-background events don't have specific instances. TODO: better solution
+ }
+ function getSegAnchorAttrs(seg, context) {
+ let { def, instance } = seg.eventRange;
+ let { url } = def;
+ if (url) {
+ return { href: url };
+ }
+ let { emitter, options } = context;
+ let { eventInteractive } = options;
+ if (eventInteractive == null) {
+ eventInteractive = def.interactive;
+ if (eventInteractive == null) {
+ eventInteractive = Boolean(emitter.hasHandlers('eventClick'));
+ }
+ }
+ // mock what happens in EventClicking
+ if (eventInteractive) {
+ // only attach keyboard-related handlers because click handler is already done in EventClicking
+ return createAriaKeyboardAttrs((ev) => {
+ emitter.trigger('eventClick', {
+ el: ev.target,
+ event: new EventImpl(context, def, instance),
+ jsEvent: ev,
+ view: context.viewApi,
+ });
+ });
+ }
+ return {};
+ }
+
+ const STANDARD_PROPS = {
+ start: identity,
+ end: identity,
+ allDay: Boolean,
+ };
+ function parseDateSpan(raw, dateEnv, defaultDuration) {
+ let span = parseOpenDateSpan(raw, dateEnv);
+ let { range } = span;
+ if (!range.start) {
+ return null;
+ }
+ if (!range.end) {
+ if (defaultDuration == null) {
+ return null;
+ }
+ range.end = dateEnv.add(range.start, defaultDuration);
+ }
+ return span;
+ }
+ /*
+ TODO: somehow combine with parseRange?
+ Will return null if the start/end props were present but parsed invalidly.
+ */
+ function parseOpenDateSpan(raw, dateEnv) {
+ let { refined: standardProps, extra } = refineProps(raw, STANDARD_PROPS);
+ let startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null;
+ let endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null;
+ let { allDay } = standardProps;
+ if (allDay == null) {
+ allDay = (startMeta && startMeta.isTimeUnspecified) &&
+ (!endMeta || endMeta.isTimeUnspecified);
+ }
+ return Object.assign({ range: {
+ start: startMeta ? startMeta.marker : null,
+ end: endMeta ? endMeta.marker : null,
+ }, allDay }, extra);
+ }
+ function isDateSpansEqual(span0, span1) {
+ return rangesEqual(span0.range, span1.range) &&
+ span0.allDay === span1.allDay &&
+ isSpanPropsEqual(span0, span1);
+ }
+ // the NON-DATE-RELATED props
+ function isSpanPropsEqual(span0, span1) {
+ for (let propName in span1) {
+ if (propName !== 'range' && propName !== 'allDay') {
+ if (span0[propName] !== span1[propName]) {
+ return false;
+ }
+ }
+ }
+ // are there any props that span0 has that span1 DOESN'T have?
+ // both have range/allDay, so no need to special-case.
+ for (let propName in span0) {
+ if (!(propName in span1)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ function buildDateSpanApi(span, dateEnv) {
+ return Object.assign(Object.assign({}, buildRangeApi(span.range, dateEnv, span.allDay)), { allDay: span.allDay });
+ }
+ function buildRangeApiWithTimeZone(range, dateEnv, omitTime) {
+ return Object.assign(Object.assign({}, buildRangeApi(range, dateEnv, omitTime)), { timeZone: dateEnv.timeZone });
+ }
+ function buildRangeApi(range, dateEnv, omitTime) {
+ return {
+ start: dateEnv.toDate(range.start),
+ end: dateEnv.toDate(range.end),
+ startStr: dateEnv.formatIso(range.start, { omitTime }),
+ endStr: dateEnv.formatIso(range.end, { omitTime }),
+ };
+ }
+ function fabricateEventRange(dateSpan, eventUiBases, context) {
+ let res = refineEventDef({ editable: false }, context);
+ let def = parseEventDef(res.refined, res.extra, '', // sourceId
+ dateSpan.allDay, true, // hasEnd
+ context);
+ return {
+ def,
+ ui: compileEventUi(def, eventUiBases),
+ instance: createEventInstance(def.defId, dateSpan.range),
+ range: dateSpan.range,
+ isStart: true,
+ isEnd: true,
+ };
+ }
+
+ let calendarSystemClassMap = {};
+ function registerCalendarSystem(name, theClass) {
+ calendarSystemClassMap[name] = theClass;
+ }
+ function createCalendarSystem(name) {
+ return new calendarSystemClassMap[name]();
+ }
+ class GregorianCalendarSystem {
+ getMarkerYear(d) {
+ return d.getUTCFullYear();
+ }
+ getMarkerMonth(d) {
+ return d.getUTCMonth();
+ }
+ getMarkerDay(d) {
+ return d.getUTCDate();
+ }
+ arrayToMarker(arr) {
+ return arrayToUtcDate(arr);
+ }
+ markerToArray(marker) {
+ return dateToUtcArray(marker);
+ }
+ }
+ registerCalendarSystem('gregory', GregorianCalendarSystem);
+
+ const ISO_RE = /^\s*(\d{4})(-?(\d{2})(-?(\d{2})([T ](\d{2}):?(\d{2})(:?(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/;
+ function parse(str) {
+ let m = ISO_RE.exec(str);
+ if (m) {
+ 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));
+ if (isValidDate(marker)) {
+ let timeZoneOffset = null;
+ if (m[13]) {
+ timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 +
+ Number(m[18] || 0));
+ }
+ return {
+ marker,
+ isTimeUnspecified: !m[6],
+ timeZoneOffset,
+ };
+ }
+ }
+ return null;
+ }
+
+ class DateEnv {
+ constructor(settings) {
+ let timeZone = this.timeZone = settings.timeZone;
+ let isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC';
+ if (settings.namedTimeZoneImpl && isNamedTimeZone) {
+ this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone);
+ }
+ this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl);
+ this.calendarSystem = createCalendarSystem(settings.calendarSystem);
+ this.locale = settings.locale;
+ this.weekDow = settings.locale.week.dow;
+ this.weekDoy = settings.locale.week.doy;
+ if (settings.weekNumberCalculation === 'ISO') {
+ this.weekDow = 1;
+ this.weekDoy = 4;
+ }
+ if (typeof settings.firstDay === 'number') {
+ this.weekDow = settings.firstDay;
+ }
+ if (typeof settings.weekNumberCalculation === 'function') {
+ this.weekNumberFunc = settings.weekNumberCalculation;
+ }
+ this.weekText = settings.weekText != null ? settings.weekText : settings.locale.options.weekText;
+ this.weekTextLong = (settings.weekTextLong != null ? settings.weekTextLong : settings.locale.options.weekTextLong) || this.weekText;
+ this.cmdFormatter = settings.cmdFormatter;
+ this.defaultSeparator = settings.defaultSeparator;
+ }
+ // Creating / Parsing
+ createMarker(input) {
+ let meta = this.createMarkerMeta(input);
+ if (meta === null) {
+ return null;
+ }
+ return meta.marker;
+ }
+ createNowMarker() {
+ if (this.canComputeOffset) {
+ return this.timestampToMarker(new Date().valueOf());
+ }
+ // if we can't compute the current date val for a timezone,
+ // better to give the current local date vals than UTC
+ return arrayToUtcDate(dateToLocalArray(new Date()));
+ }
+ createMarkerMeta(input) {
+ if (typeof input === 'string') {
+ return this.parse(input);
+ }
+ let marker = null;
+ if (typeof input === 'number') {
+ marker = this.timestampToMarker(input);
+ }
+ else if (input instanceof Date) {
+ input = input.valueOf();
+ if (!isNaN(input)) {
+ marker = this.timestampToMarker(input);
+ }
+ }
+ else if (Array.isArray(input)) {
+ marker = arrayToUtcDate(input);
+ }
+ if (marker === null || !isValidDate(marker)) {
+ return null;
+ }
+ return { marker, isTimeUnspecified: false, forcedTzo: null };
+ }
+ parse(s) {
+ let parts = parse(s);
+ if (parts === null) {
+ return null;
+ }
+ let { marker } = parts;
+ let forcedTzo = null;
+ if (parts.timeZoneOffset !== null) {
+ if (this.canComputeOffset) {
+ marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000);
+ }
+ else {
+ forcedTzo = parts.timeZoneOffset;
+ }
+ }
+ return { marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo };
+ }
+ // Accessors
+ getYear(marker) {
+ return this.calendarSystem.getMarkerYear(marker);
+ }
+ getMonth(marker) {
+ return this.calendarSystem.getMarkerMonth(marker);
+ }
+ // Adding / Subtracting
+ add(marker, dur) {
+ let a = this.calendarSystem.markerToArray(marker);
+ a[0] += dur.years;
+ a[1] += dur.months;
+ a[2] += dur.days;
+ a[6] += dur.milliseconds;
+ return this.calendarSystem.arrayToMarker(a);
+ }
+ subtract(marker, dur) {
+ let a = this.calendarSystem.markerToArray(marker);
+ a[0] -= dur.years;
+ a[1] -= dur.months;
+ a[2] -= dur.days;
+ a[6] -= dur.milliseconds;
+ return this.calendarSystem.arrayToMarker(a);
+ }
+ addYears(marker, n) {
+ let a = this.calendarSystem.markerToArray(marker);
+ a[0] += n;
+ return this.calendarSystem.arrayToMarker(a);
+ }
+ addMonths(marker, n) {
+ let a = this.calendarSystem.markerToArray(marker);
+ a[1] += n;
+ return this.calendarSystem.arrayToMarker(a);
+ }
+ // Diffing Whole Units
+ diffWholeYears(m0, m1) {
+ let { calendarSystem } = this;
+ if (timeAsMs(m0) === timeAsMs(m1) &&
+ calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) &&
+ calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) {
+ return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0);
+ }
+ return null;
+ }
+ diffWholeMonths(m0, m1) {
+ let { calendarSystem } = this;
+ if (timeAsMs(m0) === timeAsMs(m1) &&
+ calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) {
+ return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) +
+ (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12;
+ }
+ return null;
+ }
+ // Range / Duration
+ greatestWholeUnit(m0, m1) {
+ let n = this.diffWholeYears(m0, m1);
+ if (n !== null) {
+ return { unit: 'year', value: n };
+ }
+ n = this.diffWholeMonths(m0, m1);
+ if (n !== null) {
+ return { unit: 'month', value: n };
+ }
+ n = diffWholeWeeks(m0, m1);
+ if (n !== null) {
+ return { unit: 'week', value: n };
+ }
+ n = diffWholeDays(m0, m1);
+ if (n !== null) {
+ return { unit: 'day', value: n };
+ }
+ n = diffHours(m0, m1);
+ if (isInt(n)) {
+ return { unit: 'hour', value: n };
+ }
+ n = diffMinutes(m0, m1);
+ if (isInt(n)) {
+ return { unit: 'minute', value: n };
+ }
+ n = diffSeconds(m0, m1);
+ if (isInt(n)) {
+ return { unit: 'second', value: n };
+ }
+ return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() };
+ }
+ countDurationsBetween(m0, m1, d) {
+ // TODO: can use greatestWholeUnit
+ let diff;
+ if (d.years) {
+ diff = this.diffWholeYears(m0, m1);
+ if (diff !== null) {
+ return diff / asRoughYears(d);
+ }
+ }
+ if (d.months) {
+ diff = this.diffWholeMonths(m0, m1);
+ if (diff !== null) {
+ return diff / asRoughMonths(d);
+ }
+ }
+ if (d.days) {
+ diff = diffWholeDays(m0, m1);
+ if (diff !== null) {
+ return diff / asRoughDays(d);
+ }
+ }
+ return (m1.valueOf() - m0.valueOf()) / asRoughMs(d);
+ }
+ // Start-Of
+ // these DON'T return zoned-dates. only UTC start-of dates
+ startOf(m, unit) {
+ if (unit === 'year') {
+ return this.startOfYear(m);
+ }
+ if (unit === 'month') {
+ return this.startOfMonth(m);
+ }
+ if (unit === 'week') {
+ return this.startOfWeek(m);
+ }
+ if (unit === 'day') {
+ return startOfDay(m);
+ }
+ if (unit === 'hour') {
+ return startOfHour(m);
+ }
+ if (unit === 'minute') {
+ return startOfMinute(m);
+ }
+ if (unit === 'second') {
+ return startOfSecond(m);
+ }
+ return null;
+ }
+ startOfYear(m) {
+ return this.calendarSystem.arrayToMarker([
+ this.calendarSystem.getMarkerYear(m),
+ ]);
+ }
+ startOfMonth(m) {
+ return this.calendarSystem.arrayToMarker([
+ this.calendarSystem.getMarkerYear(m),
+ this.calendarSystem.getMarkerMonth(m),
+ ]);
+ }
+ startOfWeek(m) {
+ return this.calendarSystem.arrayToMarker([
+ this.calendarSystem.getMarkerYear(m),
+ this.calendarSystem.getMarkerMonth(m),
+ m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7),
+ ]);
+ }
+ // Week Number
+ computeWeekNumber(marker) {
+ if (this.weekNumberFunc) {
+ return this.weekNumberFunc(this.toDate(marker));
+ }
+ return weekOfYear(marker, this.weekDow, this.weekDoy);
+ }
+ // TODO: choke on timeZoneName: long
+ format(marker, formatter, dateOptions = {}) {
+ return formatter.format({
+ marker,
+ timeZoneOffset: dateOptions.forcedTzo != null ?
+ dateOptions.forcedTzo :
+ this.offsetForMarker(marker),
+ }, this);
+ }
+ formatRange(start, end, formatter, dateOptions = {}) {
+ if (dateOptions.isEndExclusive) {
+ end = addMs(end, -1);
+ }
+ return formatter.formatRange({
+ marker: start,
+ timeZoneOffset: dateOptions.forcedStartTzo != null ?
+ dateOptions.forcedStartTzo :
+ this.offsetForMarker(start),
+ }, {
+ marker: end,
+ timeZoneOffset: dateOptions.forcedEndTzo != null ?
+ dateOptions.forcedEndTzo :
+ this.offsetForMarker(end),
+ }, this, dateOptions.defaultSeparator);
+ }
+ /*
+ DUMB: the omitTime arg is dumb. if we omit the time, we want to omit the timezone offset. and if we do that,
+ might as well use buildIsoString or some other util directly
+ */
+ formatIso(marker, extraOptions = {}) {
+ let timeZoneOffset = null;
+ if (!extraOptions.omitTimeZoneOffset) {
+ if (extraOptions.forcedTzo != null) {
+ timeZoneOffset = extraOptions.forcedTzo;
+ }
+ else {
+ timeZoneOffset = this.offsetForMarker(marker);
+ }
+ }
+ return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime);
+ }
+ // TimeZone
+ timestampToMarker(ms) {
+ if (this.timeZone === 'local') {
+ return arrayToUtcDate(dateToLocalArray(new Date(ms)));
+ }
+ if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) {
+ return new Date(ms);
+ }
+ return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms));
+ }
+ offsetForMarker(m) {
+ if (this.timeZone === 'local') {
+ return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset
+ }
+ if (this.timeZone === 'UTC') {
+ return 0;
+ }
+ if (this.namedTimeZoneImpl) {
+ return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m));
+ }
+ return null;
+ }
+ // Conversion
+ toDate(m, forcedTzo) {
+ if (this.timeZone === 'local') {
+ return arrayToLocalDate(dateToUtcArray(m));
+ }
+ if (this.timeZone === 'UTC') {
+ return new Date(m.valueOf()); // make sure it's a copy
+ }
+ if (!this.namedTimeZoneImpl) {
+ return new Date(m.valueOf() - (forcedTzo || 0));
+ }
+ return new Date(m.valueOf() -
+ this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60);
+ }
+ }
+
+ class NamedTimeZoneImpl {
+ constructor(timeZoneName) {
+ this.timeZoneName = timeZoneName;
+ }
+ }
+
+ class SegHierarchy {
+ constructor() {
+ // settings
+ this.strictOrder = false;
+ this.allowReslicing = false;
+ this.maxCoord = -1; // -1 means no max
+ this.maxStackCnt = -1; // -1 means no max
+ this.levelCoords = []; // ordered
+ this.entriesByLevel = []; // parallel with levelCoords
+ this.stackCnts = {}; // TODO: use better technique!?
+ }
+ addSegs(inputs) {
+ let hiddenEntries = [];
+ for (let input of inputs) {
+ this.insertEntry(input, hiddenEntries);
+ }
+ return hiddenEntries;
+ }
+ insertEntry(entry, hiddenEntries) {
+ let insertion = this.findInsertion(entry);
+ if (this.isInsertionValid(insertion, entry)) {
+ this.insertEntryAt(entry, insertion);
+ return 1;
+ }
+ return this.handleInvalidInsertion(insertion, entry, hiddenEntries);
+ }
+ isInsertionValid(insertion, entry) {
+ return (this.maxCoord === -1 || insertion.levelCoord + entry.thickness <= this.maxCoord) &&
+ (this.maxStackCnt === -1 || insertion.stackCnt < this.maxStackCnt);
+ }
+ // returns number of new entries inserted
+ handleInvalidInsertion(insertion, entry, hiddenEntries) {
+ if (this.allowReslicing && insertion.touchingEntry) {
+ return this.splitEntry(entry, insertion.touchingEntry, hiddenEntries);
+ }
+ hiddenEntries.push(entry);
+ return 0;
+ }
+ splitEntry(entry, barrier, hiddenEntries) {
+ let partCnt = 0;
+ let splitHiddenEntries = [];
+ let entrySpan = entry.span;
+ let barrierSpan = barrier.span;
+ if (entrySpan.start < barrierSpan.start) {
+ partCnt += this.insertEntry({
+ index: entry.index,
+ thickness: entry.thickness,
+ span: { start: entrySpan.start, end: barrierSpan.start },
+ }, splitHiddenEntries);
+ }
+ if (entrySpan.end > barrierSpan.end) {
+ partCnt += this.insertEntry({
+ index: entry.index,
+ thickness: entry.thickness,
+ span: { start: barrierSpan.end, end: entrySpan.end },
+ }, splitHiddenEntries);
+ }
+ if (partCnt) {
+ hiddenEntries.push({
+ index: entry.index,
+ thickness: entry.thickness,
+ span: intersectSpans(barrierSpan, entrySpan), // guaranteed to intersect
+ }, ...splitHiddenEntries);
+ return partCnt;
+ }
+ hiddenEntries.push(entry);
+ return 0;
+ }
+ insertEntryAt(entry, insertion) {
+ let { entriesByLevel, levelCoords } = this;
+ if (insertion.lateral === -1) {
+ // create a new level
+ insertAt(levelCoords, insertion.level, insertion.levelCoord);
+ insertAt(entriesByLevel, insertion.level, [entry]);
+ }
+ else {
+ // insert into existing level
+ insertAt(entriesByLevel[insertion.level], insertion.lateral, entry);
+ }
+ this.stackCnts[buildEntryKey(entry)] = insertion.stackCnt;
+ }
+ findInsertion(newEntry) {
+ let { levelCoords, entriesByLevel, strictOrder, stackCnts } = this;
+ let levelCnt = levelCoords.length;
+ let candidateCoord = 0;
+ let touchingLevel = -1;
+ let touchingLateral = -1;
+ let touchingEntry = null;
+ let stackCnt = 0;
+ for (let trackingLevel = 0; trackingLevel < levelCnt; trackingLevel += 1) {
+ let trackingCoord = levelCoords[trackingLevel];
+ // if the current level is past the placed entry, we have found a good empty space and can stop.
+ // if strictOrder, keep finding more lateral intersections.
+ if (!strictOrder && trackingCoord >= candidateCoord + newEntry.thickness) {
+ break;
+ }
+ let trackingEntries = entriesByLevel[trackingLevel];
+ let trackingEntry;
+ let searchRes = binarySearch(trackingEntries, newEntry.span.start, getEntrySpanEnd); // find first entry after newEntry's end
+ let lateralIndex = searchRes[0] + searchRes[1]; // if exact match (which doesn't collide), go to next one
+ while ( // loop through entries that horizontally intersect
+ (trackingEntry = trackingEntries[lateralIndex]) && // but not past the whole entry list
+ trackingEntry.span.start < newEntry.span.end // and not entirely past newEntry
+ ) {
+ let trackingEntryBottom = trackingCoord + trackingEntry.thickness;
+ // intersects into the top of the candidate?
+ if (trackingEntryBottom > candidateCoord) {
+ candidateCoord = trackingEntryBottom;
+ touchingEntry = trackingEntry;
+ touchingLevel = trackingLevel;
+ touchingLateral = lateralIndex;
+ }
+ // butts up against top of candidate? (will happen if just intersected as well)
+ if (trackingEntryBottom === candidateCoord) {
+ // accumulate the highest possible stackCnt of the trackingEntries that butt up
+ stackCnt = Math.max(stackCnt, stackCnts[buildEntryKey(trackingEntry)] + 1);
+ }
+ lateralIndex += 1;
+ }
+ }
+ // the destination level will be after touchingEntry's level. find it
+ let destLevel = 0;
+ if (touchingEntry) {
+ destLevel = touchingLevel + 1;
+ while (destLevel < levelCnt && levelCoords[destLevel] < candidateCoord) {
+ destLevel += 1;
+ }
+ }
+ // if adding to an existing level, find where to insert
+ let destLateral = -1;
+ if (destLevel < levelCnt && levelCoords[destLevel] === candidateCoord) {
+ destLateral = binarySearch(entriesByLevel[destLevel], newEntry.span.end, getEntrySpanEnd)[0];
+ }
+ return {
+ touchingLevel,
+ touchingLateral,
+ touchingEntry,
+ stackCnt,
+ levelCoord: candidateCoord,
+ level: destLevel,
+ lateral: destLateral,
+ };
+ }
+ // sorted by levelCoord (lowest to highest)
+ toRects() {
+ let { entriesByLevel, levelCoords } = this;
+ let levelCnt = entriesByLevel.length;
+ let rects = [];
+ for (let level = 0; level < levelCnt; level += 1) {
+ let entries = entriesByLevel[level];
+ let levelCoord = levelCoords[level];
+ for (let entry of entries) {
+ rects.push(Object.assign(Object.assign({}, entry), { levelCoord }));
+ }
+ }
+ return rects;
+ }
+ }
+ function getEntrySpanEnd(entry) {
+ return entry.span.end;
+ }
+ function buildEntryKey(entry) {
+ return entry.index + ':' + entry.span.start;
+ }
+ // returns groups with entries sorted by input order
+ function groupIntersectingEntries(entries) {
+ let merges = [];
+ for (let entry of entries) {
+ let filteredMerges = [];
+ let hungryMerge = {
+ span: entry.span,
+ entries: [entry],
+ };
+ for (let merge of merges) {
+ if (intersectSpans(merge.span, hungryMerge.span)) {
+ hungryMerge = {
+ entries: merge.entries.concat(hungryMerge.entries),
+ span: joinSpans(merge.span, hungryMerge.span),
+ };
+ }
+ else {
+ filteredMerges.push(merge);
+ }
+ }
+ filteredMerges.push(hungryMerge);
+ merges = filteredMerges;
+ }
+ return merges;
+ }
+ function joinSpans(span0, span1) {
+ return {
+ start: Math.min(span0.start, span1.start),
+ end: Math.max(span0.end, span1.end),
+ };
+ }
+ function intersectSpans(span0, span1) {
+ let start = Math.max(span0.start, span1.start);
+ let end = Math.min(span0.end, span1.end);
+ if (start < end) {
+ return { start, end };
+ }
+ return null;
+ }
+ // general util
+ // ---------------------------------------------------------------------------------------------------------------------
+ function insertAt(arr, index, item) {
+ arr.splice(index, 0, item);
+ }
+ function binarySearch(a, searchVal, getItemVal) {
+ let startIndex = 0;
+ let endIndex = a.length; // exclusive
+ if (!endIndex || searchVal < getItemVal(a[startIndex])) { // no items OR before first item
+ return [0, 0];
+ }
+ if (searchVal > getItemVal(a[endIndex - 1])) { // after last item
+ return [endIndex, 0];
+ }
+ while (startIndex < endIndex) {
+ let middleIndex = Math.floor(startIndex + (endIndex - startIndex) / 2);
+ let middleVal = getItemVal(a[middleIndex]);
+ if (searchVal < middleVal) {
+ endIndex = middleIndex;
+ }
+ else if (searchVal > middleVal) {
+ startIndex = middleIndex + 1;
+ }
+ else { // equal!
+ return [middleIndex, 1];
+ }
+ }
+ return [startIndex, 0];
+ }
+
+ class Interaction {
+ constructor(settings) {
+ this.component = settings.component;
+ this.isHitComboAllowed = settings.isHitComboAllowed || null;
+ }
+ destroy() {
+ }
+ }
+ function parseInteractionSettings(component, input) {
+ return {
+ component,
+ el: input.el,
+ useEventCenter: input.useEventCenter != null ? input.useEventCenter : true,
+ isHitComboAllowed: input.isHitComboAllowed || null,
+ };
+ }
+ function interactionSettingsToStore(settings) {
+ return {
+ [settings.component.uid]: settings,
+ };
+ }
+ // global state
+ const interactionSettingsStore = {};
+
+ /*
+ An abstraction for a dragging interaction originating on an event.
+ Does higher-level things than PointerDragger, such as possibly:
+ - a "mirror" that moves with the pointer
+ - a minimum number of pixels or other criteria for a true drag to begin
+
+ subclasses must emit:
+ - pointerdown
+ - dragstart
+ - dragmove
+ - pointerup
+ - dragend
+ */
+ class ElementDragging {
+ constructor(el, selector) {
+ this.emitter = new Emitter();
+ }
+ destroy() {
+ }
+ setMirrorIsVisible(bool) {
+ // optional if subclass doesn't want to support a mirror
+ }
+ setMirrorNeedsRevert(bool) {
+ // optional if subclass doesn't want to support a mirror
+ }
+ setAutoScrollEnabled(bool) {
+ // optional
+ }
+ }
+
+ // TODO: get rid of this in favor of options system,
+ // tho it's really easy to access this globally rather than pass thru options.
+ const config = {};
+
+ /*
+ Information about what will happen when an external element is dragged-and-dropped
+ onto a calendar. Contains information for creating an event.
+ */
+ const DRAG_META_REFINERS = {
+ startTime: createDuration,
+ duration: createDuration,
+ create: Boolean,
+ sourceId: String,
+ };
+ function parseDragMeta(raw) {
+ let { refined, extra } = refineProps(raw, DRAG_META_REFINERS);
+ return {
+ startTime: refined.startTime || null,
+ duration: refined.duration || null,
+ create: refined.create != null ? refined.create : true,
+ sourceId: refined.sourceId,
+ leftoverProps: extra,
+ };
+ }
+
+ class CalendarRoot extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.state = {
+ forPrint: false,
+ };
+ this.handleBeforePrint = () => {
+ this.setState({ forPrint: true });
+ };
+ this.handleAfterPrint = () => {
+ this.setState({ forPrint: false });
+ };
+ }
+ render() {
+ let { props } = this;
+ let { options } = props;
+ let { forPrint } = this.state;
+ let isHeightAuto = forPrint || options.height === 'auto' || options.contentHeight === 'auto';
+ let height = (!isHeightAuto && options.height != null) ? options.height : '';
+ let classNames = [
+ 'fc',
+ forPrint ? 'fc-media-print' : 'fc-media-screen',
+ `fc-direction-${options.direction}`,
+ props.theme.getClass('root'),
+ ];
+ if (!getCanVGrowWithinCell()) {
+ classNames.push('fc-liquid-hack');
+ }
+ return props.children(classNames, height, isHeightAuto, forPrint);
+ }
+ componentDidMount() {
+ let { emitter } = this.props;
+ emitter.on('_beforeprint', this.handleBeforePrint);
+ emitter.on('_afterprint', this.handleAfterPrint);
+ }
+ componentWillUnmount() {
+ let { emitter } = this.props;
+ emitter.off('_beforeprint', this.handleBeforePrint);
+ emitter.off('_afterprint', this.handleAfterPrint);
+ }
+ }
+
+ // Computes a default column header formatting string if `colFormat` is not explicitly defined
+ function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
+ // if more than one week row, or if there are a lot of columns with not much space,
+ // put just the day numbers will be in each cell
+ if (!datesRepDistinctDays || dayCnt > 10) {
+ return createFormatter({ weekday: 'short' }); // "Sat"
+ }
+ if (dayCnt > 1) {
+ return createFormatter({ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }); // "Sat 11/12"
+ }
+ return createFormatter({ weekday: 'long' }); // "Saturday"
+ }
+
+ const CLASS_NAME = 'fc-col-header-cell'; // do the cushion too? no
+ function renderInner$1(renderProps) {
+ return renderProps.text;
+ }
+
+ class ContentInjector extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.id = guid();
+ this.currentDomNodes = [];
+ this.queuedDomNodes = [];
+ this.handleEl = (el) => {
+ if (this.props.elRef) {
+ setRef(this.props.elRef, el);
+ }
+ };
+ }
+ render() {
+ const { props, context } = this;
+ const { options } = context;
+ const { generator, renderProps } = props;
+ const attrs = buildElAttrs(props);
+ let innerContent;
+ let queuedDomNodes = [];
+ if (hasCustomRenderingHandler(props.generatorName, options)) {
+ if (options.customRenderingReplacesEl) {
+ delete attrs.elRef; // because handleEl will be used
+ }
+ }
+ else {
+ const customContent = typeof generator === 'function' ?
+ generator(renderProps, h) :
+ generator;
+ if (typeof customContent === 'string' ||
+ i$1(customContent) ||
+ Array.isArray(customContent)) {
+ innerContent = customContent;
+ }
+ else if (typeof customContent === 'object') {
+ if ('html' in customContent) {
+ attrs.dangerouslySetInnerHTML = { __html: customContent.html };
+ }
+ else if ('domNodes' in customContent) {
+ queuedDomNodes = Array.prototype.slice.call(customContent.domNodes);
+ }
+ }
+ }
+ this.queuedDomNodes = queuedDomNodes;
+ return h(props.elTag, attrs, innerContent);
+ }
+ componentDidMount() {
+ this.applyQueueudDomNodes();
+ this.triggerCustomRendering(true);
+ }
+ componentDidUpdate() {
+ this.applyQueueudDomNodes();
+ this.triggerCustomRendering(true);
+ }
+ componentWillUnmount() {
+ this.triggerCustomRendering(false); // TODO: different API for removal?
+ }
+ triggerCustomRendering(isActive) {
+ const { props, context } = this;
+ const { handleCustomRendering, customRenderingMetaMap } = context.options;
+ if (handleCustomRendering) {
+ const customRenderingMeta = customRenderingMetaMap === null || customRenderingMetaMap === void 0 ? void 0 : customRenderingMetaMap[props.generatorName];
+ if (customRenderingMeta) {
+ handleCustomRendering(Object.assign({ id: this.id, isActive, containerEl: this.base, reportNewContainerEl: this.handleEl, generatorMeta: customRenderingMeta }, props));
+ }
+ }
+ }
+ applyQueueudDomNodes() {
+ const { queuedDomNodes, currentDomNodes } = this;
+ const el = this.base;
+ if (!isArraysEqual(queuedDomNodes, currentDomNodes)) {
+ currentDomNodes.forEach(removeElement);
+ for (let newNode of queuedDomNodes) {
+ el.appendChild(newNode);
+ }
+ this.currentDomNodes = queuedDomNodes;
+ }
+ }
+ }
+ ContentInjector.addPropsEquality({
+ elClasses: isArraysEqual,
+ elStyle: isPropsEqual,
+ elAttrs: isNonHandlerPropsEqual,
+ renderProps: isPropsEqual,
+ });
+ // Util
+ function hasCustomRenderingHandler(generatorName, options) {
+ var _a;
+ return Boolean(options.handleCustomRendering &&
+ generatorName &&
+ ((_a = options.customRenderingMetaMap) === null || _a === void 0 ? void 0 : _a[generatorName]));
+ }
+ function buildElAttrs(props, extraClassNames) {
+ const attrs = Object.assign(Object.assign({}, props.elAttrs), { ref: props.elRef });
+ if (props.elClasses || extraClassNames) {
+ attrs.className = (props.elClasses || [])
+ .concat(extraClassNames || [])
+ .concat(attrs.className || [])
+ .filter(Boolean)
+ .join(' ');
+ }
+ if (props.elStyle) {
+ attrs.style = props.elStyle;
+ }
+ return attrs;
+ }
+
+ const RenderId = createContext(0);
+
+ class ContentContainer extends d {
+ constructor() {
+ super(...arguments);
+ this.InnerContent = InnerContentInjector.bind(undefined, this);
+ }
+ render() {
+ const { props } = this;
+ const generatedClassNames = generateClassNames(props.classNameGenerator, props.renderProps);
+ if (props.children) {
+ const elAttrs = buildElAttrs(props, generatedClassNames);
+ const children = props.children(this.InnerContent, props.renderProps, elAttrs);
+ if (props.elTag) {
+ return h(props.elTag, elAttrs, children);
+ }
+ else {
+ return children;
+ }
+ }
+ else {
+ return h((ContentInjector), Object.assign(Object.assign({}, props), { elTag: props.elTag || 'div', elClasses: (props.elClasses || []).concat(generatedClassNames), renderId: this.context }));
+ }
+ }
+ componentDidMount() {
+ var _a, _b;
+ (_b = (_a = this.props).didMount) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.props.renderProps), { el: this.base }));
+ }
+ componentWillUnmount() {
+ var _a, _b;
+ (_b = (_a = this.props).willUnmount) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.props.renderProps), { el: this.base }));
+ }
+ }
+ ContentContainer.contextType = RenderId;
+ function InnerContentInjector(containerComponent, props) {
+ const parentProps = containerComponent.props;
+ return h((ContentInjector), Object.assign({ renderProps: parentProps.renderProps, generatorName: parentProps.generatorName, generator: parentProps.generator, renderId: containerComponent.context }, props));
+ }
+ // Utils
+ function generateClassNames(classNameGenerator, renderProps) {
+ const classNames = typeof classNameGenerator === 'function' ?
+ classNameGenerator(renderProps) :
+ classNameGenerator || [];
+ return typeof classNames === 'string' ? [classNames] : classNames;
+ }
+
+ // BAD name for this class now. used in the Header
+ class TableDateCell extends BaseComponent {
+ render() {
+ let { dateEnv, options, theme, viewApi } = this.context;
+ let { props } = this;
+ let { date, dateProfile } = props;
+ let dayMeta = getDateMeta(date, props.todayRange, null, dateProfile);
+ let classNames = [CLASS_NAME].concat(getDayClassNames(dayMeta, theme));
+ let text = dateEnv.format(date, props.dayHeaderFormat);
+ // if colCnt is 1, we are already in a day-view and don't need a navlink
+ let navLinkAttrs = (!dayMeta.isDisabled && props.colCnt > 1)
+ ? buildNavLinkAttrs(this.context, date)
+ : {};
+ let renderProps = Object.assign(Object.assign(Object.assign({ date: dateEnv.toDate(date), view: viewApi }, props.extraRenderProps), { text }), dayMeta);
+ return (h(ContentContainer, { elTag: "th", elClasses: classNames, elAttrs: Object.assign({ role: 'columnheader', colSpan: props.colSpan, 'data-date': !dayMeta.isDisabled ? formatDayString(date) : undefined }, props.extraDataAttrs), renderProps: renderProps, generatorName: "dayHeaderContent", generator: options.dayHeaderContent || renderInner$1, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContainer) => (h("div", { className: "fc-scrollgrid-sync-inner" }, !dayMeta.isDisabled && (h(InnerContainer, { elTag: "a", elAttrs: navLinkAttrs, elClasses: [
+ 'fc-col-header-cell-cushion',
+ props.isSticky && 'fc-sticky',
+ ] }))))));
+ }
+ }
+
+ const WEEKDAY_FORMAT = createFormatter({ weekday: 'long' });
+ class TableDowCell extends BaseComponent {
+ render() {
+ let { props } = this;
+ let { dateEnv, theme, viewApi, options } = this.context;
+ let date = addDays(new Date(259200000), props.dow); // start with Sun, 04 Jan 1970 00:00:00 GMT
+ let dateMeta = {
+ dow: props.dow,
+ isDisabled: false,
+ isFuture: false,
+ isPast: false,
+ isToday: false,
+ isOther: false,
+ };
+ let text = dateEnv.format(date, props.dayHeaderFormat);
+ let renderProps = Object.assign(Object.assign(Object.assign(Object.assign({ // TODO: make this public?
+ date }, dateMeta), { view: viewApi }), props.extraRenderProps), { text });
+ return (h(ContentContainer, { elTag: "th", elClasses: [
+ CLASS_NAME,
+ ...getDayClassNames(dateMeta, theme),
+ ...(props.extraClassNames || []),
+ ], elAttrs: Object.assign({ role: 'columnheader', colSpan: props.colSpan }, props.extraDataAttrs), renderProps: renderProps, generatorName: "dayHeaderContent", generator: options.dayHeaderContent || renderInner$1, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => (h("div", { className: "fc-scrollgrid-sync-inner" },
+ h(InnerContent, { elTag: "a", elClasses: [
+ 'fc-col-header-cell-cushion',
+ props.isSticky && 'fc-sticky',
+ ], elAttrs: {
+ 'aria-label': dateEnv.format(date, WEEKDAY_FORMAT),
+ } })))));
+ }
+ }
+
+ class NowTimer extends d {
+ constructor(props, context) {
+ super(props, context);
+ this.initialNowDate = getNow(context.options.now, context.dateEnv);
+ this.initialNowQueriedMs = new Date().valueOf();
+ this.state = this.computeTiming().currentState;
+ }
+ render() {
+ let { props, state } = this;
+ return props.children(state.nowDate, state.todayRange);
+ }
+ componentDidMount() {
+ this.setTimeout();
+ }
+ componentDidUpdate(prevProps) {
+ if (prevProps.unit !== this.props.unit) {
+ this.clearTimeout();
+ this.setTimeout();
+ }
+ }
+ componentWillUnmount() {
+ this.clearTimeout();
+ }
+ computeTiming() {
+ let { props, context } = this;
+ let unroundedNow = addMs(this.initialNowDate, new Date().valueOf() - this.initialNowQueriedMs);
+ let currentUnitStart = context.dateEnv.startOf(unroundedNow, props.unit);
+ let nextUnitStart = context.dateEnv.add(currentUnitStart, createDuration(1, props.unit));
+ let waitMs = nextUnitStart.valueOf() - unroundedNow.valueOf();
+ // there is a max setTimeout ms value (https://stackoverflow.com/a/3468650/96342)
+ // ensure no longer than a day
+ waitMs = Math.min(1000 * 60 * 60 * 24, waitMs);
+ return {
+ currentState: { nowDate: currentUnitStart, todayRange: buildDayRange(currentUnitStart) },
+ nextState: { nowDate: nextUnitStart, todayRange: buildDayRange(nextUnitStart) },
+ waitMs,
+ };
+ }
+ setTimeout() {
+ let { nextState, waitMs } = this.computeTiming();
+ this.timeoutId = setTimeout(() => {
+ this.setState(nextState, () => {
+ this.setTimeout();
+ });
+ }, waitMs);
+ }
+ clearTimeout() {
+ if (this.timeoutId) {
+ clearTimeout(this.timeoutId);
+ }
+ }
+ }
+ NowTimer.contextType = ViewContextType;
+ function buildDayRange(date) {
+ let start = startOfDay(date);
+ let end = addDays(start, 1);
+ return { start, end };
+ }
+
+ class DayHeader extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.createDayHeaderFormatter = memoize(createDayHeaderFormatter);
+ }
+ render() {
+ let { context } = this;
+ let { dates, dateProfile, datesRepDistinctDays, renderIntro } = this.props;
+ let dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dates.length);
+ return (h(NowTimer, { unit: "day" }, (nowDate, todayRange) => (h("tr", { role: "row" },
+ renderIntro && renderIntro('day'),
+ dates.map((date) => (datesRepDistinctDays ? (h(TableDateCell, { key: date.toISOString(), date: date, dateProfile: dateProfile, todayRange: todayRange, colCnt: dates.length, dayHeaderFormat: dayHeaderFormat })) : (h(TableDowCell, { key: date.getUTCDay(), dow: date.getUTCDay(), dayHeaderFormat: dayHeaderFormat }))))))));
+ }
+ }
+ function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) {
+ return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt);
+ }
+
+ class DaySeriesModel {
+ constructor(range, dateProfileGenerator) {
+ let date = range.start;
+ let { end } = range;
+ let indices = [];
+ let dates = [];
+ let dayIndex = -1;
+ while (date < end) { // loop each day from start to end
+ if (dateProfileGenerator.isHiddenDay(date)) {
+ indices.push(dayIndex + 0.5); // mark that it's between indices
+ }
+ else {
+ dayIndex += 1;
+ indices.push(dayIndex);
+ dates.push(date);
+ }
+ date = addDays(date, 1);
+ }
+ this.dates = dates;
+ this.indices = indices;
+ this.cnt = dates.length;
+ }
+ sliceRange(range) {
+ let firstIndex = this.getDateDayIndex(range.start); // inclusive first index
+ let lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index
+ let clippedFirstIndex = Math.max(0, firstIndex);
+ let clippedLastIndex = Math.min(this.cnt - 1, lastIndex);
+ // deal with in-between indices
+ clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell
+ clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell
+ if (clippedFirstIndex <= clippedLastIndex) {
+ return {
+ firstIndex: clippedFirstIndex,
+ lastIndex: clippedLastIndex,
+ isStart: firstIndex === clippedFirstIndex,
+ isEnd: lastIndex === clippedLastIndex,
+ };
+ }
+ return null;
+ }
+ // Given a date, returns its chronolocial cell-index from the first cell of the grid.
+ // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.
+ // If before the first offset, returns a negative number.
+ // If after the last offset, returns an offset past the last cell offset.
+ // Only works for *start* dates of cells. Will not work for exclusive end dates for cells.
+ getDateDayIndex(date) {
+ let { indices } = this;
+ let dayOffset = Math.floor(diffDays(this.dates[0], date));
+ if (dayOffset < 0) {
+ return indices[0] - 1;
+ }
+ if (dayOffset >= indices.length) {
+ return indices[indices.length - 1] + 1;
+ }
+ return indices[dayOffset];
+ }
+ }
+
+ class DayTableModel {
+ constructor(daySeries, breakOnWeeks) {
+ let { dates } = daySeries;
+ let daysPerRow;
+ let firstDay;
+ let rowCnt;
+ if (breakOnWeeks) {
+ // count columns until the day-of-week repeats
+ firstDay = dates[0].getUTCDay();
+ for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow += 1) {
+ if (dates[daysPerRow].getUTCDay() === firstDay) {
+ break;
+ }
+ }
+ rowCnt = Math.ceil(dates.length / daysPerRow);
+ }
+ else {
+ rowCnt = 1;
+ daysPerRow = dates.length;
+ }
+ this.rowCnt = rowCnt;
+ this.colCnt = daysPerRow;
+ this.daySeries = daySeries;
+ this.cells = this.buildCells();
+ this.headerDates = this.buildHeaderDates();
+ }
+ buildCells() {
+ let rows = [];
+ for (let row = 0; row < this.rowCnt; row += 1) {
+ let cells = [];
+ for (let col = 0; col < this.colCnt; col += 1) {
+ cells.push(this.buildCell(row, col));
+ }
+ rows.push(cells);
+ }
+ return rows;
+ }
+ buildCell(row, col) {
+ let date = this.daySeries.dates[row * this.colCnt + col];
+ return {
+ key: date.toISOString(),
+ date,
+ };
+ }
+ buildHeaderDates() {
+ let dates = [];
+ for (let col = 0; col < this.colCnt; col += 1) {
+ dates.push(this.cells[0][col].date);
+ }
+ return dates;
+ }
+ sliceRange(range) {
+ let { colCnt } = this;
+ let seriesSeg = this.daySeries.sliceRange(range);
+ let segs = [];
+ if (seriesSeg) {
+ let { firstIndex, lastIndex } = seriesSeg;
+ let index = firstIndex;
+ while (index <= lastIndex) {
+ let row = Math.floor(index / colCnt);
+ let nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1);
+ segs.push({
+ row,
+ firstCol: index % colCnt,
+ lastCol: (nextIndex - 1) % colCnt,
+ isStart: seriesSeg.isStart && index === firstIndex,
+ isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex,
+ });
+ index = nextIndex;
+ }
+ }
+ return segs;
+ }
+ }
+
+ class Slicer {
+ constructor() {
+ this.sliceBusinessHours = memoize(this._sliceBusinessHours);
+ this.sliceDateSelection = memoize(this._sliceDateSpan);
+ this.sliceEventStore = memoize(this._sliceEventStore);
+ this.sliceEventDrag = memoize(this._sliceInteraction);
+ this.sliceEventResize = memoize(this._sliceInteraction);
+ this.forceDayIfListItem = false; // hack
+ }
+ sliceProps(props, dateProfile, nextDayThreshold, context, ...extraArgs) {
+ let { eventUiBases } = props;
+ let eventSegs = this.sliceEventStore(props.eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs);
+ return {
+ dateSelectionSegs: this.sliceDateSelection(props.dateSelection, eventUiBases, context, ...extraArgs),
+ businessHourSegs: this.sliceBusinessHours(props.businessHours, dateProfile, nextDayThreshold, context, ...extraArgs),
+ fgEventSegs: eventSegs.fg,
+ bgEventSegs: eventSegs.bg,
+ eventDrag: this.sliceEventDrag(props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs),
+ eventResize: this.sliceEventResize(props.eventResize, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs),
+ eventSelection: props.eventSelection,
+ }; // TODO: give interactionSegs?
+ }
+ sliceNowDate(// does not memoize
+ date, context, ...extraArgs) {
+ return this._sliceDateSpan({ range: { start: date, end: addMs(date, 1) }, allDay: false }, // add 1 ms, protect against null range
+ {}, context, ...extraArgs);
+ }
+ _sliceBusinessHours(businessHours, dateProfile, nextDayThreshold, context, ...extraArgs) {
+ if (!businessHours) {
+ return [];
+ }
+ return this._sliceEventStore(expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), context), {}, dateProfile, nextDayThreshold, ...extraArgs).bg;
+ }
+ _sliceEventStore(eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs) {
+ if (eventStore) {
+ let rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
+ return {
+ bg: this.sliceEventRanges(rangeRes.bg, extraArgs),
+ fg: this.sliceEventRanges(rangeRes.fg, extraArgs),
+ };
+ }
+ return { bg: [], fg: [] };
+ }
+ _sliceInteraction(interaction, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs) {
+ if (!interaction) {
+ return null;
+ }
+ let rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
+ return {
+ segs: this.sliceEventRanges(rangeRes.fg, extraArgs),
+ affectedInstances: interaction.affectedEvents.instances,
+ isEvent: interaction.isEvent,
+ };
+ }
+ _sliceDateSpan(dateSpan, eventUiBases, context, ...extraArgs) {
+ if (!dateSpan) {
+ return [];
+ }
+ let eventRange = fabricateEventRange(dateSpan, eventUiBases, context);
+ let segs = this.sliceRange(dateSpan.range, ...extraArgs);
+ for (let seg of segs) {
+ seg.eventRange = eventRange;
+ }
+ return segs;
+ }
+ /*
+ "complete" seg means it has component and eventRange
+ */
+ sliceEventRanges(eventRanges, extraArgs) {
+ let segs = [];
+ for (let eventRange of eventRanges) {
+ segs.push(...this.sliceEventRange(eventRange, extraArgs));
+ }
+ return segs;
+ }
+ /*
+ "complete" seg means it has component and eventRange
+ */
+ sliceEventRange(eventRange, extraArgs) {
+ let dateRange = eventRange.range;
+ // hack to make multi-day events that are being force-displayed as list-items to take up only one day
+ if (this.forceDayIfListItem && eventRange.ui.display === 'list-item') {
+ dateRange = {
+ start: dateRange.start,
+ end: addDays(dateRange.start, 1),
+ };
+ }
+ let segs = this.sliceRange(dateRange, ...extraArgs);
+ for (let seg of segs) {
+ seg.eventRange = eventRange;
+ seg.isStart = eventRange.isStart && seg.isStart;
+ seg.isEnd = eventRange.isEnd && seg.isEnd;
+ }
+ return segs;
+ }
+ }
+ /*
+ for incorporating slotMinTime/slotMaxTime if appropriate
+ TODO: should be part of DateProfile!
+ TimelineDateProfile already does this btw
+ */
+ function computeActiveRange(dateProfile, isComponentAllDay) {
+ let range = dateProfile.activeRange;
+ if (isComponentAllDay) {
+ return range;
+ }
+ return {
+ start: addMs(range.start, dateProfile.slotMinTime.milliseconds),
+ end: addMs(range.end, dateProfile.slotMaxTime.milliseconds - 864e5), // 864e5 = ms in a day
+ };
+ }
+
+ function reduceEventStore(eventStore, action, eventSources, dateProfile, context) {
+ switch (action.type) {
+ case 'RECEIVE_EVENTS': // raw
+ return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, context);
+ case 'ADD_EVENTS': // already parsed, but not expanded
+ return addEvent(eventStore, action.eventStore, // new ones
+ dateProfile ? dateProfile.activeRange : null, context);
+ case 'RESET_EVENTS':
+ return action.eventStore;
+ case 'MERGE_EVENTS': // already parsed and expanded
+ return mergeEventStores(eventStore, action.eventStore);
+ case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
+ case 'NEXT':
+ case 'CHANGE_DATE':
+ case 'CHANGE_VIEW_TYPE':
+ if (dateProfile) {
+ return expandRecurring(eventStore, dateProfile.activeRange, context);
+ }
+ return eventStore;
+ case 'REMOVE_EVENTS':
+ return excludeSubEventStore(eventStore, action.eventStore);
+ case 'REMOVE_EVENT_SOURCE':
+ return excludeEventsBySourceId(eventStore, action.sourceId);
+ case 'REMOVE_ALL_EVENT_SOURCES':
+ return filterEventStoreDefs(eventStore, (eventDef) => (!eventDef.sourceId // only keep events with no source id
+ ));
+ case 'REMOVE_ALL_EVENTS':
+ return createEmptyEventStore();
+ default:
+ return eventStore;
+ }
+ }
+ function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, context) {
+ if (eventSource && // not already removed
+ fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources
+ ) {
+ let subset = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context);
+ if (fetchRange) {
+ subset = expandRecurring(subset, fetchRange, context);
+ }
+ return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset);
+ }
+ return eventStore;
+ }
+ function transformRawEvents(rawEvents, eventSource, context) {
+ let calEachTransform = context.options.eventDataTransform;
+ let sourceEachTransform = eventSource ? eventSource.eventDataTransform : null;
+ if (sourceEachTransform) {
+ rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform);
+ }
+ if (calEachTransform) {
+ rawEvents = transformEachRawEvent(rawEvents, calEachTransform);
+ }
+ return rawEvents;
+ }
+ function transformEachRawEvent(rawEvents, func) {
+ let refinedEvents;
+ if (!func) {
+ refinedEvents = rawEvents;
+ }
+ else {
+ refinedEvents = [];
+ for (let rawEvent of rawEvents) {
+ let refinedEvent = func(rawEvent);
+ if (refinedEvent) {
+ refinedEvents.push(refinedEvent);
+ }
+ else if (refinedEvent == null) {
+ refinedEvents.push(rawEvent);
+ } // if a different falsy value, do nothing
+ }
+ }
+ return refinedEvents;
+ }
+ function addEvent(eventStore, subset, expandRange, context) {
+ if (expandRange) {
+ subset = expandRecurring(subset, expandRange, context);
+ }
+ return mergeEventStores(eventStore, subset);
+ }
+ function rezoneEventStoreDates(eventStore, oldDateEnv, newDateEnv) {
+ let { defs } = eventStore;
+ let instances = mapHash(eventStore.instances, (instance) => {
+ let def = defs[instance.defId];
+ if (def.allDay || def.recurringDef) {
+ return instance; // isn't dependent on timezone
+ }
+ return Object.assign(Object.assign({}, instance), { range: {
+ start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)),
+ end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo)),
+ }, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo });
+ });
+ return { defs, instances };
+ }
+ function excludeEventsBySourceId(eventStore, sourceId) {
+ return filterEventStoreDefs(eventStore, (eventDef) => eventDef.sourceId !== sourceId);
+ }
+ // QUESTION: why not just return instances? do a general object-property-exclusion util
+ function excludeInstances(eventStore, removals) {
+ return {
+ defs: eventStore.defs,
+ instances: filterHash(eventStore.instances, (instance) => !removals[instance.instanceId]),
+ };
+ }
+
+ // high-level segmenting-aware tester functions
+ // ------------------------------------------------------------------------------------------------------------------------
+ function isInteractionValid(interaction, dateProfile, context) {
+ let { instances } = interaction.mutatedEvents;
+ for (let instanceId in instances) {
+ if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) {
+ return false;
+ }
+ }
+ return isNewPropsValid({ eventDrag: interaction }, context); // HACK: the eventDrag props is used for ALL interactions
+ }
+ function isDateSelectionValid(dateSelection, dateProfile, context) {
+ if (!rangeContainsRange(dateProfile.validRange, dateSelection.range)) {
+ return false;
+ }
+ return isNewPropsValid({ dateSelection }, context);
+ }
+ function isNewPropsValid(newProps, context) {
+ let calendarState = context.getCurrentData();
+ let props = Object.assign({ businessHours: calendarState.businessHours, dateSelection: '', eventStore: calendarState.eventStore, eventUiBases: calendarState.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps);
+ return (context.pluginHooks.isPropsValid || isPropsValid)(props, context);
+ }
+ function isPropsValid(state, context, dateSpanMeta = {}, filterConfig) {
+ if (state.eventDrag && !isInteractionPropsValid(state, context, dateSpanMeta, filterConfig)) {
+ return false;
+ }
+ if (state.dateSelection && !isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig)) {
+ return false;
+ }
+ return true;
+ }
+ // Moving Event Validation
+ // ------------------------------------------------------------------------------------------------------------------------
+ function isInteractionPropsValid(state, context, dateSpanMeta, filterConfig) {
+ let currentState = context.getCurrentData();
+ let interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions
+ let subjectEventStore = interaction.mutatedEvents;
+ let subjectDefs = subjectEventStore.defs;
+ let subjectInstances = subjectEventStore.instances;
+ let subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ?
+ state.eventUiBases :
+ { '': currentState.selectionConfig });
+ if (filterConfig) {
+ subjectConfigs = mapHash(subjectConfigs, filterConfig);
+ }
+ // exclude the subject events. TODO: exclude defs too?
+ let otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances);
+ let otherDefs = otherEventStore.defs;
+ let otherInstances = otherEventStore.instances;
+ let otherConfigs = compileEventUis(otherDefs, state.eventUiBases);
+ for (let subjectInstanceId in subjectInstances) {
+ let subjectInstance = subjectInstances[subjectInstanceId];
+ let subjectRange = subjectInstance.range;
+ let subjectConfig = subjectConfigs[subjectInstance.defId];
+ let subjectDef = subjectDefs[subjectInstance.defId];
+ // constraint
+ if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, context)) {
+ return false;
+ }
+ // overlap
+ let { eventOverlap } = context.options;
+ let eventOverlapFunc = typeof eventOverlap === 'function' ? eventOverlap : null;
+ for (let otherInstanceId in otherInstances) {
+ let otherInstance = otherInstances[otherInstanceId];
+ // intersect! evaluate
+ if (rangesIntersect(subjectRange, otherInstance.range)) {
+ let otherOverlap = otherConfigs[otherInstance.defId].overlap;
+ // consider the other event's overlap. only do this if the subject event is a "real" event
+ if (otherOverlap === false && interaction.isEvent) {
+ return false;
+ }
+ if (subjectConfig.overlap === false) {
+ return false;
+ }
+ if (eventOverlapFunc && !eventOverlapFunc(new EventImpl(context, otherDefs[otherInstance.defId], otherInstance), // still event
+ new EventImpl(context, subjectDef, subjectInstance))) {
+ return false;
+ }
+ }
+ }
+ // allow (a function)
+ let calendarEventStore = currentState.eventStore; // need global-to-calendar, not local to component (splittable)state
+ for (let subjectAllow of subjectConfig.allows) {
+ let subjectDateSpan = Object.assign(Object.assign({}, dateSpanMeta), { range: subjectInstance.range, allDay: subjectDef.allDay });
+ let origDef = calendarEventStore.defs[subjectDef.defId];
+ let origInstance = calendarEventStore.instances[subjectInstanceId];
+ let eventApi;
+ if (origDef) { // was previously in the calendar
+ eventApi = new EventImpl(context, origDef, origInstance);
+ }
+ else { // was an external event
+ eventApi = new EventImpl(context, subjectDef); // no instance, because had no dates
+ }
+ if (!subjectAllow(buildDateSpanApiWithContext(subjectDateSpan, context), eventApi)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ // Date Selection Validation
+ // ------------------------------------------------------------------------------------------------------------------------
+ function isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig) {
+ let relevantEventStore = state.eventStore;
+ let relevantDefs = relevantEventStore.defs;
+ let relevantInstances = relevantEventStore.instances;
+ let selection = state.dateSelection;
+ let selectionRange = selection.range;
+ let { selectionConfig } = context.getCurrentData();
+ if (filterConfig) {
+ selectionConfig = filterConfig(selectionConfig);
+ }
+ // constraint
+ if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, context)) {
+ return false;
+ }
+ // overlap
+ let { selectOverlap } = context.options;
+ let selectOverlapFunc = typeof selectOverlap === 'function' ? selectOverlap : null;
+ for (let relevantInstanceId in relevantInstances) {
+ let relevantInstance = relevantInstances[relevantInstanceId];
+ // intersect! evaluate
+ if (rangesIntersect(selectionRange, relevantInstance.range)) {
+ if (selectionConfig.overlap === false) {
+ return false;
+ }
+ if (selectOverlapFunc && !selectOverlapFunc(new EventImpl(context, relevantDefs[relevantInstance.defId], relevantInstance), null)) {
+ return false;
+ }
+ }
+ }
+ // allow (a function)
+ for (let selectionAllow of selectionConfig.allows) {
+ let fullDateSpan = Object.assign(Object.assign({}, dateSpanMeta), selection);
+ if (!selectionAllow(buildDateSpanApiWithContext(fullDateSpan, context), null)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ // Constraint Utils
+ // ------------------------------------------------------------------------------------------------------------------------
+ function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, context) {
+ for (let constraint of constraints) {
+ if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, context), subjectRange)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours
+ otherEventStore, // for if constraint is an even group ID
+ businessHoursUnexpanded, // for if constraint is 'businessHours'
+ context) {
+ if (constraint === 'businessHours') {
+ return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, context));
+ }
+ if (typeof constraint === 'string') { // an group ID
+ return eventStoreToRanges(filterEventStoreDefs(otherEventStore, (eventDef) => eventDef.groupId === constraint));
+ }
+ if (typeof constraint === 'object' && constraint) { // non-null object
+ return eventStoreToRanges(expandRecurring(constraint, subjectRange, context));
+ }
+ return []; // if it's false
+ }
+ // TODO: move to event-store file?
+ function eventStoreToRanges(eventStore) {
+ let { instances } = eventStore;
+ let ranges = [];
+ for (let instanceId in instances) {
+ ranges.push(instances[instanceId].range);
+ }
+ return ranges;
+ }
+ // TODO: move to geom file?
+ function anyRangesContainRange(outerRanges, innerRange) {
+ for (let outerRange of outerRanges) {
+ if (rangeContainsRange(outerRange, innerRange)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ class JsonRequestError extends Error {
+ constructor(message, response) {
+ super(message);
+ this.response = response;
+ }
+ }
+ function requestJson(method, url, params) {
+ method = method.toUpperCase();
+ const fetchOptions = {
+ method,
+ };
+ if (method === 'GET') {
+ url += (url.indexOf('?') === -1 ? '?' : '&') +
+ new URLSearchParams(params);
+ }
+ else {
+ fetchOptions.body = new URLSearchParams(params);
+ fetchOptions.headers = {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ };
+ }
+ return fetch(url, fetchOptions).then((fetchRes) => {
+ if (fetchRes.ok) {
+ return fetchRes.json().then((parsedResponse) => {
+ return [parsedResponse, fetchRes];
+ }, () => {
+ throw new JsonRequestError('Failure parsing JSON', fetchRes);
+ });
+ }
+ else {
+ throw new JsonRequestError('Request failed', fetchRes);
+ }
+ });
+ }
+
+ class DelayedRunner {
+ constructor(drainedOption) {
+ this.drainedOption = drainedOption;
+ this.isRunning = false;
+ this.isDirty = false;
+ this.pauseDepths = {};
+ this.timeoutId = 0;
+ }
+ request(delay) {
+ this.isDirty = true;
+ if (!this.isPaused()) {
+ this.clearTimeout();
+ if (delay == null) {
+ this.tryDrain();
+ }
+ else {
+ this.timeoutId = setTimeout(// NOT OPTIMAL! TODO: look at debounce
+ this.tryDrain.bind(this), delay);
+ }
+ }
+ }
+ pause(scope = '') {
+ let { pauseDepths } = this;
+ pauseDepths[scope] = (pauseDepths[scope] || 0) + 1;
+ this.clearTimeout();
+ }
+ resume(scope = '', force) {
+ let { pauseDepths } = this;
+ if (scope in pauseDepths) {
+ if (force) {
+ delete pauseDepths[scope];
+ }
+ else {
+ pauseDepths[scope] -= 1;
+ let depth = pauseDepths[scope];
+ if (depth <= 0) {
+ delete pauseDepths[scope];
+ }
+ }
+ this.tryDrain();
+ }
+ }
+ isPaused() {
+ return Object.keys(this.pauseDepths).length;
+ }
+ tryDrain() {
+ if (!this.isRunning && !this.isPaused()) {
+ this.isRunning = true;
+ while (this.isDirty) {
+ this.isDirty = false;
+ this.drained(); // might set isDirty to true again
+ }
+ this.isRunning = false;
+ }
+ }
+ clear() {
+ this.clearTimeout();
+ this.isDirty = false;
+ this.pauseDepths = {};
+ }
+ clearTimeout() {
+ if (this.timeoutId) {
+ clearTimeout(this.timeoutId);
+ this.timeoutId = 0;
+ }
+ }
+ drained() {
+ if (this.drainedOption) {
+ this.drainedOption();
+ }
+ }
+ }
+
+ const VISIBLE_HIDDEN_RE = /^(visible|hidden)$/;
+ class Scroller extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.handleEl = (el) => {
+ this.el = el;
+ setRef(this.props.elRef, el);
+ };
+ }
+ render() {
+ let { props } = this;
+ let { liquid, liquidIsAbsolute } = props;
+ let isAbsolute = liquid && liquidIsAbsolute;
+ let className = ['fc-scroller'];
+ if (liquid) {
+ if (liquidIsAbsolute) {
+ className.push('fc-scroller-liquid-absolute');
+ }
+ else {
+ className.push('fc-scroller-liquid');
+ }
+ }
+ return (h("div", { ref: this.handleEl, className: className.join(' '), style: {
+ overflowX: props.overflowX,
+ overflowY: props.overflowY,
+ left: (isAbsolute && -(props.overcomeLeft || 0)) || '',
+ right: (isAbsolute && -(props.overcomeRight || 0)) || '',
+ bottom: (isAbsolute && -(props.overcomeBottom || 0)) || '',
+ marginLeft: (!isAbsolute && -(props.overcomeLeft || 0)) || '',
+ marginRight: (!isAbsolute && -(props.overcomeRight || 0)) || '',
+ marginBottom: (!isAbsolute && -(props.overcomeBottom || 0)) || '',
+ maxHeight: props.maxHeight || '',
+ } }, props.children));
+ }
+ needsXScrolling() {
+ if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {
+ return false;
+ }
+ // testing scrollWidth>clientWidth is unreliable cross-browser when pixel heights aren't integers.
+ // much more reliable to see if children are taller than the scroller, even tho doesn't account for
+ // inner-child margins and absolute positioning
+ let { el } = this;
+ let realClientWidth = this.el.getBoundingClientRect().width - this.getYScrollbarWidth();
+ let { children } = el;
+ for (let i = 0; i < children.length; i += 1) {
+ let childEl = children[i];
+ if (childEl.getBoundingClientRect().width > realClientWidth) {
+ return true;
+ }
+ }
+ return false;
+ }
+ needsYScrolling() {
+ if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {
+ return false;
+ }
+ // testing scrollHeight>clientHeight is unreliable cross-browser when pixel heights aren't integers.
+ // much more reliable to see if children are taller than the scroller, even tho doesn't account for
+ // inner-child margins and absolute positioning
+ let { el } = this;
+ let realClientHeight = this.el.getBoundingClientRect().height - this.getXScrollbarWidth();
+ let { children } = el;
+ for (let i = 0; i < children.length; i += 1) {
+ let childEl = children[i];
+ if (childEl.getBoundingClientRect().height > realClientHeight) {
+ return true;
+ }
+ }
+ return false;
+ }
+ getXScrollbarWidth() {
+ if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {
+ return 0;
+ }
+ return this.el.offsetHeight - this.el.clientHeight; // only works because we guarantee no borders. TODO: add to CSS with important?
+ }
+ getYScrollbarWidth() {
+ if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {
+ return 0;
+ }
+ return this.el.offsetWidth - this.el.clientWidth; // only works because we guarantee no borders. TODO: add to CSS with important?
+ }
+ }
+
+ /*
+ TODO: somehow infer OtherArgs from masterCallback?
+ TODO: infer RefType from masterCallback if provided
+ */
+ class RefMap {
+ constructor(masterCallback) {
+ this.masterCallback = masterCallback;
+ this.currentMap = {};
+ this.depths = {};
+ this.callbackMap = {};
+ this.handleValue = (val, key) => {
+ let { depths, currentMap } = this;
+ let removed = false;
+ let added = false;
+ if (val !== null) {
+ // for bug... ACTUALLY: can probably do away with this now that callers don't share numeric indices anymore
+ removed = (key in currentMap);
+ currentMap[key] = val;
+ depths[key] = (depths[key] || 0) + 1;
+ added = true;
+ }
+ else {
+ depths[key] -= 1;
+ if (!depths[key]) {
+ delete currentMap[key];
+ delete this.callbackMap[key];
+ removed = true;
+ }
+ }
+ if (this.masterCallback) {
+ if (removed) {
+ this.masterCallback(null, String(key));
+ }
+ if (added) {
+ this.masterCallback(val, String(key));
+ }
+ }
+ };
+ }
+ createRef(key) {
+ let refCallback = this.callbackMap[key];
+ if (!refCallback) {
+ refCallback = this.callbackMap[key] = (val) => {
+ this.handleValue(val, String(key));
+ };
+ }
+ return refCallback;
+ }
+ // TODO: check callers that don't care about order. should use getAll instead
+ // NOTE: this method has become less valuable now that we are encouraged to map order by some other index
+ // TODO: provide ONE array-export function, buildArray, which fails on non-numeric indexes. caller can manipulate and "collect"
+ collect(startIndex, endIndex, step) {
+ return collectFromHash(this.currentMap, startIndex, endIndex, step);
+ }
+ getAll() {
+ return hashValuesToArray(this.currentMap);
+ }
+ }
+
+ function computeShrinkWidth(chunkEls) {
+ let shrinkCells = findElements(chunkEls, '.fc-scrollgrid-shrink');
+ let largestWidth = 0;
+ for (let shrinkCell of shrinkCells) {
+ largestWidth = Math.max(largestWidth, computeSmallestCellWidth(shrinkCell));
+ }
+ return Math.ceil(largestWidth); // <table> elements work best with integers. round up to ensure contents fits
+ }
+ function getSectionHasLiquidHeight(props, sectionConfig) {
+ return props.liquid && sectionConfig.liquid; // does the section do liquid-height? (need to have whole scrollgrid liquid-height as well)
+ }
+ function getAllowYScrolling(props, sectionConfig) {
+ return sectionConfig.maxHeight != null || // if its possible for the height to max out, we might need scrollbars
+ getSectionHasLiquidHeight(props, sectionConfig); // if the section is liquid height, it might condense enough to require scrollbars
+ }
+ // TODO: ONLY use `arg`. force out internal function to use same API
+ function renderChunkContent(sectionConfig, chunkConfig, arg, isHeader) {
+ let { expandRows } = arg;
+ let content = typeof chunkConfig.content === 'function' ?
+ chunkConfig.content(arg) :
+ h('table', {
+ role: 'presentation',
+ className: [
+ chunkConfig.tableClassName,
+ sectionConfig.syncRowHeights ? 'fc-scrollgrid-sync-table' : '',
+ ].join(' '),
+ style: {
+ minWidth: arg.tableMinWidth,
+ width: arg.clientWidth,
+ height: expandRows ? arg.clientHeight : '', // css `height` on a <table> serves as a min-height
+ },
+ }, arg.tableColGroupNode, h(isHeader ? 'thead' : 'tbody', {
+ role: 'presentation',
+ }, typeof chunkConfig.rowContent === 'function'
+ ? chunkConfig.rowContent(arg)
+ : chunkConfig.rowContent));
+ return content;
+ }
+ function isColPropsEqual(cols0, cols1) {
+ return isArraysEqual(cols0, cols1, isPropsEqual);
+ }
+ function renderMicroColGroup(cols, shrinkWidth) {
+ let colNodes = [];
+ /*
+ for ColProps with spans, it would have been great to make a single <col span="">
+ HOWEVER, Chrome was getting messing up distributing the width to <td>/<th> elements with colspans.
+ SOLUTION: making individual <col> elements makes Chrome behave.
+ */
+ for (let colProps of cols) {
+ let span = colProps.span || 1;
+ for (let i = 0; i < span; i += 1) {
+ colNodes.push(h("col", { style: {
+ width: colProps.width === 'shrink' ? sanitizeShrinkWidth(shrinkWidth) : (colProps.width || ''),
+ minWidth: colProps.minWidth || '',
+ } }));
+ }
+ }
+ return h('colgroup', {}, ...colNodes);
+ }
+ function sanitizeShrinkWidth(shrinkWidth) {
+ /* why 4? if we do 0, it will kill any border, which are needed for computeSmallestCellWidth
+ 4 accounts for 2 2-pixel borders. TODO: better solution? */
+ return shrinkWidth == null ? 4 : shrinkWidth;
+ }
+ function hasShrinkWidth(cols) {
+ for (let col of cols) {
+ if (col.width === 'shrink') {
+ return true;
+ }
+ }
+ return false;
+ }
+ function getScrollGridClassNames(liquid, context) {
+ let classNames = [
+ 'fc-scrollgrid',
+ context.theme.getClass('table'),
+ ];
+ if (liquid) {
+ classNames.push('fc-scrollgrid-liquid');
+ }
+ return classNames;
+ }
+ function getSectionClassNames(sectionConfig, wholeTableVGrow) {
+ let classNames = [
+ 'fc-scrollgrid-section',
+ `fc-scrollgrid-section-${sectionConfig.type}`,
+ sectionConfig.className, // used?
+ ];
+ if (wholeTableVGrow && sectionConfig.liquid && sectionConfig.maxHeight == null) {
+ classNames.push('fc-scrollgrid-section-liquid');
+ }
+ if (sectionConfig.isSticky) {
+ classNames.push('fc-scrollgrid-section-sticky');
+ }
+ return classNames;
+ }
+ function renderScrollShim(arg) {
+ return (h("div", { className: "fc-scrollgrid-sticky-shim", style: {
+ width: arg.clientWidth,
+ minWidth: arg.tableMinWidth,
+ } }));
+ }
+ function getStickyHeaderDates(options) {
+ let { stickyHeaderDates } = options;
+ if (stickyHeaderDates == null || stickyHeaderDates === 'auto') {
+ stickyHeaderDates = options.height === 'auto' || options.viewHeight === 'auto';
+ }
+ return stickyHeaderDates;
+ }
+ function getStickyFooterScrollbar(options) {
+ let { stickyFooterScrollbar } = options;
+ if (stickyFooterScrollbar == null || stickyFooterScrollbar === 'auto') {
+ stickyFooterScrollbar = options.height === 'auto' || options.viewHeight === 'auto';
+ }
+ return stickyFooterScrollbar;
+ }
+
+ class SimpleScrollGrid extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.processCols = memoize((a) => a, isColPropsEqual); // so we get same `cols` props every time
+ // yucky to memoize VNodes, but much more efficient for consumers
+ this.renderMicroColGroup = memoize(renderMicroColGroup);
+ this.scrollerRefs = new RefMap();
+ this.scrollerElRefs = new RefMap(this._handleScrollerEl.bind(this));
+ this.state = {
+ shrinkWidth: null,
+ forceYScrollbars: false,
+ scrollerClientWidths: {},
+ scrollerClientHeights: {},
+ };
+ // TODO: can do a really simple print-view. dont need to join rows
+ this.handleSizing = () => {
+ this.safeSetState(Object.assign({ shrinkWidth: this.computeShrinkWidth() }, this.computeScrollerDims()));
+ };
+ }
+ render() {
+ let { props, state, context } = this;
+ let sectionConfigs = props.sections || [];
+ let cols = this.processCols(props.cols);
+ let microColGroupNode = this.renderMicroColGroup(cols, state.shrinkWidth);
+ let classNames = getScrollGridClassNames(props.liquid, context);
+ if (props.collapsibleWidth) {
+ classNames.push('fc-scrollgrid-collapsible');
+ }
+ // TODO: make DRY
+ let configCnt = sectionConfigs.length;
+ let configI = 0;
+ let currentConfig;
+ let headSectionNodes = [];
+ let bodySectionNodes = [];
+ let footSectionNodes = [];
+ while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'header') {
+ headSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));
+ configI += 1;
+ }
+ while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'body') {
+ bodySectionNodes.push(this.renderSection(currentConfig, microColGroupNode, false));
+ configI += 1;
+ }
+ while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'footer') {
+ footSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));
+ configI += 1;
+ }
+ // firefox bug: when setting height on table and there is a thead or tfoot,
+ // the necessary height:100% on the liquid-height body section forces the *whole* table to be taller. (bug #5524)
+ // use getCanVGrowWithinCell as a way to detect table-stupid firefox.
+ // if so, use a simpler dom structure, jam everything into a lone tbody.
+ let isBuggy = !getCanVGrowWithinCell();
+ const roleAttrs = { role: 'rowgroup' };
+ return h('table', {
+ role: 'grid',
+ className: classNames.join(' '),
+ style: { height: props.height },
+ }, Boolean(!isBuggy && headSectionNodes.length) && h('thead', roleAttrs, ...headSectionNodes), Boolean(!isBuggy && bodySectionNodes.length) && h('tbody', roleAttrs, ...bodySectionNodes), Boolean(!isBuggy && footSectionNodes.length) && h('tfoot', roleAttrs, ...footSectionNodes), isBuggy && h('tbody', roleAttrs, ...headSectionNodes, ...bodySectionNodes, ...footSectionNodes));
+ }
+ renderSection(sectionConfig, microColGroupNode, isHeader) {
+ if ('outerContent' in sectionConfig) {
+ return (h(p, { key: sectionConfig.key }, sectionConfig.outerContent));
+ }
+ return (h("tr", { key: sectionConfig.key, role: "presentation", className: getSectionClassNames(sectionConfig, this.props.liquid).join(' ') }, this.renderChunkTd(sectionConfig, microColGroupNode, sectionConfig.chunk, isHeader)));
+ }
+ renderChunkTd(sectionConfig, microColGroupNode, chunkConfig, isHeader) {
+ if ('outerContent' in chunkConfig) {
+ return chunkConfig.outerContent;
+ }
+ let { props } = this;
+ let { forceYScrollbars, scrollerClientWidths, scrollerClientHeights } = this.state;
+ let needsYScrolling = getAllowYScrolling(props, sectionConfig); // TODO: do lazily. do in section config?
+ let isLiquid = getSectionHasLiquidHeight(props, sectionConfig);
+ // for `!props.liquid` - is WHOLE scrollgrid natural height?
+ // TODO: do same thing in advanced scrollgrid? prolly not b/c always has horizontal scrollbars
+ let overflowY = !props.liquid ? 'visible' :
+ forceYScrollbars ? 'scroll' :
+ !needsYScrolling ? 'hidden' :
+ 'auto';
+ let sectionKey = sectionConfig.key;
+ let content = renderChunkContent(sectionConfig, chunkConfig, {
+ tableColGroupNode: microColGroupNode,
+ tableMinWidth: '',
+ clientWidth: (!props.collapsibleWidth && scrollerClientWidths[sectionKey] !== undefined) ? scrollerClientWidths[sectionKey] : null,
+ clientHeight: scrollerClientHeights[sectionKey] !== undefined ? scrollerClientHeights[sectionKey] : null,
+ expandRows: sectionConfig.expandRows,
+ syncRowHeights: false,
+ rowSyncHeights: [],
+ reportRowHeightChange: () => { },
+ }, isHeader);
+ return h(isHeader ? 'th' : 'td', {
+ ref: chunkConfig.elRef,
+ role: 'presentation',
+ }, h("div", { className: `fc-scroller-harness${isLiquid ? ' fc-scroller-harness-liquid' : ''}` },
+ h(Scroller, { ref: this.scrollerRefs.createRef(sectionKey), elRef: this.scrollerElRefs.createRef(sectionKey), overflowY: overflowY, overflowX: !props.liquid ? 'visible' : 'hidden' /* natural height? */, maxHeight: sectionConfig.maxHeight, liquid: isLiquid, liquidIsAbsolute // because its within a harness
+ : true }, content)));
+ }
+ _handleScrollerEl(scrollerEl, key) {
+ let section = getSectionByKey(this.props.sections, key);
+ if (section) {
+ setRef(section.chunk.scrollerElRef, scrollerEl);
+ }
+ }
+ componentDidMount() {
+ this.handleSizing();
+ this.context.addResizeHandler(this.handleSizing);
+ }
+ componentDidUpdate() {
+ // TODO: need better solution when state contains non-sizing things
+ this.handleSizing();
+ }
+ componentWillUnmount() {
+ this.context.removeResizeHandler(this.handleSizing);
+ }
+ computeShrinkWidth() {
+ return hasShrinkWidth(this.props.cols)
+ ? computeShrinkWidth(this.scrollerElRefs.getAll())
+ : 0;
+ }
+ computeScrollerDims() {
+ let scrollbarWidth = getScrollbarWidths();
+ let { scrollerRefs, scrollerElRefs } = this;
+ let forceYScrollbars = false;
+ let scrollerClientWidths = {};
+ let scrollerClientHeights = {};
+ for (let sectionKey in scrollerRefs.currentMap) {
+ let scroller = scrollerRefs.currentMap[sectionKey];
+ if (scroller && scroller.needsYScrolling()) {
+ forceYScrollbars = true;
+ break;
+ }
+ }
+ for (let section of this.props.sections) {
+ let sectionKey = section.key;
+ let scrollerEl = scrollerElRefs.currentMap[sectionKey];
+ if (scrollerEl) {
+ let harnessEl = scrollerEl.parentNode; // TODO: weird way to get this. need harness b/c doesn't include table borders
+ scrollerClientWidths[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().width - (forceYScrollbars
+ ? scrollbarWidth.y // use global because scroller might not have scrollbars yet but will need them in future
+ : 0));
+ scrollerClientHeights[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().height);
+ }
+ }
+ return { forceYScrollbars, scrollerClientWidths, scrollerClientHeights };
+ }
+ }
+ SimpleScrollGrid.addStateEquality({
+ scrollerClientWidths: isPropsEqual,
+ scrollerClientHeights: isPropsEqual,
+ });
+ function getSectionByKey(sections, key) {
+ for (let section of sections) {
+ if (section.key === key) {
+ return section;
+ }
+ }
+ return null;
+ }
+
+ class EventContainer extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.handleEl = (el) => {
+ this.el = el;
+ if (el) {
+ setElSeg(el, this.props.seg);
+ }
+ };
+ }
+ render() {
+ const { props, context } = this;
+ const { options } = context;
+ const { seg } = props;
+ const { eventRange } = seg;
+ const { ui } = eventRange;
+ const renderProps = {
+ event: new EventImpl(context, eventRange.def, eventRange.instance),
+ view: context.viewApi,
+ timeText: props.timeText,
+ textColor: ui.textColor,
+ backgroundColor: ui.backgroundColor,
+ borderColor: ui.borderColor,
+ isDraggable: !props.disableDragging && computeSegDraggable(seg, context),
+ isStartResizable: !props.disableResizing && computeSegStartResizable(seg, context),
+ isEndResizable: !props.disableResizing && computeSegEndResizable(seg),
+ isMirror: Boolean(props.isDragging || props.isResizing || props.isDateSelecting),
+ isStart: Boolean(seg.isStart),
+ isEnd: Boolean(seg.isEnd),
+ isPast: Boolean(props.isPast),
+ isFuture: Boolean(props.isFuture),
+ isToday: Boolean(props.isToday),
+ isSelected: Boolean(props.isSelected),
+ isDragging: Boolean(props.isDragging),
+ isResizing: Boolean(props.isResizing),
+ };
+ return (h(ContentContainer, Object.assign({}, props /* contains children */, { elRef: this.handleEl, elClasses: [
+ ...getEventClassNames(renderProps),
+ ...seg.eventRange.ui.classNames,
+ ...(props.elClasses || []),
+ ], renderProps: renderProps, generatorName: "eventContent", generator: options.eventContent || props.defaultGenerator, classNameGenerator: options.eventClassNames, didMount: options.eventDidMount, willUnmount: options.eventWillUnmount })));
+ }
+ componentDidUpdate(prevProps) {
+ if (this.el && this.props.seg !== prevProps.seg) {
+ setElSeg(this.el, this.props.seg);
+ }
+ }
+ }
+
+ // should not be a purecomponent
+ class StandardEvent extends BaseComponent {
+ render() {
+ let { props, context } = this;
+ let { options } = context;
+ let { seg } = props;
+ let { ui } = seg.eventRange;
+ let timeFormat = options.eventTimeFormat || props.defaultTimeFormat;
+ let timeText = buildSegTimeText(seg, timeFormat, context, props.defaultDisplayEventTime, props.defaultDisplayEventEnd);
+ return (h(EventContainer, Object.assign({}, props /* includes elRef */, { elTag: "a", elStyle: {
+ borderColor: ui.borderColor,
+ backgroundColor: ui.backgroundColor,
+ }, elAttrs: getSegAnchorAttrs(seg, context), defaultGenerator: renderInnerContent$1$1, timeText: timeText }), (InnerContent, eventContentArg) => (h(p, null,
+ h(InnerContent, { elTag: "div", elClasses: ['fc-event-main'], elStyle: { color: eventContentArg.textColor } }),
+ Boolean(eventContentArg.isStartResizable) && (h("div", { className: "fc-event-resizer fc-event-resizer-start" })),
+ Boolean(eventContentArg.isEndResizable) && (h("div", { className: "fc-event-resizer fc-event-resizer-end" }))))));
+ }
+ }
+ function renderInnerContent$1$1(innerProps) {
+ return (h("div", { className: "fc-event-main-frame" },
+ innerProps.timeText && (h("div", { className: "fc-event-time" }, innerProps.timeText)),
+ h("div", { className: "fc-event-title-container" },
+ h("div", { className: "fc-event-title fc-sticky" }, innerProps.event.title || h(p, null, "\u00A0")))));
+ }
+
+ const NowIndicatorContainer = (props) => (h(ViewContextType.Consumer, null, (context) => {
+ let { options } = context;
+ let renderProps = {
+ isAxis: props.isAxis,
+ date: context.dateEnv.toDate(props.date),
+ view: context.viewApi,
+ };
+ return (h(ContentContainer, Object.assign({}, props /* includes children */, { elTag: props.elTag || 'div', renderProps: renderProps, generatorName: "nowIndicatorContent", generator: options.nowIndicatorContent, classNameGenerator: options.nowIndicatorClassNames, didMount: options.nowIndicatorDidMount, willUnmount: options.nowIndicatorWillUnmount })));
+ }));
+
+ const DAY_NUM_FORMAT = createFormatter({ day: 'numeric' });
+ class DayCellContainer extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.refineRenderProps = memoizeObjArg(refineRenderProps);
+ }
+ render() {
+ let { props, context } = this;
+ let { options } = context;
+ let renderProps = this.refineRenderProps({
+ date: props.date,
+ dateProfile: props.dateProfile,
+ todayRange: props.todayRange,
+ showDayNumber: props.showDayNumber,
+ extraRenderProps: props.extraRenderProps,
+ viewApi: context.viewApi,
+ dateEnv: context.dateEnv,
+ });
+ return (h(ContentContainer, Object.assign({}, props /* includes children */, { elClasses: [
+ ...getDayClassNames(renderProps, context.theme),
+ ...(props.elClasses || []),
+ ], elAttrs: Object.assign(Object.assign({}, props.elAttrs), (renderProps.isDisabled ? {} : { 'data-date': formatDayString(props.date) })), renderProps: renderProps, generatorName: "dayCellContent", generator: options.dayCellContent || props.defaultGenerator, classNameGenerator:
+ // don't use custom classNames if disabled
+ renderProps.isDisabled ? undefined : options.dayCellClassNames, didMount: options.dayCellDidMount, willUnmount: options.dayCellWillUnmount })));
+ }
+ }
+ function hasCustomDayCellContent(options) {
+ return Boolean(options.dayCellContent || hasCustomRenderingHandler('dayCellContent', options));
+ }
+ function refineRenderProps(raw) {
+ let { date, dateEnv } = raw;
+ let dayMeta = getDateMeta(date, raw.todayRange, null, raw.dateProfile);
+ return Object.assign(Object.assign(Object.assign({ date: dateEnv.toDate(date), view: raw.viewApi }, dayMeta), { dayNumberText: raw.showDayNumber ? dateEnv.format(date, DAY_NUM_FORMAT) : '' }), raw.extraRenderProps);
+ }
+
+ class BgEvent extends BaseComponent {
+ render() {
+ let { props } = this;
+ let { seg } = props;
+ return (h(EventContainer, { elTag: "div", elClasses: ['fc-bg-event'], elStyle: { backgroundColor: seg.eventRange.ui.backgroundColor }, defaultGenerator: renderInnerContent$3, seg: seg, timeText: "", isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false, isPast: props.isPast, isFuture: props.isFuture, isToday: props.isToday, disableDragging: true, disableResizing: true }));
+ }
+ }
+ function renderInnerContent$3(props) {
+ let { title } = props.event;
+ return title && (h("div", { className: "fc-event-title" }, props.event.title));
+ }
+ function renderFill(fillType) {
+ return (h("div", { className: `fc-${fillType}` }));
+ }
+
+ const WeekNumberContainer = (props) => (h(ViewContextType.Consumer, null, (context) => {
+ let { dateEnv, options } = context;
+ let { date } = props;
+ let format = options.weekNumberFormat || props.defaultFormat;
+ let num = dateEnv.computeWeekNumber(date); // TODO: somehow use for formatting as well?
+ let text = dateEnv.format(date, format);
+ let renderProps = { num, text, date };
+ return (h(ContentContainer // why isn't WeekNumberContentArg being auto-detected?
+ , Object.assign({}, props /* includes children */, { renderProps: renderProps, generatorName: "weekNumberContent", generator: options.weekNumberContent || renderInner, classNameGenerator: options.weekNumberClassNames, didMount: options.weekNumberDidMount, willUnmount: options.weekNumberWillUnmount })));
+ }));
+ function renderInner(innerProps) {
+ return innerProps.text;
+ }
+
+ const PADDING_FROM_VIEWPORT = 10;
+ class Popover extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.state = {
+ titleId: getUniqueDomId(),
+ };
+ this.handleRootEl = (el) => {
+ this.rootEl = el;
+ if (this.props.elRef) {
+ setRef(this.props.elRef, el);
+ }
+ };
+ // Triggered when the user clicks *anywhere* in the document, for the autoHide feature
+ this.handleDocumentMouseDown = (ev) => {
+ // only hide the popover if the click happened outside the popover
+ const target = getEventTargetViaRoot(ev);
+ if (!this.rootEl.contains(target)) {
+ this.handleCloseClick();
+ }
+ };
+ this.handleDocumentKeyDown = (ev) => {
+ if (ev.key === 'Escape') {
+ this.handleCloseClick();
+ }
+ };
+ this.handleCloseClick = () => {
+ let { onClose } = this.props;
+ if (onClose) {
+ onClose();
+ }
+ };
+ }
+ render() {
+ let { theme, options } = this.context;
+ let { props, state } = this;
+ let classNames = [
+ 'fc-popover',
+ theme.getClass('popover'),
+ ].concat(props.extraClassNames || []);
+ return j(h("div", Object.assign({}, props.extraAttrs, { id: props.id, className: classNames.join(' '), "aria-labelledby": state.titleId, ref: this.handleRootEl }),
+ h("div", { className: 'fc-popover-header ' + theme.getClass('popoverHeader') },
+ h("span", { className: "fc-popover-title", id: state.titleId }, props.title),
+ h("span", { className: 'fc-popover-close ' + theme.getIconClass('close'), title: options.closeHint, onClick: this.handleCloseClick })),
+ h("div", { className: 'fc-popover-body ' + theme.getClass('popoverContent') }, props.children)), props.parentEl);
+ }
+ componentDidMount() {
+ document.addEventListener('mousedown', this.handleDocumentMouseDown);
+ document.addEventListener('keydown', this.handleDocumentKeyDown);
+ this.updateSize();
+ }
+ componentWillUnmount() {
+ document.removeEventListener('mousedown', this.handleDocumentMouseDown);
+ document.removeEventListener('keydown', this.handleDocumentKeyDown);
+ }
+ updateSize() {
+ let { isRtl } = this.context;
+ let { alignmentEl, alignGridTop } = this.props;
+ let { rootEl } = this;
+ let alignmentRect = computeClippedClientRect(alignmentEl);
+ if (alignmentRect) {
+ let popoverDims = rootEl.getBoundingClientRect();
+ // position relative to viewport
+ let popoverTop = alignGridTop
+ ? elementClosest(alignmentEl, '.fc-scrollgrid').getBoundingClientRect().top
+ : alignmentRect.top;
+ let popoverLeft = isRtl ? alignmentRect.right - popoverDims.width : alignmentRect.left;
+ // constrain
+ popoverTop = Math.max(popoverTop, PADDING_FROM_VIEWPORT);
+ popoverLeft = Math.min(popoverLeft, document.documentElement.clientWidth - PADDING_FROM_VIEWPORT - popoverDims.width);
+ popoverLeft = Math.max(popoverLeft, PADDING_FROM_VIEWPORT);
+ let origin = rootEl.offsetParent.getBoundingClientRect();
+ applyStyle(rootEl, {
+ top: popoverTop - origin.top,
+ left: popoverLeft - origin.left,
+ });
+ }
+ }
+ }
+
+ class MorePopover extends DateComponent {
+ constructor() {
+ super(...arguments);
+ this.handleRootEl = (rootEl) => {
+ this.rootEl = rootEl;
+ if (rootEl) {
+ this.context.registerInteractiveComponent(this, {
+ el: rootEl,
+ useEventCenter: false,
+ });
+ }
+ else {
+ this.context.unregisterInteractiveComponent(this);
+ }
+ };
+ }
+ render() {
+ let { options, dateEnv } = this.context;
+ let { props } = this;
+ let { startDate, todayRange, dateProfile } = props;
+ let title = dateEnv.format(startDate, options.dayPopoverFormat);
+ return (h(DayCellContainer, { elRef: this.handleRootEl, date: startDate, dateProfile: dateProfile, todayRange: todayRange }, (InnerContent, renderProps, elAttrs) => (h(Popover, { elRef: elAttrs.ref, id: props.id, title: title, extraClassNames: ['fc-more-popover'].concat(elAttrs.className || []), extraAttrs: elAttrs /* TODO: make these time-based when not whole-day? */, parentEl: props.parentEl, alignmentEl: props.alignmentEl, alignGridTop: props.alignGridTop, onClose: props.onClose },
+ hasCustomDayCellContent(options) && (h(InnerContent, { elTag: "div", elClasses: ['fc-more-popover-misc'] })),
+ props.children))));
+ }
+ queryHit(positionLeft, positionTop, elWidth, elHeight) {
+ let { rootEl, props } = this;
+ if (positionLeft >= 0 && positionLeft < elWidth &&
+ positionTop >= 0 && positionTop < elHeight) {
+ return {
+ dateProfile: props.dateProfile,
+ dateSpan: Object.assign({ allDay: true, range: {
+ start: props.startDate,
+ end: props.endDate,
+ } }, props.extraDateSpan),
+ dayEl: rootEl,
+ rect: {
+ left: 0,
+ top: 0,
+ right: elWidth,
+ bottom: elHeight,
+ },
+ layer: 1, // important when comparing with hits from other components
+ };
+ }
+ return null;
+ }
+ }
+
+ class MoreLinkContainer extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.state = {
+ isPopoverOpen: false,
+ popoverId: getUniqueDomId(),
+ };
+ this.handleLinkEl = (linkEl) => {
+ this.linkEl = linkEl;
+ if (this.props.elRef) {
+ setRef(this.props.elRef, linkEl);
+ }
+ };
+ this.handleClick = (ev) => {
+ let { props, context } = this;
+ let { moreLinkClick } = context.options;
+ let date = computeRange(props).start;
+ function buildPublicSeg(seg) {
+ let { def, instance, range } = seg.eventRange;
+ return {
+ event: new EventImpl(context, def, instance),
+ start: context.dateEnv.toDate(range.start),
+ end: context.dateEnv.toDate(range.end),
+ isStart: seg.isStart,
+ isEnd: seg.isEnd,
+ };
+ }
+ if (typeof moreLinkClick === 'function') {
+ moreLinkClick = moreLinkClick({
+ date,
+ allDay: Boolean(props.allDayDate),
+ allSegs: props.allSegs.map(buildPublicSeg),
+ hiddenSegs: props.hiddenSegs.map(buildPublicSeg),
+ jsEvent: ev,
+ view: context.viewApi,
+ });
+ }
+ if (!moreLinkClick || moreLinkClick === 'popover') {
+ this.setState({ isPopoverOpen: true });
+ }
+ else if (typeof moreLinkClick === 'string') { // a view name
+ context.calendarApi.zoomTo(date, moreLinkClick);
+ }
+ };
+ this.handlePopoverClose = () => {
+ this.setState({ isPopoverOpen: false });
+ };
+ }
+ render() {
+ let { props, state } = this;
+ return (h(ViewContextType.Consumer, null, (context) => {
+ let { viewApi, options, calendarApi } = context;
+ let { moreLinkText } = options;
+ let { moreCnt } = props;
+ let range = computeRange(props);
+ let text = typeof moreLinkText === 'function' // TODO: eventually use formatWithOrdinals
+ ? moreLinkText.call(calendarApi, moreCnt)
+ : `+${moreCnt} ${moreLinkText}`;
+ let hint = formatWithOrdinals(options.moreLinkHint, [moreCnt], text);
+ let renderProps = {
+ num: moreCnt,
+ shortText: `+${moreCnt}`,
+ text,
+ view: viewApi,
+ };
+ return (h(p, null,
+ Boolean(props.moreCnt) && (h(ContentContainer, { elTag: props.elTag || 'a', elRef: this.handleLinkEl, elClasses: [
+ ...(props.elClasses || []),
+ 'fc-more-link',
+ ], 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", generator: options.moreLinkContent || props.defaultGenerator || renderMoreLinkInner$1, classNameGenerator: options.moreLinkClassNames, didMount: options.moreLinkDidMount, willUnmount: options.moreLinkWillUnmount }, props.children)),
+ state.isPopoverOpen && (h(MorePopover, { id: state.popoverId, startDate: range.start, endDate: range.end, dateProfile: props.dateProfile, todayRange: props.todayRange, extraDateSpan: props.extraDateSpan, parentEl: this.parentEl, alignmentEl: props.alignmentElRef ?
+ props.alignmentElRef.current :
+ this.linkEl, alignGridTop: props.alignGridTop, onClose: this.handlePopoverClose }, props.popoverContent()))));
+ }));
+ }
+ componentDidMount() {
+ this.updateParentEl();
+ }
+ componentDidUpdate() {
+ this.updateParentEl();
+ }
+ updateParentEl() {
+ if (this.linkEl) {
+ this.parentEl = elementClosest(this.linkEl, '.fc-view-harness');
+ }
+ }
+ }
+ function renderMoreLinkInner$1(props) {
+ return props.text;
+ }
+ function computeRange(props) {
+ if (props.allDayDate) {
+ return {
+ start: props.allDayDate,
+ end: addDays(props.allDayDate, 1),
+ };
+ }
+ let { hiddenSegs } = props;
+ return {
+ start: computeEarliestSegStart(hiddenSegs),
+ end: computeLatestSegEnd(hiddenSegs),
+ };
+ }
+ function computeEarliestSegStart(segs) {
+ return segs.reduce(pickEarliestStart).eventRange.range.start;
+ }
+ function pickEarliestStart(seg0, seg1) {
+ return seg0.eventRange.range.start < seg1.eventRange.range.start ? seg0 : seg1;
+ }
+ function computeLatestSegEnd(segs) {
+ return segs.reduce(pickLatestEnd).eventRange.range.end;
+ }
+ function pickLatestEnd(seg0, seg1) {
+ return seg0.eventRange.range.end > seg1.eventRange.range.end ? seg0 : seg1;
+ }
+
+ class ViewContainer$1 extends BaseComponent {
+ render() {
+ let { props, context } = this;
+ let { options } = context;
+ let renderProps = { view: context.viewApi };
+ return (h(ContentContainer, Object.assign({}, props, { elTag: props.elTag || 'div', elClasses: [
+ ...buildViewClassNames(props.viewSpec),
+ ...(props.elClasses || []),
+ ], renderProps: renderProps, classNameGenerator: options.viewClassNames, generatorName: undefined, generator: undefined, didMount: options.viewDidMount, willUnmount: options.viewWillUnmount }), () => props.children));
+ }
+ }
+ function buildViewClassNames(viewSpec) {
+ return [
+ `fc-${viewSpec.type}-view`,
+ 'fc-view',
+ ];
+ }
+
+ function injectStyles(css) {
+ if (!css || typeof document === 'undefined') {
+ return;
+ }
+ const head = document.head || document.getElementsByTagName('head')[0];
+ const style = document.createElement('style');
+ style.type = 'text/css';
+ head.appendChild(style);
+ if (style.styleSheet) {
+ style.styleSheet.cssText = css;
+ }
+ else {
+ style.appendChild(document.createTextNode(css));
+ }
+ }
+
+ const EVENT_SOURCE_REFINERS = {
+ id: String,
+ defaultAllDay: Boolean,
+ url: String,
+ format: String,
+ events: identity,
+ eventDataTransform: identity,
+ // for any network-related sources
+ success: identity,
+ failure: identity,
+ };
+ function parseEventSource(raw, context, refiners = buildEventSourceRefiners(context)) {
+ let rawObj;
+ if (typeof raw === 'string') {
+ rawObj = { url: raw };
+ }
+ else if (typeof raw === 'function' || Array.isArray(raw)) {
+ rawObj = { events: raw };
+ }
+ else if (typeof raw === 'object' && raw) { // not null
+ rawObj = raw;
+ }
+ if (rawObj) {
+ let { refined, extra } = refineProps(rawObj, refiners);
+ let metaRes = buildEventSourceMeta(refined, context);
+ if (metaRes) {
+ return {
+ _raw: raw,
+ isFetching: false,
+ latestFetchId: '',
+ fetchRange: null,
+ defaultAllDay: refined.defaultAllDay,
+ eventDataTransform: refined.eventDataTransform,
+ success: refined.success,
+ failure: refined.failure,
+ publicId: refined.id || '',
+ sourceId: guid(),
+ sourceDefId: metaRes.sourceDefId,
+ meta: metaRes.meta,
+ ui: createEventUi(refined, context),
+ extendedProps: extra,
+ };
+ }
+ }
+ return null;
+ }
+ function buildEventSourceRefiners(context) {
+ return Object.assign(Object.assign(Object.assign({}, EVENT_UI_REFINERS), EVENT_SOURCE_REFINERS), context.pluginHooks.eventSourceRefiners);
+ }
+ function buildEventSourceMeta(raw, context) {
+ let defs = context.pluginHooks.eventSourceDefs;
+ for (let i = defs.length - 1; i >= 0; i -= 1) { // later-added plugins take precedence
+ let def = defs[i];
+ let meta = def.parseMeta(raw);
+ if (meta) {
+ return { sourceDefId: i, meta };
+ }
+ }
+ return null;
+ }
+
+ class CalendarImpl {
+ getCurrentData() {
+ return this.currentDataManager.getCurrentData();
+ }
+ dispatch(action) {
+ this.currentDataManager.dispatch(action);
+ }
+ get view() { return this.getCurrentData().viewApi; }
+ batchRendering(callback) {
+ callback();
+ }
+ updateSize() {
+ this.trigger('_resize', true);
+ }
+ // Options
+ // -----------------------------------------------------------------------------------------------------------------
+ setOption(name, val) {
+ this.dispatch({
+ type: 'SET_OPTION',
+ optionName: name,
+ rawOptionValue: val,
+ });
+ }
+ getOption(name) {
+ return this.currentDataManager.currentCalendarOptionsInput[name];
+ }
+ getAvailableLocaleCodes() {
+ return Object.keys(this.getCurrentData().availableRawLocales);
+ }
+ // Trigger
+ // -----------------------------------------------------------------------------------------------------------------
+ on(handlerName, handler) {
+ let { currentDataManager } = this;
+ if (currentDataManager.currentCalendarOptionsRefiners[handlerName]) {
+ currentDataManager.emitter.on(handlerName, handler);
+ }
+ else {
+ console.warn(`Unknown listener name '${handlerName}'`);
+ }
+ }
+ off(handlerName, handler) {
+ this.currentDataManager.emitter.off(handlerName, handler);
+ }
+ // not meant for public use
+ trigger(handlerName, ...args) {
+ this.currentDataManager.emitter.trigger(handlerName, ...args);
+ }
+ // View
+ // -----------------------------------------------------------------------------------------------------------------
+ changeView(viewType, dateOrRange) {
+ this.batchRendering(() => {
+ this.unselect();
+ if (dateOrRange) {
+ if (dateOrRange.start && dateOrRange.end) { // a range
+ this.dispatch({
+ type: 'CHANGE_VIEW_TYPE',
+ viewType,
+ });
+ this.dispatch({
+ type: 'SET_OPTION',
+ optionName: 'visibleRange',
+ rawOptionValue: dateOrRange,
+ });
+ }
+ else {
+ let { dateEnv } = this.getCurrentData();
+ this.dispatch({
+ type: 'CHANGE_VIEW_TYPE',
+ viewType,
+ dateMarker: dateEnv.createMarker(dateOrRange),
+ });
+ }
+ }
+ else {
+ this.dispatch({
+ type: 'CHANGE_VIEW_TYPE',
+ viewType,
+ });
+ }
+ });
+ }
+ // Forces navigation to a view for the given date.
+ // `viewType` can be a specific view name or a generic one like "week" or "day".
+ // needs to change
+ zoomTo(dateMarker, viewType) {
+ let state = this.getCurrentData();
+ let spec;
+ viewType = viewType || 'day'; // day is default zoom
+ spec = state.viewSpecs[viewType] || this.getUnitViewSpec(viewType);
+ this.unselect();
+ if (spec) {
+ this.dispatch({
+ type: 'CHANGE_VIEW_TYPE',
+ viewType: spec.type,
+ dateMarker,
+ });
+ }
+ else {
+ this.dispatch({
+ type: 'CHANGE_DATE',
+ dateMarker,
+ });
+ }
+ }
+ // Given a duration singular unit, like "week" or "day", finds a matching view spec.
+ // Preference is given to views that have corresponding buttons.
+ getUnitViewSpec(unit) {
+ let { viewSpecs, toolbarConfig } = this.getCurrentData();
+ let viewTypes = [].concat(toolbarConfig.header ? toolbarConfig.header.viewsWithButtons : [], toolbarConfig.footer ? toolbarConfig.footer.viewsWithButtons : []);
+ let i;
+ let spec;
+ for (let viewType in viewSpecs) {
+ viewTypes.push(viewType);
+ }
+ for (i = 0; i < viewTypes.length; i += 1) {
+ spec = viewSpecs[viewTypes[i]];
+ if (spec) {
+ if (spec.singleUnit === unit) {
+ return spec;
+ }
+ }
+ }
+ return null;
+ }
+ // Current Date
+ // -----------------------------------------------------------------------------------------------------------------
+ prev() {
+ this.unselect();
+ this.dispatch({ type: 'PREV' });
+ }
+ next() {
+ this.unselect();
+ this.dispatch({ type: 'NEXT' });
+ }
+ prevYear() {
+ let state = this.getCurrentData();
+ this.unselect();
+ this.dispatch({
+ type: 'CHANGE_DATE',
+ dateMarker: state.dateEnv.addYears(state.currentDate, -1),
+ });
+ }
+ nextYear() {
+ let state = this.getCurrentData();
+ this.unselect();
+ this.dispatch({
+ type: 'CHANGE_DATE',
+ dateMarker: state.dateEnv.addYears(state.currentDate, 1),
+ });
+ }
+ today() {
+ let state = this.getCurrentData();
+ this.unselect();
+ this.dispatch({
+ type: 'CHANGE_DATE',
+ dateMarker: getNow(state.calendarOptions.now, state.dateEnv),
+ });
+ }
+ gotoDate(zonedDateInput) {
+ let state = this.getCurrentData();
+ this.unselect();
+ this.dispatch({
+ type: 'CHANGE_DATE',
+ dateMarker: state.dateEnv.createMarker(zonedDateInput),
+ });
+ }
+ incrementDate(deltaInput) {
+ let state = this.getCurrentData();
+ let delta = createDuration(deltaInput);
+ if (delta) { // else, warn about invalid input?
+ this.unselect();
+ this.dispatch({
+ type: 'CHANGE_DATE',
+ dateMarker: state.dateEnv.add(state.currentDate, delta),
+ });
+ }
+ }
+ getDate() {
+ let state = this.getCurrentData();
+ return state.dateEnv.toDate(state.currentDate);
+ }
+ // Date Formatting Utils
+ // -----------------------------------------------------------------------------------------------------------------
+ formatDate(d, formatter) {
+ let { dateEnv } = this.getCurrentData();
+ return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter));
+ }
+ // `settings` is for formatter AND isEndExclusive
+ formatRange(d0, d1, settings) {
+ let { dateEnv } = this.getCurrentData();
+ return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings), settings);
+ }
+ formatIso(d, omitTime) {
+ let { dateEnv } = this.getCurrentData();
+ return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime });
+ }
+ // Date Selection / Event Selection / DayClick
+ // -----------------------------------------------------------------------------------------------------------------
+ select(dateOrObj, endDate) {
+ let selectionInput;
+ if (endDate == null) {
+ if (dateOrObj.start != null) {
+ selectionInput = dateOrObj;
+ }
+ else {
+ selectionInput = {
+ start: dateOrObj,
+ end: null,
+ };
+ }
+ }
+ else {
+ selectionInput = {
+ start: dateOrObj,
+ end: endDate,
+ };
+ }
+ let state = this.getCurrentData();
+ let selection = parseDateSpan(selectionInput, state.dateEnv, createDuration({ days: 1 }));
+ if (selection) { // throw parse error otherwise?
+ this.dispatch({ type: 'SELECT_DATES', selection });
+ triggerDateSelect(selection, null, state);
+ }
+ }
+ unselect(pev) {
+ let state = this.getCurrentData();
+ if (state.dateSelection) {
+ this.dispatch({ type: 'UNSELECT_DATES' });
+ triggerDateUnselect(pev, state);
+ }
+ }
+ // Public Events API
+ // -----------------------------------------------------------------------------------------------------------------
+ addEvent(eventInput, sourceInput) {
+ if (eventInput instanceof EventImpl) {
+ let def = eventInput._def;
+ let instance = eventInput._instance;
+ let currentData = this.getCurrentData();
+ // not already present? don't want to add an old snapshot
+ if (!currentData.eventStore.defs[def.defId]) {
+ this.dispatch({
+ type: 'ADD_EVENTS',
+ eventStore: eventTupleToStore({ def, instance }), // TODO: better util for two args?
+ });
+ this.triggerEventAdd(eventInput);
+ }
+ return eventInput;
+ }
+ let state = this.getCurrentData();
+ let eventSource;
+ if (sourceInput instanceof EventSourceImpl) {
+ eventSource = sourceInput.internalEventSource;
+ }
+ else if (typeof sourceInput === 'boolean') {
+ if (sourceInput) { // true. part of the first event source
+ [eventSource] = hashValuesToArray(state.eventSources);
+ }
+ }
+ else if (sourceInput != null) { // an ID. accepts a number too
+ let sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function
+ if (!sourceApi) {
+ console.warn(`Could not find an event source with ID "${sourceInput}"`); // TODO: test
+ return null;
+ }
+ eventSource = sourceApi.internalEventSource;
+ }
+ let tuple = parseEvent(eventInput, eventSource, state, false);
+ if (tuple) {
+ let newEventApi = new EventImpl(state, tuple.def, tuple.def.recurringDef ? null : tuple.instance);
+ this.dispatch({
+ type: 'ADD_EVENTS',
+ eventStore: eventTupleToStore(tuple),
+ });
+ this.triggerEventAdd(newEventApi);
+ return newEventApi;
+ }
+ return null;
+ }
+ triggerEventAdd(eventApi) {
+ let { emitter } = this.getCurrentData();
+ emitter.trigger('eventAdd', {
+ event: eventApi,
+ relatedEvents: [],
+ revert: () => {
+ this.dispatch({
+ type: 'REMOVE_EVENTS',
+ eventStore: eventApiToStore(eventApi),
+ });
+ },
+ });
+ }
+ // TODO: optimize
+ getEventById(id) {
+ let state = this.getCurrentData();
+ let { defs, instances } = state.eventStore;
+ id = String(id);
+ for (let defId in defs) {
+ let def = defs[defId];
+ if (def.publicId === id) {
+ if (def.recurringDef) {
+ return new EventImpl(state, def, null);
+ }
+ for (let instanceId in instances) {
+ let instance = instances[instanceId];
+ if (instance.defId === def.defId) {
+ return new EventImpl(state, def, instance);
+ }
+ }
+ }
+ }
+ return null;
+ }
+ getEvents() {
+ let currentData = this.getCurrentData();
+ return buildEventApis(currentData.eventStore, currentData);
+ }
+ removeAllEvents() {
+ this.dispatch({ type: 'REMOVE_ALL_EVENTS' });
+ }
+ // Public Event Sources API
+ // -----------------------------------------------------------------------------------------------------------------
+ getEventSources() {
+ let state = this.getCurrentData();
+ let sourceHash = state.eventSources;
+ let sourceApis = [];
+ for (let internalId in sourceHash) {
+ sourceApis.push(new EventSourceImpl(state, sourceHash[internalId]));
+ }
+ return sourceApis;
+ }
+ getEventSourceById(id) {
+ let state = this.getCurrentData();
+ let sourceHash = state.eventSources;
+ id = String(id);
+ for (let sourceId in sourceHash) {
+ if (sourceHash[sourceId].publicId === id) {
+ return new EventSourceImpl(state, sourceHash[sourceId]);
+ }
+ }
+ return null;
+ }
+ addEventSource(sourceInput) {
+ let state = this.getCurrentData();
+ if (sourceInput instanceof EventSourceImpl) {
+ // not already present? don't want to add an old snapshot
+ if (!state.eventSources[sourceInput.internalEventSource.sourceId]) {
+ this.dispatch({
+ type: 'ADD_EVENT_SOURCES',
+ sources: [sourceInput.internalEventSource],
+ });
+ }
+ return sourceInput;
+ }
+ let eventSource = parseEventSource(sourceInput, state);
+ if (eventSource) { // TODO: error otherwise?
+ this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] });
+ return new EventSourceImpl(state, eventSource);
+ }
+ return null;
+ }
+ removeAllEventSources() {
+ this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' });
+ }
+ refetchEvents() {
+ this.dispatch({ type: 'FETCH_EVENT_SOURCES', isRefetch: true });
+ }
+ // Scroll
+ // -----------------------------------------------------------------------------------------------------------------
+ scrollToTime(timeInput) {
+ let time = createDuration(timeInput);
+ if (time) {
+ this.trigger('_scrollRequest', { time });
+ }
+ }
+ }
+
+ class Store {
+ constructor() {
+ this.handlers = [];
+ }
+ set(value) {
+ this.currentValue = value;
+ for (let handler of this.handlers) {
+ handler(value);
+ }
+ }
+ subscribe(handler) {
+ this.handlers.push(handler);
+ if (this.currentValue !== undefined) {
+ handler(this.currentValue);
+ }
+ }
+ }
+
+ /*
+ Subscribers will get a LIST of CustomRenderings
+ */
+ class CustomRenderingStore extends Store {
+ constructor() {
+ super(...arguments);
+ this.map = new Map();
+ }
+ // for consistent order
+ handle(customRendering) {
+ const { map } = this;
+ let updated = false;
+ if (customRendering.isActive) {
+ map.set(customRendering.id, customRendering);
+ updated = true;
+ }
+ else if (map.has(customRendering.id)) {
+ map.delete(customRendering.id);
+ updated = true;
+ }
+ if (updated) {
+ this.set(map);
+ }
+ }
+ }
+
+ var internal_esm = {
+ __proto__: null,
+ BASE_OPTION_DEFAULTS: BASE_OPTION_DEFAULTS,
+ BaseComponent: BaseComponent,
+ BgEvent: BgEvent,
+ CalendarImpl: CalendarImpl,
+ CalendarRoot: CalendarRoot,
+ ContentContainer: ContentContainer,
+ CustomRenderingStore: CustomRenderingStore,
+ DateComponent: DateComponent,
+ DateEnv: DateEnv,
+ DateProfileGenerator: DateProfileGenerator,
+ DayCellContainer: DayCellContainer,
+ DayHeader: DayHeader,
+ DaySeriesModel: DaySeriesModel,
+ DayTableModel: DayTableModel,
+ DelayedRunner: DelayedRunner,
+ ElementDragging: ElementDragging,
+ ElementScrollController: ElementScrollController,
+ Emitter: Emitter,
+ EventContainer: EventContainer,
+ EventImpl: EventImpl,
+ Interaction: Interaction,
+ MoreLinkContainer: MoreLinkContainer,
+ NamedTimeZoneImpl: NamedTimeZoneImpl,
+ NowIndicatorContainer: NowIndicatorContainer,
+ NowTimer: NowTimer,
+ PositionCache: PositionCache,
+ RefMap: RefMap,
+ ScrollController: ScrollController,
+ ScrollResponder: ScrollResponder,
+ Scroller: Scroller,
+ SegHierarchy: SegHierarchy,
+ SimpleScrollGrid: SimpleScrollGrid,
+ Slicer: Slicer,
+ Splitter: Splitter,
+ StandardEvent: StandardEvent,
+ TableDateCell: TableDateCell,
+ TableDowCell: TableDowCell,
+ Theme: Theme,
+ ViewContainer: ViewContainer$1,
+ ViewContextType: ViewContextType,
+ WeekNumberContainer: WeekNumberContainer,
+ WindowScrollController: WindowScrollController,
+ addDays: addDays,
+ addDurations: addDurations,
+ addMs: addMs,
+ addWeeks: addWeeks,
+ allowContextMenu: allowContextMenu,
+ allowSelection: allowSelection,
+ applyMutationToEventStore: applyMutationToEventStore,
+ applyStyle: applyStyle,
+ asCleanDays: asCleanDays,
+ asRoughMinutes: asRoughMinutes,
+ asRoughMs: asRoughMs,
+ asRoughSeconds: asRoughSeconds,
+ binarySearch: binarySearch,
+ buildElAttrs: buildElAttrs,
+ buildEntryKey: buildEntryKey,
+ buildEventApis: buildEventApis,
+ buildEventRangeKey: buildEventRangeKey,
+ buildIsoString: buildIsoString,
+ buildNavLinkAttrs: buildNavLinkAttrs,
+ buildSegTimeText: buildSegTimeText,
+ collectFromHash: collectFromHash,
+ combineEventUis: combineEventUis,
+ compareByFieldSpecs: compareByFieldSpecs,
+ compareNumbers: compareNumbers,
+ compareObjs: compareObjs,
+ computeEarliestSegStart: computeEarliestSegStart,
+ computeEdges: computeEdges,
+ computeFallbackHeaderFormat: computeFallbackHeaderFormat,
+ computeInnerRect: computeInnerRect,
+ computeRect: computeRect,
+ computeShrinkWidth: computeShrinkWidth,
+ computeVisibleDayRange: computeVisibleDayRange,
+ config: config,
+ constrainPoint: constrainPoint,
+ createDuration: createDuration,
+ createEmptyEventStore: createEmptyEventStore,
+ createEventInstance: createEventInstance,
+ createEventUi: createEventUi,
+ createFormatter: createFormatter,
+ diffDates: diffDates,
+ diffDayAndTime: diffDayAndTime,
+ diffDays: diffDays,
+ diffPoints: diffPoints,
+ diffWeeks: diffWeeks,
+ diffWholeDays: diffWholeDays,
+ diffWholeWeeks: diffWholeWeeks,
+ disableCursor: disableCursor,
+ elementClosest: elementClosest,
+ elementMatches: elementMatches,
+ enableCursor: enableCursor,
+ eventTupleToStore: eventTupleToStore,
+ filterHash: filterHash,
+ findDirectChildren: findDirectChildren,
+ findElements: findElements,
+ flexibleCompare: flexibleCompare,
+ formatDayString: formatDayString,
+ formatIsoTimeString: formatIsoTimeString,
+ getAllowYScrolling: getAllowYScrolling,
+ getCanVGrowWithinCell: getCanVGrowWithinCell,
+ getClippingParents: getClippingParents,
+ getDateMeta: getDateMeta,
+ getDayClassNames: getDayClassNames,
+ getDefaultEventEnd: getDefaultEventEnd,
+ getElRoot: getElRoot,
+ getElSeg: getElSeg,
+ getEntrySpanEnd: getEntrySpanEnd,
+ getEventTargetViaRoot: getEventTargetViaRoot,
+ getIsRtlScrollbarOnLeft: getIsRtlScrollbarOnLeft,
+ getRectCenter: getRectCenter,
+ getRelevantEvents: getRelevantEvents,
+ getScrollGridClassNames: getScrollGridClassNames,
+ getScrollbarWidths: getScrollbarWidths,
+ getSectionClassNames: getSectionClassNames,
+ getSectionHasLiquidHeight: getSectionHasLiquidHeight,
+ getSegAnchorAttrs: getSegAnchorAttrs,
+ getSegMeta: getSegMeta,
+ getSlotClassNames: getSlotClassNames,
+ getStickyFooterScrollbar: getStickyFooterScrollbar,
+ getStickyHeaderDates: getStickyHeaderDates,
+ getUniqueDomId: getUniqueDomId,
+ greatestDurationDenominator: greatestDurationDenominator,
+ groupIntersectingEntries: groupIntersectingEntries,
+ guid: guid,
+ hasBgRendering: hasBgRendering,
+ hasCustomDayCellContent: hasCustomDayCellContent,
+ hasShrinkWidth: hasShrinkWidth,
+ identity: identity,
+ injectStyles: injectStyles,
+ interactionSettingsStore: interactionSettingsStore,
+ interactionSettingsToStore: interactionSettingsToStore,
+ intersectRanges: intersectRanges,
+ intersectRects: intersectRects,
+ intersectSpans: intersectSpans,
+ isArraysEqual: isArraysEqual,
+ isColPropsEqual: isColPropsEqual,
+ isDateSelectionValid: isDateSelectionValid,
+ isDateSpansEqual: isDateSpansEqual,
+ isInt: isInt,
+ isInteractionValid: isInteractionValid,
+ isMultiDayRange: isMultiDayRange,
+ isPropsEqual: isPropsEqual,
+ isPropsValid: isPropsValid,
+ isValidDate: isValidDate,
+ mapHash: mapHash,
+ memoize: memoize,
+ memoizeArraylike: memoizeArraylike,
+ memoizeHashlike: memoizeHashlike,
+ memoizeObjArg: memoizeObjArg,
+ mergeEventStores: mergeEventStores,
+ multiplyDuration: multiplyDuration,
+ padStart: padStart,
+ parseBusinessHours: parseBusinessHours,
+ parseClassNames: parseClassNames,
+ parseDragMeta: parseDragMeta,
+ parseEventDef: parseEventDef,
+ parseFieldSpecs: parseFieldSpecs,
+ parseMarker: parse,
+ pointInsideRect: pointInsideRect,
+ preventContextMenu: preventContextMenu,
+ preventDefault: preventDefault,
+ preventSelection: preventSelection,
+ rangeContainsMarker: rangeContainsMarker,
+ rangeContainsRange: rangeContainsRange,
+ rangesEqual: rangesEqual,
+ rangesIntersect: rangesIntersect,
+ refineEventDef: refineEventDef,
+ refineProps: refineProps,
+ removeElement: removeElement,
+ removeExact: removeExact,
+ renderChunkContent: renderChunkContent,
+ renderFill: renderFill,
+ renderMicroColGroup: renderMicroColGroup,
+ renderScrollShim: renderScrollShim,
+ requestJson: requestJson,
+ sanitizeShrinkWidth: sanitizeShrinkWidth,
+ setRef: setRef,
+ sliceEventStore: sliceEventStore,
+ sortEventSegs: sortEventSegs,
+ startOfDay: startOfDay,
+ translateRect: translateRect,
+ triggerDateSelect: triggerDateSelect,
+ unpromisify: unpromisify,
+ whenTransitionDone: whenTransitionDone,
+ wholeDivideDurations: wholeDivideDurations
+ };
+
+ var css_248z$3 = ":root{--fc-small-font-size:.85em;--fc-page-bg-color:#fff;--fc-neutral-bg-color:hsla(0,0%,82%,.3);--fc-neutral-text-color:grey;--fc-border-color:#ddd;--fc-button-text-color:#fff;--fc-button-bg-color:#2c3e50;--fc-button-border-color:#2c3e50;--fc-button-hover-bg-color:#1e2b37;--fc-button-hover-border-color:#1a252f;--fc-button-active-bg-color:#1a252f;--fc-button-active-border-color:#151e27;--fc-event-bg-color:#3788d8;--fc-event-border-color:#3788d8;--fc-event-text-color:#fff;--fc-event-selected-overlay-color:rgba(0,0,0,.25);--fc-more-link-bg-color:#d0d0d0;--fc-more-link-text-color:inherit;--fc-event-resizer-thickness:8px;--fc-event-resizer-dot-total-width:8px;--fc-event-resizer-dot-border-width:1px;--fc-non-business-color:hsla(0,0%,84%,.3);--fc-bg-event-color:#8fdf82;--fc-bg-event-opacity:0.3;--fc-highlight-color:rgba(188,232,241,.3);--fc-today-bg-color:rgba(255,220,40,.15);--fc-now-indicator-color:red}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc-unselectable{-webkit-touch-callout:none;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-moz-user-select:none;user-select:none}.fc{display:flex;flex-direction:column;font-size:1em}.fc,.fc *,.fc :after,.fc :before{box-sizing:border-box}.fc table{border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{padding:0;vertical-align:top}.fc a[data-navlink]{cursor:pointer}.fc a[data-navlink]:hover{text-decoration:underline}.fc-direction-ltr{direction:ltr;text-align:left}.fc-direction-rtl{direction:rtl;text-align:right}.fc-theme-standard td,.fc-theme-standard th{border:1px solid var(--fc-border-color)}.fc-liquid-hack td,.fc-liquid-hack th{position:relative}@font-face{font-family:fcicons;font-style:normal;font-weight:400;src:url(\"data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBfAAAAC8AAAAYGNtYXAXVtKNAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5ZgYydxIAAAF4AAAFNGhlYWQUJ7cIAAAGrAAAADZoaGVhB20DzAAABuQAAAAkaG10eCIABhQAAAcIAAAALGxvY2ED4AU6AAAHNAAAABhtYXhwAA8AjAAAB0wAAAAgbmFtZXsr690AAAdsAAABhnBvc3QAAwAAAAAI9AAAACAAAwPAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpBgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6Qb//f//AAAAAAAg6QD//f//AAH/4xcEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAWIAjQKeAskAEwAAJSc3NjQnJiIHAQYUFwEWMjc2NCcCnuLiDQ0MJAz/AA0NAQAMJAwNDcni4gwjDQwM/wANIwz/AA0NDCMNAAAAAQFiAI0CngLJABMAACUBNjQnASYiBwYUHwEHBhQXFjI3AZ4BAA0N/wAMJAwNDeLiDQ0MJAyNAQAMIw0BAAwMDSMM4uINIwwNDQAAAAIA4gC3Ax4CngATACcAACUnNzY0JyYiDwEGFB8BFjI3NjQnISc3NjQnJiIPAQYUHwEWMjc2NCcB87e3DQ0MIw3VDQ3VDSMMDQ0BK7e3DQ0MJAzVDQ3VDCQMDQ3zuLcMJAwNDdUNIwzWDAwNIwy4twwkDA0N1Q0jDNYMDA0jDAAAAgDiALcDHgKeABMAJwAAJTc2NC8BJiIHBhQfAQcGFBcWMjchNzY0LwEmIgcGFB8BBwYUFxYyNwJJ1Q0N1Q0jDA0Nt7cNDQwjDf7V1Q0N1QwkDA0Nt7cNDQwkDLfWDCMN1Q0NDCQMt7gMIw0MDNYMIw3VDQ0MJAy3uAwjDQwMAAADAFUAAAOrA1UAMwBoAHcAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMhMjY1NCYjISIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAAVYRGRkR/qoRGRkRA1UFBAUOCQkVDAsZDf2rDRkLDBUJCA4FBQUFBQUOCQgVDAsZDQJVDRkLDBUJCQ4FBAVVAgECBQMCBwQECAX9qwQJAwQHAwMFAQICAgIBBQMDBwQDCQQCVQUIBAQHAgMFAgEC/oAZEhEZGRESGQAAAAADAFUAAAOrA1UAMwBoAIkAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMzFRQWMzI2PQEzMjY1NCYrATU0JiMiBh0BIyIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAgBkSEhmAERkZEYAZEhIZgBEZGREDVQUEBQ4JCRUMCxkN/asNGQsMFQkIDgUFBQUFBQ4JCBUMCxkNAlUNGQsMFQkJDgUEBVUCAQIFAwIHBAQIBf2rBAkDBAcDAwUBAgICAgEFAwMHBAMJBAJVBQgEBAcCAwUCAQL+gIASGRkSgBkSERmAEhkZEoAZERIZAAABAOIAjQMeAskAIAAAExcHBhQXFjI/ARcWMjc2NC8BNzY0JyYiDwEnJiIHBhQX4uLiDQ0MJAzi4gwkDA0N4uINDQwkDOLiDCQMDQ0CjeLiDSMMDQ3h4Q0NDCMN4uIMIw0MDOLiDAwNIwwAAAABAAAAAQAAa5n0y18PPPUACwQAAAAAANivOVsAAAAA2K85WwAAAAADqwNVAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAAAAAOrAAEAAAAAAAAAAAAAAAAAAAALBAAAAAAAAAAAAAAAAgAAAAQAAWIEAAFiBAAA4gQAAOIEAABVBAAAVQQAAOIAAAAAAAoAFAAeAEQAagCqAOoBngJkApoAAQAAAAsAigADAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGZjaWNvbnMAZgBjAGkAYwBvAG4Ac1ZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGZjaWNvbnMAZgBjAGkAYwBvAG4Ac2ZjaWNvbnMAZgBjAGkAYwBvAG4Ac1JlZ3VsYXIAUgBlAGcAdQBsAGEAcmZjaWNvbnMAZgBjAGkAYwBvAG4Ac0ZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\") format(\"truetype\")}.fc-icon{speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font-family:fcicons!important;font-style:normal;font-variant:normal;font-weight:400;height:1em;line-height:1;text-align:center;text-transform:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:1em}.fc-icon-chevron-left:before{content:\"\\e900\"}.fc-icon-chevron-right:before{content:\"\\e901\"}.fc-icon-chevrons-left:before{content:\"\\e902\"}.fc-icon-chevrons-right:before{content:\"\\e903\"}.fc-icon-minus-square:before{content:\"\\e904\"}.fc-icon-plus-square:before{content:\"\\e905\"}.fc-icon-x:before{content:\"\\e906\"}.fc .fc-button{border-radius:0;font-family:inherit;font-size:inherit;line-height:inherit;margin:0;overflow:visible;text-transform:none}.fc .fc-button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.fc .fc-button{-webkit-appearance:button}.fc .fc-button:not(:disabled){cursor:pointer}.fc .fc-button::-moz-focus-inner{border-style:none;padding:0}.fc .fc-button{background-color:transparent;border:1px solid transparent;border-radius:.25em;display:inline-block;font-size:1em;font-weight:400;line-height:1.5;padding:.4em .65em;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}.fc .fc-button:hover{text-decoration:none}.fc .fc-button:focus{box-shadow:0 0 0 .2rem rgba(44,62,80,.25);outline:0}.fc .fc-button:disabled{opacity:.65}.fc .fc-button-primary{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:hover{background-color:var(--fc-button-hover-bg-color);border-color:var(--fc-button-hover-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:disabled{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button-primary:not(:disabled).fc-button-active,.fc .fc-button-primary:not(:disabled):active{background-color:var(--fc-button-active-bg-color);border-color:var(--fc-button-active-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:not(:disabled).fc-button-active:focus,.fc .fc-button-primary:not(:disabled):active:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button .fc-icon{font-size:1.5em;vertical-align:middle}.fc .fc-button-group{display:inline-flex;position:relative;vertical-align:middle}.fc .fc-button-group>.fc-button{flex:1 1 auto;position:relative}.fc .fc-button-group>.fc-button.fc-button-active,.fc .fc-button-group>.fc-button:active,.fc .fc-button-group>.fc-button:focus,.fc .fc-button-group>.fc-button:hover{z-index:1}.fc-direction-ltr .fc-button-group>.fc-button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;margin-left:-1px}.fc-direction-ltr .fc-button-group>.fc-button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.fc-direction-rtl .fc-button-group>.fc-button:not(:first-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.fc-direction-rtl .fc-button-group>.fc-button:not(:last-child){border-bottom-left-radius:0;border-top-left-radius:0}.fc .fc-toolbar{align-items:center;display:flex;justify-content:space-between}.fc .fc-toolbar.fc-header-toolbar{margin-bottom:1.5em}.fc .fc-toolbar.fc-footer-toolbar{margin-top:1.5em}.fc .fc-toolbar-title{font-size:1.75em;margin:0}.fc-direction-ltr .fc-toolbar>*>:not(:first-child){margin-left:.75em}.fc-direction-rtl .fc-toolbar>*>:not(:first-child){margin-right:.75em}.fc-direction-rtl .fc-toolbar-ltr{flex-direction:row-reverse}.fc .fc-scroller{-webkit-overflow-scrolling:touch;position:relative}.fc .fc-scroller-liquid{height:100%}.fc .fc-scroller-liquid-absolute{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-scroller-harness{direction:ltr;overflow:hidden;position:relative}.fc .fc-scroller-harness-liquid{height:100%}.fc-direction-rtl .fc-scroller-harness>.fc-scroller{direction:rtl}.fc-theme-standard .fc-scrollgrid{border:1px solid var(--fc-border-color)}.fc .fc-scrollgrid,.fc .fc-scrollgrid table{table-layout:fixed;width:100%}.fc .fc-scrollgrid table{border-left-style:hidden;border-right-style:hidden;border-top-style:hidden}.fc .fc-scrollgrid{border-bottom-width:0;border-collapse:separate;border-right-width:0}.fc .fc-scrollgrid-liquid{height:100%}.fc .fc-scrollgrid-section,.fc .fc-scrollgrid-section table,.fc .fc-scrollgrid-section>td{height:1px}.fc .fc-scrollgrid-section-liquid>td{height:100%}.fc .fc-scrollgrid-section>*{border-left-width:0;border-top-width:0}.fc .fc-scrollgrid-section-footer>*,.fc .fc-scrollgrid-section-header>*{border-bottom-width:0}.fc .fc-scrollgrid-section-body table,.fc .fc-scrollgrid-section-footer table{border-bottom-style:hidden}.fc .fc-scrollgrid-section-sticky>*{background:var(--fc-page-bg-color);position:sticky;z-index:3}.fc .fc-scrollgrid-section-header.fc-scrollgrid-section-sticky>*{top:0}.fc .fc-scrollgrid-section-footer.fc-scrollgrid-section-sticky>*{bottom:0}.fc .fc-scrollgrid-sticky-shim{height:1px;margin-bottom:-1px}.fc-sticky{position:sticky}.fc .fc-view-harness{flex-grow:1;position:relative}.fc .fc-view-harness-active>.fc-view{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-col-header-cell-cushion{display:inline-block;padding:2px 4px}.fc .fc-bg-event,.fc .fc-highlight,.fc .fc-non-business{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-non-business{background:var(--fc-non-business-color)}.fc .fc-bg-event{background:var(--fc-bg-event-color);opacity:var(--fc-bg-event-opacity)}.fc .fc-bg-event .fc-event-title{font-size:var(--fc-small-font-size);font-style:italic;margin:.5em}.fc .fc-highlight{background:var(--fc-highlight-color)}.fc .fc-cell-shaded,.fc .fc-day-disabled{background:var(--fc-neutral-bg-color)}a.fc-event,a.fc-event:hover{text-decoration:none}.fc-event.fc-event-draggable,.fc-event[href]{cursor:pointer}.fc-event .fc-event-main{position:relative;z-index:2}.fc-event-dragging:not(.fc-event-selected){opacity:.75}.fc-event-dragging.fc-event-selected{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-event .fc-event-resizer{display:none;position:absolute;z-index:4}.fc-event-selected .fc-event-resizer,.fc-event:hover .fc-event-resizer{display:block}.fc-event-selected .fc-event-resizer{background:var(--fc-page-bg-color);border-color:inherit;border-radius:calc(var(--fc-event-resizer-dot-total-width)/2);border-style:solid;border-width:var(--fc-event-resizer-dot-border-width);height:var(--fc-event-resizer-dot-total-width);width:var(--fc-event-resizer-dot-total-width)}.fc-event-selected .fc-event-resizer:before{bottom:-20px;content:\"\";left:-20px;position:absolute;right:-20px;top:-20px}.fc-event-selected,.fc-event:focus{box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event-selected:before,.fc-event:focus:before{bottom:0;content:\"\";left:0;position:absolute;right:0;top:0;z-index:3}.fc-event-selected:after,.fc-event:focus:after{background:var(--fc-event-selected-overlay-color);bottom:-1px;content:\"\";left:-1px;position:absolute;right:-1px;top:-1px;z-index:1}.fc-h-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-h-event .fc-event-main{color:var(--fc-event-text-color)}.fc-h-event .fc-event-main-frame{display:flex}.fc-h-event .fc-event-time{max-width:100%;overflow:hidden}.fc-h-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-width:0}.fc-h-event .fc-event-title{display:inline-block;left:0;max-width:100%;overflow:hidden;right:0;vertical-align:top}.fc-h-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-start),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-end){border-bottom-left-radius:0;border-left-width:0;border-top-left-radius:0}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-end),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-start){border-bottom-right-radius:0;border-right-width:0;border-top-right-radius:0}.fc-h-event:not(.fc-event-selected) .fc-event-resizer{bottom:0;top:0;width:var(--fc-event-resizer-thickness)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end{cursor:w-resize;left:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start{cursor:e-resize;right:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-h-event.fc-event-selected .fc-event-resizer{margin-top:calc(var(--fc-event-resizer-dot-total-width)*-.5);top:50%}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-start,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-end{left:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-end,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-start{right:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc .fc-popover{box-shadow:0 2px 6px rgba(0,0,0,.15);position:absolute;z-index:9999}.fc .fc-popover-header{align-items:center;display:flex;flex-direction:row;justify-content:space-between;padding:3px 4px}.fc .fc-popover-title{margin:0 2px}.fc .fc-popover-close{cursor:pointer;font-size:1.1em;opacity:.65}.fc-theme-standard .fc-popover{background:var(--fc-page-bg-color);border:1px solid var(--fc-border-color)}.fc-theme-standard .fc-popover-header{background:var(--fc-neutral-bg-color)}";
+ injectStyles(css_248z$3);
+
+ const globalLocales = [];
+
+ const MINIMAL_RAW_EN_LOCALE = {
+ code: 'en',
+ week: {
+ dow: 0,
+ doy: 4, // 4 days need to be within the year to be considered the first week
+ },
+ direction: 'ltr',
+ buttonText: {
+ prev: 'prev',
+ next: 'next',
+ prevYear: 'prev year',
+ nextYear: 'next year',
+ year: 'year',
+ today: 'today',
+ month: 'month',
+ week: 'week',
+ day: 'day',
+ list: 'list',
+ },
+ weekText: 'W',
+ weekTextLong: 'Week',
+ closeHint: 'Close',
+ timeHint: 'Time',
+ eventHint: 'Event',
+ allDayText: 'all-day',
+ moreLinkText: 'more',
+ noEventsText: 'No events to display',
+ };
+ const RAW_EN_LOCALE = Object.assign(Object.assign({}, MINIMAL_RAW_EN_LOCALE), {
+ // Includes things we don't want other locales to inherit,
+ // things that derive from other translatable strings.
+ buttonHints: {
+ prev: 'Previous $0',
+ next: 'Next $0',
+ today(buttonText, unit) {
+ return (unit === 'day')
+ ? 'Today'
+ : `This ${buttonText}`;
+ },
+ }, viewHint: '$0 view', navLinkHint: 'Go to $0', moreLinkHint(eventCnt) {
+ return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;
+ } });
+ function organizeRawLocales(explicitRawLocales) {
+ let defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en';
+ let allRawLocales = globalLocales.concat(explicitRawLocales);
+ let rawLocaleMap = {
+ en: RAW_EN_LOCALE,
+ };
+ for (let rawLocale of allRawLocales) {
+ rawLocaleMap[rawLocale.code] = rawLocale;
+ }
+ return {
+ map: rawLocaleMap,
+ defaultCode,
+ };
+ }
+ function buildLocale(inputSingular, available) {
+ if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) {
+ return parseLocale(inputSingular.code, [inputSingular.code], inputSingular);
+ }
+ return queryLocale(inputSingular, available);
+ }
+ function queryLocale(codeArg, available) {
+ let codes = [].concat(codeArg || []); // will convert to array
+ let raw = queryRawLocale(codes, available) || RAW_EN_LOCALE;
+ return parseLocale(codeArg, codes, raw);
+ }
+ function queryRawLocale(codes, available) {
+ for (let i = 0; i < codes.length; i += 1) {
+ let parts = codes[i].toLocaleLowerCase().split('-');
+ for (let j = parts.length; j > 0; j -= 1) {
+ let simpleId = parts.slice(0, j).join('-');
+ if (available[simpleId]) {
+ return available[simpleId];
+ }
+ }
+ }
+ return null;
+ }
+ function parseLocale(codeArg, codes, raw) {
+ let merged = mergeProps([MINIMAL_RAW_EN_LOCALE, raw], ['buttonText']);
+ delete merged.code; // don't want this part of the options
+ let { week } = merged;
+ delete merged.week;
+ return {
+ codeArg,
+ codes,
+ week,
+ simpleNumberFormat: new Intl.NumberFormat(codeArg),
+ options: merged,
+ };
+ }
+
+ // TODO: easier way to add new hooks? need to update a million things
+ function createPlugin(input) {
+ return {
+ id: guid(),
+ name: input.name,
+ premiumReleaseDate: input.premiumReleaseDate ? new Date(input.premiumReleaseDate) : undefined,
+ deps: input.deps || [],
+ reducers: input.reducers || [],
+ isLoadingFuncs: input.isLoadingFuncs || [],
+ contextInit: [].concat(input.contextInit || []),
+ eventRefiners: input.eventRefiners || {},
+ eventDefMemberAdders: input.eventDefMemberAdders || [],
+ eventSourceRefiners: input.eventSourceRefiners || {},
+ isDraggableTransformers: input.isDraggableTransformers || [],
+ eventDragMutationMassagers: input.eventDragMutationMassagers || [],
+ eventDefMutationAppliers: input.eventDefMutationAppliers || [],
+ dateSelectionTransformers: input.dateSelectionTransformers || [],
+ datePointTransforms: input.datePointTransforms || [],
+ dateSpanTransforms: input.dateSpanTransforms || [],
+ views: input.views || {},
+ viewPropsTransformers: input.viewPropsTransformers || [],
+ isPropsValid: input.isPropsValid || null,
+ externalDefTransforms: input.externalDefTransforms || [],
+ viewContainerAppends: input.viewContainerAppends || [],
+ eventDropTransformers: input.eventDropTransformers || [],
+ componentInteractions: input.componentInteractions || [],
+ calendarInteractions: input.calendarInteractions || [],
+ themeClasses: input.themeClasses || {},
+ eventSourceDefs: input.eventSourceDefs || [],
+ cmdFormatter: input.cmdFormatter,
+ recurringTypes: input.recurringTypes || [],
+ namedTimeZonedImpl: input.namedTimeZonedImpl,
+ initialView: input.initialView || '',
+ elementDraggingImpl: input.elementDraggingImpl,
+ optionChangeHandlers: input.optionChangeHandlers || {},
+ scrollGridImpl: input.scrollGridImpl || null,
+ listenerRefiners: input.listenerRefiners || {},
+ optionRefiners: input.optionRefiners || {},
+ propSetHandlers: input.propSetHandlers || {},
+ };
+ }
+ function buildPluginHooks(pluginDefs, globalDefs) {
+ let currentPluginIds = {};
+ let hooks = {
+ premiumReleaseDate: undefined,
+ reducers: [],
+ isLoadingFuncs: [],
+ contextInit: [],
+ eventRefiners: {},
+ eventDefMemberAdders: [],
+ eventSourceRefiners: {},
+ isDraggableTransformers: [],
+ eventDragMutationMassagers: [],
+ eventDefMutationAppliers: [],
+ dateSelectionTransformers: [],
+ datePointTransforms: [],
+ dateSpanTransforms: [],
+ views: {},
+ viewPropsTransformers: [],
+ isPropsValid: null,
+ externalDefTransforms: [],
+ viewContainerAppends: [],
+ eventDropTransformers: [],
+ componentInteractions: [],
+ calendarInteractions: [],
+ themeClasses: {},
+ eventSourceDefs: [],
+ cmdFormatter: null,
+ recurringTypes: [],
+ namedTimeZonedImpl: null,
+ initialView: '',
+ elementDraggingImpl: null,
+ optionChangeHandlers: {},
+ scrollGridImpl: null,
+ listenerRefiners: {},
+ optionRefiners: {},
+ propSetHandlers: {},
+ };
+ function addDefs(defs) {
+ for (let def of defs) {
+ const pluginName = def.name;
+ const currentId = currentPluginIds[pluginName];
+ if (currentId === undefined) {
+ currentPluginIds[pluginName] = def.id;
+ addDefs(def.deps);
+ hooks = combineHooks(hooks, def);
+ }
+ else if (currentId !== def.id) {
+ // different ID than the one already added
+ console.warn(`Duplicate plugin '${pluginName}'`);
+ }
+ }
+ }
+ if (pluginDefs) {
+ addDefs(pluginDefs);
+ }
+ addDefs(globalDefs);
+ return hooks;
+ }
+ function buildBuildPluginHooks() {
+ let currentOverrideDefs = [];
+ let currentGlobalDefs = [];
+ let currentHooks;
+ return (overrideDefs, globalDefs) => {
+ if (!currentHooks || !isArraysEqual(overrideDefs, currentOverrideDefs) || !isArraysEqual(globalDefs, currentGlobalDefs)) {
+ currentHooks = buildPluginHooks(overrideDefs, globalDefs);
+ }
+ currentOverrideDefs = overrideDefs;
+ currentGlobalDefs = globalDefs;
+ return currentHooks;
+ };
+ }
+ function combineHooks(hooks0, hooks1) {
+ return {
+ premiumReleaseDate: compareOptionalDates(hooks0.premiumReleaseDate, hooks1.premiumReleaseDate),
+ reducers: hooks0.reducers.concat(hooks1.reducers),
+ isLoadingFuncs: hooks0.isLoadingFuncs.concat(hooks1.isLoadingFuncs),
+ contextInit: hooks0.contextInit.concat(hooks1.contextInit),
+ eventRefiners: Object.assign(Object.assign({}, hooks0.eventRefiners), hooks1.eventRefiners),
+ eventDefMemberAdders: hooks0.eventDefMemberAdders.concat(hooks1.eventDefMemberAdders),
+ eventSourceRefiners: Object.assign(Object.assign({}, hooks0.eventSourceRefiners), hooks1.eventSourceRefiners),
+ isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers),
+ eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers),
+ eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers),
+ dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers),
+ datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms),
+ dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms),
+ views: Object.assign(Object.assign({}, hooks0.views), hooks1.views),
+ viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers),
+ isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid,
+ externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms),
+ viewContainerAppends: hooks0.viewContainerAppends.concat(hooks1.viewContainerAppends),
+ eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers),
+ calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions),
+ componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions),
+ themeClasses: Object.assign(Object.assign({}, hooks0.themeClasses), hooks1.themeClasses),
+ eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs),
+ cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter,
+ recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes),
+ namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl,
+ initialView: hooks0.initialView || hooks1.initialView,
+ elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl,
+ optionChangeHandlers: Object.assign(Object.assign({}, hooks0.optionChangeHandlers), hooks1.optionChangeHandlers),
+ scrollGridImpl: hooks1.scrollGridImpl || hooks0.scrollGridImpl,
+ listenerRefiners: Object.assign(Object.assign({}, hooks0.listenerRefiners), hooks1.listenerRefiners),
+ optionRefiners: Object.assign(Object.assign({}, hooks0.optionRefiners), hooks1.optionRefiners),
+ propSetHandlers: Object.assign(Object.assign({}, hooks0.propSetHandlers), hooks1.propSetHandlers),
+ };
+ }
+ function compareOptionalDates(date0, date1) {
+ if (date0 === undefined) {
+ return date1;
+ }
+ if (date1 === undefined) {
+ return date0;
+ }
+ return new Date(Math.max(date0.valueOf(), date1.valueOf()));
+ }
+
+ class StandardTheme extends Theme {
+ }
+ StandardTheme.prototype.classes = {
+ root: 'fc-theme-standard',
+ tableCellShaded: 'fc-cell-shaded',
+ buttonGroup: 'fc-button-group',
+ button: 'fc-button fc-button-primary',
+ buttonActive: 'fc-button-active',
+ };
+ StandardTheme.prototype.baseIconClass = 'fc-icon';
+ StandardTheme.prototype.iconClasses = {
+ close: 'fc-icon-x',
+ prev: 'fc-icon-chevron-left',
+ next: 'fc-icon-chevron-right',
+ prevYear: 'fc-icon-chevrons-left',
+ nextYear: 'fc-icon-chevrons-right',
+ };
+ StandardTheme.prototype.rtlIconClasses = {
+ prev: 'fc-icon-chevron-right',
+ next: 'fc-icon-chevron-left',
+ prevYear: 'fc-icon-chevrons-right',
+ nextYear: 'fc-icon-chevrons-left',
+ };
+ StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; // TODO: make TS-friendly
+ StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon';
+ StandardTheme.prototype.iconOverridePrefix = 'fc-icon-';
+
+ function compileViewDefs(defaultConfigs, overrideConfigs) {
+ let hash = {};
+ let viewType;
+ for (viewType in defaultConfigs) {
+ ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
+ }
+ for (viewType in overrideConfigs) {
+ ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
+ }
+ return hash;
+ }
+ function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
+ if (hash[viewType]) {
+ return hash[viewType];
+ }
+ let viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs);
+ if (viewDef) {
+ hash[viewType] = viewDef;
+ }
+ return viewDef;
+ }
+ function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
+ let defaultConfig = defaultConfigs[viewType];
+ let overrideConfig = overrideConfigs[viewType];
+ let queryProp = (name) => ((defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] :
+ ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null));
+ let theComponent = queryProp('component');
+ let superType = queryProp('superType');
+ let superDef = null;
+ if (superType) {
+ if (superType === viewType) {
+ throw new Error('Can\'t have a custom view type that references itself');
+ }
+ superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs);
+ }
+ if (!theComponent && superDef) {
+ theComponent = superDef.component;
+ }
+ if (!theComponent) {
+ return null; // don't throw a warning, might be settings for a single-unit view
+ }
+ return {
+ type: viewType,
+ component: theComponent,
+ defaults: Object.assign(Object.assign({}, (superDef ? superDef.defaults : {})), (defaultConfig ? defaultConfig.rawOptions : {})),
+ overrides: Object.assign(Object.assign({}, (superDef ? superDef.overrides : {})), (overrideConfig ? overrideConfig.rawOptions : {})),
+ };
+ }
+
+ function parseViewConfigs(inputs) {
+ return mapHash(inputs, parseViewConfig);
+ }
+ function parseViewConfig(input) {
+ let rawOptions = typeof input === 'function' ?
+ { component: input } :
+ input;
+ let { component } = rawOptions;
+ if (rawOptions.content) {
+ component = createViewHookComponent(rawOptions);
+ // TODO: remove content/classNames/didMount/etc from options?
+ }
+ return {
+ superType: rawOptions.type,
+ component: component,
+ rawOptions, // includes type and component too :(
+ };
+ }
+ function createViewHookComponent(options) {
+ return (viewProps) => (h(ViewContextType.Consumer, null, (context) => (h(ContentContainer, { elTag: "div", elClasses: buildViewClassNames(context.viewSpec), renderProps: Object.assign(Object.assign({}, viewProps), { nextDayThreshold: context.options.nextDayThreshold }), generatorName: undefined, generator: options.content, classNameGenerator: options.classNames, didMount: options.didMount, willUnmount: options.willUnmount }))));
+ }
+
+ function buildViewSpecs(defaultInputs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
+ let defaultConfigs = parseViewConfigs(defaultInputs);
+ let overrideConfigs = parseViewConfigs(optionOverrides.views);
+ let viewDefs = compileViewDefs(defaultConfigs, overrideConfigs);
+ return mapHash(viewDefs, (viewDef) => buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults));
+ }
+ function buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
+ let durationInput = viewDef.overrides.duration ||
+ viewDef.defaults.duration ||
+ dynamicOptionOverrides.duration ||
+ optionOverrides.duration;
+ let duration = null;
+ let durationUnit = '';
+ let singleUnit = '';
+ let singleUnitOverrides = {};
+ if (durationInput) {
+ duration = createDurationCached(durationInput);
+ if (duration) { // valid?
+ let denom = greatestDurationDenominator(duration);
+ durationUnit = denom.unit;
+ if (denom.value === 1) {
+ singleUnit = durationUnit;
+ singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].rawOptions : {};
+ }
+ }
+ }
+ let queryButtonText = (optionsSubset) => {
+ let buttonTextMap = optionsSubset.buttonText || {};
+ let buttonTextKey = viewDef.defaults.buttonTextKey;
+ if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) {
+ return buttonTextMap[buttonTextKey];
+ }
+ if (buttonTextMap[viewDef.type] != null) {
+ return buttonTextMap[viewDef.type];
+ }
+ if (buttonTextMap[singleUnit] != null) {
+ return buttonTextMap[singleUnit];
+ }
+ return null;
+ };
+ let queryButtonTitle = (optionsSubset) => {
+ let buttonHints = optionsSubset.buttonHints || {};
+ let buttonKey = viewDef.defaults.buttonTextKey; // use same key as text
+ if (buttonKey != null && buttonHints[buttonKey] != null) {
+ return buttonHints[buttonKey];
+ }
+ if (buttonHints[viewDef.type] != null) {
+ return buttonHints[viewDef.type];
+ }
+ if (buttonHints[singleUnit] != null) {
+ return buttonHints[singleUnit];
+ }
+ return null;
+ };
+ return {
+ type: viewDef.type,
+ component: viewDef.component,
+ duration,
+ durationUnit,
+ singleUnit,
+ optionDefaults: viewDef.defaults,
+ optionOverrides: Object.assign(Object.assign({}, singleUnitOverrides), viewDef.overrides),
+ buttonTextOverride: queryButtonText(dynamicOptionOverrides) ||
+ queryButtonText(optionOverrides) || // constructor-specified buttonText lookup hash takes precedence
+ viewDef.overrides.buttonText,
+ buttonTextDefault: queryButtonText(localeDefaults) ||
+ viewDef.defaults.buttonText ||
+ queryButtonText(BASE_OPTION_DEFAULTS) ||
+ viewDef.type,
+ // not DRY
+ buttonTitleOverride: queryButtonTitle(dynamicOptionOverrides) ||
+ queryButtonTitle(optionOverrides) ||
+ viewDef.overrides.buttonHint,
+ buttonTitleDefault: queryButtonTitle(localeDefaults) ||
+ viewDef.defaults.buttonHint ||
+ queryButtonTitle(BASE_OPTION_DEFAULTS),
+ // will eventually fall back to buttonText
+ };
+ }
+ // hack to get memoization working
+ let durationInputMap = {};
+ function createDurationCached(durationInput) {
+ let json = JSON.stringify(durationInput);
+ let res = durationInputMap[json];
+ if (res === undefined) {
+ res = createDuration(durationInput);
+ durationInputMap[json] = res;
+ }
+ return res;
+ }
+
+ function reduceViewType(viewType, action) {
+ switch (action.type) {
+ case 'CHANGE_VIEW_TYPE':
+ viewType = action.viewType;
+ }
+ return viewType;
+ }
+
+ function reduceDynamicOptionOverrides(dynamicOptionOverrides, action) {
+ switch (action.type) {
+ case 'SET_OPTION':
+ return Object.assign(Object.assign({}, dynamicOptionOverrides), { [action.optionName]: action.rawOptionValue });
+ default:
+ return dynamicOptionOverrides;
+ }
+ }
+
+ function reduceDateProfile(currentDateProfile, action, currentDate, dateProfileGenerator) {
+ let dp;
+ switch (action.type) {
+ case 'CHANGE_VIEW_TYPE':
+ return dateProfileGenerator.build(action.dateMarker || currentDate);
+ case 'CHANGE_DATE':
+ return dateProfileGenerator.build(action.dateMarker);
+ case 'PREV':
+ dp = dateProfileGenerator.buildPrev(currentDateProfile, currentDate);
+ if (dp.isValid) {
+ return dp;
+ }
+ break;
+ case 'NEXT':
+ dp = dateProfileGenerator.buildNext(currentDateProfile, currentDate);
+ if (dp.isValid) {
+ return dp;
+ }
+ break;
+ }
+ return currentDateProfile;
+ }
+
+ function initEventSources(calendarOptions, dateProfile, context) {
+ let activeRange = dateProfile ? dateProfile.activeRange : null;
+ return addSources({}, parseInitialSources(calendarOptions, context), activeRange, context);
+ }
+ function reduceEventSources(eventSources, action, dateProfile, context) {
+ let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
+ switch (action.type) {
+ case 'ADD_EVENT_SOURCES': // already parsed
+ return addSources(eventSources, action.sources, activeRange, context);
+ case 'REMOVE_EVENT_SOURCE':
+ return removeSource(eventSources, action.sourceId);
+ case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
+ case 'NEXT':
+ case 'CHANGE_DATE':
+ case 'CHANGE_VIEW_TYPE':
+ if (dateProfile) {
+ return fetchDirtySources(eventSources, activeRange, context);
+ }
+ return eventSources;
+ case 'FETCH_EVENT_SOURCES':
+ return fetchSourcesByIds(eventSources, action.sourceIds ? // why no type?
+ arrayToHash(action.sourceIds) :
+ excludeStaticSources(eventSources, context), activeRange, action.isRefetch || false, context);
+ case 'RECEIVE_EVENTS':
+ case 'RECEIVE_EVENT_ERROR':
+ return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange);
+ case 'REMOVE_ALL_EVENT_SOURCES':
+ return {};
+ default:
+ return eventSources;
+ }
+ }
+ function reduceEventSourcesNewTimeZone(eventSources, dateProfile, context) {
+ let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
+ return fetchSourcesByIds(eventSources, excludeStaticSources(eventSources, context), activeRange, true, context);
+ }
+ function computeEventSourcesLoading(eventSources) {
+ for (let sourceId in eventSources) {
+ if (eventSources[sourceId].isFetching) {
+ return true;
+ }
+ }
+ return false;
+ }
+ function addSources(eventSourceHash, sources, fetchRange, context) {
+ let hash = {};
+ for (let source of sources) {
+ hash[source.sourceId] = source;
+ }
+ if (fetchRange) {
+ hash = fetchDirtySources(hash, fetchRange, context);
+ }
+ return Object.assign(Object.assign({}, eventSourceHash), hash);
+ }
+ function removeSource(eventSourceHash, sourceId) {
+ return filterHash(eventSourceHash, (eventSource) => eventSource.sourceId !== sourceId);
+ }
+ function fetchDirtySources(sourceHash, fetchRange, context) {
+ return fetchSourcesByIds(sourceHash, filterHash(sourceHash, (eventSource) => isSourceDirty(eventSource, fetchRange, context)), fetchRange, false, context);
+ }
+ function isSourceDirty(eventSource, fetchRange, context) {
+ if (!doesSourceNeedRange(eventSource, context)) {
+ return !eventSource.latestFetchId;
+ }
+ return !context.options.lazyFetching ||
+ !eventSource.fetchRange ||
+ eventSource.isFetching || // always cancel outdated in-progress fetches
+ fetchRange.start < eventSource.fetchRange.start ||
+ fetchRange.end > eventSource.fetchRange.end;
+ }
+ function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, isRefetch, context) {
+ let nextSources = {};
+ for (let sourceId in prevSources) {
+ let source = prevSources[sourceId];
+ if (sourceIdHash[sourceId]) {
+ nextSources[sourceId] = fetchSource(source, fetchRange, isRefetch, context);
+ }
+ else {
+ nextSources[sourceId] = source;
+ }
+ }
+ return nextSources;
+ }
+ function fetchSource(eventSource, fetchRange, isRefetch, context) {
+ let { options, calendarApi } = context;
+ let sourceDef = context.pluginHooks.eventSourceDefs[eventSource.sourceDefId];
+ let fetchId = guid();
+ sourceDef.fetch({
+ eventSource,
+ range: fetchRange,
+ isRefetch,
+ context,
+ }, (res) => {
+ let { rawEvents } = res;
+ if (options.eventSourceSuccess) {
+ rawEvents = options.eventSourceSuccess.call(calendarApi, rawEvents, res.response) || rawEvents;
+ }
+ if (eventSource.success) {
+ rawEvents = eventSource.success.call(calendarApi, rawEvents, res.response) || rawEvents;
+ }
+ context.dispatch({
+ type: 'RECEIVE_EVENTS',
+ sourceId: eventSource.sourceId,
+ fetchId,
+ fetchRange,
+ rawEvents,
+ });
+ }, (error) => {
+ let errorHandled = false;
+ if (options.eventSourceFailure) {
+ options.eventSourceFailure.call(calendarApi, error);
+ errorHandled = true;
+ }
+ if (eventSource.failure) {
+ eventSource.failure(error);
+ errorHandled = true;
+ }
+ if (!errorHandled) {
+ console.warn(error.message, error);
+ }
+ context.dispatch({
+ type: 'RECEIVE_EVENT_ERROR',
+ sourceId: eventSource.sourceId,
+ fetchId,
+ fetchRange,
+ error,
+ });
+ });
+ return Object.assign(Object.assign({}, eventSource), { isFetching: true, latestFetchId: fetchId });
+ }
+ function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) {
+ let eventSource = sourceHash[sourceId];
+ if (eventSource && // not already removed
+ fetchId === eventSource.latestFetchId) {
+ return Object.assign(Object.assign({}, sourceHash), { [sourceId]: Object.assign(Object.assign({}, eventSource), { isFetching: false, fetchRange }) });
+ }
+ return sourceHash;
+ }
+ function excludeStaticSources(eventSources, context) {
+ return filterHash(eventSources, (eventSource) => doesSourceNeedRange(eventSource, context));
+ }
+ function parseInitialSources(rawOptions, context) {
+ let refiners = buildEventSourceRefiners(context);
+ let rawSources = [].concat(rawOptions.eventSources || []);
+ let sources = []; // parsed
+ if (rawOptions.initialEvents) {
+ rawSources.unshift(rawOptions.initialEvents);
+ }
+ if (rawOptions.events) {
+ rawSources.unshift(rawOptions.events);
+ }
+ for (let rawSource of rawSources) {
+ let source = parseEventSource(rawSource, context, refiners);
+ if (source) {
+ sources.push(source);
+ }
+ }
+ return sources;
+ }
+ function doesSourceNeedRange(eventSource, context) {
+ let defs = context.pluginHooks.eventSourceDefs;
+ return !defs[eventSource.sourceDefId].ignoreRange;
+ }
+
+ function reduceDateSelection(currentSelection, action) {
+ switch (action.type) {
+ case 'UNSELECT_DATES':
+ return null;
+ case 'SELECT_DATES':
+ return action.selection;
+ default:
+ return currentSelection;
+ }
+ }
+
+ function reduceSelectedEvent(currentInstanceId, action) {
+ switch (action.type) {
+ case 'UNSELECT_EVENT':
+ return '';
+ case 'SELECT_EVENT':
+ return action.eventInstanceId;
+ default:
+ return currentInstanceId;
+ }
+ }
+
+ function reduceEventDrag(currentDrag, action) {
+ let newDrag;
+ switch (action.type) {
+ case 'UNSET_EVENT_DRAG':
+ return null;
+ case 'SET_EVENT_DRAG':
+ newDrag = action.state;
+ return {
+ affectedEvents: newDrag.affectedEvents,
+ mutatedEvents: newDrag.mutatedEvents,
+ isEvent: newDrag.isEvent,
+ };
+ default:
+ return currentDrag;
+ }
+ }
+
+ function reduceEventResize(currentResize, action) {
+ let newResize;
+ switch (action.type) {
+ case 'UNSET_EVENT_RESIZE':
+ return null;
+ case 'SET_EVENT_RESIZE':
+ newResize = action.state;
+ return {
+ affectedEvents: newResize.affectedEvents,
+ mutatedEvents: newResize.mutatedEvents,
+ isEvent: newResize.isEvent,
+ };
+ default:
+ return currentResize;
+ }
+ }
+
+ function parseToolbars(calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
+ let header = calendarOptions.headerToolbar ? parseToolbar(calendarOptions.headerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
+ let footer = calendarOptions.footerToolbar ? parseToolbar(calendarOptions.footerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
+ return { header, footer };
+ }
+ function parseToolbar(sectionStrHash, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
+ let sectionWidgets = {};
+ let viewsWithButtons = [];
+ let hasTitle = false;
+ for (let sectionName in sectionStrHash) {
+ let sectionStr = sectionStrHash[sectionName];
+ let sectionRes = parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi);
+ sectionWidgets[sectionName] = sectionRes.widgets;
+ viewsWithButtons.push(...sectionRes.viewsWithButtons);
+ hasTitle = hasTitle || sectionRes.hasTitle;
+ }
+ return { sectionWidgets, viewsWithButtons, hasTitle };
+ }
+ /*
+ BAD: querying icons and text here. should be done at render time
+ */
+ function parseSection(sectionStr, calendarOptions, // defaults+overrides, then refined
+ calendarOptionOverrides, // overrides only!, unrefined :(
+ theme, viewSpecs, calendarApi) {
+ let isRtl = calendarOptions.direction === 'rtl';
+ let calendarCustomButtons = calendarOptions.customButtons || {};
+ let calendarButtonTextOverrides = calendarOptionOverrides.buttonText || {};
+ let calendarButtonText = calendarOptions.buttonText || {};
+ let calendarButtonHintOverrides = calendarOptionOverrides.buttonHints || {};
+ let calendarButtonHints = calendarOptions.buttonHints || {};
+ let sectionSubstrs = sectionStr ? sectionStr.split(' ') : [];
+ let viewsWithButtons = [];
+ let hasTitle = false;
+ let widgets = sectionSubstrs.map((buttonGroupStr) => (buttonGroupStr.split(',').map((buttonName) => {
+ if (buttonName === 'title') {
+ hasTitle = true;
+ return { buttonName };
+ }
+ let customButtonProps;
+ let viewSpec;
+ let buttonClick;
+ let buttonIcon; // only one of these will be set
+ let buttonText; // "
+ let buttonHint;
+ // ^ for the title="" attribute, for accessibility
+ if ((customButtonProps = calendarCustomButtons[buttonName])) {
+ buttonClick = (ev) => {
+ if (customButtonProps.click) {
+ customButtonProps.click.call(ev.target, ev, ev.target); // TODO: use Calendar this context?
+ }
+ };
+ (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) ||
+ (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
+ (buttonText = customButtonProps.text);
+ buttonHint = customButtonProps.hint || customButtonProps.text;
+ }
+ else if ((viewSpec = viewSpecs[buttonName])) {
+ viewsWithButtons.push(buttonName);
+ buttonClick = () => {
+ calendarApi.changeView(buttonName);
+ };
+ (buttonText = viewSpec.buttonTextOverride) ||
+ (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
+ (buttonText = viewSpec.buttonTextDefault);
+ let textFallback = viewSpec.buttonTextOverride ||
+ viewSpec.buttonTextDefault;
+ buttonHint = formatWithOrdinals(viewSpec.buttonTitleOverride ||
+ viewSpec.buttonTitleDefault ||
+ calendarOptions.viewHint, [textFallback, buttonName], // view-name = buttonName
+ textFallback);
+ }
+ else if (calendarApi[buttonName]) { // a calendarApi method
+ buttonClick = () => {
+ calendarApi[buttonName]();
+ };
+ (buttonText = calendarButtonTextOverrides[buttonName]) ||
+ (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
+ (buttonText = calendarButtonText[buttonName]); // everything else is considered default
+ if (buttonName === 'prevYear' || buttonName === 'nextYear') {
+ let prevOrNext = buttonName === 'prevYear' ? 'prev' : 'next';
+ buttonHint = formatWithOrdinals(calendarButtonHintOverrides[prevOrNext] ||
+ calendarButtonHints[prevOrNext], [
+ calendarButtonText.year || 'year',
+ 'year',
+ ], calendarButtonText[buttonName]);
+ }
+ else {
+ buttonHint = (navUnit) => formatWithOrdinals(calendarButtonHintOverrides[buttonName] ||
+ calendarButtonHints[buttonName], [
+ calendarButtonText[navUnit] || navUnit,
+ navUnit,
+ ], calendarButtonText[buttonName]);
+ }
+ }
+ return { buttonName, buttonClick, buttonIcon, buttonText, buttonHint };
+ })));
+ return { widgets, viewsWithButtons, hasTitle };
+ }
+
+ // always represents the current view. otherwise, it'd need to change value every time date changes
+ class ViewImpl {
+ constructor(type, getCurrentData, dateEnv) {
+ this.type = type;
+ this.getCurrentData = getCurrentData;
+ this.dateEnv = dateEnv;
+ }
+ get calendar() {
+ return this.getCurrentData().calendarApi;
+ }
+ get title() {
+ return this.getCurrentData().viewTitle;
+ }
+ get activeStart() {
+ return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.start);
+ }
+ get activeEnd() {
+ return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.end);
+ }
+ get currentStart() {
+ return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.start);
+ }
+ get currentEnd() {
+ return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.end);
+ }
+ getOption(name) {
+ return this.getCurrentData().options[name]; // are the view-specific options
+ }
+ }
+
+ let eventSourceDef$2 = {
+ ignoreRange: true,
+ parseMeta(refined) {
+ if (Array.isArray(refined.events)) {
+ return refined.events;
+ }
+ return null;
+ },
+ fetch(arg, successCallback) {
+ successCallback({
+ rawEvents: arg.eventSource.meta,
+ });
+ },
+ };
+ const arrayEventSourcePlugin = createPlugin({
+ name: 'array-event-source',
+ eventSourceDefs: [eventSourceDef$2],
+ });
+
+ let eventSourceDef$1 = {
+ parseMeta(refined) {
+ if (typeof refined.events === 'function') {
+ return refined.events;
+ }
+ return null;
+ },
+ fetch(arg, successCallback, errorCallback) {
+ const { dateEnv } = arg.context;
+ const func = arg.eventSource.meta;
+ unpromisify(func.bind(null, buildRangeApiWithTimeZone(arg.range, dateEnv)), (rawEvents) => successCallback({ rawEvents }), errorCallback);
+ },
+ };
+ const funcEventSourcePlugin = createPlugin({
+ name: 'func-event-source',
+ eventSourceDefs: [eventSourceDef$1],
+ });
+
+ const JSON_FEED_EVENT_SOURCE_REFINERS = {
+ method: String,
+ extraParams: identity,
+ startParam: String,
+ endParam: String,
+ timeZoneParam: String,
+ };
+
+ let eventSourceDef = {
+ parseMeta(refined) {
+ if (refined.url && (refined.format === 'json' || !refined.format)) {
+ return {
+ url: refined.url,
+ format: 'json',
+ method: (refined.method || 'GET').toUpperCase(),
+ extraParams: refined.extraParams,
+ startParam: refined.startParam,
+ endParam: refined.endParam,
+ timeZoneParam: refined.timeZoneParam,
+ };
+ }
+ return null;
+ },
+ fetch(arg, successCallback, errorCallback) {
+ const { meta } = arg.eventSource;
+ const requestParams = buildRequestParams(meta, arg.range, arg.context);
+ requestJson(meta.method, meta.url, requestParams).then(([rawEvents, response]) => {
+ successCallback({ rawEvents, response });
+ }, errorCallback);
+ },
+ };
+ const jsonFeedEventSourcePlugin = createPlugin({
+ name: 'json-event-source',
+ eventSourceRefiners: JSON_FEED_EVENT_SOURCE_REFINERS,
+ eventSourceDefs: [eventSourceDef],
+ });
+ function buildRequestParams(meta, range, context) {
+ let { dateEnv, options } = context;
+ let startParam;
+ let endParam;
+ let timeZoneParam;
+ let customRequestParams;
+ let params = {};
+ startParam = meta.startParam;
+ if (startParam == null) {
+ startParam = options.startParam;
+ }
+ endParam = meta.endParam;
+ if (endParam == null) {
+ endParam = options.endParam;
+ }
+ timeZoneParam = meta.timeZoneParam;
+ if (timeZoneParam == null) {
+ timeZoneParam = options.timeZoneParam;
+ }
+ // retrieve any outbound GET/POST data from the options
+ if (typeof meta.extraParams === 'function') {
+ // supplied as a function that returns a key/value object
+ customRequestParams = meta.extraParams();
+ }
+ else {
+ // probably supplied as a straight key/value object
+ customRequestParams = meta.extraParams || {};
+ }
+ Object.assign(params, customRequestParams);
+ params[startParam] = dateEnv.formatIso(range.start);
+ params[endParam] = dateEnv.formatIso(range.end);
+ if (dateEnv.timeZone !== 'local') {
+ params[timeZoneParam] = dateEnv.timeZone;
+ }
+ return params;
+ }
+
+ const SIMPLE_RECURRING_REFINERS = {
+ daysOfWeek: identity,
+ startTime: createDuration,
+ endTime: createDuration,
+ duration: createDuration,
+ startRecur: identity,
+ endRecur: identity,
+ };
+
+ let recurring = {
+ parse(refined, dateEnv) {
+ if (refined.daysOfWeek || refined.startTime || refined.endTime || refined.startRecur || refined.endRecur) {
+ let recurringData = {
+ daysOfWeek: refined.daysOfWeek || null,
+ startTime: refined.startTime || null,
+ endTime: refined.endTime || null,
+ startRecur: refined.startRecur ? dateEnv.createMarker(refined.startRecur) : null,
+ endRecur: refined.endRecur ? dateEnv.createMarker(refined.endRecur) : null,
+ };
+ let duration;
+ if (refined.duration) {
+ duration = refined.duration;
+ }
+ if (!duration && refined.startTime && refined.endTime) {
+ duration = subtractDurations(refined.endTime, refined.startTime);
+ }
+ return {
+ allDayGuess: Boolean(!refined.startTime && !refined.endTime),
+ duration,
+ typeData: recurringData, // doesn't need endTime anymore but oh well
+ };
+ }
+ return null;
+ },
+ expand(typeData, framingRange, dateEnv) {
+ let clippedFramingRange = intersectRanges(framingRange, { start: typeData.startRecur, end: typeData.endRecur });
+ if (clippedFramingRange) {
+ return expandRanges(typeData.daysOfWeek, typeData.startTime, clippedFramingRange, dateEnv);
+ }
+ return [];
+ },
+ };
+ const simpleRecurringEventsPlugin = createPlugin({
+ name: 'simple-recurring-event',
+ recurringTypes: [recurring],
+ eventRefiners: SIMPLE_RECURRING_REFINERS,
+ });
+ function expandRanges(daysOfWeek, startTime, framingRange, dateEnv) {
+ let dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null;
+ let dayMarker = startOfDay(framingRange.start);
+ let endMarker = framingRange.end;
+ let instanceStarts = [];
+ while (dayMarker < endMarker) {
+ let instanceStart;
+ // if everyday, or this particular day-of-week
+ if (!dowHash || dowHash[dayMarker.getUTCDay()]) {
+ if (startTime) {
+ instanceStart = dateEnv.add(dayMarker, startTime);
+ }
+ else {
+ instanceStart = dayMarker;
+ }
+ instanceStarts.push(instanceStart);
+ }
+ dayMarker = addDays(dayMarker, 1);
+ }
+ return instanceStarts;
+ }
+
+ const changeHandlerPlugin = createPlugin({
+ name: 'change-handler',
+ optionChangeHandlers: {
+ events(events, context) {
+ handleEventSources([events], context);
+ },
+ eventSources: handleEventSources,
+ },
+ });
+ /*
+ BUG: if `event` was supplied, all previously-given `eventSources` will be wiped out
+ */
+ function handleEventSources(inputs, context) {
+ let unfoundSources = hashValuesToArray(context.getCurrentData().eventSources);
+ let newInputs = [];
+ for (let input of inputs) {
+ let inputFound = false;
+ for (let i = 0; i < unfoundSources.length; i += 1) {
+ if (unfoundSources[i]._raw === input) {
+ unfoundSources.splice(i, 1); // delete
+ inputFound = true;
+ break;
+ }
+ }
+ if (!inputFound) {
+ newInputs.push(input);
+ }
+ }
+ for (let unfoundSource of unfoundSources) {
+ context.dispatch({
+ type: 'REMOVE_EVENT_SOURCE',
+ sourceId: unfoundSource.sourceId,
+ });
+ }
+ for (let newInput of newInputs) {
+ context.calendarApi.addEventSource(newInput);
+ }
+ }
+
+ function handleDateProfile(dateProfile, context) {
+ context.emitter.trigger('datesSet', Object.assign(Object.assign({}, buildRangeApiWithTimeZone(dateProfile.activeRange, context.dateEnv)), { view: context.viewApi }));
+ }
+
+ function handleEventStore(eventStore, context) {
+ let { emitter } = context;
+ if (emitter.hasHandlers('eventsSet')) {
+ emitter.trigger('eventsSet', buildEventApis(eventStore, context));
+ }
+ }
+
+ /*
+ this array is exposed on the root namespace so that UMD plugins can add to it.
+ see the rollup-bundles script.
+ */
+ const globalPlugins = [
+ arrayEventSourcePlugin,
+ funcEventSourcePlugin,
+ jsonFeedEventSourcePlugin,
+ simpleRecurringEventsPlugin,
+ changeHandlerPlugin,
+ createPlugin({
+ name: 'misc',
+ isLoadingFuncs: [
+ (state) => computeEventSourcesLoading(state.eventSources),
+ ],
+ propSetHandlers: {
+ dateProfile: handleDateProfile,
+ eventStore: handleEventStore,
+ },
+ }),
+ ];
+
+ class TaskRunner {
+ constructor(runTaskOption, drainedOption) {
+ this.runTaskOption = runTaskOption;
+ this.drainedOption = drainedOption;
+ this.queue = [];
+ this.delayedRunner = new DelayedRunner(this.drain.bind(this));
+ }
+ request(task, delay) {
+ this.queue.push(task);
+ this.delayedRunner.request(delay);
+ }
+ pause(scope) {
+ this.delayedRunner.pause(scope);
+ }
+ resume(scope, force) {
+ this.delayedRunner.resume(scope, force);
+ }
+ drain() {
+ let { queue } = this;
+ while (queue.length) {
+ let completedTasks = [];
+ let task;
+ while ((task = queue.shift())) {
+ this.runTask(task);
+ completedTasks.push(task);
+ }
+ this.drained(completedTasks);
+ } // keep going, in case new tasks were added in the drained handler
+ }
+ runTask(task) {
+ if (this.runTaskOption) {
+ this.runTaskOption(task);
+ }
+ }
+ drained(completedTasks) {
+ if (this.drainedOption) {
+ this.drainedOption(completedTasks);
+ }
+ }
+ }
+
+ // Computes what the title at the top of the calendarApi should be for this view
+ function buildTitle(dateProfile, viewOptions, dateEnv) {
+ let range;
+ // for views that span a large unit of time, show the proper interval, ignoring stray days before and after
+ if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) {
+ range = dateProfile.currentRange;
+ }
+ else { // for day units or smaller, use the actual day range
+ range = dateProfile.activeRange;
+ }
+ return dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || buildTitleFormat(dateProfile)), {
+ isEndExclusive: dateProfile.isRangeAllDay,
+ defaultSeparator: viewOptions.titleRangeSeparator,
+ });
+ }
+ // Generates the format string that should be used to generate the title for the current date range.
+ // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
+ function buildTitleFormat(dateProfile) {
+ let { currentRangeUnit } = dateProfile;
+ if (currentRangeUnit === 'year') {
+ return { year: 'numeric' };
+ }
+ if (currentRangeUnit === 'month') {
+ return { year: 'numeric', month: 'long' }; // like "September 2014"
+ }
+ let days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end);
+ if (days !== null && days > 1) {
+ // multi-day range. shorter, like "Sep 9 - 10 2014"
+ return { year: 'numeric', month: 'short', day: 'numeric' };
+ }
+ // one day. longer, like "September 9 2014"
+ return { year: 'numeric', month: 'long', day: 'numeric' };
+ }
+
+ // in future refactor, do the redux-style function(state=initial) for initial-state
+ // also, whatever is happening in constructor, have it happen in action queue too
+ class CalendarDataManager {
+ constructor(props) {
+ this.computeOptionsData = memoize(this._computeOptionsData);
+ this.computeCurrentViewData = memoize(this._computeCurrentViewData);
+ this.organizeRawLocales = memoize(organizeRawLocales);
+ this.buildLocale = memoize(buildLocale);
+ this.buildPluginHooks = buildBuildPluginHooks();
+ this.buildDateEnv = memoize(buildDateEnv$1);
+ this.buildTheme = memoize(buildTheme);
+ this.parseToolbars = memoize(parseToolbars);
+ this.buildViewSpecs = memoize(buildViewSpecs);
+ this.buildDateProfileGenerator = memoizeObjArg(buildDateProfileGenerator);
+ this.buildViewApi = memoize(buildViewApi);
+ this.buildViewUiProps = memoizeObjArg(buildViewUiProps);
+ this.buildEventUiBySource = memoize(buildEventUiBySource, isPropsEqual);
+ this.buildEventUiBases = memoize(buildEventUiBases);
+ this.parseContextBusinessHours = memoizeObjArg(parseContextBusinessHours);
+ this.buildTitle = memoize(buildTitle);
+ this.emitter = new Emitter();
+ this.actionRunner = new TaskRunner(this._handleAction.bind(this), this.updateData.bind(this));
+ this.currentCalendarOptionsInput = {};
+ this.currentCalendarOptionsRefined = {};
+ this.currentViewOptionsInput = {};
+ this.currentViewOptionsRefined = {};
+ this.currentCalendarOptionsRefiners = {};
+ this.getCurrentData = () => this.data;
+ this.dispatch = (action) => {
+ this.actionRunner.request(action); // protects against recursive calls to _handleAction
+ };
+ this.props = props;
+ this.actionRunner.pause();
+ let dynamicOptionOverrides = {};
+ let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
+ let currentViewType = optionsData.calendarOptions.initialView || optionsData.pluginHooks.initialView;
+ let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
+ // wire things up
+ // TODO: not DRY
+ props.calendarApi.currentDataManager = this;
+ this.emitter.setThisContext(props.calendarApi);
+ this.emitter.setOptions(currentViewData.options);
+ let currentDate = getInitialDate(optionsData.calendarOptions, optionsData.dateEnv);
+ let dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
+ if (!rangeContainsMarker(dateProfile.activeRange, currentDate)) {
+ currentDate = dateProfile.currentRange.start;
+ }
+ let calendarContext = {
+ dateEnv: optionsData.dateEnv,
+ options: optionsData.calendarOptions,
+ pluginHooks: optionsData.pluginHooks,
+ calendarApi: props.calendarApi,
+ dispatch: this.dispatch,
+ emitter: this.emitter,
+ getCurrentData: this.getCurrentData,
+ };
+ // needs to be after setThisContext
+ for (let callback of optionsData.pluginHooks.contextInit) {
+ callback(calendarContext);
+ }
+ // NOT DRY
+ let eventSources = initEventSources(optionsData.calendarOptions, dateProfile, calendarContext);
+ let initialState = {
+ dynamicOptionOverrides,
+ currentViewType,
+ currentDate,
+ dateProfile,
+ businessHours: this.parseContextBusinessHours(calendarContext),
+ eventSources,
+ eventUiBases: {},
+ eventStore: createEmptyEventStore(),
+ renderableEventStore: createEmptyEventStore(),
+ dateSelection: null,
+ eventSelection: '',
+ eventDrag: null,
+ eventResize: null,
+ selectionConfig: this.buildViewUiProps(calendarContext).selectionConfig,
+ };
+ let contextAndState = Object.assign(Object.assign({}, calendarContext), initialState);
+ for (let reducer of optionsData.pluginHooks.reducers) {
+ Object.assign(initialState, reducer(null, null, contextAndState));
+ }
+ if (computeIsLoading(initialState, calendarContext)) {
+ this.emitter.trigger('loading', true); // NOT DRY
+ }
+ this.state = initialState;
+ this.updateData();
+ this.actionRunner.resume();
+ }
+ resetOptions(optionOverrides, append) {
+ let { props } = this;
+ props.optionOverrides = append
+ ? Object.assign(Object.assign({}, props.optionOverrides), optionOverrides) : optionOverrides;
+ this.actionRunner.request({
+ type: 'NOTHING',
+ });
+ }
+ _handleAction(action) {
+ let { props, state, emitter } = this;
+ let dynamicOptionOverrides = reduceDynamicOptionOverrides(state.dynamicOptionOverrides, action);
+ let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
+ let currentViewType = reduceViewType(state.currentViewType, action);
+ let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
+ // wire things up
+ // TODO: not DRY
+ props.calendarApi.currentDataManager = this;
+ emitter.setThisContext(props.calendarApi);
+ emitter.setOptions(currentViewData.options);
+ let calendarContext = {
+ dateEnv: optionsData.dateEnv,
+ options: optionsData.calendarOptions,
+ pluginHooks: optionsData.pluginHooks,
+ calendarApi: props.calendarApi,
+ dispatch: this.dispatch,
+ emitter,
+ getCurrentData: this.getCurrentData,
+ };
+ let { currentDate, dateProfile } = state;
+ if (this.data && this.data.dateProfileGenerator !== currentViewData.dateProfileGenerator) { // hack
+ dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
+ }
+ currentDate = reduceCurrentDate(currentDate, action);
+ dateProfile = reduceDateProfile(dateProfile, action, currentDate, currentViewData.dateProfileGenerator);
+ if (action.type === 'PREV' || // TODO: move this logic into DateProfileGenerator
+ action.type === 'NEXT' || // "
+ !rangeContainsMarker(dateProfile.currentRange, currentDate)) {
+ currentDate = dateProfile.currentRange.start;
+ }
+ let eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendarContext);
+ let eventStore = reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendarContext);
+ let isEventsLoading = computeEventSourcesLoading(eventSources); // BAD. also called in this func in computeIsLoading
+ let renderableEventStore = (isEventsLoading && !currentViewData.options.progressiveEventRendering) ?
+ (state.renderableEventStore || eventStore) : // try from previous state
+ eventStore;
+ let { eventUiSingleBase, selectionConfig } = this.buildViewUiProps(calendarContext); // will memoize obj
+ let eventUiBySource = this.buildEventUiBySource(eventSources);
+ let eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource);
+ let newState = {
+ dynamicOptionOverrides,
+ currentViewType,
+ currentDate,
+ dateProfile,
+ eventSources,
+ eventStore,
+ renderableEventStore,
+ selectionConfig,
+ eventUiBases,
+ businessHours: this.parseContextBusinessHours(calendarContext),
+ dateSelection: reduceDateSelection(state.dateSelection, action),
+ eventSelection: reduceSelectedEvent(state.eventSelection, action),
+ eventDrag: reduceEventDrag(state.eventDrag, action),
+ eventResize: reduceEventResize(state.eventResize, action),
+ };
+ let contextAndState = Object.assign(Object.assign({}, calendarContext), newState);
+ for (let reducer of optionsData.pluginHooks.reducers) {
+ Object.assign(newState, reducer(state, action, contextAndState)); // give the OLD state, for old value
+ }
+ let wasLoading = computeIsLoading(state, calendarContext);
+ let isLoading = computeIsLoading(newState, calendarContext);
+ // TODO: use propSetHandlers in plugin system
+ if (!wasLoading && isLoading) {
+ emitter.trigger('loading', true);
+ }
+ else if (wasLoading && !isLoading) {
+ emitter.trigger('loading', false);
+ }
+ this.state = newState;
+ if (props.onAction) {
+ props.onAction(action);
+ }
+ }
+ updateData() {
+ let { props, state } = this;
+ let oldData = this.data;
+ let optionsData = this.computeOptionsData(props.optionOverrides, state.dynamicOptionOverrides, props.calendarApi);
+ let currentViewData = this.computeCurrentViewData(state.currentViewType, optionsData, props.optionOverrides, state.dynamicOptionOverrides);
+ let data = this.data = Object.assign(Object.assign(Object.assign({ viewTitle: this.buildTitle(state.dateProfile, currentViewData.options, optionsData.dateEnv), calendarApi: props.calendarApi, dispatch: this.dispatch, emitter: this.emitter, getCurrentData: this.getCurrentData }, optionsData), currentViewData), state);
+ let changeHandlers = optionsData.pluginHooks.optionChangeHandlers;
+ let oldCalendarOptions = oldData && oldData.calendarOptions;
+ let newCalendarOptions = optionsData.calendarOptions;
+ if (oldCalendarOptions && oldCalendarOptions !== newCalendarOptions) {
+ if (oldCalendarOptions.timeZone !== newCalendarOptions.timeZone) {
+ // hack
+ state.eventSources = data.eventSources = reduceEventSourcesNewTimeZone(data.eventSources, state.dateProfile, data);
+ state.eventStore = data.eventStore = rezoneEventStoreDates(data.eventStore, oldData.dateEnv, data.dateEnv);
+ }
+ for (let optionName in changeHandlers) {
+ if (oldCalendarOptions[optionName] !== newCalendarOptions[optionName]) {
+ changeHandlers[optionName](newCalendarOptions[optionName], data);
+ }
+ }
+ }
+ if (props.onData) {
+ props.onData(data);
+ }
+ }
+ _computeOptionsData(optionOverrides, dynamicOptionOverrides, calendarApi) {
+ // TODO: blacklist options that are handled by optionChangeHandlers
+ let { refinedOptions, pluginHooks, localeDefaults, availableLocaleData, extra, } = this.processRawCalendarOptions(optionOverrides, dynamicOptionOverrides);
+ warnUnknownOptions(extra);
+ let dateEnv = this.buildDateEnv(refinedOptions.timeZone, refinedOptions.locale, refinedOptions.weekNumberCalculation, refinedOptions.firstDay, refinedOptions.weekText, pluginHooks, availableLocaleData, refinedOptions.defaultRangeSeparator);
+ let viewSpecs = this.buildViewSpecs(pluginHooks.views, optionOverrides, dynamicOptionOverrides, localeDefaults);
+ let theme = this.buildTheme(refinedOptions, pluginHooks);
+ let toolbarConfig = this.parseToolbars(refinedOptions, optionOverrides, theme, viewSpecs, calendarApi);
+ return {
+ calendarOptions: refinedOptions,
+ pluginHooks,
+ dateEnv,
+ viewSpecs,
+ theme,
+ toolbarConfig,
+ localeDefaults,
+ availableRawLocales: availableLocaleData.map,
+ };
+ }
+ // always called from behind a memoizer
+ processRawCalendarOptions(optionOverrides, dynamicOptionOverrides) {
+ let { locales, locale } = mergeRawOptions([
+ BASE_OPTION_DEFAULTS,
+ optionOverrides,
+ dynamicOptionOverrides,
+ ]);
+ let availableLocaleData = this.organizeRawLocales(locales);
+ let availableRawLocales = availableLocaleData.map;
+ let localeDefaults = this.buildLocale(locale || availableLocaleData.defaultCode, availableRawLocales).options;
+ let pluginHooks = this.buildPluginHooks(optionOverrides.plugins || [], globalPlugins);
+ 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);
+ let extra = {};
+ let raw = mergeRawOptions([
+ BASE_OPTION_DEFAULTS,
+ localeDefaults,
+ optionOverrides,
+ dynamicOptionOverrides,
+ ]);
+ let refined = {};
+ let currentRaw = this.currentCalendarOptionsInput;
+ let currentRefined = this.currentCalendarOptionsRefined;
+ let anyChanges = false;
+ for (let optionName in raw) {
+ if (optionName !== 'plugins') { // because plugins is special-cased
+ if (raw[optionName] === currentRaw[optionName] ||
+ (COMPLEX_OPTION_COMPARATORS[optionName] &&
+ (optionName in currentRaw) &&
+ COMPLEX_OPTION_COMPARATORS[optionName](currentRaw[optionName], raw[optionName]))) {
+ refined[optionName] = currentRefined[optionName];
+ }
+ else if (refiners[optionName]) {
+ refined[optionName] = refiners[optionName](raw[optionName]);
+ anyChanges = true;
+ }
+ else {
+ extra[optionName] = currentRaw[optionName];
+ }
+ }
+ }
+ if (anyChanges) {
+ this.currentCalendarOptionsInput = raw;
+ this.currentCalendarOptionsRefined = refined;
+ }
+ return {
+ rawOptions: this.currentCalendarOptionsInput,
+ refinedOptions: this.currentCalendarOptionsRefined,
+ pluginHooks,
+ availableLocaleData,
+ localeDefaults,
+ extra,
+ };
+ }
+ _computeCurrentViewData(viewType, optionsData, optionOverrides, dynamicOptionOverrides) {
+ let viewSpec = optionsData.viewSpecs[viewType];
+ if (!viewSpec) {
+ throw new Error(`viewType "${viewType}" is not available. Please make sure you've loaded all neccessary plugins`);
+ }
+ let { refinedOptions, extra } = this.processRawViewOptions(viewSpec, optionsData.pluginHooks, optionsData.localeDefaults, optionOverrides, dynamicOptionOverrides);
+ warnUnknownOptions(extra);
+ let dateProfileGenerator = this.buildDateProfileGenerator({
+ dateProfileGeneratorClass: viewSpec.optionDefaults.dateProfileGeneratorClass,
+ duration: viewSpec.duration,
+ durationUnit: viewSpec.durationUnit,
+ usesMinMaxTime: viewSpec.optionDefaults.usesMinMaxTime,
+ dateEnv: optionsData.dateEnv,
+ calendarApi: this.props.calendarApi,
+ slotMinTime: refinedOptions.slotMinTime,
+ slotMaxTime: refinedOptions.slotMaxTime,
+ showNonCurrentDates: refinedOptions.showNonCurrentDates,
+ dayCount: refinedOptions.dayCount,
+ dateAlignment: refinedOptions.dateAlignment,
+ dateIncrement: refinedOptions.dateIncrement,
+ hiddenDays: refinedOptions.hiddenDays,
+ weekends: refinedOptions.weekends,
+ nowInput: refinedOptions.now,
+ validRangeInput: refinedOptions.validRange,
+ visibleRangeInput: refinedOptions.visibleRange,
+ monthMode: refinedOptions.monthMode,
+ fixedWeekCount: refinedOptions.fixedWeekCount,
+ });
+ let viewApi = this.buildViewApi(viewType, this.getCurrentData, optionsData.dateEnv);
+ return { viewSpec, options: refinedOptions, dateProfileGenerator, viewApi };
+ }
+ processRawViewOptions(viewSpec, pluginHooks, localeDefaults, optionOverrides, dynamicOptionOverrides) {
+ let raw = mergeRawOptions([
+ BASE_OPTION_DEFAULTS,
+ viewSpec.optionDefaults,
+ localeDefaults,
+ optionOverrides,
+ viewSpec.optionOverrides,
+ dynamicOptionOverrides,
+ ]);
+ 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);
+ let refined = {};
+ let currentRaw = this.currentViewOptionsInput;
+ let currentRefined = this.currentViewOptionsRefined;
+ let anyChanges = false;
+ let extra = {};
+ for (let optionName in raw) {
+ if (raw[optionName] === currentRaw[optionName] ||
+ (COMPLEX_OPTION_COMPARATORS[optionName] &&
+ COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], currentRaw[optionName]))) {
+ refined[optionName] = currentRefined[optionName];
+ }
+ else {
+ if (raw[optionName] === this.currentCalendarOptionsInput[optionName] ||
+ (COMPLEX_OPTION_COMPARATORS[optionName] &&
+ COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], this.currentCalendarOptionsInput[optionName]))) {
+ if (optionName in this.currentCalendarOptionsRefined) { // might be an "extra" prop
+ refined[optionName] = this.currentCalendarOptionsRefined[optionName];
+ }
+ }
+ else if (refiners[optionName]) {
+ refined[optionName] = refiners[optionName](raw[optionName]);
+ }
+ else {
+ extra[optionName] = raw[optionName];
+ }
+ anyChanges = true;
+ }
+ }
+ if (anyChanges) {
+ this.currentViewOptionsInput = raw;
+ this.currentViewOptionsRefined = refined;
+ }
+ return {
+ rawOptions: this.currentViewOptionsInput,
+ refinedOptions: this.currentViewOptionsRefined,
+ extra,
+ };
+ }
+ }
+ function buildDateEnv$1(timeZone, explicitLocale, weekNumberCalculation, firstDay, weekText, pluginHooks, availableLocaleData, defaultSeparator) {
+ let locale = buildLocale(explicitLocale || availableLocaleData.defaultCode, availableLocaleData.map);
+ return new DateEnv({
+ calendarSystem: 'gregory',
+ timeZone,
+ namedTimeZoneImpl: pluginHooks.namedTimeZonedImpl,
+ locale,
+ weekNumberCalculation,
+ firstDay,
+ weekText,
+ cmdFormatter: pluginHooks.cmdFormatter,
+ defaultSeparator,
+ });
+ }
+ function buildTheme(options, pluginHooks) {
+ let ThemeClass = pluginHooks.themeClasses[options.themeSystem] || StandardTheme;
+ return new ThemeClass(options);
+ }
+ function buildDateProfileGenerator(props) {
+ let DateProfileGeneratorClass = props.dateProfileGeneratorClass || DateProfileGenerator;
+ return new DateProfileGeneratorClass(props);
+ }
+ function buildViewApi(type, getCurrentData, dateEnv) {
+ return new ViewImpl(type, getCurrentData, dateEnv);
+ }
+ function buildEventUiBySource(eventSources) {
+ return mapHash(eventSources, (eventSource) => eventSource.ui);
+ }
+ function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) {
+ let eventUiBases = { '': eventUiSingleBase };
+ for (let defId in eventDefs) {
+ let def = eventDefs[defId];
+ if (def.sourceId && eventUiBySource[def.sourceId]) {
+ eventUiBases[defId] = eventUiBySource[def.sourceId];
+ }
+ }
+ return eventUiBases;
+ }
+ function buildViewUiProps(calendarContext) {
+ let { options } = calendarContext;
+ return {
+ eventUiSingleBase: createEventUi({
+ display: options.eventDisplay,
+ editable: options.editable,
+ startEditable: options.eventStartEditable,
+ durationEditable: options.eventDurationEditable,
+ constraint: options.eventConstraint,
+ overlap: typeof options.eventOverlap === 'boolean' ? options.eventOverlap : undefined,
+ allow: options.eventAllow,
+ backgroundColor: options.eventBackgroundColor,
+ borderColor: options.eventBorderColor,
+ textColor: options.eventTextColor,
+ color: options.eventColor,
+ // classNames: options.eventClassNames // render hook will handle this
+ }, calendarContext),
+ selectionConfig: createEventUi({
+ constraint: options.selectConstraint,
+ overlap: typeof options.selectOverlap === 'boolean' ? options.selectOverlap : undefined,
+ allow: options.selectAllow,
+ }, calendarContext),
+ };
+ }
+ function computeIsLoading(state, context) {
+ for (let isLoadingFunc of context.pluginHooks.isLoadingFuncs) {
+ if (isLoadingFunc(state)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ function parseContextBusinessHours(calendarContext) {
+ return parseBusinessHours(calendarContext.options.businessHours, calendarContext);
+ }
+ function warnUnknownOptions(options, viewName) {
+ for (let optionName in options) {
+ console.warn(`Unknown option '${optionName}'` +
+ (viewName ? ` for view '${viewName}'` : ''));
+ }
+ }
+
+ class ToolbarSection extends BaseComponent {
+ render() {
+ let children = this.props.widgetGroups.map((widgetGroup) => this.renderWidgetGroup(widgetGroup));
+ return h('div', { className: 'fc-toolbar-chunk' }, ...children);
+ }
+ renderWidgetGroup(widgetGroup) {
+ let { props } = this;
+ let { theme } = this.context;
+ let children = [];
+ let isOnlyButtons = true;
+ for (let widget of widgetGroup) {
+ let { buttonName, buttonClick, buttonText, buttonIcon, buttonHint } = widget;
+ if (buttonName === 'title') {
+ isOnlyButtons = false;
+ children.push(h("h2", { className: "fc-toolbar-title", id: props.titleId }, props.title));
+ }
+ else {
+ let isPressed = buttonName === props.activeButton;
+ let isDisabled = (!props.isTodayEnabled && buttonName === 'today') ||
+ (!props.isPrevEnabled && buttonName === 'prev') ||
+ (!props.isNextEnabled && buttonName === 'next');
+ let buttonClasses = [`fc-${buttonName}-button`, theme.getClass('button')];
+ if (isPressed) {
+ buttonClasses.push(theme.getClass('buttonActive'));
+ }
+ children.push(h("button", { type: "button", title: typeof buttonHint === 'function' ? buttonHint(props.navUnit) : buttonHint, disabled: isDisabled, "aria-pressed": isPressed, className: buttonClasses.join(' '), onClick: buttonClick }, buttonText || (buttonIcon ? h("span", { className: buttonIcon }) : '')));
+ }
+ }
+ if (children.length > 1) {
+ let groupClassName = (isOnlyButtons && theme.getClass('buttonGroup')) || '';
+ return h('div', { className: groupClassName }, ...children);
+ }
+ return children[0];
+ }
+ }
+
+ class Toolbar extends BaseComponent {
+ render() {
+ let { model, extraClassName } = this.props;
+ let forceLtr = false;
+ let startContent;
+ let endContent;
+ let sectionWidgets = model.sectionWidgets;
+ let centerContent = sectionWidgets.center;
+ if (sectionWidgets.left) {
+ forceLtr = true;
+ startContent = sectionWidgets.left;
+ }
+ else {
+ startContent = sectionWidgets.start;
+ }
+ if (sectionWidgets.right) {
+ forceLtr = true;
+ endContent = sectionWidgets.right;
+ }
+ else {
+ endContent = sectionWidgets.end;
+ }
+ let classNames = [
+ extraClassName || '',
+ 'fc-toolbar',
+ forceLtr ? 'fc-toolbar-ltr' : '',
+ ];
+ return (h("div", { className: classNames.join(' ') },
+ this.renderSection('start', startContent || []),
+ this.renderSection('center', centerContent || []),
+ this.renderSection('end', endContent || [])));
+ }
+ renderSection(key, widgetGroups) {
+ let { props } = this;
+ return (h(ToolbarSection, { key: key, widgetGroups: widgetGroups, title: props.title, navUnit: props.navUnit, activeButton: props.activeButton, isTodayEnabled: props.isTodayEnabled, isPrevEnabled: props.isPrevEnabled, isNextEnabled: props.isNextEnabled, titleId: props.titleId }));
+ }
+ }
+
+ // TODO: do function component?
+ class ViewContainer extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.state = {
+ availableWidth: null,
+ };
+ this.handleEl = (el) => {
+ this.el = el;
+ setRef(this.props.elRef, el);
+ this.updateAvailableWidth();
+ };
+ this.handleResize = () => {
+ this.updateAvailableWidth();
+ };
+ }
+ render() {
+ let { props, state } = this;
+ let { aspectRatio } = props;
+ let classNames = [
+ 'fc-view-harness',
+ (aspectRatio || props.liquid || props.height)
+ ? 'fc-view-harness-active' // harness controls the height
+ : 'fc-view-harness-passive', // let the view do the height
+ ];
+ let height = '';
+ let paddingBottom = '';
+ if (aspectRatio) {
+ if (state.availableWidth !== null) {
+ height = state.availableWidth / aspectRatio;
+ }
+ else {
+ // while waiting to know availableWidth, we can't set height to *zero*
+ // because will cause lots of unnecessary scrollbars within scrollgrid.
+ // BETTER: don't start rendering ANYTHING yet until we know container width
+ // NOTE: why not always use paddingBottom? Causes height oscillation (issue 5606)
+ paddingBottom = `${(1 / aspectRatio) * 100}%`;
+ }
+ }
+ else {
+ height = props.height || '';
+ }
+ return (h("div", { "aria-labelledby": props.labeledById, ref: this.handleEl, className: classNames.join(' '), style: { height, paddingBottom } }, props.children));
+ }
+ componentDidMount() {
+ this.context.addResizeHandler(this.handleResize);
+ }
+ componentWillUnmount() {
+ this.context.removeResizeHandler(this.handleResize);
+ }
+ updateAvailableWidth() {
+ if (this.el && // needed. but why?
+ this.props.aspectRatio // aspectRatio is the only height setting that needs availableWidth
+ ) {
+ this.setState({ availableWidth: this.el.offsetWidth });
+ }
+ }
+ }
+
+ /*
+ Detects when the user clicks on an event within a DateComponent
+ */
+ class EventClicking extends Interaction {
+ constructor(settings) {
+ super(settings);
+ this.handleSegClick = (ev, segEl) => {
+ let { component } = this;
+ let { context } = component;
+ let seg = getElSeg(segEl);
+ if (seg && // might be the <div> surrounding the more link
+ component.isValidSegDownEl(ev.target)) {
+ // our way to simulate a link click for elements that can't be <a> tags
+ // grab before trigger fired in case trigger trashes DOM thru rerendering
+ let hasUrlContainer = elementClosest(ev.target, '.fc-event-forced-url');
+ let url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : '';
+ context.emitter.trigger('eventClick', {
+ el: segEl,
+ event: new EventImpl(component.context, seg.eventRange.def, seg.eventRange.instance),
+ jsEvent: ev,
+ view: context.viewApi,
+ });
+ if (url && !ev.defaultPrevented) {
+ window.location.href = url;
+ }
+ }
+ };
+ this.destroy = listenBySelector(settings.el, 'click', '.fc-event', // on both fg and bg events
+ this.handleSegClick);
+ }
+ }
+
+ /*
+ Triggers events and adds/removes core classNames when the user's pointer
+ enters/leaves event-elements of a component.
+ */
+ class EventHovering extends Interaction {
+ constructor(settings) {
+ super(settings);
+ // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it
+ this.handleEventElRemove = (el) => {
+ if (el === this.currentSegEl) {
+ this.handleSegLeave(null, this.currentSegEl);
+ }
+ };
+ this.handleSegEnter = (ev, segEl) => {
+ if (getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper
+ this.currentSegEl = segEl;
+ this.triggerEvent('eventMouseEnter', ev, segEl);
+ }
+ };
+ this.handleSegLeave = (ev, segEl) => {
+ if (this.currentSegEl) {
+ this.currentSegEl = null;
+ this.triggerEvent('eventMouseLeave', ev, segEl);
+ }
+ };
+ this.removeHoverListeners = listenToHoverBySelector(settings.el, '.fc-event', // on both fg and bg events
+ this.handleSegEnter, this.handleSegLeave);
+ }
+ destroy() {
+ this.removeHoverListeners();
+ }
+ triggerEvent(publicEvName, ev, segEl) {
+ let { component } = this;
+ let { context } = component;
+ let seg = getElSeg(segEl);
+ if (!ev || component.isValidSegDownEl(ev.target)) {
+ context.emitter.trigger(publicEvName, {
+ el: segEl,
+ event: new EventImpl(context, seg.eventRange.def, seg.eventRange.instance),
+ jsEvent: ev,
+ view: context.viewApi,
+ });
+ }
+ }
+ }
+
+ class CalendarContent extends PureComponent {
+ constructor() {
+ super(...arguments);
+ this.buildViewContext = memoize(buildViewContext);
+ this.buildViewPropTransformers = memoize(buildViewPropTransformers);
+ this.buildToolbarProps = memoize(buildToolbarProps);
+ this.headerRef = y();
+ this.footerRef = y();
+ this.interactionsStore = {};
+ // eslint-disable-next-line
+ this.state = {
+ viewLabelId: getUniqueDomId(),
+ };
+ // Component Registration
+ // -----------------------------------------------------------------------------------------------------------------
+ this.registerInteractiveComponent = (component, settingsInput) => {
+ let settings = parseInteractionSettings(component, settingsInput);
+ let DEFAULT_INTERACTIONS = [
+ EventClicking,
+ EventHovering,
+ ];
+ let interactionClasses = DEFAULT_INTERACTIONS.concat(this.props.pluginHooks.componentInteractions);
+ let interactions = interactionClasses.map((TheInteractionClass) => new TheInteractionClass(settings));
+ this.interactionsStore[component.uid] = interactions;
+ interactionSettingsStore[component.uid] = settings;
+ };
+ this.unregisterInteractiveComponent = (component) => {
+ let listeners = this.interactionsStore[component.uid];
+ if (listeners) {
+ for (let listener of listeners) {
+ listener.destroy();
+ }
+ delete this.interactionsStore[component.uid];
+ }
+ delete interactionSettingsStore[component.uid];
+ };
+ // Resizing
+ // -----------------------------------------------------------------------------------------------------------------
+ this.resizeRunner = new DelayedRunner(() => {
+ this.props.emitter.trigger('_resize', true); // should window resizes be considered "forced" ?
+ this.props.emitter.trigger('windowResize', { view: this.props.viewApi });
+ });
+ this.handleWindowResize = (ev) => {
+ let { options } = this.props;
+ if (options.handleWindowResize &&
+ ev.target === window // avoid jqui events
+ ) {
+ this.resizeRunner.request(options.windowResizeDelay);
+ }
+ };
+ }
+ /*
+ renders INSIDE of an outer div
+ */
+ render() {
+ let { props } = this;
+ let { toolbarConfig, options } = props;
+ let toolbarProps = this.buildToolbarProps(props.viewSpec, props.dateProfile, props.dateProfileGenerator, props.currentDate, getNow(props.options.now, props.dateEnv), // TODO: use NowTimer????
+ props.viewTitle);
+ let viewVGrow = false;
+ let viewHeight = '';
+ let viewAspectRatio;
+ if (props.isHeightAuto || props.forPrint) {
+ viewHeight = '';
+ }
+ else if (options.height != null) {
+ viewVGrow = true;
+ }
+ else if (options.contentHeight != null) {
+ viewHeight = options.contentHeight;
+ }
+ else {
+ viewAspectRatio = Math.max(options.aspectRatio, 0.5); // prevent from getting too tall
+ }
+ let viewContext = this.buildViewContext(props.viewSpec, props.viewApi, props.options, props.dateProfileGenerator, props.dateEnv, props.theme, props.pluginHooks, props.dispatch, props.getCurrentData, props.emitter, props.calendarApi, this.registerInteractiveComponent, this.unregisterInteractiveComponent);
+ let viewLabelId = (toolbarConfig.header && toolbarConfig.header.hasTitle)
+ ? this.state.viewLabelId
+ : '';
+ return (h(ViewContextType.Provider, { value: viewContext },
+ toolbarConfig.header && (h(Toolbar, Object.assign({ ref: this.headerRef, extraClassName: "fc-header-toolbar", model: toolbarConfig.header, titleId: viewLabelId }, toolbarProps))),
+ h(ViewContainer, { liquid: viewVGrow, height: viewHeight, aspectRatio: viewAspectRatio, labeledById: viewLabelId },
+ this.renderView(props),
+ this.buildAppendContent()),
+ toolbarConfig.footer && (h(Toolbar, Object.assign({ ref: this.footerRef, extraClassName: "fc-footer-toolbar", model: toolbarConfig.footer, titleId: "" }, toolbarProps)))));
+ }
+ componentDidMount() {
+ let { props } = this;
+ this.calendarInteractions = props.pluginHooks.calendarInteractions
+ .map((CalendarInteractionClass) => new CalendarInteractionClass(props));
+ window.addEventListener('resize', this.handleWindowResize);
+ let { propSetHandlers } = props.pluginHooks;
+ for (let propName in propSetHandlers) {
+ propSetHandlers[propName](props[propName], props);
+ }
+ }
+ componentDidUpdate(prevProps) {
+ let { props } = this;
+ let { propSetHandlers } = props.pluginHooks;
+ for (let propName in propSetHandlers) {
+ if (props[propName] !== prevProps[propName]) {
+ propSetHandlers[propName](props[propName], props);
+ }
+ }
+ }
+ componentWillUnmount() {
+ window.removeEventListener('resize', this.handleWindowResize);
+ this.resizeRunner.clear();
+ for (let interaction of this.calendarInteractions) {
+ interaction.destroy();
+ }
+ this.props.emitter.trigger('_unmount');
+ }
+ buildAppendContent() {
+ let { props } = this;
+ let children = props.pluginHooks.viewContainerAppends.map((buildAppendContent) => buildAppendContent(props));
+ return h(p, {}, ...children);
+ }
+ renderView(props) {
+ let { pluginHooks } = props;
+ let { viewSpec } = props;
+ let viewProps = {
+ dateProfile: props.dateProfile,
+ businessHours: props.businessHours,
+ eventStore: props.renderableEventStore,
+ eventUiBases: props.eventUiBases,
+ dateSelection: props.dateSelection,
+ eventSelection: props.eventSelection,
+ eventDrag: props.eventDrag,
+ eventResize: props.eventResize,
+ isHeightAuto: props.isHeightAuto,
+ forPrint: props.forPrint,
+ };
+ let transformers = this.buildViewPropTransformers(pluginHooks.viewPropsTransformers);
+ for (let transformer of transformers) {
+ Object.assign(viewProps, transformer.transform(viewProps, props));
+ }
+ let ViewComponent = viewSpec.component;
+ return (h(ViewComponent, Object.assign({}, viewProps)));
+ }
+ }
+ function buildToolbarProps(viewSpec, dateProfile, dateProfileGenerator, currentDate, now, title) {
+ // don't force any date-profiles to valid date profiles (the `false`) so that we can tell if it's invalid
+ let todayInfo = dateProfileGenerator.build(now, undefined, false); // TODO: need `undefined` or else INFINITE LOOP for some reason
+ let prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate, false);
+ let nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate, false);
+ return {
+ title,
+ activeButton: viewSpec.type,
+ navUnit: viewSpec.singleUnit,
+ isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now),
+ isPrevEnabled: prevInfo.isValid,
+ isNextEnabled: nextInfo.isValid,
+ };
+ }
+ // Plugin
+ // -----------------------------------------------------------------------------------------------------------------
+ function buildViewPropTransformers(theClasses) {
+ return theClasses.map((TheClass) => new TheClass());
+ }
+
+ class Calendar extends CalendarImpl {
+ constructor(el, optionOverrides = {}) {
+ super();
+ this.isRendering = false;
+ this.isRendered = false;
+ this.currentClassNames = [];
+ this.customContentRenderId = 0;
+ this.handleAction = (action) => {
+ // actions we know we want to render immediately
+ switch (action.type) {
+ case 'SET_EVENT_DRAG':
+ case 'SET_EVENT_RESIZE':
+ this.renderRunner.tryDrain();
+ }
+ };
+ this.handleData = (data) => {
+ this.currentData = data;
+ this.renderRunner.request(data.calendarOptions.rerenderDelay);
+ };
+ this.handleRenderRequest = () => {
+ if (this.isRendering) {
+ this.isRendered = true;
+ let { currentData } = this;
+ flushSync(() => {
+ P$1(h(CalendarRoot, { options: currentData.calendarOptions, theme: currentData.theme, emitter: currentData.emitter }, (classNames, height, isHeightAuto, forPrint) => {
+ this.setClassNames(classNames);
+ this.setHeight(height);
+ return (h(RenderId.Provider, { value: this.customContentRenderId },
+ h(CalendarContent, Object.assign({ isHeightAuto: isHeightAuto, forPrint: forPrint }, currentData))));
+ }), this.el);
+ });
+ }
+ else if (this.isRendered) {
+ this.isRendered = false;
+ P$1(null, this.el);
+ this.setClassNames([]);
+ this.setHeight('');
+ }
+ };
+ this.el = el;
+ this.renderRunner = new DelayedRunner(this.handleRenderRequest);
+ new CalendarDataManager({
+ optionOverrides,
+ calendarApi: this,
+ onAction: this.handleAction,
+ onData: this.handleData,
+ });
+ }
+ render() {
+ let wasRendering = this.isRendering;
+ if (!wasRendering) {
+ this.isRendering = true;
+ }
+ else {
+ this.customContentRenderId += 1;
+ }
+ this.renderRunner.request();
+ if (wasRendering) {
+ this.updateSize();
+ }
+ }
+ destroy() {
+ if (this.isRendering) {
+ this.isRendering = false;
+ this.renderRunner.request();
+ }
+ }
+ updateSize() {
+ flushSync(() => {
+ super.updateSize();
+ });
+ }
+ batchRendering(func) {
+ this.renderRunner.pause('batchRendering');
+ func();
+ this.renderRunner.resume('batchRendering');
+ }
+ pauseRendering() {
+ this.renderRunner.pause('pauseRendering');
+ }
+ resumeRendering() {
+ this.renderRunner.resume('pauseRendering', true);
+ }
+ resetOptions(optionOverrides, append) {
+ this.currentDataManager.resetOptions(optionOverrides, append);
+ }
+ setClassNames(classNames) {
+ if (!isArraysEqual(classNames, this.currentClassNames)) {
+ let { classList } = this.el;
+ for (let className of this.currentClassNames) {
+ classList.remove(className);
+ }
+ for (let className of classNames) {
+ classList.add(className);
+ }
+ this.currentClassNames = classNames;
+ }
+ }
+ setHeight(height) {
+ applyStyleProp(this.el, 'height', height);
+ }
+ }
+
+ function formatDate(dateInput, options = {}) {
+ let dateEnv = buildDateEnv(options);
+ let formatter = createFormatter(options);
+ let dateMeta = dateEnv.createMarkerMeta(dateInput);
+ if (!dateMeta) { // TODO: warning?
+ return '';
+ }
+ return dateEnv.format(dateMeta.marker, formatter, {
+ forcedTzo: dateMeta.forcedTzo,
+ });
+ }
+ function formatRange(startInput, endInput, options) {
+ let dateEnv = buildDateEnv(typeof options === 'object' && options ? options : {}); // pass in if non-null object
+ let formatter = createFormatter(options);
+ let startMeta = dateEnv.createMarkerMeta(startInput);
+ let endMeta = dateEnv.createMarkerMeta(endInput);
+ if (!startMeta || !endMeta) { // TODO: warning?
+ return '';
+ }
+ return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, {
+ forcedStartTzo: startMeta.forcedTzo,
+ forcedEndTzo: endMeta.forcedTzo,
+ isEndExclusive: options.isEndExclusive,
+ defaultSeparator: BASE_OPTION_DEFAULTS.defaultRangeSeparator,
+ });
+ }
+ // TODO: more DRY and optimized
+ function buildDateEnv(settings) {
+ let locale = buildLocale(settings.locale || 'en', organizeRawLocales([]).map); // TODO: don't hardcode 'en' everywhere
+ return new DateEnv(Object.assign(Object.assign({ timeZone: BASE_OPTION_DEFAULTS.timeZone, calendarSystem: 'gregory' }, settings), { locale }));
+ }
+
+ // HELPERS
+ /*
+ if nextDayThreshold is specified, slicing is done in an all-day fashion.
+ you can get nextDayThreshold from context.nextDayThreshold
+ */
+ function sliceEvents(props, allDay) {
+ return sliceEventStore(props.eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? props.nextDayThreshold : null).fg;
+ }
+
+ const version = '6.0.3';
+
+ config.touchMouseIgnoreWait = 500;
+ let ignoreMouseDepth = 0;
+ let listenerCnt = 0;
+ let isWindowTouchMoveCancelled = false;
+ /*
+ Uses a "pointer" abstraction, which monitors UI events for both mouse and touch.
+ Tracks when the pointer "drags" on a certain element, meaning down+move+up.
+
+ Also, tracks if there was touch-scrolling.
+ Also, can prevent touch-scrolling from happening.
+ Also, can fire pointermove events when scrolling happens underneath, even when no real pointer movement.
+
+ emits:
+ - pointerdown
+ - pointermove
+ - pointerup
+ */
+ class PointerDragging {
+ constructor(containerEl) {
+ this.subjectEl = null;
+ // options that can be directly assigned by caller
+ this.selector = ''; // will cause subjectEl in all emitted events to be this element
+ this.handleSelector = '';
+ this.shouldIgnoreMove = false;
+ this.shouldWatchScroll = true; // for simulating pointermove on scroll
+ // internal states
+ this.isDragging = false;
+ this.isTouchDragging = false;
+ this.wasTouchScroll = false;
+ // Mouse
+ // ----------------------------------------------------------------------------------------------------
+ this.handleMouseDown = (ev) => {
+ if (!this.shouldIgnoreMouse() &&
+ isPrimaryMouseButton(ev) &&
+ this.tryStart(ev)) {
+ let pev = this.createEventFromMouse(ev, true);
+ this.emitter.trigger('pointerdown', pev);
+ this.initScrollWatch(pev);
+ if (!this.shouldIgnoreMove) {
+ document.addEventListener('mousemove', this.handleMouseMove);
+ }
+ document.addEventListener('mouseup', this.handleMouseUp);
+ }
+ };
+ this.handleMouseMove = (ev) => {
+ let pev = this.createEventFromMouse(ev);
+ this.recordCoords(pev);
+ this.emitter.trigger('pointermove', pev);
+ };
+ this.handleMouseUp = (ev) => {
+ document.removeEventListener('mousemove', this.handleMouseMove);
+ document.removeEventListener('mouseup', this.handleMouseUp);
+ this.emitter.trigger('pointerup', this.createEventFromMouse(ev));
+ this.cleanup(); // call last so that pointerup has access to props
+ };
+ // Touch
+ // ----------------------------------------------------------------------------------------------------
+ this.handleTouchStart = (ev) => {
+ if (this.tryStart(ev)) {
+ this.isTouchDragging = true;
+ let pev = this.createEventFromTouch(ev, true);
+ this.emitter.trigger('pointerdown', pev);
+ this.initScrollWatch(pev);
+ // unlike mouse, need to attach to target, not document
+ // https://stackoverflow.com/a/45760014
+ let targetEl = ev.target;
+ if (!this.shouldIgnoreMove) {
+ targetEl.addEventListener('touchmove', this.handleTouchMove);
+ }
+ targetEl.addEventListener('touchend', this.handleTouchEnd);
+ targetEl.addEventListener('touchcancel', this.handleTouchEnd); // treat it as a touch end
+ // attach a handler to get called when ANY scroll action happens on the page.
+ // this was impossible to do with normal on/off because 'scroll' doesn't bubble.
+ // http://stackoverflow.com/a/32954565/96342
+ window.addEventListener('scroll', this.handleTouchScroll, true);
+ }
+ };
+ this.handleTouchMove = (ev) => {
+ let pev = this.createEventFromTouch(ev);
+ this.recordCoords(pev);
+ this.emitter.trigger('pointermove', pev);
+ };
+ this.handleTouchEnd = (ev) => {
+ if (this.isDragging) { // done to guard against touchend followed by touchcancel
+ let targetEl = ev.target;
+ targetEl.removeEventListener('touchmove', this.handleTouchMove);
+ targetEl.removeEventListener('touchend', this.handleTouchEnd);
+ targetEl.removeEventListener('touchcancel', this.handleTouchEnd);
+ window.removeEventListener('scroll', this.handleTouchScroll, true); // useCaptured=true
+ this.emitter.trigger('pointerup', this.createEventFromTouch(ev));
+ this.cleanup(); // call last so that pointerup has access to props
+ this.isTouchDragging = false;
+ startIgnoringMouse();
+ }
+ };
+ this.handleTouchScroll = () => {
+ this.wasTouchScroll = true;
+ };
+ this.handleScroll = (ev) => {
+ if (!this.shouldIgnoreMove) {
+ let pageX = (window.pageXOffset - this.prevScrollX) + this.prevPageX;
+ let pageY = (window.pageYOffset - this.prevScrollY) + this.prevPageY;
+ this.emitter.trigger('pointermove', {
+ origEvent: ev,
+ isTouch: this.isTouchDragging,
+ subjectEl: this.subjectEl,
+ pageX,
+ pageY,
+ deltaX: pageX - this.origPageX,
+ deltaY: pageY - this.origPageY,
+ });
+ }
+ };
+ this.containerEl = containerEl;
+ this.emitter = new Emitter();
+ containerEl.addEventListener('mousedown', this.handleMouseDown);
+ containerEl.addEventListener('touchstart', this.handleTouchStart, { passive: true });
+ listenerCreated();
+ }
+ destroy() {
+ this.containerEl.removeEventListener('mousedown', this.handleMouseDown);
+ this.containerEl.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
+ listenerDestroyed();
+ }
+ tryStart(ev) {
+ let subjectEl = this.querySubjectEl(ev);
+ let downEl = ev.target;
+ if (subjectEl &&
+ (!this.handleSelector || elementClosest(downEl, this.handleSelector))) {
+ this.subjectEl = subjectEl;
+ this.isDragging = true; // do this first so cancelTouchScroll will work
+ this.wasTouchScroll = false;
+ return true;
+ }
+ return false;
+ }
+ cleanup() {
+ isWindowTouchMoveCancelled = false;
+ this.isDragging = false;
+ this.subjectEl = null;
+ // keep wasTouchScroll around for later access
+ this.destroyScrollWatch();
+ }
+ querySubjectEl(ev) {
+ if (this.selector) {
+ return elementClosest(ev.target, this.selector);
+ }
+ return this.containerEl;
+ }
+ shouldIgnoreMouse() {
+ return ignoreMouseDepth || this.isTouchDragging;
+ }
+ // can be called by user of this class, to cancel touch-based scrolling for the current drag
+ cancelTouchScroll() {
+ if (this.isDragging) {
+ isWindowTouchMoveCancelled = true;
+ }
+ }
+ // Scrolling that simulates pointermoves
+ // ----------------------------------------------------------------------------------------------------
+ initScrollWatch(ev) {
+ if (this.shouldWatchScroll) {
+ this.recordCoords(ev);
+ window.addEventListener('scroll', this.handleScroll, true); // useCapture=true
+ }
+ }
+ recordCoords(ev) {
+ if (this.shouldWatchScroll) {
+ this.prevPageX = ev.pageX;
+ this.prevPageY = ev.pageY;
+ this.prevScrollX = window.pageXOffset;
+ this.prevScrollY = window.pageYOffset;
+ }
+ }
+ destroyScrollWatch() {
+ if (this.shouldWatchScroll) {
+ window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true
+ }
+ }
+ // Event Normalization
+ // ----------------------------------------------------------------------------------------------------
+ createEventFromMouse(ev, isFirst) {
+ let deltaX = 0;
+ let deltaY = 0;
+ // TODO: repeat code
+ if (isFirst) {
+ this.origPageX = ev.pageX;
+ this.origPageY = ev.pageY;
+ }
+ else {
+ deltaX = ev.pageX - this.origPageX;
+ deltaY = ev.pageY - this.origPageY;
+ }
+ return {
+ origEvent: ev,
+ isTouch: false,
+ subjectEl: this.subjectEl,
+ pageX: ev.pageX,
+ pageY: ev.pageY,
+ deltaX,
+ deltaY,
+ };
+ }
+ createEventFromTouch(ev, isFirst) {
+ let touches = ev.touches;
+ let pageX;
+ let pageY;
+ let deltaX = 0;
+ let deltaY = 0;
+ // if touch coords available, prefer,
+ // because FF would give bad ev.pageX ev.pageY
+ if (touches && touches.length) {
+ pageX = touches[0].pageX;
+ pageY = touches[0].pageY;
+ }
+ else {
+ pageX = ev.pageX;
+ pageY = ev.pageY;
+ }
+ // TODO: repeat code
+ if (isFirst) {
+ this.origPageX = pageX;
+ this.origPageY = pageY;
+ }
+ else {
+ deltaX = pageX - this.origPageX;
+ deltaY = pageY - this.origPageY;
+ }
+ return {
+ origEvent: ev,
+ isTouch: true,
+ subjectEl: this.subjectEl,
+ pageX,
+ pageY,
+ deltaX,
+ deltaY,
+ };
+ }
+ }
+ // Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)
+ function isPrimaryMouseButton(ev) {
+ return ev.button === 0 && !ev.ctrlKey;
+ }
+ // Ignoring fake mouse events generated by touch
+ // ----------------------------------------------------------------------------------------------------
+ function startIgnoringMouse() {
+ ignoreMouseDepth += 1;
+ setTimeout(() => {
+ ignoreMouseDepth -= 1;
+ }, config.touchMouseIgnoreWait);
+ }
+ // We want to attach touchmove as early as possible for Safari
+ // ----------------------------------------------------------------------------------------------------
+ function listenerCreated() {
+ listenerCnt += 1;
+ if (listenerCnt === 1) {
+ window.addEventListener('touchmove', onWindowTouchMove, { passive: false });
+ }
+ }
+ function listenerDestroyed() {
+ listenerCnt -= 1;
+ if (!listenerCnt) {
+ window.removeEventListener('touchmove', onWindowTouchMove, { passive: false });
+ }
+ }
+ function onWindowTouchMove(ev) {
+ if (isWindowTouchMoveCancelled) {
+ ev.preventDefault();
+ }
+ }
+
+ /*
+ An effect in which an element follows the movement of a pointer across the screen.
+ The moving element is a clone of some other element.
+ Must call start + handleMove + stop.
+ */
+ class ElementMirror {
+ constructor() {
+ this.isVisible = false; // must be explicitly enabled
+ this.sourceEl = null;
+ this.mirrorEl = null;
+ this.sourceElRect = null; // screen coords relative to viewport
+ // options that can be set directly by caller
+ this.parentNode = document.body; // HIGHLY SUGGESTED to set this to sidestep ShadowDOM issues
+ this.zIndex = 9999;
+ this.revertDuration = 0;
+ }
+ start(sourceEl, pageX, pageY) {
+ this.sourceEl = sourceEl;
+ this.sourceElRect = this.sourceEl.getBoundingClientRect();
+ this.origScreenX = pageX - window.pageXOffset;
+ this.origScreenY = pageY - window.pageYOffset;
+ this.deltaX = 0;
+ this.deltaY = 0;
+ this.updateElPosition();
+ }
+ handleMove(pageX, pageY) {
+ this.deltaX = (pageX - window.pageXOffset) - this.origScreenX;
+ this.deltaY = (pageY - window.pageYOffset) - this.origScreenY;
+ this.updateElPosition();
+ }
+ // can be called before start
+ setIsVisible(bool) {
+ if (bool) {
+ if (!this.isVisible) {
+ if (this.mirrorEl) {
+ this.mirrorEl.style.display = '';
+ }
+ this.isVisible = bool; // needs to happen before updateElPosition
+ this.updateElPosition(); // because was not updating the position while invisible
+ }
+ }
+ else if (this.isVisible) {
+ if (this.mirrorEl) {
+ this.mirrorEl.style.display = 'none';
+ }
+ this.isVisible = bool;
+ }
+ }
+ // always async
+ stop(needsRevertAnimation, callback) {
+ let done = () => {
+ this.cleanup();
+ callback();
+ };
+ if (needsRevertAnimation &&
+ this.mirrorEl &&
+ this.isVisible &&
+ this.revertDuration && // if 0, transition won't work
+ (this.deltaX || this.deltaY) // if same coords, transition won't work
+ ) {
+ this.doRevertAnimation(done, this.revertDuration);
+ }
+ else {
+ setTimeout(done, 0);
+ }
+ }
+ doRevertAnimation(callback, revertDuration) {
+ let mirrorEl = this.mirrorEl;
+ let finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened
+ mirrorEl.style.transition =
+ 'top ' + revertDuration + 'ms,' +
+ 'left ' + revertDuration + 'ms';
+ applyStyle(mirrorEl, {
+ left: finalSourceElRect.left,
+ top: finalSourceElRect.top,
+ });
+ whenTransitionDone(mirrorEl, () => {
+ mirrorEl.style.transition = '';
+ callback();
+ });
+ }
+ cleanup() {
+ if (this.mirrorEl) {
+ removeElement(this.mirrorEl);
+ this.mirrorEl = null;
+ }
+ this.sourceEl = null;
+ }
+ updateElPosition() {
+ if (this.sourceEl && this.isVisible) {
+ applyStyle(this.getMirrorEl(), {
+ left: this.sourceElRect.left + this.deltaX,
+ top: this.sourceElRect.top + this.deltaY,
+ });
+ }
+ }
+ getMirrorEl() {
+ let sourceElRect = this.sourceElRect;
+ let mirrorEl = this.mirrorEl;
+ if (!mirrorEl) {
+ mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true
+ // we don't want long taps or any mouse interaction causing selection/menus.
+ // would use preventSelection(), but that prevents selectstart, causing problems.
+ mirrorEl.classList.add('fc-unselectable');
+ mirrorEl.classList.add('fc-event-dragging');
+ applyStyle(mirrorEl, {
+ position: 'fixed',
+ zIndex: this.zIndex,
+ visibility: '',
+ boxSizing: 'border-box',
+ width: sourceElRect.right - sourceElRect.left,
+ height: sourceElRect.bottom - sourceElRect.top,
+ right: 'auto',
+ bottom: 'auto',
+ margin: 0,
+ });
+ this.parentNode.appendChild(mirrorEl);
+ }
+ return mirrorEl;
+ }
+ }
+
+ /*
+ Is a cache for a given element's scroll information (all the info that ScrollController stores)
+ in addition the "client rectangle" of the element.. the area within the scrollbars.
+
+ The cache can be in one of two modes:
+ - doesListening:false - ignores when the container is scrolled by someone else
+ - doesListening:true - watch for scrolling and update the cache
+ */
+ class ScrollGeomCache extends ScrollController {
+ constructor(scrollController, doesListening) {
+ super();
+ this.handleScroll = () => {
+ this.scrollTop = this.scrollController.getScrollTop();
+ this.scrollLeft = this.scrollController.getScrollLeft();
+ this.handleScrollChange();
+ };
+ this.scrollController = scrollController;
+ this.doesListening = doesListening;
+ this.scrollTop = this.origScrollTop = scrollController.getScrollTop();
+ this.scrollLeft = this.origScrollLeft = scrollController.getScrollLeft();
+ this.scrollWidth = scrollController.getScrollWidth();
+ this.scrollHeight = scrollController.getScrollHeight();
+ this.clientWidth = scrollController.getClientWidth();
+ this.clientHeight = scrollController.getClientHeight();
+ this.clientRect = this.computeClientRect(); // do last in case it needs cached values
+ if (this.doesListening) {
+ this.getEventTarget().addEventListener('scroll', this.handleScroll);
+ }
+ }
+ destroy() {
+ if (this.doesListening) {
+ this.getEventTarget().removeEventListener('scroll', this.handleScroll);
+ }
+ }
+ getScrollTop() {
+ return this.scrollTop;
+ }
+ getScrollLeft() {
+ return this.scrollLeft;
+ }
+ setScrollTop(top) {
+ this.scrollController.setScrollTop(top);
+ if (!this.doesListening) {
+ // we are not relying on the element to normalize out-of-bounds scroll values
+ // so we need to sanitize ourselves
+ this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0);
+ this.handleScrollChange();
+ }
+ }
+ setScrollLeft(top) {
+ this.scrollController.setScrollLeft(top);
+ if (!this.doesListening) {
+ // we are not relying on the element to normalize out-of-bounds scroll values
+ // so we need to sanitize ourselves
+ this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0);
+ this.handleScrollChange();
+ }
+ }
+ getClientWidth() {
+ return this.clientWidth;
+ }
+ getClientHeight() {
+ return this.clientHeight;
+ }
+ getScrollWidth() {
+ return this.scrollWidth;
+ }
+ getScrollHeight() {
+ return this.scrollHeight;
+ }
+ handleScrollChange() {
+ }
+ }
+
+ class ElementScrollGeomCache extends ScrollGeomCache {
+ constructor(el, doesListening) {
+ super(new ElementScrollController(el), doesListening);
+ }
+ getEventTarget() {
+ return this.scrollController.el;
+ }
+ computeClientRect() {
+ return computeInnerRect(this.scrollController.el);
+ }
+ }
+
+ class WindowScrollGeomCache extends ScrollGeomCache {
+ constructor(doesListening) {
+ super(new WindowScrollController(), doesListening);
+ }
+ getEventTarget() {
+ return window;
+ }
+ computeClientRect() {
+ return {
+ left: this.scrollLeft,
+ right: this.scrollLeft + this.clientWidth,
+ top: this.scrollTop,
+ bottom: this.scrollTop + this.clientHeight,
+ };
+ }
+ // the window is the only scroll object that changes it's rectangle relative
+ // to the document's topleft as it scrolls
+ handleScrollChange() {
+ this.clientRect = this.computeClientRect();
+ }
+ }
+
+ // If available we are using native "performance" API instead of "Date"
+ // Read more about it on MDN:
+ // https://developer.mozilla.org/en-US/docs/Web/API/Performance
+ const getTime = typeof performance === 'function' ? performance.now : Date.now;
+ /*
+ For a pointer interaction, automatically scrolls certain scroll containers when the pointer
+ approaches the edge.
+
+ The caller must call start + handleMove + stop.
+ */
+ class AutoScroller {
+ constructor() {
+ // options that can be set by caller
+ this.isEnabled = true;
+ this.scrollQuery = [window, '.fc-scroller'];
+ this.edgeThreshold = 50; // pixels
+ this.maxVelocity = 300; // pixels per second
+ // internal state
+ this.pointerScreenX = null;
+ this.pointerScreenY = null;
+ this.isAnimating = false;
+ this.scrollCaches = null;
+ // protect against the initial pointerdown being too close to an edge and starting the scroll
+ this.everMovedUp = false;
+ this.everMovedDown = false;
+ this.everMovedLeft = false;
+ this.everMovedRight = false;
+ this.animate = () => {
+ if (this.isAnimating) { // wasn't cancelled between animation calls
+ let edge = this.computeBestEdge(this.pointerScreenX + window.pageXOffset, this.pointerScreenY + window.pageYOffset);
+ if (edge) {
+ let now = getTime();
+ this.handleSide(edge, (now - this.msSinceRequest) / 1000);
+ this.requestAnimation(now);
+ }
+ else {
+ this.isAnimating = false; // will stop animation
+ }
+ }
+ };
+ }
+ start(pageX, pageY, scrollStartEl) {
+ if (this.isEnabled) {
+ this.scrollCaches = this.buildCaches(scrollStartEl);
+ this.pointerScreenX = null;
+ this.pointerScreenY = null;
+ this.everMovedUp = false;
+ this.everMovedDown = false;
+ this.everMovedLeft = false;
+ this.everMovedRight = false;
+ this.handleMove(pageX, pageY);
+ }
+ }
+ handleMove(pageX, pageY) {
+ if (this.isEnabled) {
+ let pointerScreenX = pageX - window.pageXOffset;
+ let pointerScreenY = pageY - window.pageYOffset;
+ let yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY;
+ let xDelta = this.pointerScreenX === null ? 0 : pointerScreenX - this.pointerScreenX;
+ if (yDelta < 0) {
+ this.everMovedUp = true;
+ }
+ else if (yDelta > 0) {
+ this.everMovedDown = true;
+ }
+ if (xDelta < 0) {
+ this.everMovedLeft = true;
+ }
+ else if (xDelta > 0) {
+ this.everMovedRight = true;
+ }
+ this.pointerScreenX = pointerScreenX;
+ this.pointerScreenY = pointerScreenY;
+ if (!this.isAnimating) {
+ this.isAnimating = true;
+ this.requestAnimation(getTime());
+ }
+ }
+ }
+ stop() {
+ if (this.isEnabled) {
+ this.isAnimating = false; // will stop animation
+ for (let scrollCache of this.scrollCaches) {
+ scrollCache.destroy();
+ }
+ this.scrollCaches = null;
+ }
+ }
+ requestAnimation(now) {
+ this.msSinceRequest = now;
+ requestAnimationFrame(this.animate);
+ }
+ handleSide(edge, seconds) {
+ let { scrollCache } = edge;
+ let { edgeThreshold } = this;
+ let invDistance = edgeThreshold - edge.distance;
+ let velocity = // the closer to the edge, the faster we scroll
+ ((invDistance * invDistance) / (edgeThreshold * edgeThreshold)) * // quadratic
+ this.maxVelocity * seconds;
+ let sign = 1;
+ switch (edge.name) {
+ case 'left':
+ sign = -1;
+ // falls through
+ case 'right':
+ scrollCache.setScrollLeft(scrollCache.getScrollLeft() + velocity * sign);
+ break;
+ case 'top':
+ sign = -1;
+ // falls through
+ case 'bottom':
+ scrollCache.setScrollTop(scrollCache.getScrollTop() + velocity * sign);
+ break;
+ }
+ }
+ // left/top are relative to document topleft
+ computeBestEdge(left, top) {
+ let { edgeThreshold } = this;
+ let bestSide = null;
+ let scrollCaches = this.scrollCaches || [];
+ for (let scrollCache of scrollCaches) {
+ let rect = scrollCache.clientRect;
+ let leftDist = left - rect.left;
+ let rightDist = rect.right - left;
+ let topDist = top - rect.top;
+ let bottomDist = rect.bottom - top;
+ // completely within the rect?
+ if (leftDist >= 0 && rightDist >= 0 && topDist >= 0 && bottomDist >= 0) {
+ if (topDist <= edgeThreshold && this.everMovedUp && scrollCache.canScrollUp() &&
+ (!bestSide || bestSide.distance > topDist)) {
+ bestSide = { scrollCache, name: 'top', distance: topDist };
+ }
+ if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() &&
+ (!bestSide || bestSide.distance > bottomDist)) {
+ bestSide = { scrollCache, name: 'bottom', distance: bottomDist };
+ }
+ if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() &&
+ (!bestSide || bestSide.distance > leftDist)) {
+ bestSide = { scrollCache, name: 'left', distance: leftDist };
+ }
+ if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() &&
+ (!bestSide || bestSide.distance > rightDist)) {
+ bestSide = { scrollCache, name: 'right', distance: rightDist };
+ }
+ }
+ }
+ return bestSide;
+ }
+ buildCaches(scrollStartEl) {
+ return this.queryScrollEls(scrollStartEl).map((el) => {
+ if (el === window) {
+ return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls
+ }
+ return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls
+ });
+ }
+ queryScrollEls(scrollStartEl) {
+ let els = [];
+ for (let query of this.scrollQuery) {
+ if (typeof query === 'object') {
+ els.push(query);
+ }
+ else {
+ els.push(...Array.prototype.slice.call(getElRoot(scrollStartEl).querySelectorAll(query)));
+ }
+ }
+ return els;
+ }
+ }
+
+ /*
+ Monitors dragging on an element. Has a number of high-level features:
+ - minimum distance required before dragging
+ - minimum wait time ("delay") before dragging
+ - a mirror element that follows the pointer
+ */
+ class FeaturefulElementDragging extends ElementDragging {
+ constructor(containerEl, selector) {
+ super(containerEl);
+ this.containerEl = containerEl;
+ // options that can be directly set by caller
+ // the caller can also set the PointerDragging's options as well
+ this.delay = null;
+ this.minDistance = 0;
+ this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag
+ this.mirrorNeedsRevert = false;
+ this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup
+ this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation
+ this.isDelayEnded = false;
+ this.isDistanceSurpassed = false;
+ this.delayTimeoutId = null;
+ this.onPointerDown = (ev) => {
+ if (!this.isDragging) { // so new drag doesn't happen while revert animation is going
+ this.isInteracting = true;
+ this.isDelayEnded = false;
+ this.isDistanceSurpassed = false;
+ preventSelection(document.body);
+ preventContextMenu(document.body);
+ // prevent links from being visited if there's an eventual drag.
+ // also prevents selection in older browsers (maybe?).
+ // not necessary for touch, besides, browser would complain about passiveness.
+ if (!ev.isTouch) {
+ ev.origEvent.preventDefault();
+ }
+ this.emitter.trigger('pointerdown', ev);
+ if (this.isInteracting && // not destroyed via pointerdown handler
+ !this.pointer.shouldIgnoreMove) {
+ // actions related to initiating dragstart+dragmove+dragend...
+ this.mirror.setIsVisible(false); // reset. caller must set-visible
+ this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down
+ this.startDelay(ev);
+ if (!this.minDistance) {
+ this.handleDistanceSurpassed(ev);
+ }
+ }
+ }
+ };
+ this.onPointerMove = (ev) => {
+ if (this.isInteracting) {
+ this.emitter.trigger('pointermove', ev);
+ if (!this.isDistanceSurpassed) {
+ let minDistance = this.minDistance;
+ let distanceSq; // current distance from the origin, squared
+ let { deltaX, deltaY } = ev;
+ distanceSq = deltaX * deltaX + deltaY * deltaY;
+ if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem
+ this.handleDistanceSurpassed(ev);
+ }
+ }
+ if (this.isDragging) {
+ // a real pointer move? (not one simulated by scrolling)
+ if (ev.origEvent.type !== 'scroll') {
+ this.mirror.handleMove(ev.pageX, ev.pageY);
+ this.autoScroller.handleMove(ev.pageX, ev.pageY);
+ }
+ this.emitter.trigger('dragmove', ev);
+ }
+ }
+ };
+ this.onPointerUp = (ev) => {
+ if (this.isInteracting) {
+ this.isInteracting = false;
+ allowSelection(document.body);
+ allowContextMenu(document.body);
+ this.emitter.trigger('pointerup', ev); // can potentially set mirrorNeedsRevert
+ if (this.isDragging) {
+ this.autoScroller.stop();
+ this.tryStopDrag(ev); // which will stop the mirror
+ }
+ if (this.delayTimeoutId) {
+ clearTimeout(this.delayTimeoutId);
+ this.delayTimeoutId = null;
+ }
+ }
+ };
+ let pointer = this.pointer = new PointerDragging(containerEl);
+ pointer.emitter.on('pointerdown', this.onPointerDown);
+ pointer.emitter.on('pointermove', this.onPointerMove);
+ pointer.emitter.on('pointerup', this.onPointerUp);
+ if (selector) {
+ pointer.selector = selector;
+ }
+ this.mirror = new ElementMirror();
+ this.autoScroller = new AutoScroller();
+ }
+ destroy() {
+ this.pointer.destroy();
+ // HACK: simulate a pointer-up to end the current drag
+ // TODO: fire 'dragend' directly and stop interaction. discourage use of pointerup event (b/c might not fire)
+ this.onPointerUp({});
+ }
+ startDelay(ev) {
+ if (typeof this.delay === 'number') {
+ this.delayTimeoutId = setTimeout(() => {
+ this.delayTimeoutId = null;
+ this.handleDelayEnd(ev);
+ }, this.delay); // not assignable to number!
+ }
+ else {
+ this.handleDelayEnd(ev);
+ }
+ }
+ handleDelayEnd(ev) {
+ this.isDelayEnded = true;
+ this.tryStartDrag(ev);
+ }
+ handleDistanceSurpassed(ev) {
+ this.isDistanceSurpassed = true;
+ this.tryStartDrag(ev);
+ }
+ tryStartDrag(ev) {
+ if (this.isDelayEnded && this.isDistanceSurpassed) {
+ if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) {
+ this.isDragging = true;
+ this.mirrorNeedsRevert = false;
+ this.autoScroller.start(ev.pageX, ev.pageY, this.containerEl);
+ this.emitter.trigger('dragstart', ev);
+ if (this.touchScrollAllowed === false) {
+ this.pointer.cancelTouchScroll();
+ }
+ }
+ }
+ }
+ tryStopDrag(ev) {
+ // .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events
+ // that come from the document to fire beforehand. much more convenient this way.
+ this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev));
+ }
+ stopDrag(ev) {
+ this.isDragging = false;
+ this.emitter.trigger('dragend', ev);
+ }
+ // fill in the implementations...
+ setIgnoreMove(bool) {
+ this.pointer.shouldIgnoreMove = bool;
+ }
+ setMirrorIsVisible(bool) {
+ this.mirror.setIsVisible(bool);
+ }
+ setMirrorNeedsRevert(bool) {
+ this.mirrorNeedsRevert = bool;
+ }
+ setAutoScrollEnabled(bool) {
+ this.autoScroller.isEnabled = bool;
+ }
+ }
+
+ /*
+ When this class is instantiated, it records the offset of an element (relative to the document topleft),
+ and continues to monitor scrolling, updating the cached coordinates if it needs to.
+ Does not access the DOM after instantiation, so highly performant.
+
+ Also keeps track of all scrolling/overflow:hidden containers that are parents of the given element
+ and an determine if a given point is inside the combined clipping rectangle.
+ */
+ class OffsetTracker {
+ constructor(el) {
+ this.origRect = computeRect(el);
+ // will work fine for divs that have overflow:hidden
+ this.scrollCaches = getClippingParents(el).map((scrollEl) => new ElementScrollGeomCache(scrollEl, true));
+ }
+ destroy() {
+ for (let scrollCache of this.scrollCaches) {
+ scrollCache.destroy();
+ }
+ }
+ computeLeft() {
+ let left = this.origRect.left;
+ for (let scrollCache of this.scrollCaches) {
+ left += scrollCache.origScrollLeft - scrollCache.getScrollLeft();
+ }
+ return left;
+ }
+ computeTop() {
+ let top = this.origRect.top;
+ for (let scrollCache of this.scrollCaches) {
+ top += scrollCache.origScrollTop - scrollCache.getScrollTop();
+ }
+ return top;
+ }
+ isWithinClipping(pageX, pageY) {
+ let point = { left: pageX, top: pageY };
+ for (let scrollCache of this.scrollCaches) {
+ if (!isIgnoredClipping(scrollCache.getEventTarget()) &&
+ !pointInsideRect(point, scrollCache.clientRect)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ // certain clipping containers should never constrain interactions, like <html> and <body>
+ // https://github.com/fullcalendar/fullcalendar/issues/3615
+ function isIgnoredClipping(node) {
+ let tagName = node.tagName;
+ return tagName === 'HTML' || tagName === 'BODY';
+ }
+
+ /*
+ Tracks movement over multiple droppable areas (aka "hits")
+ that exist in one or more DateComponents.
+ Relies on an existing draggable.
+
+ emits:
+ - pointerdown
+ - dragstart
+ - hitchange - fires initially, even if not over a hit
+ - pointerup
+ - (hitchange - again, to null, if ended over a hit)
+ - dragend
+ */
+ class HitDragging {
+ constructor(dragging, droppableStore) {
+ // options that can be set by caller
+ this.useSubjectCenter = false;
+ this.requireInitial = true; // if doesn't start out on a hit, won't emit any events
+ this.initialHit = null;
+ this.movingHit = null;
+ this.finalHit = null; // won't ever be populated if shouldIgnoreMove
+ this.handlePointerDown = (ev) => {
+ let { dragging } = this;
+ this.initialHit = null;
+ this.movingHit = null;
+ this.finalHit = null;
+ this.prepareHits();
+ this.processFirstCoord(ev);
+ if (this.initialHit || !this.requireInitial) {
+ dragging.setIgnoreMove(false);
+ // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :(
+ this.emitter.trigger('pointerdown', ev);
+ }
+ else {
+ dragging.setIgnoreMove(true);
+ }
+ };
+ this.handleDragStart = (ev) => {
+ this.emitter.trigger('dragstart', ev);
+ this.handleMove(ev, true); // force = fire even if initially null
+ };
+ this.handleDragMove = (ev) => {
+ this.emitter.trigger('dragmove', ev);
+ this.handleMove(ev);
+ };
+ this.handlePointerUp = (ev) => {
+ this.releaseHits();
+ this.emitter.trigger('pointerup', ev);
+ };
+ this.handleDragEnd = (ev) => {
+ if (this.movingHit) {
+ this.emitter.trigger('hitupdate', null, true, ev);
+ }
+ this.finalHit = this.movingHit;
+ this.movingHit = null;
+ this.emitter.trigger('dragend', ev);
+ };
+ this.droppableStore = droppableStore;
+ dragging.emitter.on('pointerdown', this.handlePointerDown);
+ dragging.emitter.on('dragstart', this.handleDragStart);
+ dragging.emitter.on('dragmove', this.handleDragMove);
+ dragging.emitter.on('pointerup', this.handlePointerUp);
+ dragging.emitter.on('dragend', this.handleDragEnd);
+ this.dragging = dragging;
+ this.emitter = new Emitter();
+ }
+ // sets initialHit
+ // sets coordAdjust
+ processFirstCoord(ev) {
+ let origPoint = { left: ev.pageX, top: ev.pageY };
+ let adjustedPoint = origPoint;
+ let subjectEl = ev.subjectEl;
+ let subjectRect;
+ if (subjectEl instanceof HTMLElement) { // i.e. not a Document/ShadowRoot
+ subjectRect = computeRect(subjectEl);
+ adjustedPoint = constrainPoint(adjustedPoint, subjectRect);
+ }
+ let initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top);
+ if (initialHit) {
+ if (this.useSubjectCenter && subjectRect) {
+ let slicedSubjectRect = intersectRects(subjectRect, initialHit.rect);
+ if (slicedSubjectRect) {
+ adjustedPoint = getRectCenter(slicedSubjectRect);
+ }
+ }
+ this.coordAdjust = diffPoints(adjustedPoint, origPoint);
+ }
+ else {
+ this.coordAdjust = { left: 0, top: 0 };
+ }
+ }
+ handleMove(ev, forceHandle) {
+ let hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top);
+ if (forceHandle || !isHitsEqual(this.movingHit, hit)) {
+ this.movingHit = hit;
+ this.emitter.trigger('hitupdate', hit, false, ev);
+ }
+ }
+ prepareHits() {
+ this.offsetTrackers = mapHash(this.droppableStore, (interactionSettings) => {
+ interactionSettings.component.prepareHits();
+ return new OffsetTracker(interactionSettings.el);
+ });
+ }
+ releaseHits() {
+ let { offsetTrackers } = this;
+ for (let id in offsetTrackers) {
+ offsetTrackers[id].destroy();
+ }
+ this.offsetTrackers = {};
+ }
+ queryHitForOffset(offsetLeft, offsetTop) {
+ let { droppableStore, offsetTrackers } = this;
+ let bestHit = null;
+ for (let id in droppableStore) {
+ let component = droppableStore[id].component;
+ let offsetTracker = offsetTrackers[id];
+ if (offsetTracker && // wasn't destroyed mid-drag
+ offsetTracker.isWithinClipping(offsetLeft, offsetTop)) {
+ let originLeft = offsetTracker.computeLeft();
+ let originTop = offsetTracker.computeTop();
+ let positionLeft = offsetLeft - originLeft;
+ let positionTop = offsetTop - originTop;
+ let { origRect } = offsetTracker;
+ let width = origRect.right - origRect.left;
+ let height = origRect.bottom - origRect.top;
+ if (
+ // must be within the element's bounds
+ positionLeft >= 0 && positionLeft < width &&
+ positionTop >= 0 && positionTop < height) {
+ let hit = component.queryHit(positionLeft, positionTop, width, height);
+ if (hit && (
+ // make sure the hit is within activeRange, meaning it's not a dead cell
+ rangeContainsRange(hit.dateProfile.activeRange, hit.dateSpan.range)) &&
+ (!bestHit || hit.layer > bestHit.layer)) {
+ hit.componentId = id;
+ hit.context = component.context;
+ // TODO: better way to re-orient rectangle
+ hit.rect.left += originLeft;
+ hit.rect.right += originLeft;
+ hit.rect.top += originTop;
+ hit.rect.bottom += originTop;
+ bestHit = hit;
+ }
+ }
+ }
+ }
+ return bestHit;
+ }
+ }
+ function isHitsEqual(hit0, hit1) {
+ if (!hit0 && !hit1) {
+ return true;
+ }
+ if (Boolean(hit0) !== Boolean(hit1)) {
+ return false;
+ }
+ return isDateSpansEqual(hit0.dateSpan, hit1.dateSpan);
+ }
+
+ function buildDatePointApiWithContext(dateSpan, context) {
+ let props = {};
+ for (let transform of context.pluginHooks.datePointTransforms) {
+ Object.assign(props, transform(dateSpan, context));
+ }
+ Object.assign(props, buildDatePointApi(dateSpan, context.dateEnv));
+ return props;
+ }
+ function buildDatePointApi(span, dateEnv) {
+ return {
+ date: dateEnv.toDate(span.range.start),
+ dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }),
+ allDay: span.allDay,
+ };
+ }
+
+ /*
+ Monitors when the user clicks on a specific date/time of a component.
+ A pointerdown+pointerup on the same "hit" constitutes a click.
+ */
+ class DateClicking extends Interaction {
+ constructor(settings) {
+ super(settings);
+ this.handlePointerDown = (pev) => {
+ let { dragging } = this;
+ let downEl = pev.origEvent.target;
+ // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired
+ dragging.setIgnoreMove(!this.component.isValidDateDownEl(downEl));
+ };
+ // won't even fire if moving was ignored
+ this.handleDragEnd = (ev) => {
+ let { component } = this;
+ let { pointer } = this.dragging;
+ if (!pointer.wasTouchScroll) {
+ let { initialHit, finalHit } = this.hitDragging;
+ if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) {
+ let { context } = component;
+ let arg = Object.assign(Object.assign({}, buildDatePointApiWithContext(initialHit.dateSpan, context)), { dayEl: initialHit.dayEl, jsEvent: ev.origEvent, view: context.viewApi || context.calendarApi.view });
+ context.emitter.trigger('dateClick', arg);
+ }
+ }
+ };
+ // we DO want to watch pointer moves because otherwise finalHit won't get populated
+ this.dragging = new FeaturefulElementDragging(settings.el);
+ this.dragging.autoScroller.isEnabled = false;
+ let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
+ hitDragging.emitter.on('pointerdown', this.handlePointerDown);
+ hitDragging.emitter.on('dragend', this.handleDragEnd);
+ }
+ destroy() {
+ this.dragging.destroy();
+ }
+ }
+
+ /*
+ Tracks when the user selects a portion of time of a component,
+ constituted by a drag over date cells, with a possible delay at the beginning of the drag.
+ */
+ class DateSelecting extends Interaction {
+ constructor(settings) {
+ super(settings);
+ this.dragSelection = null;
+ this.handlePointerDown = (ev) => {
+ let { component, dragging } = this;
+ let { options } = component.context;
+ let canSelect = options.selectable &&
+ component.isValidDateDownEl(ev.origEvent.target);
+ // don't bother to watch expensive moves if component won't do selection
+ dragging.setIgnoreMove(!canSelect);
+ // if touch, require user to hold down
+ dragging.delay = ev.isTouch ? getComponentTouchDelay$1(component) : null;
+ };
+ this.handleDragStart = (ev) => {
+ this.component.context.calendarApi.unselect(ev); // unselect previous selections
+ };
+ this.handleHitUpdate = (hit, isFinal) => {
+ let { context } = this.component;
+ let dragSelection = null;
+ let isInvalid = false;
+ if (hit) {
+ let initialHit = this.hitDragging.initialHit;
+ let disallowed = hit.componentId === initialHit.componentId
+ && this.isHitComboAllowed
+ && !this.isHitComboAllowed(initialHit, hit);
+ if (!disallowed) {
+ dragSelection = joinHitsIntoSelection(initialHit, hit, context.pluginHooks.dateSelectionTransformers);
+ }
+ if (!dragSelection || !isDateSelectionValid(dragSelection, hit.dateProfile, context)) {
+ isInvalid = true;
+ dragSelection = null;
+ }
+ }
+ if (dragSelection) {
+ context.dispatch({ type: 'SELECT_DATES', selection: dragSelection });
+ }
+ else if (!isFinal) { // only unselect if moved away while dragging
+ context.dispatch({ type: 'UNSELECT_DATES' });
+ }
+ if (!isInvalid) {
+ enableCursor();
+ }
+ else {
+ disableCursor();
+ }
+ if (!isFinal) {
+ this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging
+ }
+ };
+ this.handlePointerUp = (pev) => {
+ if (this.dragSelection) {
+ // selection is already rendered, so just need to report selection
+ triggerDateSelect(this.dragSelection, pev, this.component.context);
+ this.dragSelection = null;
+ }
+ };
+ let { component } = settings;
+ let { options } = component.context;
+ let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
+ dragging.touchScrollAllowed = false;
+ dragging.minDistance = options.selectMinDistance || 0;
+ dragging.autoScroller.isEnabled = options.dragScroll;
+ let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
+ hitDragging.emitter.on('pointerdown', this.handlePointerDown);
+ hitDragging.emitter.on('dragstart', this.handleDragStart);
+ hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
+ hitDragging.emitter.on('pointerup', this.handlePointerUp);
+ }
+ destroy() {
+ this.dragging.destroy();
+ }
+ }
+ function getComponentTouchDelay$1(component) {
+ let { options } = component.context;
+ let delay = options.selectLongPressDelay;
+ if (delay == null) {
+ delay = options.longPressDelay;
+ }
+ return delay;
+ }
+ function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) {
+ let dateSpan0 = hit0.dateSpan;
+ let dateSpan1 = hit1.dateSpan;
+ let ms = [
+ dateSpan0.range.start,
+ dateSpan0.range.end,
+ dateSpan1.range.start,
+ dateSpan1.range.end,
+ ];
+ ms.sort(compareNumbers);
+ let props = {};
+ for (let transformer of dateSelectionTransformers) {
+ let res = transformer(hit0, hit1);
+ if (res === false) {
+ return null;
+ }
+ if (res) {
+ Object.assign(props, res);
+ }
+ }
+ props.range = { start: ms[0], end: ms[3] };
+ props.allDay = dateSpan0.allDay;
+ return props;
+ }
+
+ class EventDragging extends Interaction {
+ constructor(settings) {
+ super(settings);
+ // internal state
+ this.subjectEl = null;
+ this.subjectSeg = null; // the seg being selected/dragged
+ this.isDragging = false;
+ this.eventRange = null;
+ this.relevantEvents = null; // the events being dragged
+ this.receivingContext = null;
+ this.validMutation = null;
+ this.mutatedRelevantEvents = null;
+ this.handlePointerDown = (ev) => {
+ let origTarget = ev.origEvent.target;
+ let { component, dragging } = this;
+ let { mirror } = dragging;
+ let { options } = component.context;
+ let initialContext = component.context;
+ this.subjectEl = ev.subjectEl;
+ let subjectSeg = this.subjectSeg = getElSeg(ev.subjectEl);
+ let eventRange = this.eventRange = subjectSeg.eventRange;
+ let eventInstanceId = eventRange.instance.instanceId;
+ this.relevantEvents = getRelevantEvents(initialContext.getCurrentData().eventStore, eventInstanceId);
+ dragging.minDistance = ev.isTouch ? 0 : options.eventDragMinDistance;
+ dragging.delay =
+ // only do a touch delay if touch and this event hasn't been selected yet
+ (ev.isTouch && eventInstanceId !== component.props.eventSelection) ?
+ getComponentTouchDelay(component) :
+ null;
+ if (options.fixedMirrorParent) {
+ mirror.parentNode = options.fixedMirrorParent;
+ }
+ else {
+ mirror.parentNode = elementClosest(origTarget, '.fc');
+ }
+ mirror.revertDuration = options.dragRevertDuration;
+ let isValid = component.isValidSegDownEl(origTarget) &&
+ !elementClosest(origTarget, '.fc-event-resizer'); // NOT on a resizer
+ dragging.setIgnoreMove(!isValid);
+ // disable dragging for elements that are resizable (ie, selectable)
+ // but are not draggable
+ this.isDragging = isValid &&
+ ev.subjectEl.classList.contains('fc-event-draggable');
+ };
+ this.handleDragStart = (ev) => {
+ let initialContext = this.component.context;
+ let eventRange = this.eventRange;
+ let eventInstanceId = eventRange.instance.instanceId;
+ if (ev.isTouch) {
+ // need to select a different event?
+ if (eventInstanceId !== this.component.props.eventSelection) {
+ initialContext.dispatch({ type: 'SELECT_EVENT', eventInstanceId });
+ }
+ }
+ else {
+ // if now using mouse, but was previous touch interaction, clear selected event
+ initialContext.dispatch({ type: 'UNSELECT_EVENT' });
+ }
+ if (this.isDragging) {
+ initialContext.calendarApi.unselect(ev); // unselect *date* selection
+ initialContext.emitter.trigger('eventDragStart', {
+ el: this.subjectEl,
+ event: new EventImpl(initialContext, eventRange.def, eventRange.instance),
+ jsEvent: ev.origEvent,
+ view: initialContext.viewApi,
+ });
+ }
+ };
+ this.handleHitUpdate = (hit, isFinal) => {
+ if (!this.isDragging) {
+ return;
+ }
+ let relevantEvents = this.relevantEvents;
+ let initialHit = this.hitDragging.initialHit;
+ let initialContext = this.component.context;
+ // states based on new hit
+ let receivingContext = null;
+ let mutation = null;
+ let mutatedRelevantEvents = null;
+ let isInvalid = false;
+ let interaction = {
+ affectedEvents: relevantEvents,
+ mutatedEvents: createEmptyEventStore(),
+ isEvent: true,
+ };
+ if (hit) {
+ receivingContext = hit.context;
+ let receivingOptions = receivingContext.options;
+ if (initialContext === receivingContext ||
+ (receivingOptions.editable && receivingOptions.droppable)) {
+ mutation = computeEventMutation(initialHit, hit, receivingContext.getCurrentData().pluginHooks.eventDragMutationMassagers);
+ if (mutation) {
+ mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, receivingContext.getCurrentData().eventUiBases, mutation, receivingContext);
+ interaction.mutatedEvents = mutatedRelevantEvents;
+ if (!isInteractionValid(interaction, hit.dateProfile, receivingContext)) {
+ isInvalid = true;
+ mutation = null;
+ mutatedRelevantEvents = null;
+ interaction.mutatedEvents = createEmptyEventStore();
+ }
+ }
+ }
+ else {
+ receivingContext = null;
+ }
+ }
+ this.displayDrag(receivingContext, interaction);
+ if (!isInvalid) {
+ enableCursor();
+ }
+ else {
+ disableCursor();
+ }
+ if (!isFinal) {
+ if (initialContext === receivingContext && // TODO: write test for this
+ isHitsEqual(initialHit, hit)) {
+ mutation = null;
+ }
+ this.dragging.setMirrorNeedsRevert(!mutation);
+ // render the mirror if no already-rendered mirror
+ // TODO: wish we could somehow wait for dispatch to guarantee render
+ this.dragging.setMirrorIsVisible(!hit || !getElRoot(this.subjectEl).querySelector('.fc-event-mirror'));
+ // assign states based on new hit
+ this.receivingContext = receivingContext;
+ this.validMutation = mutation;
+ this.mutatedRelevantEvents = mutatedRelevantEvents;
+ }
+ };
+ this.handlePointerUp = () => {
+ if (!this.isDragging) {
+ this.cleanup(); // because handleDragEnd won't fire
+ }
+ };
+ this.handleDragEnd = (ev) => {
+ if (this.isDragging) {
+ let initialContext = this.component.context;
+ let initialView = initialContext.viewApi;
+ let { receivingContext, validMutation } = this;
+ let eventDef = this.eventRange.def;
+ let eventInstance = this.eventRange.instance;
+ let eventApi = new EventImpl(initialContext, eventDef, eventInstance);
+ let relevantEvents = this.relevantEvents;
+ let mutatedRelevantEvents = this.mutatedRelevantEvents;
+ let { finalHit } = this.hitDragging;
+ this.clearDrag(); // must happen after revert animation
+ initialContext.emitter.trigger('eventDragStop', {
+ el: this.subjectEl,
+ event: eventApi,
+ jsEvent: ev.origEvent,
+ view: initialView,
+ });
+ if (validMutation) {
+ // dropped within same calendar
+ if (receivingContext === initialContext) {
+ let updatedEventApi = new EventImpl(initialContext, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null);
+ initialContext.dispatch({
+ type: 'MERGE_EVENTS',
+ eventStore: mutatedRelevantEvents,
+ });
+ let eventChangeArg = {
+ oldEvent: eventApi,
+ event: updatedEventApi,
+ relatedEvents: buildEventApis(mutatedRelevantEvents, initialContext, eventInstance),
+ revert() {
+ initialContext.dispatch({
+ type: 'MERGE_EVENTS',
+ eventStore: relevantEvents, // the pre-change data
+ });
+ },
+ };
+ let transformed = {};
+ for (let transformer of initialContext.getCurrentData().pluginHooks.eventDropTransformers) {
+ Object.assign(transformed, transformer(validMutation, initialContext));
+ }
+ initialContext.emitter.trigger('eventDrop', Object.assign(Object.assign(Object.assign({}, eventChangeArg), transformed), { el: ev.subjectEl, delta: validMutation.datesDelta, jsEvent: ev.origEvent, view: initialView }));
+ initialContext.emitter.trigger('eventChange', eventChangeArg);
+ // dropped in different calendar
+ }
+ else if (receivingContext) {
+ let eventRemoveArg = {
+ event: eventApi,
+ relatedEvents: buildEventApis(relevantEvents, initialContext, eventInstance),
+ revert() {
+ initialContext.dispatch({
+ type: 'MERGE_EVENTS',
+ eventStore: relevantEvents,
+ });
+ },
+ };
+ initialContext.emitter.trigger('eventLeave', Object.assign(Object.assign({}, eventRemoveArg), { draggedEl: ev.subjectEl, view: initialView }));
+ initialContext.dispatch({
+ type: 'REMOVE_EVENTS',
+ eventStore: relevantEvents,
+ });
+ initialContext.emitter.trigger('eventRemove', eventRemoveArg);
+ let addedEventDef = mutatedRelevantEvents.defs[eventDef.defId];
+ let addedEventInstance = mutatedRelevantEvents.instances[eventInstance.instanceId];
+ let addedEventApi = new EventImpl(receivingContext, addedEventDef, addedEventInstance);
+ receivingContext.dispatch({
+ type: 'MERGE_EVENTS',
+ eventStore: mutatedRelevantEvents,
+ });
+ let eventAddArg = {
+ event: addedEventApi,
+ relatedEvents: buildEventApis(mutatedRelevantEvents, receivingContext, addedEventInstance),
+ revert() {
+ receivingContext.dispatch({
+ type: 'REMOVE_EVENTS',
+ eventStore: mutatedRelevantEvents,
+ });
+ },
+ };
+ receivingContext.emitter.trigger('eventAdd', eventAddArg);
+ if (ev.isTouch) {
+ receivingContext.dispatch({
+ type: 'SELECT_EVENT',
+ eventInstanceId: eventInstance.instanceId,
+ });
+ }
+ receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.context.viewApi }));
+ receivingContext.emitter.trigger('eventReceive', Object.assign(Object.assign({}, eventAddArg), { draggedEl: ev.subjectEl, view: finalHit.context.viewApi }));
+ }
+ }
+ else {
+ initialContext.emitter.trigger('_noEventDrop');
+ }
+ }
+ this.cleanup();
+ };
+ let { component } = this;
+ let { options } = component.context;
+ let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
+ dragging.pointer.selector = EventDragging.SELECTOR;
+ dragging.touchScrollAllowed = false;
+ dragging.autoScroller.isEnabled = options.dragScroll;
+ let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsStore);
+ hitDragging.useSubjectCenter = settings.useEventCenter;
+ hitDragging.emitter.on('pointerdown', this.handlePointerDown);
+ hitDragging.emitter.on('dragstart', this.handleDragStart);
+ hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
+ hitDragging.emitter.on('pointerup', this.handlePointerUp);
+ hitDragging.emitter.on('dragend', this.handleDragEnd);
+ }
+ destroy() {
+ this.dragging.destroy();
+ }
+ // render a drag state on the next receivingCalendar
+ displayDrag(nextContext, state) {
+ let initialContext = this.component.context;
+ let prevContext = this.receivingContext;
+ // does the previous calendar need to be cleared?
+ if (prevContext && prevContext !== nextContext) {
+ // does the initial calendar need to be cleared?
+ // if so, don't clear all the way. we still need to to hide the affectedEvents
+ if (prevContext === initialContext) {
+ prevContext.dispatch({
+ type: 'SET_EVENT_DRAG',
+ state: {
+ affectedEvents: state.affectedEvents,
+ mutatedEvents: createEmptyEventStore(),
+ isEvent: true,
+ },
+ });
+ // completely clear the old calendar if it wasn't the initial
+ }
+ else {
+ prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
+ }
+ }
+ if (nextContext) {
+ nextContext.dispatch({ type: 'SET_EVENT_DRAG', state });
+ }
+ }
+ clearDrag() {
+ let initialCalendar = this.component.context;
+ let { receivingContext } = this;
+ if (receivingContext) {
+ receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
+ }
+ // the initial calendar might have an dummy drag state from displayDrag
+ if (initialCalendar !== receivingContext) {
+ initialCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
+ }
+ }
+ cleanup() {
+ this.subjectSeg = null;
+ this.isDragging = false;
+ this.eventRange = null;
+ this.relevantEvents = null;
+ this.receivingContext = null;
+ this.validMutation = null;
+ this.mutatedRelevantEvents = null;
+ }
+ }
+ // TODO: test this in IE11
+ // QUESTION: why do we need it on the resizable???
+ EventDragging.SELECTOR = '.fc-event-draggable, .fc-event-resizable';
+ function computeEventMutation(hit0, hit1, massagers) {
+ let dateSpan0 = hit0.dateSpan;
+ let dateSpan1 = hit1.dateSpan;
+ let date0 = dateSpan0.range.start;
+ let date1 = dateSpan1.range.start;
+ let standardProps = {};
+ if (dateSpan0.allDay !== dateSpan1.allDay) {
+ standardProps.allDay = dateSpan1.allDay;
+ standardProps.hasEnd = hit1.context.options.allDayMaintainDuration;
+ if (dateSpan1.allDay) {
+ // means date1 is already start-of-day,
+ // but date0 needs to be converted
+ date0 = startOfDay(date0);
+ }
+ }
+ let delta = diffDates(date0, date1, hit0.context.dateEnv, hit0.componentId === hit1.componentId ?
+ hit0.largeUnit :
+ null);
+ if (delta.milliseconds) { // has hours/minutes/seconds
+ standardProps.allDay = false;
+ }
+ let mutation = {
+ datesDelta: delta,
+ standardProps,
+ };
+ for (let massager of massagers) {
+ massager(mutation, hit0, hit1);
+ }
+ return mutation;
+ }
+ function getComponentTouchDelay(component) {
+ let { options } = component.context;
+ let delay = options.eventLongPressDelay;
+ if (delay == null) {
+ delay = options.longPressDelay;
+ }
+ return delay;
+ }
+
+ class EventResizing extends Interaction {
+ constructor(settings) {
+ super(settings);
+ // internal state
+ this.draggingSegEl = null;
+ this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg?
+ this.eventRange = null;
+ this.relevantEvents = null;
+ this.validMutation = null;
+ this.mutatedRelevantEvents = null;
+ this.handlePointerDown = (ev) => {
+ let { component } = this;
+ let segEl = this.querySegEl(ev);
+ let seg = getElSeg(segEl);
+ let eventRange = this.eventRange = seg.eventRange;
+ this.dragging.minDistance = component.context.options.eventDragMinDistance;
+ // if touch, need to be working with a selected event
+ this.dragging.setIgnoreMove(!this.component.isValidSegDownEl(ev.origEvent.target) ||
+ (ev.isTouch && this.component.props.eventSelection !== eventRange.instance.instanceId));
+ };
+ this.handleDragStart = (ev) => {
+ let { context } = this.component;
+ let eventRange = this.eventRange;
+ this.relevantEvents = getRelevantEvents(context.getCurrentData().eventStore, this.eventRange.instance.instanceId);
+ let segEl = this.querySegEl(ev);
+ this.draggingSegEl = segEl;
+ this.draggingSeg = getElSeg(segEl);
+ context.calendarApi.unselect();
+ context.emitter.trigger('eventResizeStart', {
+ el: segEl,
+ event: new EventImpl(context, eventRange.def, eventRange.instance),
+ jsEvent: ev.origEvent,
+ view: context.viewApi,
+ });
+ };
+ this.handleHitUpdate = (hit, isFinal, ev) => {
+ let { context } = this.component;
+ let relevantEvents = this.relevantEvents;
+ let initialHit = this.hitDragging.initialHit;
+ let eventInstance = this.eventRange.instance;
+ let mutation = null;
+ let mutatedRelevantEvents = null;
+ let isInvalid = false;
+ let interaction = {
+ affectedEvents: relevantEvents,
+ mutatedEvents: createEmptyEventStore(),
+ isEvent: true,
+ };
+ if (hit) {
+ let disallowed = hit.componentId === initialHit.componentId
+ && this.isHitComboAllowed
+ && !this.isHitComboAllowed(initialHit, hit);
+ if (!disallowed) {
+ mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-event-resizer-start'), eventInstance.range);
+ }
+ }
+ if (mutation) {
+ mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, context.getCurrentData().eventUiBases, mutation, context);
+ interaction.mutatedEvents = mutatedRelevantEvents;
+ if (!isInteractionValid(interaction, hit.dateProfile, context)) {
+ isInvalid = true;
+ mutation = null;
+ mutatedRelevantEvents = null;
+ interaction.mutatedEvents = null;
+ }
+ }
+ if (mutatedRelevantEvents) {
+ context.dispatch({
+ type: 'SET_EVENT_RESIZE',
+ state: interaction,
+ });
+ }
+ else {
+ context.dispatch({ type: 'UNSET_EVENT_RESIZE' });
+ }
+ if (!isInvalid) {
+ enableCursor();
+ }
+ else {
+ disableCursor();
+ }
+ if (!isFinal) {
+ if (mutation && isHitsEqual(initialHit, hit)) {
+ mutation = null;
+ }
+ this.validMutation = mutation;
+ this.mutatedRelevantEvents = mutatedRelevantEvents;
+ }
+ };
+ this.handleDragEnd = (ev) => {
+ let { context } = this.component;
+ let eventDef = this.eventRange.def;
+ let eventInstance = this.eventRange.instance;
+ let eventApi = new EventImpl(context, eventDef, eventInstance);
+ let relevantEvents = this.relevantEvents;
+ let mutatedRelevantEvents = this.mutatedRelevantEvents;
+ context.emitter.trigger('eventResizeStop', {
+ el: this.draggingSegEl,
+ event: eventApi,
+ jsEvent: ev.origEvent,
+ view: context.viewApi,
+ });
+ if (this.validMutation) {
+ let updatedEventApi = new EventImpl(context, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null);
+ context.dispatch({
+ type: 'MERGE_EVENTS',
+ eventStore: mutatedRelevantEvents,
+ });
+ let eventChangeArg = {
+ oldEvent: eventApi,
+ event: updatedEventApi,
+ relatedEvents: buildEventApis(mutatedRelevantEvents, context, eventInstance),
+ revert() {
+ context.dispatch({
+ type: 'MERGE_EVENTS',
+ eventStore: relevantEvents, // the pre-change events
+ });
+ },
+ };
+ 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 }));
+ context.emitter.trigger('eventChange', eventChangeArg);
+ }
+ else {
+ context.emitter.trigger('_noEventResize');
+ }
+ // reset all internal state
+ this.draggingSeg = null;
+ this.relevantEvents = null;
+ this.validMutation = null;
+ // okay to keep eventInstance around. useful to set it in handlePointerDown
+ };
+ let { component } = settings;
+ let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
+ dragging.pointer.selector = '.fc-event-resizer';
+ dragging.touchScrollAllowed = false;
+ dragging.autoScroller.isEnabled = component.context.options.dragScroll;
+ let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
+ hitDragging.emitter.on('pointerdown', this.handlePointerDown);
+ hitDragging.emitter.on('dragstart', this.handleDragStart);
+ hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
+ hitDragging.emitter.on('dragend', this.handleDragEnd);
+ }
+ destroy() {
+ this.dragging.destroy();
+ }
+ querySegEl(ev) {
+ return elementClosest(ev.subjectEl, '.fc-event');
+ }
+ }
+ function computeMutation(hit0, hit1, isFromStart, instanceRange) {
+ let dateEnv = hit0.context.dateEnv;
+ let date0 = hit0.dateSpan.range.start;
+ let date1 = hit1.dateSpan.range.start;
+ let delta = diffDates(date0, date1, dateEnv, hit0.largeUnit);
+ if (isFromStart) {
+ if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) {
+ return { startDelta: delta };
+ }
+ }
+ else if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) {
+ return { endDelta: delta };
+ }
+ return null;
+ }
+
+ class UnselectAuto {
+ constructor(context) {
+ this.context = context;
+ this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system
+ this.matchesCancel = false;
+ this.matchesEvent = false;
+ this.onSelect = (selectInfo) => {
+ if (selectInfo.jsEvent) {
+ this.isRecentPointerDateSelect = true;
+ }
+ };
+ this.onDocumentPointerDown = (pev) => {
+ let unselectCancel = this.context.options.unselectCancel;
+ let downEl = getEventTargetViaRoot(pev.origEvent);
+ this.matchesCancel = !!elementClosest(downEl, unselectCancel);
+ this.matchesEvent = !!elementClosest(downEl, EventDragging.SELECTOR); // interaction started on an event?
+ };
+ this.onDocumentPointerUp = (pev) => {
+ let { context } = this;
+ let { documentPointer } = this;
+ let calendarState = context.getCurrentData();
+ // touch-scrolling should never unfocus any type of selection
+ if (!documentPointer.wasTouchScroll) {
+ if (calendarState.dateSelection && // an existing date selection?
+ !this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp?
+ ) {
+ let unselectAuto = context.options.unselectAuto;
+ if (unselectAuto && (!unselectAuto || !this.matchesCancel)) {
+ context.calendarApi.unselect(pev);
+ }
+ }
+ if (calendarState.eventSelection && // an existing event selected?
+ !this.matchesEvent // interaction DIDN'T start on an event
+ ) {
+ context.dispatch({ type: 'UNSELECT_EVENT' });
+ }
+ }
+ this.isRecentPointerDateSelect = false;
+ };
+ let documentPointer = this.documentPointer = new PointerDragging(document);
+ documentPointer.shouldIgnoreMove = true;
+ documentPointer.shouldWatchScroll = false;
+ documentPointer.emitter.on('pointerdown', this.onDocumentPointerDown);
+ documentPointer.emitter.on('pointerup', this.onDocumentPointerUp);
+ /*
+ TODO: better way to know about whether there was a selection with the pointer
+ */
+ context.emitter.on('select', this.onSelect);
+ }
+ destroy() {
+ this.context.emitter.off('select', this.onSelect);
+ this.documentPointer.destroy();
+ }
+ }
+
+ const OPTION_REFINERS$2 = {
+ fixedMirrorParent: identity,
+ };
+ const LISTENER_REFINERS = {
+ dateClick: identity,
+ eventDragStart: identity,
+ eventDragStop: identity,
+ eventDrop: identity,
+ eventResizeStart: identity,
+ eventResizeStop: identity,
+ eventResize: identity,
+ drop: identity,
+ eventReceive: identity,
+ eventLeave: identity,
+ };
+
+ /*
+ Given an already instantiated draggable object for one-or-more elements,
+ Interprets any dragging as an attempt to drag an events that lives outside
+ of a calendar onto a calendar.
+ */
+ class ExternalElementDragging {
+ constructor(dragging, suppliedDragMeta) {
+ this.receivingContext = null;
+ this.droppableEvent = null; // will exist for all drags, even if create:false
+ this.suppliedDragMeta = null;
+ this.dragMeta = null;
+ this.handleDragStart = (ev) => {
+ this.dragMeta = this.buildDragMeta(ev.subjectEl);
+ };
+ this.handleHitUpdate = (hit, isFinal, ev) => {
+ let { dragging } = this.hitDragging;
+ let receivingContext = null;
+ let droppableEvent = null;
+ let isInvalid = false;
+ let interaction = {
+ affectedEvents: createEmptyEventStore(),
+ mutatedEvents: createEmptyEventStore(),
+ isEvent: this.dragMeta.create,
+ };
+ if (hit) {
+ receivingContext = hit.context;
+ if (this.canDropElOnCalendar(ev.subjectEl, receivingContext)) {
+ droppableEvent = computeEventForDateSpan(hit.dateSpan, this.dragMeta, receivingContext);
+ interaction.mutatedEvents = eventTupleToStore(droppableEvent);
+ isInvalid = !isInteractionValid(interaction, hit.dateProfile, receivingContext);
+ if (isInvalid) {
+ interaction.mutatedEvents = createEmptyEventStore();
+ droppableEvent = null;
+ }
+ }
+ }
+ this.displayDrag(receivingContext, interaction);
+ // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?)
+ // TODO: wish we could somehow wait for dispatch to guarantee render
+ dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-event-mirror'));
+ if (!isInvalid) {
+ enableCursor();
+ }
+ else {
+ disableCursor();
+ }
+ if (!isFinal) {
+ dragging.setMirrorNeedsRevert(!droppableEvent);
+ this.receivingContext = receivingContext;
+ this.droppableEvent = droppableEvent;
+ }
+ };
+ this.handleDragEnd = (pev) => {
+ let { receivingContext, droppableEvent } = this;
+ this.clearDrag();
+ if (receivingContext && droppableEvent) {
+ let finalHit = this.hitDragging.finalHit;
+ let finalView = finalHit.context.viewApi;
+ let dragMeta = this.dragMeta;
+ receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView }));
+ if (dragMeta.create) {
+ let addingEvents = eventTupleToStore(droppableEvent);
+ receivingContext.dispatch({
+ type: 'MERGE_EVENTS',
+ eventStore: addingEvents,
+ });
+ if (pev.isTouch) {
+ receivingContext.dispatch({
+ type: 'SELECT_EVENT',
+ eventInstanceId: droppableEvent.instance.instanceId,
+ });
+ }
+ // signal that an external event landed
+ receivingContext.emitter.trigger('eventReceive', {
+ event: new EventImpl(receivingContext, droppableEvent.def, droppableEvent.instance),
+ relatedEvents: [],
+ revert() {
+ receivingContext.dispatch({
+ type: 'REMOVE_EVENTS',
+ eventStore: addingEvents,
+ });
+ },
+ draggedEl: pev.subjectEl,
+ view: finalView,
+ });
+ }
+ }
+ this.receivingContext = null;
+ this.droppableEvent = null;
+ };
+ let hitDragging = this.hitDragging = new HitDragging(dragging, interactionSettingsStore);
+ hitDragging.requireInitial = false; // will start outside of a component
+ hitDragging.emitter.on('dragstart', this.handleDragStart);
+ hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
+ hitDragging.emitter.on('dragend', this.handleDragEnd);
+ this.suppliedDragMeta = suppliedDragMeta;
+ }
+ buildDragMeta(subjectEl) {
+ if (typeof this.suppliedDragMeta === 'object') {
+ return parseDragMeta(this.suppliedDragMeta);
+ }
+ if (typeof this.suppliedDragMeta === 'function') {
+ return parseDragMeta(this.suppliedDragMeta(subjectEl));
+ }
+ return getDragMetaFromEl(subjectEl);
+ }
+ displayDrag(nextContext, state) {
+ let prevContext = this.receivingContext;
+ if (prevContext && prevContext !== nextContext) {
+ prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
+ }
+ if (nextContext) {
+ nextContext.dispatch({ type: 'SET_EVENT_DRAG', state });
+ }
+ }
+ clearDrag() {
+ if (this.receivingContext) {
+ this.receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
+ }
+ }
+ canDropElOnCalendar(el, receivingContext) {
+ let dropAccept = receivingContext.options.dropAccept;
+ if (typeof dropAccept === 'function') {
+ return dropAccept.call(receivingContext.calendarApi, el);
+ }
+ if (typeof dropAccept === 'string' && dropAccept) {
+ return Boolean(elementMatches(el, dropAccept));
+ }
+ return true;
+ }
+ }
+ // Utils for computing event store from the DragMeta
+ // ----------------------------------------------------------------------------------------------------
+ function computeEventForDateSpan(dateSpan, dragMeta, context) {
+ let defProps = Object.assign({}, dragMeta.leftoverProps);
+ for (let transform of context.pluginHooks.externalDefTransforms) {
+ Object.assign(defProps, transform(dateSpan, dragMeta));
+ }
+ let { refined, extra } = refineEventDef(defProps, context);
+ let def = parseEventDef(refined, extra, dragMeta.sourceId, dateSpan.allDay, context.options.forceEventDuration || Boolean(dragMeta.duration), // hasEnd
+ context);
+ let start = dateSpan.range.start;
+ // only rely on time info if drop zone is all-day,
+ // otherwise, we already know the time
+ if (dateSpan.allDay && dragMeta.startTime) {
+ start = context.dateEnv.add(start, dragMeta.startTime);
+ }
+ let end = dragMeta.duration ?
+ context.dateEnv.add(start, dragMeta.duration) :
+ getDefaultEventEnd(dateSpan.allDay, start, context);
+ let instance = createEventInstance(def.defId, { start, end });
+ return { def, instance };
+ }
+ // Utils for extracting data from element
+ // ----------------------------------------------------------------------------------------------------
+ function getDragMetaFromEl(el) {
+ let str = getEmbeddedElData(el, 'event');
+ let obj = str ?
+ JSON.parse(str) :
+ { create: false }; // if no embedded data, assume no event creation
+ return parseDragMeta(obj);
+ }
+ config.dataAttrPrefix = '';
+ function getEmbeddedElData(el, name) {
+ let prefix = config.dataAttrPrefix;
+ let prefixedName = (prefix ? prefix + '-' : '') + name;
+ return el.getAttribute('data-' + prefixedName) || '';
+ }
+
+ /*
+ Makes an element (that is *external* to any calendar) draggable.
+ Can pass in data that determines how an event will be created when dropped onto a calendar.
+ Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system.
+ */
+ class ExternalDraggable {
+ constructor(el, settings = {}) {
+ this.handlePointerDown = (ev) => {
+ let { dragging } = this;
+ let { minDistance, longPressDelay } = this.settings;
+ dragging.minDistance =
+ minDistance != null ?
+ minDistance :
+ (ev.isTouch ? 0 : BASE_OPTION_DEFAULTS.eventDragMinDistance);
+ dragging.delay =
+ ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv
+ (longPressDelay != null ? longPressDelay : BASE_OPTION_DEFAULTS.longPressDelay) :
+ 0;
+ };
+ this.handleDragStart = (ev) => {
+ if (ev.isTouch &&
+ this.dragging.delay &&
+ ev.subjectEl.classList.contains('fc-event')) {
+ this.dragging.mirror.getMirrorEl().classList.add('fc-event-selected');
+ }
+ };
+ this.settings = settings;
+ let dragging = this.dragging = new FeaturefulElementDragging(el);
+ dragging.touchScrollAllowed = false;
+ if (settings.itemSelector != null) {
+ dragging.pointer.selector = settings.itemSelector;
+ }
+ if (settings.appendTo != null) {
+ dragging.mirror.parentNode = settings.appendTo; // TODO: write tests
+ }
+ dragging.emitter.on('pointerdown', this.handlePointerDown);
+ dragging.emitter.on('dragstart', this.handleDragStart);
+ new ExternalElementDragging(dragging, settings.eventData); // eslint-disable-line no-new
+ }
+ destroy() {
+ this.dragging.destroy();
+ }
+ }
+
+ /*
+ Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements.
+ The third-party system is responsible for drawing the visuals effects of the drag.
+ This class simply monitors for pointer movements and fires events.
+ It also has the ability to hide the moving element (the "mirror") during the drag.
+ */
+ class InferredElementDragging extends ElementDragging {
+ constructor(containerEl) {
+ super(containerEl);
+ this.shouldIgnoreMove = false;
+ this.mirrorSelector = '';
+ this.currentMirrorEl = null;
+ this.handlePointerDown = (ev) => {
+ this.emitter.trigger('pointerdown', ev);
+ if (!this.shouldIgnoreMove) {
+ // fire dragstart right away. does not support delay or min-distance
+ this.emitter.trigger('dragstart', ev);
+ }
+ };
+ this.handlePointerMove = (ev) => {
+ if (!this.shouldIgnoreMove) {
+ this.emitter.trigger('dragmove', ev);
+ }
+ };
+ this.handlePointerUp = (ev) => {
+ this.emitter.trigger('pointerup', ev);
+ if (!this.shouldIgnoreMove) {
+ // fire dragend right away. does not support a revert animation
+ this.emitter.trigger('dragend', ev);
+ }
+ };
+ let pointer = this.pointer = new PointerDragging(containerEl);
+ pointer.emitter.on('pointerdown', this.handlePointerDown);
+ pointer.emitter.on('pointermove', this.handlePointerMove);
+ pointer.emitter.on('pointerup', this.handlePointerUp);
+ }
+ destroy() {
+ this.pointer.destroy();
+ }
+ setIgnoreMove(bool) {
+ this.shouldIgnoreMove = bool;
+ }
+ setMirrorIsVisible(bool) {
+ if (bool) {
+ // restore a previously hidden element.
+ // use the reference in case the selector class has already been removed.
+ if (this.currentMirrorEl) {
+ this.currentMirrorEl.style.visibility = '';
+ this.currentMirrorEl = null;
+ }
+ }
+ else {
+ let mirrorEl = this.mirrorSelector
+ // TODO: somehow query FullCalendars WITHIN shadow-roots
+ ? document.querySelector(this.mirrorSelector)
+ : null;
+ if (mirrorEl) {
+ this.currentMirrorEl = mirrorEl;
+ mirrorEl.style.visibility = 'hidden';
+ }
+ }
+ }
+ }
+
+ /*
+ Bridges third-party drag-n-drop systems with FullCalendar.
+ Must be instantiated and destroyed by caller.
+ */
+ class ThirdPartyDraggable {
+ constructor(containerOrSettings, settings) {
+ let containerEl = document;
+ if (
+ // wish we could just test instanceof EventTarget, but doesn't work in IE11
+ containerOrSettings === document ||
+ containerOrSettings instanceof Element) {
+ containerEl = containerOrSettings;
+ settings = settings || {};
+ }
+ else {
+ settings = (containerOrSettings || {});
+ }
+ let dragging = this.dragging = new InferredElementDragging(containerEl);
+ if (typeof settings.itemSelector === 'string') {
+ dragging.pointer.selector = settings.itemSelector;
+ }
+ else if (containerEl === document) {
+ dragging.pointer.selector = '[data-event]';
+ }
+ if (typeof settings.mirrorSelector === 'string') {
+ dragging.mirrorSelector = settings.mirrorSelector;
+ }
+ new ExternalElementDragging(dragging, settings.eventData); // eslint-disable-line no-new
+ }
+ destroy() {
+ this.dragging.destroy();
+ }
+ }
+
+ var index$3 = createPlugin({
+ name: '@fullcalendar/interaction',
+ componentInteractions: [DateClicking, DateSelecting, EventDragging, EventResizing],
+ calendarInteractions: [UnselectAuto],
+ elementDraggingImpl: FeaturefulElementDragging,
+ optionRefiners: OPTION_REFINERS$2,
+ listenerRefiners: LISTENER_REFINERS,
+ });
+
+ /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.
+ ----------------------------------------------------------------------------------------------------------------------*/
+ // It is a manager for a Table subcomponent, which does most of the heavy lifting.
+ // It is responsible for managing width/height.
+ class TableView extends DateComponent {
+ constructor() {
+ super(...arguments);
+ this.headerElRef = y();
+ }
+ renderSimpleLayout(headerRowContent, bodyContent) {
+ let { props, context } = this;
+ let sections = [];
+ let stickyHeaderDates = getStickyHeaderDates(context.options);
+ if (headerRowContent) {
+ sections.push({
+ type: 'header',
+ key: 'header',
+ isSticky: stickyHeaderDates,
+ chunk: {
+ elRef: this.headerElRef,
+ tableClassName: 'fc-col-header',
+ rowContent: headerRowContent,
+ },
+ });
+ }
+ sections.push({
+ type: 'body',
+ key: 'body',
+ liquid: true,
+ chunk: { content: bodyContent },
+ });
+ return (h(ViewContainer$1, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
+ h(SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [] /* TODO: make optional? */, sections: sections })));
+ }
+ renderHScrollLayout(headerRowContent, bodyContent, colCnt, dayMinWidth) {
+ let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
+ if (!ScrollGrid) {
+ throw new Error('No ScrollGrid implementation');
+ }
+ let { props, context } = this;
+ let stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options);
+ let stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options);
+ let sections = [];
+ if (headerRowContent) {
+ sections.push({
+ type: 'header',
+ key: 'header',
+ isSticky: stickyHeaderDates,
+ chunks: [{
+ key: 'main',
+ elRef: this.headerElRef,
+ tableClassName: 'fc-col-header',
+ rowContent: headerRowContent,
+ }],
+ });
+ }
+ sections.push({
+ type: 'body',
+ key: 'body',
+ liquid: true,
+ chunks: [{
+ key: 'main',
+ content: bodyContent,
+ }],
+ });
+ if (stickyFooterScrollbar) {
+ sections.push({
+ type: 'footer',
+ key: 'footer',
+ isSticky: true,
+ chunks: [{
+ key: 'main',
+ content: renderScrollShim,
+ }],
+ });
+ }
+ return (h(ViewContainer$1, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
+ h(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }], sections: sections })));
+ }
+ }
+
+ function splitSegsByRow(segs, rowCnt) {
+ let byRow = [];
+ for (let i = 0; i < rowCnt; i += 1) {
+ byRow[i] = [];
+ }
+ for (let seg of segs) {
+ byRow[seg.row].push(seg);
+ }
+ return byRow;
+ }
+ function splitSegsByFirstCol(segs, colCnt) {
+ let byCol = [];
+ for (let i = 0; i < colCnt; i += 1) {
+ byCol[i] = [];
+ }
+ for (let seg of segs) {
+ byCol[seg.firstCol].push(seg);
+ }
+ return byCol;
+ }
+ function splitInteractionByRow(ui, rowCnt) {
+ let byRow = [];
+ if (!ui) {
+ for (let i = 0; i < rowCnt; i += 1) {
+ byRow[i] = null;
+ }
+ }
+ else {
+ for (let i = 0; i < rowCnt; i += 1) {
+ byRow[i] = {
+ affectedInstances: ui.affectedInstances,
+ isEvent: ui.isEvent,
+ segs: [],
+ };
+ }
+ for (let seg of ui.segs) {
+ byRow[seg.row].segs.push(seg);
+ }
+ }
+ return byRow;
+ }
+
+ const DEFAULT_TABLE_EVENT_TIME_FORMAT = createFormatter({
+ hour: 'numeric',
+ minute: '2-digit',
+ omitZeroMinute: true,
+ meridiem: 'narrow',
+ });
+ function hasListItemDisplay(seg) {
+ let { display } = seg.eventRange.ui;
+ return display === 'list-item' || (display === 'auto' &&
+ !seg.eventRange.def.allDay &&
+ seg.firstCol === seg.lastCol && // can't be multi-day
+ seg.isStart && // "
+ seg.isEnd // "
+ );
+ }
+
+ class TableBlockEvent extends BaseComponent {
+ render() {
+ let { props } = this;
+ return (h(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 })));
+ }
+ }
+
+ class TableListItemEvent extends BaseComponent {
+ render() {
+ let { props, context } = this;
+ let { options } = context;
+ let { seg } = props;
+ let timeFormat = options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT;
+ let timeText = buildSegTimeText(seg, timeFormat, context, true, props.defaultDisplayEventEnd);
+ return (h(EventContainer, Object.assign({}, props, { elTag: "a", elClasses: ['fc-daygrid-event', 'fc-daygrid-dot-event'], elAttrs: getSegAnchorAttrs(props.seg, context), defaultGenerator: renderInnerContent$2, timeText: timeText, isResizing: false, isDateSelecting: false })));
+ }
+ }
+ function renderInnerContent$2(renderProps) {
+ return (h(p, null,
+ h("div", { className: "fc-daygrid-event-dot", style: { borderColor: renderProps.borderColor || renderProps.backgroundColor } }),
+ renderProps.timeText && (h("div", { className: "fc-event-time" }, renderProps.timeText)),
+ h("div", { className: "fc-event-title" }, renderProps.event.title || h(p, null, "\u00A0"))));
+ }
+
+ class TableCellMoreLink extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.compileSegs = memoize(compileSegs);
+ }
+ render() {
+ let { props } = this;
+ let { allSegs, invisibleSegs } = this.compileSegs(props.singlePlacements);
+ return (h(MoreLinkContainer, { elClasses: ['fc-daygrid-more-link'], dateProfile: props.dateProfile, todayRange: props.todayRange, allDayDate: props.allDayDate, moreCnt: props.moreCnt, allSegs: allSegs, hiddenSegs: invisibleSegs, alignmentElRef: props.alignmentElRef, alignGridTop: props.alignGridTop, extraDateSpan: props.extraDateSpan, popoverContent: () => {
+ let isForcedInvisible = (props.eventDrag ? props.eventDrag.affectedInstances : null) ||
+ (props.eventResize ? props.eventResize.affectedInstances : null) ||
+ {};
+ return (h(p, null, allSegs.map((seg) => {
+ let instanceId = seg.eventRange.instance.instanceId;
+ return (h("div", { className: "fc-daygrid-event-harness", key: instanceId, style: {
+ visibility: isForcedInvisible[instanceId] ? 'hidden' : '',
+ } }, hasListItemDisplay(seg) ? (h(TableListItemEvent, Object.assign({ seg: seg, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, getSegMeta(seg, props.todayRange)))) : (h(TableBlockEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, getSegMeta(seg, props.todayRange))))));
+ })));
+ } }));
+ }
+ }
+ function compileSegs(singlePlacements) {
+ let allSegs = [];
+ let invisibleSegs = [];
+ for (let placement of singlePlacements) {
+ allSegs.push(placement.seg);
+ if (!placement.isVisible) {
+ invisibleSegs.push(placement.seg);
+ }
+ }
+ return { allSegs, invisibleSegs };
+ }
+
+ const DEFAULT_WEEK_NUM_FORMAT$1 = createFormatter({ week: 'narrow' });
+ class TableCell extends DateComponent {
+ constructor() {
+ super(...arguments);
+ this.rootElRef = y();
+ this.state = {
+ dayNumberId: getUniqueDomId(),
+ };
+ this.handleRootEl = (el) => {
+ setRef(this.rootElRef, el);
+ setRef(this.props.elRef, el);
+ };
+ }
+ render() {
+ let { context, props, state, rootElRef } = this;
+ let { options } = context;
+ let { date, dateProfile } = props;
+ return (h(DayCellContainer, { elTag: "td", elRef: this.handleRootEl, elClasses: [
+ 'fc-daygrid-day',
+ ...(props.extraClassNames || []),
+ ], elAttrs: Object.assign(Object.assign(Object.assign({}, props.extraDataAttrs), (props.showDayNumber ? { 'aria-labelledby': state.dayNumberId } : {})), { role: 'gridcell' }), defaultGenerator: renderTopInner, date: date, dateProfile: dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, extraRenderProps: props.extraRenderProps }, (InnerContent, renderProps) => (h("div", { className: "fc-daygrid-day-frame fc-scrollgrid-sync-inner", ref: props.innerElRef },
+ props.showWeekNumber && (h(WeekNumberContainer, { elTag: "a", elClasses: ['fc-daygrid-week-number'], elAttrs: buildNavLinkAttrs(context, date, 'week'), date: date, defaultFormat: DEFAULT_WEEK_NUM_FORMAT$1 })),
+ Boolean(!renderProps.isDisabled &&
+ (props.showDayNumber || hasCustomDayCellContent(options) || props.forceDayTop)) && (h("div", { className: "fc-daygrid-day-top" },
+ h(InnerContent, { elTag: "a", elClasses: ['fc-daygrid-day-number'], elAttrs: Object.assign(Object.assign({}, buildNavLinkAttrs(context, date)), { id: state.dayNumberId }) }))),
+ h("div", { className: "fc-daygrid-day-events", ref: props.fgContentElRef },
+ props.fgContent,
+ h("div", { className: "fc-daygrid-day-bottom", style: { marginTop: props.moreMarginTop } },
+ h(TableCellMoreLink, { allDayDate: date, singlePlacements: props.singlePlacements, moreCnt: props.moreCnt, alignmentElRef: rootElRef, alignGridTop: !props.showDayNumber, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange }))),
+ h("div", { className: "fc-daygrid-day-bg" }, props.bgContent)))));
+ }
+ }
+ function renderTopInner(props) {
+ return props.dayNumberText || h(p, null, "\u00A0");
+ }
+
+ function computeFgSegPlacement(segs, // assumed already sorted
+ dayMaxEvents, dayMaxEventRows, strictOrder, eventInstanceHeights, maxContentHeight, cells) {
+ let hierarchy = new DayGridSegHierarchy();
+ hierarchy.allowReslicing = true;
+ hierarchy.strictOrder = strictOrder;
+ if (dayMaxEvents === true || dayMaxEventRows === true) {
+ hierarchy.maxCoord = maxContentHeight;
+ hierarchy.hiddenConsumes = true;
+ }
+ else if (typeof dayMaxEvents === 'number') {
+ hierarchy.maxStackCnt = dayMaxEvents;
+ }
+ else if (typeof dayMaxEventRows === 'number') {
+ hierarchy.maxStackCnt = dayMaxEventRows;
+ hierarchy.hiddenConsumes = true;
+ }
+ // create segInputs only for segs with known heights
+ let segInputs = [];
+ let unknownHeightSegs = [];
+ for (let i = 0; i < segs.length; i += 1) {
+ let seg = segs[i];
+ let { instanceId } = seg.eventRange.instance;
+ let eventHeight = eventInstanceHeights[instanceId];
+ if (eventHeight != null) {
+ segInputs.push({
+ index: i,
+ thickness: eventHeight,
+ span: {
+ start: seg.firstCol,
+ end: seg.lastCol + 1,
+ },
+ });
+ }
+ else {
+ unknownHeightSegs.push(seg);
+ }
+ }
+ let hiddenEntries = hierarchy.addSegs(segInputs);
+ let segRects = hierarchy.toRects();
+ let { singleColPlacements, multiColPlacements, leftoverMargins } = placeRects(segRects, segs, cells);
+ let moreCnts = [];
+ let moreMarginTops = [];
+ // add segs with unknown heights
+ for (let seg of unknownHeightSegs) {
+ multiColPlacements[seg.firstCol].push({
+ seg,
+ isVisible: false,
+ isAbsolute: true,
+ absoluteTop: 0,
+ marginTop: 0,
+ });
+ for (let col = seg.firstCol; col <= seg.lastCol; col += 1) {
+ singleColPlacements[col].push({
+ seg: resliceSeg(seg, col, col + 1, cells),
+ isVisible: false,
+ isAbsolute: false,
+ absoluteTop: 0,
+ marginTop: 0,
+ });
+ }
+ }
+ // add the hidden entries
+ for (let col = 0; col < cells.length; col += 1) {
+ moreCnts.push(0);
+ }
+ for (let hiddenEntry of hiddenEntries) {
+ let seg = segs[hiddenEntry.index];
+ let hiddenSpan = hiddenEntry.span;
+ multiColPlacements[hiddenSpan.start].push({
+ seg: resliceSeg(seg, hiddenSpan.start, hiddenSpan.end, cells),
+ isVisible: false,
+ isAbsolute: true,
+ absoluteTop: 0,
+ marginTop: 0,
+ });
+ for (let col = hiddenSpan.start; col < hiddenSpan.end; col += 1) {
+ moreCnts[col] += 1;
+ singleColPlacements[col].push({
+ seg: resliceSeg(seg, col, col + 1, cells),
+ isVisible: false,
+ isAbsolute: false,
+ absoluteTop: 0,
+ marginTop: 0,
+ });
+ }
+ }
+ // deal with leftover margins
+ for (let col = 0; col < cells.length; col += 1) {
+ moreMarginTops.push(leftoverMargins[col]);
+ }
+ return { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops };
+ }
+ // rects ordered by top coord, then left
+ function placeRects(allRects, segs, cells) {
+ let rectsByEachCol = groupRectsByEachCol(allRects, cells.length);
+ let singleColPlacements = [];
+ let multiColPlacements = [];
+ let leftoverMargins = [];
+ for (let col = 0; col < cells.length; col += 1) {
+ let rects = rectsByEachCol[col];
+ // compute all static segs in singlePlacements
+ let singlePlacements = [];
+ let currentHeight = 0;
+ let currentMarginTop = 0;
+ for (let rect of rects) {
+ let seg = segs[rect.index];
+ singlePlacements.push({
+ seg: resliceSeg(seg, col, col + 1, cells),
+ isVisible: true,
+ isAbsolute: false,
+ absoluteTop: rect.levelCoord,
+ marginTop: rect.levelCoord - currentHeight,
+ });
+ currentHeight = rect.levelCoord + rect.thickness;
+ }
+ // compute mixed static/absolute segs in multiPlacements
+ let multiPlacements = [];
+ currentHeight = 0;
+ currentMarginTop = 0;
+ for (let rect of rects) {
+ let seg = segs[rect.index];
+ let isAbsolute = rect.span.end - rect.span.start > 1; // multi-column?
+ let isFirstCol = rect.span.start === col;
+ currentMarginTop += rect.levelCoord - currentHeight; // amount of space since bottom of previous seg
+ currentHeight = rect.levelCoord + rect.thickness; // height will now be bottom of current seg
+ if (isAbsolute) {
+ currentMarginTop += rect.thickness;
+ if (isFirstCol) {
+ multiPlacements.push({
+ seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
+ isVisible: true,
+ isAbsolute: true,
+ absoluteTop: rect.levelCoord,
+ marginTop: 0,
+ });
+ }
+ }
+ else if (isFirstCol) {
+ multiPlacements.push({
+ seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
+ isVisible: true,
+ isAbsolute: false,
+ absoluteTop: rect.levelCoord,
+ marginTop: currentMarginTop, // claim the margin
+ });
+ currentMarginTop = 0;
+ }
+ }
+ singleColPlacements.push(singlePlacements);
+ multiColPlacements.push(multiPlacements);
+ leftoverMargins.push(currentMarginTop);
+ }
+ return { singleColPlacements, multiColPlacements, leftoverMargins };
+ }
+ function groupRectsByEachCol(rects, colCnt) {
+ let rectsByEachCol = [];
+ for (let col = 0; col < colCnt; col += 1) {
+ rectsByEachCol.push([]);
+ }
+ for (let rect of rects) {
+ for (let col = rect.span.start; col < rect.span.end; col += 1) {
+ rectsByEachCol[col].push(rect);
+ }
+ }
+ return rectsByEachCol;
+ }
+ function resliceSeg(seg, spanStart, spanEnd, cells) {
+ if (seg.firstCol === spanStart && seg.lastCol === spanEnd - 1) {
+ return seg;
+ }
+ let eventRange = seg.eventRange;
+ let origRange = eventRange.range;
+ let slicedRange = intersectRanges(origRange, {
+ start: cells[spanStart].date,
+ end: addDays(cells[spanEnd - 1].date, 1),
+ });
+ return Object.assign(Object.assign({}, seg), { firstCol: spanStart, lastCol: spanEnd - 1, eventRange: {
+ def: eventRange.def,
+ ui: Object.assign(Object.assign({}, eventRange.ui), { durationEditable: false }),
+ instance: eventRange.instance,
+ range: slicedRange,
+ }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() });
+ }
+ class DayGridSegHierarchy extends SegHierarchy {
+ constructor() {
+ super(...arguments);
+ // config
+ this.hiddenConsumes = false;
+ // allows us to keep hidden entries in the hierarchy so they take up space
+ this.forceHidden = {};
+ }
+ addSegs(segInputs) {
+ const hiddenSegs = super.addSegs(segInputs);
+ const { entriesByLevel } = this;
+ const excludeHidden = (entry) => !this.forceHidden[buildEntryKey(entry)];
+ // remove the forced-hidden segs
+ for (let level = 0; level < entriesByLevel.length; level += 1) {
+ entriesByLevel[level] = entriesByLevel[level].filter(excludeHidden);
+ }
+ return hiddenSegs;
+ }
+ handleInvalidInsertion(insertion, entry, hiddenEntries) {
+ const { entriesByLevel, forceHidden } = this;
+ const { touchingEntry, touchingLevel, touchingLateral } = insertion;
+ if (this.hiddenConsumes && touchingEntry) {
+ const touchingEntryId = buildEntryKey(touchingEntry);
+ // if not already hidden
+ if (!forceHidden[touchingEntryId]) {
+ if (this.allowReslicing) {
+ const placeholderEntry = Object.assign(Object.assign({}, touchingEntry), { span: intersectSpans(touchingEntry.span, entry.span) });
+ const placeholderEntryId = buildEntryKey(placeholderEntry);
+ forceHidden[placeholderEntryId] = true;
+ entriesByLevel[touchingLevel][touchingLateral] = placeholderEntry; // replace touchingEntry with our placeholder
+ this.splitEntry(touchingEntry, entry, hiddenEntries); // split up the touchingEntry, reinsert it
+ }
+ else {
+ forceHidden[touchingEntryId] = true;
+ hiddenEntries.push(touchingEntry);
+ }
+ }
+ }
+ return super.handleInvalidInsertion(insertion, entry, hiddenEntries);
+ }
+ }
+
+ class TableRow extends DateComponent {
+ constructor() {
+ super(...arguments);
+ this.cellElRefs = new RefMap(); // the <td>
+ this.frameElRefs = new RefMap(); // the fc-daygrid-day-frame
+ this.fgElRefs = new RefMap(); // the fc-daygrid-day-events
+ this.segHarnessRefs = new RefMap(); // indexed by "instanceId:firstCol"
+ this.rootElRef = y();
+ this.state = {
+ framePositions: null,
+ maxContentHeight: null,
+ eventInstanceHeights: {},
+ };
+ this.handleResize = (isForced) => {
+ if (isForced) {
+ this.updateSizing(true); // isExternal=true
+ }
+ };
+ }
+ render() {
+ let { props, state, context } = this;
+ let { options } = context;
+ let colCnt = props.cells.length;
+ let businessHoursByCol = splitSegsByFirstCol(props.businessHourSegs, colCnt);
+ let bgEventSegsByCol = splitSegsByFirstCol(props.bgEventSegs, colCnt);
+ let highlightSegsByCol = splitSegsByFirstCol(this.getHighlightSegs(), colCnt);
+ let mirrorSegsByCol = splitSegsByFirstCol(this.getMirrorSegs(), colCnt);
+ let { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops } = computeFgSegPlacement(sortEventSegs(props.fgEventSegs, options.eventOrder), props.dayMaxEvents, props.dayMaxEventRows, options.eventOrderStrict, state.eventInstanceHeights, state.maxContentHeight, props.cells);
+ let isForcedInvisible = // TODO: messy way to compute this
+ (props.eventDrag && props.eventDrag.affectedInstances) ||
+ (props.eventResize && props.eventResize.affectedInstances) ||
+ {};
+ return (h("tr", { ref: this.rootElRef, role: "row" },
+ props.renderIntro && props.renderIntro(),
+ props.cells.map((cell, col) => {
+ let normalFgNodes = this.renderFgSegs(col, props.forPrint ? singleColPlacements[col] : multiColPlacements[col], props.todayRange, isForcedInvisible);
+ let mirrorFgNodes = this.renderFgSegs(col, buildMirrorPlacements(mirrorSegsByCol[col], multiColPlacements), props.todayRange, {}, Boolean(props.eventDrag), Boolean(props.eventResize), false);
+ return (h(TableCell, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), innerElRef: this.frameElRefs.createRef(cell.key) /* FF <td> problem, but okay to use for left/right. TODO: rename prop */, dateProfile: props.dateProfile, date: cell.date, showDayNumber: props.showDayNumbers, showWeekNumber: props.showWeekNumbers && col === 0, forceDayTop: props.showWeekNumbers /* even displaying weeknum for row, not necessarily day */, todayRange: props.todayRange, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, moreCnt: moreCnts[col], moreMarginTop: moreMarginTops[col], singlePlacements: singleColPlacements[col], fgContentElRef: this.fgElRefs.createRef(cell.key), fgContent: ( // Fragment scopes the keys
+ h(p, null,
+ h(p, null, normalFgNodes),
+ h(p, null, mirrorFgNodes))), bgContent: ( // Fragment scopes the keys
+ h(p, null,
+ this.renderFillSegs(highlightSegsByCol[col], 'highlight'),
+ this.renderFillSegs(businessHoursByCol[col], 'non-business'),
+ this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))) }));
+ })));
+ }
+ componentDidMount() {
+ this.updateSizing(true);
+ this.context.addResizeHandler(this.handleResize);
+ }
+ componentDidUpdate(prevProps, prevState) {
+ let currentProps = this.props;
+ this.updateSizing(!isPropsEqual(prevProps, currentProps));
+ }
+ componentWillUnmount() {
+ this.context.removeResizeHandler(this.handleResize);
+ }
+ getHighlightSegs() {
+ let { props } = this;
+ if (props.eventDrag && props.eventDrag.segs.length) { // messy check
+ return props.eventDrag.segs;
+ }
+ if (props.eventResize && props.eventResize.segs.length) { // messy check
+ return props.eventResize.segs;
+ }
+ return props.dateSelectionSegs;
+ }
+ getMirrorSegs() {
+ let { props } = this;
+ if (props.eventResize && props.eventResize.segs.length) { // messy check
+ return props.eventResize.segs;
+ }
+ return [];
+ }
+ renderFgSegs(col, segPlacements, todayRange, isForcedInvisible, isDragging, isResizing, isDateSelecting) {
+ let { context } = this;
+ let { eventSelection } = this.props;
+ let { framePositions } = this.state;
+ let defaultDisplayEventEnd = this.props.cells.length === 1; // colCnt === 1
+ let isMirror = isDragging || isResizing || isDateSelecting;
+ let nodes = [];
+ if (framePositions) {
+ for (let placement of segPlacements) {
+ let { seg } = placement;
+ let { instanceId } = seg.eventRange.instance;
+ let key = instanceId + ':' + col;
+ let isVisible = placement.isVisible && !isForcedInvisible[instanceId];
+ let isAbsolute = placement.isAbsolute;
+ let left = '';
+ let right = '';
+ if (isAbsolute) {
+ if (context.isRtl) {
+ right = 0;
+ left = framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol];
+ }
+ else {
+ left = 0;
+ right = framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol];
+ }
+ }
+ /*
+ known bug: events that are force to be list-item but span multiple days still take up space in later columns
+ todo: in print view, for multi-day events, don't display title within non-start/end segs
+ */
+ nodes.push(h("div", { className: 'fc-daygrid-event-harness' + (isAbsolute ? ' fc-daygrid-event-harness-abs' : ''), key: key, ref: isMirror ? null : this.segHarnessRefs.createRef(key), style: {
+ visibility: isVisible ? '' : 'hidden',
+ marginTop: isAbsolute ? '' : placement.marginTop,
+ top: isAbsolute ? placement.absoluteTop : '',
+ left,
+ right,
+ } }, hasListItemDisplay(seg) ? (h(TableListItemEvent, Object.assign({ seg: seg, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getSegMeta(seg, todayRange)))) : (h(TableBlockEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getSegMeta(seg, todayRange))))));
+ }
+ }
+ return nodes;
+ }
+ renderFillSegs(segs, fillType) {
+ let { isRtl } = this.context;
+ let { todayRange } = this.props;
+ let { framePositions } = this.state;
+ let nodes = [];
+ if (framePositions) {
+ for (let seg of segs) {
+ let leftRightCss = isRtl ? {
+ right: 0,
+ left: framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol],
+ } : {
+ left: 0,
+ right: framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol],
+ };
+ nodes.push(h("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-daygrid-bg-harness", style: leftRightCss }, fillType === 'bg-event' ?
+ h(BgEvent, Object.assign({ seg: seg }, getSegMeta(seg, todayRange))) :
+ renderFill(fillType)));
+ }
+ }
+ return h(p, {}, ...nodes);
+ }
+ updateSizing(isExternalSizingChange) {
+ let { props, state, frameElRefs } = this;
+ if (!props.forPrint &&
+ props.clientWidth !== null // positioning ready?
+ ) {
+ if (isExternalSizingChange) {
+ let frameEls = props.cells.map((cell) => frameElRefs.currentMap[cell.key]);
+ if (frameEls.length) {
+ let originEl = this.rootElRef.current;
+ let newPositionCache = new PositionCache(originEl, frameEls, true, // isHorizontal
+ false);
+ if (!state.framePositions || !state.framePositions.similarTo(newPositionCache)) {
+ this.setState({
+ framePositions: new PositionCache(originEl, frameEls, true, // isHorizontal
+ false),
+ });
+ }
+ }
+ }
+ const oldInstanceHeights = this.state.eventInstanceHeights;
+ const newInstanceHeights = this.queryEventInstanceHeights();
+ const limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
+ this.safeSetState({
+ // HACK to prevent oscillations of events being shown/hidden from max-event-rows
+ // Essentially, once you compute an element's height, never null-out.
+ // TODO: always display all events, as visibility:hidden?
+ eventInstanceHeights: Object.assign(Object.assign({}, oldInstanceHeights), newInstanceHeights),
+ maxContentHeight: limitByContentHeight ? this.computeMaxContentHeight() : null,
+ });
+ }
+ }
+ queryEventInstanceHeights() {
+ let segElMap = this.segHarnessRefs.currentMap;
+ let eventInstanceHeights = {};
+ // get the max height amongst instance segs
+ for (let key in segElMap) {
+ let height = Math.round(segElMap[key].getBoundingClientRect().height);
+ let instanceId = key.split(':')[0]; // deconstruct how renderFgSegs makes the key
+ eventInstanceHeights[instanceId] = Math.max(eventInstanceHeights[instanceId] || 0, height);
+ }
+ return eventInstanceHeights;
+ }
+ computeMaxContentHeight() {
+ let firstKey = this.props.cells[0].key;
+ let cellEl = this.cellElRefs.currentMap[firstKey];
+ let fcContainerEl = this.fgElRefs.currentMap[firstKey];
+ return cellEl.getBoundingClientRect().bottom - fcContainerEl.getBoundingClientRect().top;
+ }
+ getCellEls() {
+ let elMap = this.cellElRefs.currentMap;
+ return this.props.cells.map((cell) => elMap[cell.key]);
+ }
+ }
+ TableRow.addStateEquality({
+ eventInstanceHeights: isPropsEqual,
+ });
+ function buildMirrorPlacements(mirrorSegs, colPlacements) {
+ if (!mirrorSegs.length) {
+ return [];
+ }
+ let topsByInstanceId = buildAbsoluteTopHash(colPlacements); // TODO: cache this at first render?
+ return mirrorSegs.map((seg) => ({
+ seg,
+ isVisible: true,
+ isAbsolute: true,
+ absoluteTop: topsByInstanceId[seg.eventRange.instance.instanceId],
+ marginTop: 0,
+ }));
+ }
+ function buildAbsoluteTopHash(colPlacements) {
+ let topsByInstanceId = {};
+ for (let placements of colPlacements) {
+ for (let placement of placements) {
+ topsByInstanceId[placement.seg.eventRange.instance.instanceId] = placement.absoluteTop;
+ }
+ }
+ return topsByInstanceId;
+ }
+
+ class Table extends DateComponent {
+ constructor() {
+ super(...arguments);
+ this.splitBusinessHourSegs = memoize(splitSegsByRow);
+ this.splitBgEventSegs = memoize(splitSegsByRow);
+ this.splitFgEventSegs = memoize(splitSegsByRow);
+ this.splitDateSelectionSegs = memoize(splitSegsByRow);
+ this.splitEventDrag = memoize(splitInteractionByRow);
+ this.splitEventResize = memoize(splitInteractionByRow);
+ this.rowRefs = new RefMap();
+ this.handleRootEl = (rootEl) => {
+ this.rootEl = rootEl;
+ if (rootEl) {
+ this.context.registerInteractiveComponent(this, {
+ el: rootEl,
+ isHitComboAllowed: this.props.isHitComboAllowed,
+ });
+ }
+ else {
+ this.context.unregisterInteractiveComponent(this);
+ }
+ };
+ }
+ render() {
+ let { props } = this;
+ let { dateProfile, dayMaxEventRows, dayMaxEvents, expandRows } = props;
+ let rowCnt = props.cells.length;
+ let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt);
+ let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);
+ let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt);
+ let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt);
+ let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt);
+ let eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt);
+ let limitViaBalanced = dayMaxEvents === true || dayMaxEventRows === true;
+ // if rows can't expand to fill fixed height, can't do balanced-height event limit
+ // TODO: best place to normalize these options?
+ if (limitViaBalanced && !expandRows) {
+ limitViaBalanced = false;
+ dayMaxEventRows = null;
+ dayMaxEvents = null;
+ }
+ let classNames = [
+ 'fc-daygrid-body',
+ limitViaBalanced ? 'fc-daygrid-body-balanced' : 'fc-daygrid-body-unbalanced',
+ expandRows ? '' : 'fc-daygrid-body-natural', // will height of one row depend on the others?
+ ];
+ return (h("div", { className: classNames.join(' '), ref: this.handleRootEl, style: {
+ // these props are important to give this wrapper correct dimensions for interactions
+ // TODO: if we set it here, can we avoid giving to inner tables?
+ width: props.clientWidth,
+ minWidth: props.tableMinWidth,
+ } },
+ h(NowTimer, { unit: "day" }, (nowDate, todayRange) => (h(p, null,
+ h("table", { role: "presentation", className: "fc-scrollgrid-sync-table", style: {
+ width: props.clientWidth,
+ minWidth: props.tableMinWidth,
+ height: expandRows ? props.clientHeight : '',
+ } },
+ props.colGroupNode,
+ h("tbody", { role: "presentation" }, props.cells.map((cells, row) => (h(TableRow, { ref: this.rowRefs.createRef(row), key: cells.length
+ ? cells[0].date.toISOString() /* best? or put key on cell? or use diff formatter? */
+ : row // in case there are no cells (like when resource view is loading)
+ , showDayNumbers: rowCnt > 1, showWeekNumbers: props.showWeekNumbers, todayRange: todayRange, dateProfile: dateProfile, cells: cells, renderIntro: props.renderRowIntro, businessHourSegs: businessHourSegsByRow[row], eventSelection: props.eventSelection, bgEventSegs: bgEventSegsByRow[row].filter(isSegAllDay) /* hack */, fgEventSegs: fgEventSegsByRow[row], dateSelectionSegs: dateSelectionSegsByRow[row], eventDrag: eventDragByRow[row], eventResize: eventResizeByRow[row], dayMaxEvents: dayMaxEvents, dayMaxEventRows: dayMaxEventRows, clientWidth: props.clientWidth, clientHeight: props.clientHeight, forPrint: props.forPrint }))))))))));
+ }
+ // Hit System
+ // ----------------------------------------------------------------------------------------------------
+ prepareHits() {
+ this.rowPositions = new PositionCache(this.rootEl, this.rowRefs.collect().map((rowObj) => rowObj.getCellEls()[0]), // first cell el in each row. TODO: not optimal
+ false, true);
+ this.colPositions = new PositionCache(this.rootEl, this.rowRefs.currentMap[0].getCellEls(), // cell els in first row
+ true, // horizontal
+ false);
+ }
+ queryHit(positionLeft, positionTop) {
+ let { colPositions, rowPositions } = this;
+ let col = colPositions.leftToIndex(positionLeft);
+ let row = rowPositions.topToIndex(positionTop);
+ if (row != null && col != null) {
+ let cell = this.props.cells[row][col];
+ return {
+ dateProfile: this.props.dateProfile,
+ dateSpan: Object.assign({ range: this.getCellRange(row, col), allDay: true }, cell.extraDateSpan),
+ dayEl: this.getCellEl(row, col),
+ rect: {
+ left: colPositions.lefts[col],
+ right: colPositions.rights[col],
+ top: rowPositions.tops[row],
+ bottom: rowPositions.bottoms[row],
+ },
+ layer: 0,
+ };
+ }
+ return null;
+ }
+ getCellEl(row, col) {
+ return this.rowRefs.currentMap[row].getCellEls()[col]; // TODO: not optimal
+ }
+ getCellRange(row, col) {
+ let start = this.props.cells[row][col].date;
+ let end = addDays(start, 1);
+ return { start, end };
+ }
+ }
+ function isSegAllDay(seg) {
+ return seg.eventRange.def.allDay;
+ }
+
+ class DayTableSlicer extends Slicer {
+ constructor() {
+ super(...arguments);
+ this.forceDayIfListItem = true;
+ }
+ sliceRange(dateRange, dayTableModel) {
+ return dayTableModel.sliceRange(dateRange);
+ }
+ }
+
+ class DayTable extends DateComponent {
+ constructor() {
+ super(...arguments);
+ this.slicer = new DayTableSlicer();
+ this.tableRef = y();
+ }
+ render() {
+ let { props, context } = this;
+ return (h(Table, Object.assign({ ref: this.tableRef }, this.slicer.sliceProps(props, props.dateProfile, props.nextDayThreshold, context, props.dayTableModel), { dateProfile: props.dateProfile, cells: props.dayTableModel.cells, colGroupNode: props.colGroupNode, tableMinWidth: props.tableMinWidth, renderRowIntro: props.renderRowIntro, dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, showWeekNumbers: props.showWeekNumbers, expandRows: props.expandRows, headerAlignElRef: props.headerAlignElRef, clientWidth: props.clientWidth, clientHeight: props.clientHeight, forPrint: props.forPrint })));
+ }
+ }
+
+ class DayTableView extends TableView {
+ constructor() {
+ super(...arguments);
+ this.buildDayTableModel = memoize(buildDayTableModel);
+ this.headerRef = y();
+ this.tableRef = y();
+ }
+ render() {
+ let { options, dateProfileGenerator } = this.context;
+ let { props } = this;
+ let dayTableModel = this.buildDayTableModel(props.dateProfile, dateProfileGenerator);
+ let headerContent = options.dayHeaders && (h(DayHeader, { ref: this.headerRef, dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: dayTableModel.rowCnt === 1 }));
+ let bodyContent = (contentArg) => (h(DayTable, { ref: this.tableRef, dateProfile: props.dateProfile, dayTableModel: dayTableModel, businessHours: props.businessHours, dateSelection: props.dateSelection, eventStore: props.eventStore, eventUiBases: props.eventUiBases, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, nextDayThreshold: options.nextDayThreshold, colGroupNode: contentArg.tableColGroupNode, tableMinWidth: contentArg.tableMinWidth, dayMaxEvents: options.dayMaxEvents, dayMaxEventRows: options.dayMaxEventRows, showWeekNumbers: options.weekNumbers, expandRows: !props.isHeightAuto, headerAlignElRef: this.headerElRef, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, forPrint: props.forPrint }));
+ return options.dayMinWidth
+ ? this.renderHScrollLayout(headerContent, bodyContent, dayTableModel.colCnt, options.dayMinWidth)
+ : this.renderSimpleLayout(headerContent, bodyContent);
+ }
+ }
+ function buildDayTableModel(dateProfile, dateProfileGenerator) {
+ let daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
+ return new DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
+ }
+
+ class TableDateProfileGenerator extends DateProfileGenerator {
+ // Computes the date range that will be rendered.
+ buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
+ let { dateEnv } = this.props;
+ let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay);
+ let start = renderRange.start;
+ let end = renderRange.end;
+ let endOfWeek;
+ // year and month views should be aligned with weeks. this is already done for week
+ if (/^(year|month)$/.test(currentRangeUnit)) {
+ start = dateEnv.startOfWeek(start);
+ // make end-of-week if not already
+ endOfWeek = dateEnv.startOfWeek(end);
+ if (endOfWeek.valueOf() !== end.valueOf()) {
+ end = addWeeks(endOfWeek, 1);
+ }
+ }
+ // ensure 6 weeks
+ if (this.props.monthMode &&
+ this.props.fixedWeekCount) {
+ let rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
+ diffWeeks(start, end));
+ end = addWeeks(end, 6 - rowCnt);
+ }
+ return { start, end };
+ }
+ }
+
+ var css_248z$2 = ":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-day-events{margin-top:1px}.fc .fc-daygrid-body-balanced .fc-daygrid-day-events{left:0;position:absolute;right:0}.fc .fc-daygrid-body-unbalanced .fc-daygrid-day-events{min-height:2em;position:relative}.fc .fc-daygrid-body-natural .fc-daygrid-day-events{margin-bottom:1em}.fc .fc-daygrid-event-harness{position:relative}.fc .fc-daygrid-event-harness-abs{left:0;position:absolute;right:0;top:0}.fc .fc-daygrid-bg-harness{bottom:0;position:absolute;top:0}.fc .fc-daygrid-day-bg .fc-non-business{z-index:1}.fc .fc-daygrid-day-bg .fc-bg-event{z-index:2}.fc .fc-daygrid-day-bg .fc-highlight{z-index:3}.fc .fc-daygrid-event{margin-top:1px;z-index:6}.fc .fc-daygrid-event.fc-event-mirror{z-index:7}.fc .fc-daygrid-day-bottom{font-size:.85em;padding:2px 3px 0}.fc .fc-daygrid-day-bottom:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-more-link{cursor:pointer;position:relative;z-index:4}.fc .fc-daygrid-week-number{background-color:var(--fc-neutral-bg-color);color:var(--fc-neutral-text-color);min-width:1.5em;padding:2px;position:absolute;text-align:center;top:0;z-index:5}.fc .fc-more-popover .fc-popover-body{min-width:220px;padding:10px}.fc-direction-ltr .fc-daygrid-event.fc-event-start,.fc-direction-rtl .fc-daygrid-event.fc-event-end{margin-left:2px}.fc-direction-ltr .fc-daygrid-event.fc-event-end,.fc-direction-rtl .fc-daygrid-event.fc-event-start{margin-right:2px}.fc-direction-ltr .fc-daygrid-week-number{border-radius:0 0 3px 0;left:0}.fc-direction-rtl .fc-daygrid-week-number{border-radius:0 0 0 3px;right:0}.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}";
+ injectStyles(css_248z$2);
+
+ var index$2 = createPlugin({
+ name: '@fullcalendar/daygrid',
+ initialView: 'dayGridMonth',
+ views: {
+ dayGrid: {
+ component: DayTableView,
+ dateProfileGeneratorClass: TableDateProfileGenerator,
+ },
+ dayGridDay: {
+ type: 'dayGrid',
+ duration: { days: 1 },
+ },
+ dayGridWeek: {
+ type: 'dayGrid',
+ duration: { weeks: 1 },
+ },
+ dayGridMonth: {
+ type: 'dayGrid',
+ duration: { months: 1 },
+ monthMode: true,
+ fixedWeekCount: true,
+ },
+ },
+ });
+
+ class AllDaySplitter extends Splitter {
+ getKeyInfo() {
+ return {
+ allDay: {},
+ timed: {},
+ };
+ }
+ getKeysForDateSpan(dateSpan) {
+ if (dateSpan.allDay) {
+ return ['allDay'];
+ }
+ return ['timed'];
+ }
+ getKeysForEventDef(eventDef) {
+ if (!eventDef.allDay) {
+ return ['timed'];
+ }
+ if (hasBgRendering(eventDef)) {
+ return ['timed', 'allDay'];
+ }
+ return ['allDay'];
+ }
+ }
+
+ const DEFAULT_SLAT_LABEL_FORMAT = createFormatter({
+ hour: 'numeric',
+ minute: '2-digit',
+ omitZeroMinute: true,
+ meridiem: 'short',
+ });
+ function TimeColsAxisCell(props) {
+ let classNames = [
+ 'fc-timegrid-slot',
+ 'fc-timegrid-slot-label',
+ props.isLabeled ? 'fc-scrollgrid-shrink' : 'fc-timegrid-slot-minor',
+ ];
+ return (h(ViewContextType.Consumer, null, (context) => {
+ if (!props.isLabeled) {
+ return (h("td", { className: classNames.join(' '), "data-time": props.isoTimeStr }));
+ }
+ let { dateEnv, options, viewApi } = context;
+ let labelFormat = // TODO: fully pre-parse
+ options.slotLabelFormat == null ? DEFAULT_SLAT_LABEL_FORMAT :
+ Array.isArray(options.slotLabelFormat) ? createFormatter(options.slotLabelFormat[0]) :
+ createFormatter(options.slotLabelFormat);
+ let renderProps = {
+ level: 0,
+ time: props.time,
+ date: dateEnv.toDate(props.date),
+ view: viewApi,
+ text: dateEnv.format(props.date, labelFormat),
+ };
+ return (h(ContentContainer, { elTag: "td", elClasses: classNames, elAttrs: {
+ 'data-time': props.isoTimeStr,
+ }, renderProps: renderProps, generatorName: "slotLabelContent", generator: options.slotLabelContent || renderInnerContent$1, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (h("div", { className: "fc-timegrid-slot-label-frame fc-scrollgrid-shrink-frame" },
+ h(InnerContent, { elTag: "div", elClasses: [
+ 'fc-timegrid-slot-label-cushion',
+ 'fc-scrollgrid-shrink-cushion',
+ ] })))));
+ }));
+ }
+ function renderInnerContent$1(props) {
+ return props.text;
+ }
+
+ class TimeBodyAxis extends BaseComponent {
+ render() {
+ return this.props.slatMetas.map((slatMeta) => (h("tr", { key: slatMeta.key },
+ h(TimeColsAxisCell, Object.assign({}, slatMeta)))));
+ }
+ }
+
+ const DEFAULT_WEEK_NUM_FORMAT = createFormatter({ week: 'short' });
+ const AUTO_ALL_DAY_MAX_EVENT_ROWS = 5;
+ class TimeColsView extends DateComponent {
+ constructor() {
+ super(...arguments);
+ this.allDaySplitter = new AllDaySplitter(); // for use by subclasses
+ this.headerElRef = y();
+ this.rootElRef = y();
+ this.scrollerElRef = y();
+ this.state = {
+ slatCoords: null,
+ };
+ this.handleScrollTopRequest = (scrollTop) => {
+ let scrollerEl = this.scrollerElRef.current;
+ if (scrollerEl) { // TODO: not sure how this could ever be null. weirdness with the reducer
+ scrollerEl.scrollTop = scrollTop;
+ }
+ };
+ /* Header Render Methods
+ ------------------------------------------------------------------------------------------------------------------*/
+ this.renderHeadAxis = (rowKey, frameHeight = '') => {
+ let { options } = this.context;
+ let { dateProfile } = this.props;
+ let range = dateProfile.renderRange;
+ let dayCnt = diffDays(range.start, range.end);
+ // only do in day views (to avoid doing in week views that dont need it)
+ let navLinkAttrs = (dayCnt === 1)
+ ? buildNavLinkAttrs(this.context, range.start, 'week')
+ : {};
+ if (options.weekNumbers && rowKey === 'day') {
+ return (h(WeekNumberContainer, { elTag: "th", elClasses: [
+ 'fc-timegrid-axis',
+ 'fc-scrollgrid-shrink',
+ ], elAttrs: {
+ 'aria-hidden': true,
+ }, date: range.start, defaultFormat: DEFAULT_WEEK_NUM_FORMAT }, (InnerContent) => (h("div", { className: [
+ 'fc-timegrid-axis-frame',
+ 'fc-scrollgrid-shrink-frame',
+ 'fc-timegrid-axis-frame-liquid',
+ ].join(' '), style: { height: frameHeight } },
+ h(InnerContent, { elTag: "a", elClasses: [
+ 'fc-timegrid-axis-cushion',
+ 'fc-scrollgrid-shrink-cushion',
+ 'fc-scrollgrid-sync-inner',
+ ], elAttrs: navLinkAttrs })))));
+ }
+ return (h("th", { "aria-hidden": true, className: "fc-timegrid-axis" },
+ h("div", { className: "fc-timegrid-axis-frame", style: { height: frameHeight } })));
+ };
+ /* Table Component Render Methods
+ ------------------------------------------------------------------------------------------------------------------*/
+ // only a one-way height sync. we don't send the axis inner-content height to the DayGrid,
+ // but DayGrid still needs to have classNames on inner elements in order to measure.
+ this.renderTableRowAxis = (rowHeight) => {
+ let { options, viewApi } = this.context;
+ let renderProps = {
+ text: options.allDayText,
+ view: viewApi,
+ };
+ return (
+ // TODO: make reusable hook. used in list view too
+ h(ContentContainer, { elTag: "td", elClasses: [
+ 'fc-timegrid-axis',
+ 'fc-scrollgrid-shrink',
+ ], elAttrs: {
+ 'aria-hidden': true,
+ }, renderProps: renderProps, generatorName: "allDayContent", generator: options.allDayContent || renderAllDayInner$1, classNameGenerator: options.allDayClassNames, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }, (InnerContent) => (h("div", { className: [
+ 'fc-timegrid-axis-frame',
+ 'fc-scrollgrid-shrink-frame',
+ rowHeight == null ? ' fc-timegrid-axis-frame-liquid' : '',
+ ].join(' '), style: { height: rowHeight } },
+ h(InnerContent, { elTag: "span", elClasses: [
+ 'fc-timegrid-axis-cushion',
+ 'fc-scrollgrid-shrink-cushion',
+ 'fc-scrollgrid-sync-inner',
+ ] })))));
+ };
+ this.handleSlatCoords = (slatCoords) => {
+ this.setState({ slatCoords });
+ };
+ }
+ // rendering
+ // ----------------------------------------------------------------------------------------------------
+ renderSimpleLayout(headerRowContent, allDayContent, timeContent) {
+ let { context, props } = this;
+ let sections = [];
+ let stickyHeaderDates = getStickyHeaderDates(context.options);
+ if (headerRowContent) {
+ sections.push({
+ type: 'header',
+ key: 'header',
+ isSticky: stickyHeaderDates,
+ chunk: {
+ elRef: this.headerElRef,
+ tableClassName: 'fc-col-header',
+ rowContent: headerRowContent,
+ },
+ });
+ }
+ if (allDayContent) {
+ sections.push({
+ type: 'body',
+ key: 'all-day',
+ chunk: { content: allDayContent },
+ });
+ sections.push({
+ type: 'body',
+ key: 'all-day-divider',
+ outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?
+ h("tr", { role: "presentation", className: "fc-scrollgrid-section" },
+ h("td", { className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),
+ });
+ }
+ sections.push({
+ type: 'body',
+ key: 'body',
+ liquid: true,
+ expandRows: Boolean(context.options.expandRows),
+ chunk: {
+ scrollerElRef: this.scrollerElRef,
+ content: timeContent,
+ },
+ });
+ return (h(ViewContainer$1, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },
+ h(SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [{ width: 'shrink' }], sections: sections })));
+ }
+ renderHScrollLayout(headerRowContent, allDayContent, timeContent, colCnt, dayMinWidth, slatMetas, slatCoords) {
+ let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
+ if (!ScrollGrid) {
+ throw new Error('No ScrollGrid implementation');
+ }
+ let { context, props } = this;
+ let stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options);
+ let stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options);
+ let sections = [];
+ if (headerRowContent) {
+ sections.push({
+ type: 'header',
+ key: 'header',
+ isSticky: stickyHeaderDates,
+ syncRowHeights: true,
+ chunks: [
+ {
+ key: 'axis',
+ rowContent: (arg) => (h("tr", { role: "presentation" }, this.renderHeadAxis('day', arg.rowSyncHeights[0]))),
+ },
+ {
+ key: 'cols',
+ elRef: this.headerElRef,
+ tableClassName: 'fc-col-header',
+ rowContent: headerRowContent,
+ },
+ ],
+ });
+ }
+ if (allDayContent) {
+ sections.push({
+ type: 'body',
+ key: 'all-day',
+ syncRowHeights: true,
+ chunks: [
+ {
+ key: 'axis',
+ rowContent: (contentArg) => (h("tr", { role: "presentation" }, this.renderTableRowAxis(contentArg.rowSyncHeights[0]))),
+ },
+ {
+ key: 'cols',
+ content: allDayContent,
+ },
+ ],
+ });
+ sections.push({
+ key: 'all-day-divider',
+ type: 'body',
+ outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?
+ h("tr", { role: "presentation", className: "fc-scrollgrid-section" },
+ h("td", { colSpan: 2, className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),
+ });
+ }
+ let isNowIndicator = context.options.nowIndicator;
+ sections.push({
+ type: 'body',
+ key: 'body',
+ liquid: true,
+ expandRows: Boolean(context.options.expandRows),
+ chunks: [
+ {
+ key: 'axis',
+ content: (arg) => (
+ // TODO: make this now-indicator arrow more DRY with TimeColsContent
+ h("div", { className: "fc-timegrid-axis-chunk" },
+ h("table", { "aria-hidden": true, style: { height: arg.expandRows ? arg.clientHeight : '' } },
+ arg.tableColGroupNode,
+ h("tbody", null,
+ h(TimeBodyAxis, { slatMetas: slatMetas }))),
+ h("div", { className: "fc-timegrid-now-indicator-container" },
+ h(NowTimer, { unit: isNowIndicator ? 'minute' : 'day' /* hacky */ }, (nowDate) => {
+ let nowIndicatorTop = isNowIndicator &&
+ slatCoords &&
+ slatCoords.safeComputeTop(nowDate); // might return void
+ if (typeof nowIndicatorTop === 'number') {
+ return (h(NowIndicatorContainer, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: nowDate }));
+ }
+ return null;
+ })))),
+ },
+ {
+ key: 'cols',
+ scrollerElRef: this.scrollerElRef,
+ content: timeContent,
+ },
+ ],
+ });
+ if (stickyFooterScrollbar) {
+ sections.push({
+ key: 'footer',
+ type: 'footer',
+ isSticky: true,
+ chunks: [
+ {
+ key: 'axis',
+ content: renderScrollShim,
+ },
+ {
+ key: 'cols',
+ content: renderScrollShim,
+ },
+ ],
+ });
+ }
+ return (h(ViewContainer$1, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },
+ h(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: false, colGroups: [
+ { width: 'shrink', cols: [{ width: 'shrink' }] },
+ { cols: [{ span: colCnt, minWidth: dayMinWidth }] },
+ ], sections: sections })));
+ }
+ /* Dimensions
+ ------------------------------------------------------------------------------------------------------------------*/
+ getAllDayMaxEventProps() {
+ let { dayMaxEvents, dayMaxEventRows } = this.context.options;
+ if (dayMaxEvents === true || dayMaxEventRows === true) { // is auto?
+ dayMaxEvents = undefined;
+ dayMaxEventRows = AUTO_ALL_DAY_MAX_EVENT_ROWS; // make sure "auto" goes to a real number
+ }
+ return { dayMaxEvents, dayMaxEventRows };
+ }
+ }
+ function renderAllDayInner$1(renderProps) {
+ return renderProps.text;
+ }
+
+ class TimeColsSlatsCoords {
+ constructor(positions, dateProfile, slotDuration) {
+ this.positions = positions;
+ this.dateProfile = dateProfile;
+ this.slotDuration = slotDuration;
+ }
+ safeComputeTop(date) {
+ let { dateProfile } = this;
+ if (rangeContainsMarker(dateProfile.currentRange, date)) {
+ let startOfDayDate = startOfDay(date);
+ let timeMs = date.valueOf() - startOfDayDate.valueOf();
+ if (timeMs >= asRoughMs(dateProfile.slotMinTime) &&
+ timeMs < asRoughMs(dateProfile.slotMaxTime)) {
+ return this.computeTimeTop(createDuration(timeMs));
+ }
+ }
+ return null;
+ }
+ // Computes the top coordinate, relative to the bounds of the grid, of the given date.
+ // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.
+ computeDateTop(when, startOfDayDate) {
+ if (!startOfDayDate) {
+ startOfDayDate = startOfDay(when);
+ }
+ return this.computeTimeTop(createDuration(when.valueOf() - startOfDayDate.valueOf()));
+ }
+ // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).
+ // This is a makeshify way to compute the time-top. Assumes all slatMetas dates are uniform.
+ // Eventually allow computation with arbirary slat dates.
+ computeTimeTop(duration) {
+ let { positions, dateProfile } = this;
+ let len = positions.els.length;
+ // floating-point value of # of slots covered
+ let slatCoverage = (duration.milliseconds - asRoughMs(dateProfile.slotMinTime)) / asRoughMs(this.slotDuration);
+ let slatIndex;
+ let slatRemainder;
+ // compute a floating-point number for how many slats should be progressed through.
+ // from 0 to number of slats (inclusive)
+ // constrained because slotMinTime/slotMaxTime might be customized.
+ slatCoverage = Math.max(0, slatCoverage);
+ slatCoverage = Math.min(len, slatCoverage);
+ // an integer index of the furthest whole slat
+ // from 0 to number slats (*exclusive*, so len-1)
+ slatIndex = Math.floor(slatCoverage);
+ slatIndex = Math.min(slatIndex, len - 1);
+ // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.
+ // could be 1.0 if slatCoverage is covering *all* the slots
+ slatRemainder = slatCoverage - slatIndex;
+ return positions.tops[slatIndex] +
+ positions.getHeight(slatIndex) * slatRemainder;
+ }
+ }
+
+ class TimeColsSlatsBody extends BaseComponent {
+ render() {
+ let { props, context } = this;
+ let { options } = context;
+ let { slatElRefs } = props;
+ return (h("tbody", null, props.slatMetas.map((slatMeta, i) => {
+ let renderProps = {
+ time: slatMeta.time,
+ date: context.dateEnv.toDate(slatMeta.date),
+ view: context.viewApi,
+ };
+ return (h("tr", { key: slatMeta.key, ref: slatElRefs.createRef(slatMeta.key) },
+ props.axis && (h(TimeColsAxisCell, Object.assign({}, slatMeta))),
+ h(ContentContainer, { elTag: "td", elClasses: [
+ 'fc-timegrid-slot',
+ 'fc-timegrid-slot-lane',
+ !slatMeta.isLabeled && 'fc-timegrid-slot-minor',
+ ], elAttrs: {
+ 'data-time': slatMeta.isoTimeStr,
+ }, renderProps: renderProps, generatorName: "slotLaneContent", generator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount })));
+ })));
+ }
+ }
+
+ /*
+ for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL.
+ */
+ class TimeColsSlats extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.rootElRef = y();
+ this.slatElRefs = new RefMap();
+ }
+ render() {
+ let { props, context } = this;
+ return (h("div", { ref: this.rootElRef, className: "fc-timegrid-slots" },
+ h("table", { "aria-hidden": true, className: context.theme.getClass('table'), style: {
+ minWidth: props.tableMinWidth,
+ width: props.clientWidth,
+ height: props.minHeight,
+ } },
+ props.tableColGroupNode /* relies on there only being a single <col> for the axis */,
+ h(TimeColsSlatsBody, { slatElRefs: this.slatElRefs, axis: props.axis, slatMetas: props.slatMetas }))));
+ }
+ componentDidMount() {
+ this.updateSizing();
+ }
+ componentDidUpdate() {
+ this.updateSizing();
+ }
+ componentWillUnmount() {
+ if (this.props.onCoords) {
+ this.props.onCoords(null);
+ }
+ }
+ updateSizing() {
+ let { context, props } = this;
+ if (props.onCoords &&
+ props.clientWidth !== null // means sizing has stabilized
+ ) {
+ let rootEl = this.rootElRef.current;
+ if (rootEl.offsetHeight) { // not hidden by css
+ props.onCoords(new TimeColsSlatsCoords(new PositionCache(this.rootElRef.current, collectSlatEls(this.slatElRefs.currentMap, props.slatMetas), false, true), this.props.dateProfile, context.options.slotDuration));
+ }
+ }
+ }
+ }
+ function collectSlatEls(elMap, slatMetas) {
+ return slatMetas.map((slatMeta) => elMap[slatMeta.key]);
+ }
+
+ function splitSegsByCol(segs, colCnt) {
+ let segsByCol = [];
+ let i;
+ for (i = 0; i < colCnt; i += 1) {
+ segsByCol.push([]);
+ }
+ if (segs) {
+ for (i = 0; i < segs.length; i += 1) {
+ segsByCol[segs[i].col].push(segs[i]);
+ }
+ }
+ return segsByCol;
+ }
+ function splitInteractionByCol(ui, colCnt) {
+ let byRow = [];
+ if (!ui) {
+ for (let i = 0; i < colCnt; i += 1) {
+ byRow[i] = null;
+ }
+ }
+ else {
+ for (let i = 0; i < colCnt; i += 1) {
+ byRow[i] = {
+ affectedInstances: ui.affectedInstances,
+ isEvent: ui.isEvent,
+ segs: [],
+ };
+ }
+ for (let seg of ui.segs) {
+ byRow[seg.col].segs.push(seg);
+ }
+ }
+ return byRow;
+ }
+
+ class TimeColMoreLink extends BaseComponent {
+ render() {
+ let { props } = this;
+ return (h(MoreLinkContainer, { elClasses: ['fc-timegrid-more-link'], elStyle: {
+ top: props.top,
+ bottom: props.bottom,
+ }, allDayDate: null, moreCnt: props.hiddenSegs.length, allSegs: props.hiddenSegs, hiddenSegs: props.hiddenSegs, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, todayRange: props.todayRange, popoverContent: () => renderPlainFgSegs(props.hiddenSegs, props), defaultGenerator: renderMoreLinkInner }, (InnerContent) => (h(InnerContent, { elTag: "div", elClasses: ['fc-timegrid-more-link-inner', 'fc-sticky'] }))));
+ }
+ }
+ function renderMoreLinkInner(props) {
+ return props.shortText;
+ }
+
+ // segInputs assumed sorted
+ function buildPositioning(segInputs, strictOrder, maxStackCnt) {
+ let hierarchy = new SegHierarchy();
+ if (strictOrder != null) {
+ hierarchy.strictOrder = strictOrder;
+ }
+ if (maxStackCnt != null) {
+ hierarchy.maxStackCnt = maxStackCnt;
+ }
+ let hiddenEntries = hierarchy.addSegs(segInputs);
+ let hiddenGroups = groupIntersectingEntries(hiddenEntries);
+ let web = buildWeb(hierarchy);
+ web = stretchWeb(web, 1); // all levelCoords/thickness will have 0.0-1.0
+ let segRects = webToRects(web);
+ return { segRects, hiddenGroups };
+ }
+ function buildWeb(hierarchy) {
+ const { entriesByLevel } = hierarchy;
+ const buildNode = cacheable((level, lateral) => level + ':' + lateral, (level, lateral) => {
+ let siblingRange = findNextLevelSegs(hierarchy, level, lateral);
+ let nextLevelRes = buildNodes(siblingRange, buildNode);
+ let entry = entriesByLevel[level][lateral];
+ return [
+ Object.assign(Object.assign({}, entry), { nextLevelNodes: nextLevelRes[0] }),
+ entry.thickness + nextLevelRes[1], // the pressure builds
+ ];
+ });
+ return buildNodes(entriesByLevel.length
+ ? { level: 0, lateralStart: 0, lateralEnd: entriesByLevel[0].length }
+ : null, buildNode)[0];
+ }
+ function buildNodes(siblingRange, buildNode) {
+ if (!siblingRange) {
+ return [[], 0];
+ }
+ let { level, lateralStart, lateralEnd } = siblingRange;
+ let lateral = lateralStart;
+ let pairs = [];
+ while (lateral < lateralEnd) {
+ pairs.push(buildNode(level, lateral));
+ lateral += 1;
+ }
+ pairs.sort(cmpDescPressures);
+ return [
+ pairs.map(extractNode),
+ pairs[0][1], // first item's pressure
+ ];
+ }
+ function cmpDescPressures(a, b) {
+ return b[1] - a[1];
+ }
+ function extractNode(a) {
+ return a[0];
+ }
+ function findNextLevelSegs(hierarchy, subjectLevel, subjectLateral) {
+ let { levelCoords, entriesByLevel } = hierarchy;
+ let subjectEntry = entriesByLevel[subjectLevel][subjectLateral];
+ let afterSubject = levelCoords[subjectLevel] + subjectEntry.thickness;
+ let levelCnt = levelCoords.length;
+ let level = subjectLevel;
+ // skip past levels that are too high up
+ for (; level < levelCnt && levelCoords[level] < afterSubject; level += 1)
+ ; // do nothing
+ for (; level < levelCnt; level += 1) {
+ let entries = entriesByLevel[level];
+ let entry;
+ let searchIndex = binarySearch(entries, subjectEntry.span.start, getEntrySpanEnd);
+ let lateralStart = searchIndex[0] + searchIndex[1]; // if exact match (which doesn't collide), go to next one
+ let lateralEnd = lateralStart;
+ while ( // loop through entries that horizontally intersect
+ (entry = entries[lateralEnd]) && // but not past the whole seg list
+ entry.span.start < subjectEntry.span.end) {
+ lateralEnd += 1;
+ }
+ if (lateralStart < lateralEnd) {
+ return { level, lateralStart, lateralEnd };
+ }
+ }
+ return null;
+ }
+ function stretchWeb(topLevelNodes, totalThickness) {
+ const stretchNode = cacheable((node, startCoord, prevThickness) => buildEntryKey(node), (node, startCoord, prevThickness) => {
+ let { nextLevelNodes, thickness } = node;
+ let allThickness = thickness + prevThickness;
+ let thicknessFraction = thickness / allThickness;
+ let endCoord;
+ let newChildren = [];
+ if (!nextLevelNodes.length) {
+ endCoord = totalThickness;
+ }
+ else {
+ for (let childNode of nextLevelNodes) {
+ if (endCoord === undefined) {
+ let res = stretchNode(childNode, startCoord, allThickness);
+ endCoord = res[0];
+ newChildren.push(res[1]);
+ }
+ else {
+ let res = stretchNode(childNode, endCoord, 0);
+ newChildren.push(res[1]);
+ }
+ }
+ }
+ let newThickness = (endCoord - startCoord) * thicknessFraction;
+ return [endCoord - newThickness, Object.assign(Object.assign({}, node), { thickness: newThickness, nextLevelNodes: newChildren })];
+ });
+ return topLevelNodes.map((node) => stretchNode(node, 0, 0)[1]);
+ }
+ // not sorted in any particular order
+ function webToRects(topLevelNodes) {
+ let rects = [];
+ const processNode = cacheable((node, levelCoord, stackDepth) => buildEntryKey(node), (node, levelCoord, stackDepth) => {
+ let rect = Object.assign(Object.assign({}, node), { levelCoord,
+ stackDepth, stackForward: 0 });
+ rects.push(rect);
+ return (rect.stackForward = processNodes(node.nextLevelNodes, levelCoord + node.thickness, stackDepth + 1) + 1);
+ });
+ function processNodes(nodes, levelCoord, stackDepth) {
+ let stackForward = 0;
+ for (let node of nodes) {
+ stackForward = Math.max(processNode(node, levelCoord, stackDepth), stackForward);
+ }
+ return stackForward;
+ }
+ processNodes(topLevelNodes, 0, 0);
+ return rects; // TODO: sort rects by levelCoord to be consistent with toRects?
+ }
+ // TODO: move to general util
+ function cacheable(keyFunc, workFunc) {
+ const cache = {};
+ return (...args) => {
+ let key = keyFunc(...args);
+ return (key in cache)
+ ? cache[key]
+ : (cache[key] = workFunc(...args));
+ };
+ }
+
+ function computeSegVCoords(segs, colDate, slatCoords = null, eventMinHeight = 0) {
+ let vcoords = [];
+ if (slatCoords) {
+ for (let i = 0; i < segs.length; i += 1) {
+ let seg = segs[i];
+ let spanStart = slatCoords.computeDateTop(seg.start, colDate);
+ let spanEnd = Math.max(spanStart + (eventMinHeight || 0), // :(
+ slatCoords.computeDateTop(seg.end, colDate));
+ vcoords.push({
+ start: Math.round(spanStart),
+ end: Math.round(spanEnd), //
+ });
+ }
+ }
+ return vcoords;
+ }
+ function computeFgSegPlacements(segs, segVCoords, // might not have for every seg
+ eventOrderStrict, eventMaxStack) {
+ let segInputs = [];
+ let dumbSegs = []; // segs without coords
+ for (let i = 0; i < segs.length; i += 1) {
+ let vcoords = segVCoords[i];
+ if (vcoords) {
+ segInputs.push({
+ index: i,
+ thickness: 1,
+ span: vcoords,
+ });
+ }
+ else {
+ dumbSegs.push(segs[i]);
+ }
+ }
+ let { segRects, hiddenGroups } = buildPositioning(segInputs, eventOrderStrict, eventMaxStack);
+ let segPlacements = [];
+ for (let segRect of segRects) {
+ segPlacements.push({
+ seg: segs[segRect.index],
+ rect: segRect,
+ });
+ }
+ for (let dumbSeg of dumbSegs) {
+ segPlacements.push({ seg: dumbSeg, rect: null });
+ }
+ return { segPlacements, hiddenGroups };
+ }
+
+ const DEFAULT_TIME_FORMAT$1 = createFormatter({
+ hour: 'numeric',
+ minute: '2-digit',
+ meridiem: false,
+ });
+ class TimeColEvent extends BaseComponent {
+ render() {
+ return (h(StandardEvent, Object.assign({}, this.props, { elClasses: [
+ 'fc-timegrid-event',
+ 'fc-v-event',
+ this.props.isShort && 'fc-timegrid-event-short',
+ ], defaultTimeFormat: DEFAULT_TIME_FORMAT$1 })));
+ }
+ }
+
+ class TimeCol extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.sortEventSegs = memoize(sortEventSegs);
+ }
+ // TODO: memoize event-placement?
+ render() {
+ let { props, context } = this;
+ let { options } = context;
+ let isSelectMirror = options.selectMirror;
+ let mirrorSegs = // yuck
+ (props.eventDrag && props.eventDrag.segs) ||
+ (props.eventResize && props.eventResize.segs) ||
+ (isSelectMirror && props.dateSelectionSegs) ||
+ [];
+ let interactionAffectedInstances = // TODO: messy way to compute this
+ (props.eventDrag && props.eventDrag.affectedInstances) ||
+ (props.eventResize && props.eventResize.affectedInstances) ||
+ {};
+ let sortedFgSegs = this.sortEventSegs(props.fgEventSegs, options.eventOrder);
+ return (h(DayCellContainer, { elTag: "td", elRef: props.elRef, elClasses: [
+ 'fc-timegrid-col',
+ ...(props.extraClassNames || []),
+ ], elAttrs: Object.assign({ role: 'gridcell' }, props.extraDataAttrs), date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, extraRenderProps: props.extraRenderProps }, (InnerContent) => (h("div", { className: "fc-timegrid-col-frame" },
+ h("div", { className: "fc-timegrid-col-bg" },
+ this.renderFillSegs(props.businessHourSegs, 'non-business'),
+ this.renderFillSegs(props.bgEventSegs, 'bg-event'),
+ this.renderFillSegs(props.dateSelectionSegs, 'highlight')),
+ h("div", { className: "fc-timegrid-col-events" }, this.renderFgSegs(sortedFgSegs, interactionAffectedInstances, false, false, false)),
+ h("div", { className: "fc-timegrid-col-events" }, this.renderFgSegs(mirrorSegs, {}, Boolean(props.eventDrag), Boolean(props.eventResize), Boolean(isSelectMirror))),
+ h("div", { className: "fc-timegrid-now-indicator-container" }, this.renderNowIndicator(props.nowIndicatorSegs)),
+ hasCustomDayCellContent(options) && (h(InnerContent, { elTag: "div", elClasses: ['fc-timegrid-col-misc'] }))))));
+ }
+ renderFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting) {
+ let { props } = this;
+ if (props.forPrint) {
+ return renderPlainFgSegs(sortedFgSegs, props);
+ }
+ return this.renderPositionedFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting);
+ }
+ renderPositionedFgSegs(segs, // if not mirror, needs to be sorted
+ segIsInvisible, isDragging, isResizing, isDateSelecting) {
+ let { eventMaxStack, eventShortHeight, eventOrderStrict, eventMinHeight } = this.context.options;
+ let { date, slatCoords, eventSelection, todayRange, nowDate } = this.props;
+ let isMirror = isDragging || isResizing || isDateSelecting;
+ let segVCoords = computeSegVCoords(segs, date, slatCoords, eventMinHeight);
+ let { segPlacements, hiddenGroups } = computeFgSegPlacements(segs, segVCoords, eventOrderStrict, eventMaxStack);
+ return (h(p, null,
+ this.renderHiddenGroups(hiddenGroups, segs),
+ segPlacements.map((segPlacement) => {
+ let { seg, rect } = segPlacement;
+ let instanceId = seg.eventRange.instance.instanceId;
+ let isVisible = isMirror || Boolean(!segIsInvisible[instanceId] && rect);
+ let vStyle = computeSegVStyle(rect && rect.span);
+ let hStyle = (!isMirror && rect) ? this.computeSegHStyle(rect) : { left: 0, right: 0 };
+ let isInset = Boolean(rect) && rect.stackForward > 0;
+ let isShort = Boolean(rect) && (rect.span.end - rect.span.start) < eventShortHeight; // look at other places for this problem
+ return (h("div", { className: 'fc-timegrid-event-harness' +
+ (isInset ? ' fc-timegrid-event-harness-inset' : ''), key: instanceId, style: Object.assign(Object.assign({ visibility: isVisible ? '' : 'hidden' }, vStyle), hStyle) },
+ h(TimeColEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, isShort: isShort }, getSegMeta(seg, todayRange, nowDate)))));
+ })));
+ }
+ // will already have eventMinHeight applied because segInputs already had it
+ renderHiddenGroups(hiddenGroups, segs) {
+ let { extraDateSpan, dateProfile, todayRange, nowDate, eventSelection, eventDrag, eventResize } = this.props;
+ return (h(p, null, hiddenGroups.map((hiddenGroup) => {
+ let positionCss = computeSegVStyle(hiddenGroup.span);
+ let hiddenSegs = compileSegsFromEntries(hiddenGroup.entries, segs);
+ return (h(TimeColMoreLink, { key: buildIsoString(computeEarliestSegStart(hiddenSegs)), hiddenSegs: hiddenSegs, top: positionCss.top, bottom: positionCss.bottom, extraDateSpan: extraDateSpan, dateProfile: dateProfile, todayRange: todayRange, nowDate: nowDate, eventSelection: eventSelection, eventDrag: eventDrag, eventResize: eventResize }));
+ })));
+ }
+ renderFillSegs(segs, fillType) {
+ let { props, context } = this;
+ let segVCoords = computeSegVCoords(segs, props.date, props.slatCoords, context.options.eventMinHeight); // don't assume all populated
+ let children = segVCoords.map((vcoords, i) => {
+ let seg = segs[i];
+ return (h("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-timegrid-bg-harness", style: computeSegVStyle(vcoords) }, fillType === 'bg-event' ?
+ h(BgEvent, Object.assign({ seg: seg }, getSegMeta(seg, props.todayRange, props.nowDate))) :
+ renderFill(fillType)));
+ });
+ return h(p, null, children);
+ }
+ renderNowIndicator(segs) {
+ let { slatCoords, date } = this.props;
+ if (!slatCoords) {
+ return null;
+ }
+ return segs.map((seg, i) => (h(NowIndicatorContainer
+ // key doesn't matter. will only ever be one
+ , {
+ // key doesn't matter. will only ever be one
+ key: i, elClasses: ['fc-timegrid-now-indicator-line'], elStyle: {
+ top: slatCoords.computeDateTop(seg.start, date),
+ }, isAxis: false, date: date })));
+ }
+ computeSegHStyle(segHCoords) {
+ let { isRtl, options } = this.context;
+ let shouldOverlap = options.slotEventOverlap;
+ let nearCoord = segHCoords.levelCoord; // the left side if LTR. the right side if RTL. floating-point
+ let farCoord = segHCoords.levelCoord + segHCoords.thickness; // the right side if LTR. the left side if RTL. floating-point
+ let left; // amount of space from left edge, a fraction of the total width
+ let right; // amount of space from right edge, a fraction of the total width
+ if (shouldOverlap) {
+ // double the width, but don't go beyond the maximum forward coordinate (1.0)
+ farCoord = Math.min(1, nearCoord + (farCoord - nearCoord) * 2);
+ }
+ if (isRtl) {
+ left = 1 - farCoord;
+ right = nearCoord;
+ }
+ else {
+ left = nearCoord;
+ right = 1 - farCoord;
+ }
+ let props = {
+ zIndex: segHCoords.stackDepth + 1,
+ left: left * 100 + '%',
+ right: right * 100 + '%',
+ };
+ if (shouldOverlap && !segHCoords.stackForward) {
+ // add padding to the edge so that forward stacked events don't cover the resizer's icon
+ props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
+ }
+ return props;
+ }
+ }
+ function renderPlainFgSegs(sortedFgSegs, { todayRange, nowDate, eventSelection, eventDrag, eventResize }) {
+ let hiddenInstances = (eventDrag ? eventDrag.affectedInstances : null) ||
+ (eventResize ? eventResize.affectedInstances : null) ||
+ {};
+ return (h(p, null, sortedFgSegs.map((seg) => {
+ let instanceId = seg.eventRange.instance.instanceId;
+ return (h("div", { key: instanceId, style: { visibility: hiddenInstances[instanceId] ? 'hidden' : '' } },
+ h(TimeColEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === eventSelection, isShort: false }, getSegMeta(seg, todayRange, nowDate)))));
+ })));
+ }
+ function computeSegVStyle(segVCoords) {
+ if (!segVCoords) {
+ return { top: '', bottom: '' };
+ }
+ return {
+ top: segVCoords.start,
+ bottom: -segVCoords.end,
+ };
+ }
+ function compileSegsFromEntries(segEntries, allSegs) {
+ return segEntries.map((segEntry) => allSegs[segEntry.index]);
+ }
+
+ class TimeColsContent extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.splitFgEventSegs = memoize(splitSegsByCol);
+ this.splitBgEventSegs = memoize(splitSegsByCol);
+ this.splitBusinessHourSegs = memoize(splitSegsByCol);
+ this.splitNowIndicatorSegs = memoize(splitSegsByCol);
+ this.splitDateSelectionSegs = memoize(splitSegsByCol);
+ this.splitEventDrag = memoize(splitInteractionByCol);
+ this.splitEventResize = memoize(splitInteractionByCol);
+ this.rootElRef = y();
+ this.cellElRefs = new RefMap();
+ }
+ render() {
+ let { props, context } = this;
+ let nowIndicatorTop = context.options.nowIndicator &&
+ props.slatCoords &&
+ props.slatCoords.safeComputeTop(props.nowDate); // might return void
+ let colCnt = props.cells.length;
+ let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, colCnt);
+ let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, colCnt);
+ let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, colCnt);
+ let nowIndicatorSegsByRow = this.splitNowIndicatorSegs(props.nowIndicatorSegs, colCnt);
+ let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, colCnt);
+ let eventDragByRow = this.splitEventDrag(props.eventDrag, colCnt);
+ let eventResizeByRow = this.splitEventResize(props.eventResize, colCnt);
+ return (h("div", { className: "fc-timegrid-cols", ref: this.rootElRef },
+ h("table", { role: "presentation", style: {
+ minWidth: props.tableMinWidth,
+ width: props.clientWidth,
+ } },
+ props.tableColGroupNode,
+ h("tbody", { role: "presentation" },
+ h("tr", { role: "row" },
+ props.axis && (h("td", { "aria-hidden": true, className: "fc-timegrid-col fc-timegrid-axis" },
+ h("div", { className: "fc-timegrid-col-frame" },
+ h("div", { className: "fc-timegrid-now-indicator-container" }, typeof nowIndicatorTop === 'number' && (h(NowIndicatorContainer, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: props.nowDate })))))),
+ props.cells.map((cell, i) => (h(TimeCol, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), dateProfile: props.dateProfile, date: cell.date, nowDate: props.nowDate, todayRange: props.todayRange, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, fgEventSegs: fgEventSegsByRow[i], bgEventSegs: bgEventSegsByRow[i], businessHourSegs: businessHourSegsByRow[i], nowIndicatorSegs: nowIndicatorSegsByRow[i], dateSelectionSegs: dateSelectionSegsByRow[i], eventDrag: eventDragByRow[i], eventResize: eventResizeByRow[i], slatCoords: props.slatCoords, eventSelection: props.eventSelection, forPrint: props.forPrint }))))))));
+ }
+ componentDidMount() {
+ this.updateCoords();
+ }
+ componentDidUpdate() {
+ this.updateCoords();
+ }
+ updateCoords() {
+ let { props } = this;
+ if (props.onColCoords &&
+ props.clientWidth !== null // means sizing has stabilized
+ ) {
+ props.onColCoords(new PositionCache(this.rootElRef.current, collectCellEls(this.cellElRefs.currentMap, props.cells), true, // horizontal
+ false));
+ }
+ }
+ }
+ function collectCellEls(elMap, cells) {
+ return cells.map((cell) => elMap[cell.key]);
+ }
+
+ /* A component that renders one or more columns of vertical time slots
+ ----------------------------------------------------------------------------------------------------------------------*/
+ class TimeCols extends DateComponent {
+ constructor() {
+ super(...arguments);
+ this.processSlotOptions = memoize(processSlotOptions);
+ this.state = {
+ slatCoords: null,
+ };
+ this.handleRootEl = (el) => {
+ if (el) {
+ this.context.registerInteractiveComponent(this, {
+ el,
+ isHitComboAllowed: this.props.isHitComboAllowed,
+ });
+ }
+ else {
+ this.context.unregisterInteractiveComponent(this);
+ }
+ };
+ this.handleScrollRequest = (request) => {
+ let { onScrollTopRequest } = this.props;
+ let { slatCoords } = this.state;
+ if (onScrollTopRequest && slatCoords) {
+ if (request.time) {
+ let top = slatCoords.computeTimeTop(request.time);
+ top = Math.ceil(top); // zoom can give weird floating-point values. rather scroll a little bit further
+ if (top) {
+ top += 1; // to overcome top border that slots beyond the first have. looks better
+ }
+ onScrollTopRequest(top);
+ }
+ return true;
+ }
+ return false;
+ };
+ this.handleColCoords = (colCoords) => {
+ this.colCoords = colCoords;
+ };
+ this.handleSlatCoords = (slatCoords) => {
+ this.setState({ slatCoords });
+ if (this.props.onSlatCoords) {
+ this.props.onSlatCoords(slatCoords);
+ }
+ };
+ }
+ render() {
+ let { props, state } = this;
+ return (h("div", { className: "fc-timegrid-body", ref: this.handleRootEl, style: {
+ // these props are important to give this wrapper correct dimensions for interactions
+ // TODO: if we set it here, can we avoid giving to inner tables?
+ width: props.clientWidth,
+ minWidth: props.tableMinWidth,
+ } },
+ h(TimeColsSlats, { axis: props.axis, dateProfile: props.dateProfile, slatMetas: props.slatMetas, clientWidth: props.clientWidth, minHeight: props.expandRows ? props.clientHeight : '', tableMinWidth: props.tableMinWidth, tableColGroupNode: props.axis ? props.tableColGroupNode : null /* axis depends on the colgroup's shrinking */, onCoords: this.handleSlatCoords }),
+ h(TimeColsContent, { cells: props.cells, axis: props.axis, dateProfile: props.dateProfile, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange, nowDate: props.nowDate, nowIndicatorSegs: props.nowIndicatorSegs, clientWidth: props.clientWidth, tableMinWidth: props.tableMinWidth, tableColGroupNode: props.tableColGroupNode, slatCoords: state.slatCoords, onColCoords: this.handleColCoords, forPrint: props.forPrint })));
+ }
+ componentDidMount() {
+ this.scrollResponder = this.context.createScrollResponder(this.handleScrollRequest);
+ }
+ componentDidUpdate(prevProps) {
+ this.scrollResponder.update(prevProps.dateProfile !== this.props.dateProfile);
+ }
+ componentWillUnmount() {
+ this.scrollResponder.detach();
+ }
+ queryHit(positionLeft, positionTop) {
+ let { dateEnv, options } = this.context;
+ let { colCoords } = this;
+ let { dateProfile } = this.props;
+ let { slatCoords } = this.state;
+ let { snapDuration, snapsPerSlot } = this.processSlotOptions(this.props.slotDuration, options.snapDuration);
+ let colIndex = colCoords.leftToIndex(positionLeft);
+ let slatIndex = slatCoords.positions.topToIndex(positionTop);
+ if (colIndex != null && slatIndex != null) {
+ let cell = this.props.cells[colIndex];
+ let slatTop = slatCoords.positions.tops[slatIndex];
+ let slatHeight = slatCoords.positions.getHeight(slatIndex);
+ let partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1
+ let localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat
+ let snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
+ let dayDate = this.props.cells[colIndex].date;
+ let time = addDurations(dateProfile.slotMinTime, multiplyDuration(snapDuration, snapIndex));
+ let start = dateEnv.add(dayDate, time);
+ let end = dateEnv.add(start, snapDuration);
+ return {
+ dateProfile,
+ dateSpan: Object.assign({ range: { start, end }, allDay: false }, cell.extraDateSpan),
+ dayEl: colCoords.els[colIndex],
+ rect: {
+ left: colCoords.lefts[colIndex],
+ right: colCoords.rights[colIndex],
+ top: slatTop,
+ bottom: slatTop + slatHeight,
+ },
+ layer: 0,
+ };
+ }
+ return null;
+ }
+ }
+ function processSlotOptions(slotDuration, snapDurationOverride) {
+ let snapDuration = snapDurationOverride || slotDuration;
+ let snapsPerSlot = wholeDivideDurations(slotDuration, snapDuration);
+ if (snapsPerSlot === null) {
+ snapDuration = slotDuration;
+ snapsPerSlot = 1;
+ // TODO: say warning?
+ }
+ return { snapDuration, snapsPerSlot };
+ }
+
+ class DayTimeColsSlicer extends Slicer {
+ sliceRange(range, dayRanges) {
+ let segs = [];
+ for (let col = 0; col < dayRanges.length; col += 1) {
+ let segRange = intersectRanges(range, dayRanges[col]);
+ if (segRange) {
+ segs.push({
+ start: segRange.start,
+ end: segRange.end,
+ isStart: segRange.start.valueOf() === range.start.valueOf(),
+ isEnd: segRange.end.valueOf() === range.end.valueOf(),
+ col,
+ });
+ }
+ }
+ return segs;
+ }
+ }
+
+ class DayTimeCols extends DateComponent {
+ constructor() {
+ super(...arguments);
+ this.buildDayRanges = memoize(buildDayRanges);
+ this.slicer = new DayTimeColsSlicer();
+ this.timeColsRef = y();
+ }
+ render() {
+ let { props, context } = this;
+ let { dateProfile, dayTableModel } = props;
+ let isNowIndicator = context.options.nowIndicator;
+ let dayRanges = this.buildDayRanges(dayTableModel, dateProfile, context.dateEnv);
+ // give it the first row of cells
+ // TODO: would move this further down hierarchy, but sliceNowDate needs it
+ return (h(NowTimer, { unit: isNowIndicator ? 'minute' : 'day' }, (nowDate, todayRange) => (h(TimeCols, Object.assign({ ref: this.timeColsRef }, this.slicer.sliceProps(props, dateProfile, null, context, dayRanges), { forPrint: props.forPrint, axis: props.axis, dateProfile: dateProfile, slatMetas: props.slatMetas, slotDuration: props.slotDuration, cells: dayTableModel.cells[0], tableColGroupNode: props.tableColGroupNode, tableMinWidth: props.tableMinWidth, clientWidth: props.clientWidth, clientHeight: props.clientHeight, expandRows: props.expandRows, nowDate: nowDate, nowIndicatorSegs: isNowIndicator && this.slicer.sliceNowDate(nowDate, context, dayRanges), todayRange: todayRange, onScrollTopRequest: props.onScrollTopRequest, onSlatCoords: props.onSlatCoords })))));
+ }
+ }
+ function buildDayRanges(dayTableModel, dateProfile, dateEnv) {
+ let ranges = [];
+ for (let date of dayTableModel.headerDates) {
+ ranges.push({
+ start: dateEnv.add(date, dateProfile.slotMinTime),
+ end: dateEnv.add(date, dateProfile.slotMaxTime),
+ });
+ }
+ return ranges;
+ }
+
+ // potential nice values for the slot-duration and interval-duration
+ // from largest to smallest
+ const STOCK_SUB_DURATIONS = [
+ { hours: 1 },
+ { minutes: 30 },
+ { minutes: 15 },
+ { seconds: 30 },
+ { seconds: 15 },
+ ];
+ function buildSlatMetas(slotMinTime, slotMaxTime, explicitLabelInterval, slotDuration, dateEnv) {
+ let dayStart = new Date(0);
+ let slatTime = slotMinTime;
+ let slatIterator = createDuration(0);
+ let labelInterval = explicitLabelInterval || computeLabelInterval(slotDuration);
+ let metas = [];
+ while (asRoughMs(slatTime) < asRoughMs(slotMaxTime)) {
+ let date = dateEnv.add(dayStart, slatTime);
+ let isLabeled = wholeDivideDurations(slatIterator, labelInterval) !== null;
+ metas.push({
+ date,
+ time: slatTime,
+ key: date.toISOString(),
+ isoTimeStr: formatIsoTimeString(date),
+ isLabeled,
+ });
+ slatTime = addDurations(slatTime, slotDuration);
+ slatIterator = addDurations(slatIterator, slotDuration);
+ }
+ return metas;
+ }
+ // Computes an automatic value for slotLabelInterval
+ function computeLabelInterval(slotDuration) {
+ let i;
+ let labelInterval;
+ let slotsPerLabel;
+ // find the smallest stock label interval that results in more than one slots-per-label
+ for (i = STOCK_SUB_DURATIONS.length - 1; i >= 0; i -= 1) {
+ labelInterval = createDuration(STOCK_SUB_DURATIONS[i]);
+ slotsPerLabel = wholeDivideDurations(labelInterval, slotDuration);
+ if (slotsPerLabel !== null && slotsPerLabel > 1) {
+ return labelInterval;
+ }
+ }
+ return slotDuration; // fall back
+ }
+
+ class DayTimeColsView extends TimeColsView {
+ constructor() {
+ super(...arguments);
+ this.buildTimeColsModel = memoize(buildTimeColsModel);
+ this.buildSlatMetas = memoize(buildSlatMetas);
+ }
+ render() {
+ let { options, dateEnv, dateProfileGenerator } = this.context;
+ let { props } = this;
+ let { dateProfile } = props;
+ let dayTableModel = this.buildTimeColsModel(dateProfile, dateProfileGenerator);
+ let splitProps = this.allDaySplitter.splitProps(props);
+ let slatMetas = this.buildSlatMetas(dateProfile.slotMinTime, dateProfile.slotMaxTime, options.slotLabelInterval, options.slotDuration, dateEnv);
+ let { dayMinWidth } = options;
+ let hasAttachedAxis = !dayMinWidth;
+ let hasDetachedAxis = dayMinWidth;
+ let headerContent = options.dayHeaders && (h(DayHeader, { dates: dayTableModel.headerDates, dateProfile: dateProfile, datesRepDistinctDays: true, renderIntro: hasAttachedAxis ? this.renderHeadAxis : null }));
+ let allDayContent = (options.allDaySlot !== false) && ((contentArg) => (h(DayTable, Object.assign({}, splitProps.allDay, { dateProfile: dateProfile, dayTableModel: dayTableModel, nextDayThreshold: options.nextDayThreshold, tableMinWidth: contentArg.tableMinWidth, colGroupNode: contentArg.tableColGroupNode, renderRowIntro: hasAttachedAxis ? this.renderTableRowAxis : null, showWeekNumbers: false, expandRows: false, headerAlignElRef: this.headerElRef, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, forPrint: props.forPrint }, this.getAllDayMaxEventProps()))));
+ let timeGridContent = (contentArg) => (h(DayTimeCols, Object.assign({}, splitProps.timed, { dayTableModel: dayTableModel, dateProfile: dateProfile, axis: hasAttachedAxis, slotDuration: options.slotDuration, slatMetas: slatMetas, forPrint: props.forPrint, tableColGroupNode: contentArg.tableColGroupNode, tableMinWidth: contentArg.tableMinWidth, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, onSlatCoords: this.handleSlatCoords, expandRows: contentArg.expandRows, onScrollTopRequest: this.handleScrollTopRequest })));
+ return hasDetachedAxis
+ ? this.renderHScrollLayout(headerContent, allDayContent, timeGridContent, dayTableModel.colCnt, dayMinWidth, slatMetas, this.state.slatCoords)
+ : this.renderSimpleLayout(headerContent, allDayContent, timeGridContent);
+ }
+ }
+ function buildTimeColsModel(dateProfile, dateProfileGenerator) {
+ let daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
+ return new DayTableModel(daySeries, false);
+ }
+
+ const OPTION_REFINERS$1 = {
+ allDaySlot: Boolean,
+ };
+
+ var css_248z$1 = ".fc-v-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-v-event .fc-event-main{color:var(--fc-event-text-color);height:100%}.fc-v-event .fc-event-main-frame{display:flex;flex-direction:column;height:100%}.fc-v-event .fc-event-time{flex-grow:0;flex-shrink:0;max-height:100%;overflow:hidden}.fc-v-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-height:0}.fc-v-event .fc-event-title{bottom:0;max-height:100%;overflow:hidden;top:0}.fc-v-event:not(.fc-event-start){border-top-left-radius:0;border-top-right-radius:0;border-top-width:0}.fc-v-event:not(.fc-event-end){border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-width:0}.fc-v-event.fc-event-selected:before{left:-10px;right:-10px}.fc-v-event .fc-event-resizer-start{cursor:n-resize}.fc-v-event .fc-event-resizer-end{cursor:s-resize}.fc-v-event:not(.fc-event-selected) .fc-event-resizer{height:var(--fc-event-resizer-thickness);left:0;right:0}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-start{top:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer{left:50%;margin-left:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-start{top:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc .fc-timegrid .fc-daygrid-body{z-index:2}.fc .fc-timegrid-divider{padding:0 0 2px}.fc .fc-timegrid-body{min-height:100%;position:relative;z-index:1}.fc .fc-timegrid-axis-chunk{position:relative}.fc .fc-timegrid-axis-chunk>table,.fc .fc-timegrid-slots{position:relative;z-index:1}.fc .fc-timegrid-slot{border-bottom:0;height:1.5em}.fc .fc-timegrid-slot:empty:before{content:\"\\00a0\"}.fc .fc-timegrid-slot-minor{border-top-style:dotted}.fc .fc-timegrid-slot-label-cushion{display:inline-block;white-space:nowrap}.fc .fc-timegrid-slot-label{vertical-align:middle}.fc .fc-timegrid-axis-cushion,.fc .fc-timegrid-slot-label-cushion{padding:0 4px}.fc .fc-timegrid-axis-frame-liquid{height:100%}.fc .fc-timegrid-axis-frame{align-items:center;display:flex;justify-content:flex-end;overflow:hidden}.fc .fc-timegrid-axis-cushion{flex-shrink:0;max-width:60px}.fc-direction-ltr .fc-timegrid-slot-label-frame{text-align:right}.fc-direction-rtl .fc-timegrid-slot-label-frame{text-align:left}.fc-liquid-hack .fc-timegrid-axis-frame-liquid{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-timegrid-col-frame{min-height:100%;position:relative}.fc-media-screen.fc-liquid-hack .fc-timegrid-col-frame{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols{bottom:0;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols>table{height:100%}.fc-media-screen .fc-timegrid-col-bg,.fc-media-screen .fc-timegrid-col-events,.fc-media-screen .fc-timegrid-now-indicator-container{left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col-bg{z-index:2}.fc .fc-timegrid-col-bg .fc-non-business{z-index:1}.fc .fc-timegrid-col-bg .fc-bg-event{z-index:2}.fc .fc-timegrid-col-bg .fc-highlight{z-index:3}.fc .fc-timegrid-bg-harness{left:0;position:absolute;right:0}.fc .fc-timegrid-col-events{z-index:3}.fc .fc-timegrid-now-indicator-container{bottom:0;overflow:hidden}.fc-direction-ltr .fc-timegrid-col-events{margin:0 2.5% 0 2px}.fc-direction-rtl .fc-timegrid-col-events{margin:0 2px 0 2.5%}.fc-timegrid-event-harness{position:absolute}.fc-timegrid-event-harness>.fc-timegrid-event{bottom:0;left:0;position:absolute;right:0;top:0}.fc-timegrid-event-harness-inset .fc-timegrid-event,.fc-timegrid-event.fc-event-mirror,.fc-timegrid-more-link{box-shadow:0 0 0 1px var(--fc-page-bg-color)}.fc-timegrid-event,.fc-timegrid-more-link{border-radius:3px;font-size:var(--fc-small-font-size)}.fc-timegrid-event{margin-bottom:1px}.fc-timegrid-event .fc-event-main{padding:1px 1px 0}.fc-timegrid-event .fc-event-time{font-size:var(--fc-small-font-size);margin-bottom:1px;white-space:nowrap}.fc-timegrid-event-short .fc-event-main-frame{flex-direction:row;overflow:hidden}.fc-timegrid-event-short .fc-event-time:after{content:\"\\00a0-\\00a0\"}.fc-timegrid-event-short .fc-event-title{font-size:var(--fc-small-font-size)}.fc-timegrid-more-link{background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;margin-bottom:1px;position:absolute;z-index:9999}.fc-timegrid-more-link-inner{padding:3px 2px;top:0}.fc-direction-ltr .fc-timegrid-more-link{right:0}.fc-direction-rtl .fc-timegrid-more-link{left:0}.fc .fc-timegrid-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;border-width:1px 0 0;left:0;position:absolute;right:0;z-index:4}.fc .fc-timegrid-now-indicator-arrow{border-color:var(--fc-now-indicator-color);border-style:solid;margin-top:-5px;position:absolute;z-index:4}.fc-direction-ltr .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 0 5px 6px;left:0}.fc-direction-rtl .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 6px 5px 0;right:0}";
+ injectStyles(css_248z$1);
+
+ var index$1 = createPlugin({
+ name: '@fullcalendar/timegrid',
+ initialView: 'timeGridWeek',
+ optionRefiners: OPTION_REFINERS$1,
+ views: {
+ timeGrid: {
+ component: DayTimeColsView,
+ usesMinMaxTime: true,
+ allDaySlot: true,
+ slotDuration: '00:30:00',
+ slotEventOverlap: true, // a bad name. confused with overlap/constraint system
+ },
+ timeGridDay: {
+ type: 'timeGrid',
+ duration: { days: 1 },
+ },
+ timeGridWeek: {
+ type: 'timeGrid',
+ duration: { weeks: 1 },
+ },
+ },
+ });
+
+ class ListViewHeaderRow extends BaseComponent {
+ constructor() {
+ super(...arguments);
+ this.state = {
+ textId: getUniqueDomId(),
+ };
+ }
+ render() {
+ let { theme, dateEnv, options, viewApi } = this.context;
+ let { cellId, dayDate, todayRange } = this.props;
+ let { textId } = this.state;
+ let dayMeta = getDateMeta(dayDate, todayRange);
+ // will ever be falsy?
+ let text = options.listDayFormat ? dateEnv.format(dayDate, options.listDayFormat) : '';
+ // will ever be falsy? also, BAD NAME "alt"
+ let sideText = options.listDaySideFormat ? dateEnv.format(dayDate, options.listDaySideFormat) : '';
+ let renderProps = Object.assign({ date: dateEnv.toDate(dayDate), view: viewApi, textId,
+ text,
+ sideText, navLinkAttrs: buildNavLinkAttrs(this.context, dayDate), sideNavLinkAttrs: buildNavLinkAttrs(this.context, dayDate, 'day', false) }, dayMeta);
+ // TODO: make a reusable HOC for dayHeader (used in daygrid/timegrid too)
+ return (h(ContentContainer, { elTag: "tr", elClasses: [
+ 'fc-list-day',
+ ...getDayClassNames(dayMeta, theme),
+ ], elAttrs: {
+ 'data-date': formatDayString(dayDate),
+ }, renderProps: renderProps, generatorName: "dayHeaderContent", generator: options.dayHeaderContent || renderInnerContent, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => ( // TODO: force-hide top border based on :first-child
+ h("th", { scope: "colgroup", colSpan: 3, id: cellId, "aria-labelledby": textId },
+ h(InnerContent, { elTag: "div", elClasses: [
+ 'fc-list-day-cushion',
+ theme.getClass('tableCellShaded'),
+ ] })))));
+ }
+ }
+ function renderInnerContent(props) {
+ return (h(p, null,
+ props.text && (h("a", Object.assign({ id: props.textId, className: "fc-list-day-text" }, props.navLinkAttrs), props.text)),
+ props.sideText && ( /* not keyboard tabbable */h("a", Object.assign({ "aria-hidden": true, className: "fc-list-day-side-text" }, props.sideNavLinkAttrs), props.sideText))));
+ }
+
+ const DEFAULT_TIME_FORMAT = createFormatter({
+ hour: 'numeric',
+ minute: '2-digit',
+ meridiem: 'short',
+ });
+ class ListViewEventRow extends BaseComponent {
+ render() {
+ let { props, context } = this;
+ let { options } = context;
+ let { seg, timeHeaderId, eventHeaderId, dateHeaderId } = props;
+ let timeFormat = options.eventTimeFormat || DEFAULT_TIME_FORMAT;
+ return (h(EventContainer, Object.assign({}, props, { elTag: "tr", elClasses: [
+ 'fc-list-event',
+ seg.eventRange.def.url && 'fc-event-forced-url',
+ ], defaultGenerator: () => renderEventInnerContent(seg, context) /* weird */, seg: seg, timeText: "", disableDragging: true, disableResizing: true }), (InnerContent, eventContentArg) => (h(p, null,
+ buildTimeContent(seg, timeFormat, context, timeHeaderId, dateHeaderId),
+ h("td", { "aria-hidden": true, className: "fc-list-event-graphic" },
+ h("span", { className: "fc-list-event-dot", style: {
+ borderColor: eventContentArg.borderColor || eventContentArg.backgroundColor,
+ } })),
+ h(InnerContent, { elTag: "td", elClasses: ['fc-list-event-title'], elAttrs: { headers: `${eventHeaderId} ${dateHeaderId}` } })))));
+ }
+ }
+ function renderEventInnerContent(seg, context) {
+ let interactiveAttrs = getSegAnchorAttrs(seg, context);
+ return (h("a", Object.assign({}, interactiveAttrs), seg.eventRange.def.title));
+ }
+ function buildTimeContent(seg, timeFormat, context, timeHeaderId, dateHeaderId) {
+ let { options } = context;
+ if (options.displayEventTime !== false) {
+ let eventDef = seg.eventRange.def;
+ let eventInstance = seg.eventRange.instance;
+ let doAllDay = false;
+ let timeText;
+ if (eventDef.allDay) {
+ doAllDay = true;
+ }
+ else if (isMultiDayRange(seg.eventRange.range)) { // TODO: use (!isStart || !isEnd) instead?
+ if (seg.isStart) {
+ timeText = buildSegTimeText(seg, timeFormat, context, null, null, eventInstance.range.start, seg.end);
+ }
+ else if (seg.isEnd) {
+ timeText = buildSegTimeText(seg, timeFormat, context, null, null, seg.start, eventInstance.range.end);
+ }
+ else {
+ doAllDay = true;
+ }
+ }
+ else {
+ timeText = buildSegTimeText(seg, timeFormat, context);
+ }
+ if (doAllDay) {
+ let renderProps = {
+ text: context.options.allDayText,
+ view: context.viewApi,
+ };
+ return (h(ContentContainer, { elTag: "td", elClasses: ['fc-list-event-time'], elAttrs: {
+ headers: `${timeHeaderId} ${dateHeaderId}`,
+ }, renderProps: renderProps, generatorName: "allDayContent", generator: options.allDayContent || renderAllDayInner, classNameGenerator: options.allDayClassNames, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }));
+ }
+ return (h("td", { className: "fc-list-event-time" }, timeText));
+ }
+ return null;
+ }
+ function renderAllDayInner(renderProps) {
+ return renderProps.text;
+ }
+
+ /*
+ Responsible for the scroller, and forwarding event-related actions into the "grid".
+ */
+ class ListView extends DateComponent {
+ constructor() {
+ super(...arguments);
+ this.computeDateVars = memoize(computeDateVars);
+ this.eventStoreToSegs = memoize(this._eventStoreToSegs);
+ this.state = {
+ timeHeaderId: getUniqueDomId(),
+ eventHeaderId: getUniqueDomId(),
+ dateHeaderIdRoot: getUniqueDomId(),
+ };
+ this.setRootEl = (rootEl) => {
+ if (rootEl) {
+ this.context.registerInteractiveComponent(this, {
+ el: rootEl,
+ });
+ }
+ else {
+ this.context.unregisterInteractiveComponent(this);
+ }
+ };
+ }
+ render() {
+ let { props, context } = this;
+ let { dayDates, dayRanges } = this.computeDateVars(props.dateProfile);
+ let eventSegs = this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges);
+ return (h(ViewContainer$1, { elRef: this.setRootEl, elClasses: [
+ 'fc-list',
+ context.theme.getClass('table'),
+ context.options.stickyHeaderDates !== false ?
+ 'fc-list-sticky' :
+ '',
+ ], viewSpec: context.viewSpec },
+ h(Scroller, { liquid: !props.isHeightAuto, overflowX: props.isHeightAuto ? 'visible' : 'hidden', overflowY: props.isHeightAuto ? 'visible' : 'auto' }, eventSegs.length > 0 ?
+ this.renderSegList(eventSegs, dayDates) :
+ this.renderEmptyMessage())));
+ }
+ renderEmptyMessage() {
+ let { options, viewApi } = this.context;
+ let renderProps = {
+ text: options.noEventsText,
+ view: viewApi,
+ };
+ return (h(ContentContainer, { elTag: "div", elClasses: ['fc-list-empty'], renderProps: renderProps, generatorName: "noEventsContent", generator: options.noEventsContent || renderNoEventsInner, classNameGenerator: options.noEventsClassNames, didMount: options.noEventsDidMount, willUnmount: options.noEventsWillUnmount }, (InnerContent) => (h(InnerContent, { elTag: "div", elClasses: ['fc-list-empty-cushion'] }))));
+ }
+ renderSegList(allSegs, dayDates) {
+ let { theme, options } = this.context;
+ let { timeHeaderId, eventHeaderId, dateHeaderIdRoot } = this.state;
+ let segsByDay = groupSegsByDay(allSegs); // sparse array
+ return (h(NowTimer, { unit: "day" }, (nowDate, todayRange) => {
+ let innerNodes = [];
+ for (let dayIndex = 0; dayIndex < segsByDay.length; dayIndex += 1) {
+ let daySegs = segsByDay[dayIndex];
+ if (daySegs) { // sparse array, so might be undefined
+ let dayStr = formatDayString(dayDates[dayIndex]);
+ let dateHeaderId = dateHeaderIdRoot + '-' + dayStr;
+ // append a day header
+ innerNodes.push(h(ListViewHeaderRow, { key: dayStr, cellId: dateHeaderId, dayDate: dayDates[dayIndex], todayRange: todayRange }));
+ daySegs = sortEventSegs(daySegs, options.eventOrder);
+ for (let seg of daySegs) {
+ innerNodes.push(h(ListViewEventRow, Object.assign({ key: dayStr + ':' + seg.eventRange.instance.instanceId /* are multiple segs for an instanceId */, seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false, timeHeaderId: timeHeaderId, eventHeaderId: eventHeaderId, dateHeaderId: dateHeaderId }, getSegMeta(seg, todayRange, nowDate))));
+ }
+ }
+ }
+ return (h("table", { className: 'fc-list-table ' + theme.getClass('table') },
+ h("thead", null,
+ h("tr", null,
+ h("th", { scope: "col", id: timeHeaderId }, options.timeHint),
+ h("th", { scope: "col", "aria-hidden": true }),
+ h("th", { scope: "col", id: eventHeaderId }, options.eventHint))),
+ h("tbody", null, innerNodes)));
+ }));
+ }
+ _eventStoreToSegs(eventStore, eventUiBases, dayRanges) {
+ return this.eventRangesToSegs(sliceEventStore(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.context.options.nextDayThreshold).fg, dayRanges);
+ }
+ eventRangesToSegs(eventRanges, dayRanges) {
+ let segs = [];
+ for (let eventRange of eventRanges) {
+ segs.push(...this.eventRangeToSegs(eventRange, dayRanges));
+ }
+ return segs;
+ }
+ eventRangeToSegs(eventRange, dayRanges) {
+ let { dateEnv } = this.context;
+ let { nextDayThreshold } = this.context.options;
+ let range = eventRange.range;
+ let allDay = eventRange.def.allDay;
+ let dayIndex;
+ let segRange;
+ let seg;
+ let segs = [];
+ for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex += 1) {
+ segRange = intersectRanges(range, dayRanges[dayIndex]);
+ if (segRange) {
+ seg = {
+ component: this,
+ eventRange,
+ start: segRange.start,
+ end: segRange.end,
+ isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(),
+ isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(),
+ dayIndex,
+ };
+ segs.push(seg);
+ // detect when range won't go fully into the next day,
+ // and mutate the latest seg to the be the end.
+ if (!seg.isEnd && !allDay &&
+ dayIndex + 1 < dayRanges.length &&
+ range.end <
+ dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) {
+ seg.end = range.end;
+ seg.isEnd = true;
+ break;
+ }
+ }
+ }
+ return segs;
+ }
+ }
+ function renderNoEventsInner(renderProps) {
+ return renderProps.text;
+ }
+ function computeDateVars(dateProfile) {
+ let dayStart = startOfDay(dateProfile.renderRange.start);
+ let viewEnd = dateProfile.renderRange.end;
+ let dayDates = [];
+ let dayRanges = [];
+ while (dayStart < viewEnd) {
+ dayDates.push(dayStart);
+ dayRanges.push({
+ start: dayStart,
+ end: addDays(dayStart, 1),
+ });
+ dayStart = addDays(dayStart, 1);
+ }
+ return { dayDates, dayRanges };
+ }
+ // Returns a sparse array of arrays, segs grouped by their dayIndex
+ function groupSegsByDay(segs) {
+ let segsByDay = []; // sparse array
+ let i;
+ let seg;
+ for (i = 0; i < segs.length; i += 1) {
+ seg = segs[i];
+ (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = []))
+ .push(seg);
+ }
+ return segsByDay;
+ }
+
+ const OPTION_REFINERS = {
+ listDayFormat: createFalsableFormatter,
+ listDaySideFormat: createFalsableFormatter,
+ noEventsClassNames: identity,
+ noEventsContent: identity,
+ noEventsDidMount: identity,
+ noEventsWillUnmount: identity,
+ // noEventsText is defined in base options
+ };
+ function createFalsableFormatter(input) {
+ return input === false ? null : createFormatter(input);
+ }
+
+ var css_248z = ":root{--fc-list-event-dot-width:10px;--fc-list-event-hover-bg-color:#f5f5f5}.fc-theme-standard .fc-list{border:1px solid var(--fc-border-color)}.fc .fc-list-empty{align-items:center;background-color:var(--fc-neutral-bg-color);display:flex;height:100%;justify-content:center}.fc .fc-list-empty-cushion{margin:5em 0}.fc .fc-list-table{border-style:hidden;width:100%}.fc .fc-list-table tr>*{border-left:0;border-right:0}.fc .fc-list-sticky .fc-list-day>*{background:var(--fc-page-bg-color);position:sticky;top:0}.fc .fc-list-table thead{left:-10000px;position:absolute}.fc .fc-list-table tbody>tr:first-child th{border-top:0}.fc .fc-list-table th{padding:0}.fc .fc-list-day-cushion,.fc .fc-list-table td{padding:8px 14px}.fc .fc-list-day-cushion:after{clear:both;content:\"\";display:table}.fc-theme-standard .fc-list-day-cushion{background-color:var(--fc-neutral-bg-color)}.fc-direction-ltr .fc-list-day-text,.fc-direction-rtl .fc-list-day-side-text{float:left}.fc-direction-ltr .fc-list-day-side-text,.fc-direction-rtl .fc-list-day-text{float:right}.fc-direction-ltr .fc-list-table .fc-list-event-graphic{padding-right:0}.fc-direction-rtl .fc-list-table .fc-list-event-graphic{padding-left:0}.fc .fc-list-event.fc-event-forced-url{cursor:pointer}.fc .fc-list-event:hover td{background-color:var(--fc-list-event-hover-bg-color)}.fc .fc-list-event-graphic,.fc .fc-list-event-time{white-space:nowrap;width:1px}.fc .fc-list-event-dot{border:calc(var(--fc-list-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-list-event-dot-width)/2);box-sizing:content-box;display:inline-block;height:0;width:0}.fc .fc-list-event-title a{color:inherit;text-decoration:none}.fc .fc-list-event.fc-event-forced-url:hover a{text-decoration:underline}";
+ injectStyles(css_248z);
+
+ var index = createPlugin({
+ name: '@fullcalendar/list',
+ optionRefiners: OPTION_REFINERS,
+ views: {
+ list: {
+ component: ListView,
+ buttonTextKey: 'list',
+ listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' }, // like "January 1, 2016"
+ },
+ listDay: {
+ type: 'list',
+ duration: { days: 1 },
+ listDayFormat: { weekday: 'long' }, // day-of-week is all we need. full date is probably in headerToolbar
+ },
+ listWeek: {
+ type: 'list',
+ duration: { weeks: 1 },
+ listDayFormat: { weekday: 'long' },
+ listDaySideFormat: { month: 'long', day: 'numeric', year: 'numeric' },
+ },
+ listMonth: {
+ type: 'list',
+ duration: { month: 1 },
+ listDaySideFormat: { weekday: 'long' }, // day-of-week is nice-to-have
+ },
+ listYear: {
+ type: 'list',
+ duration: { year: 1 },
+ listDaySideFormat: { weekday: 'long' }, // day-of-week is nice-to-have
+ },
+ },
+ });
+
+ globalPlugins.push(index$3, index$2, index$1, index);
+
+ exports.Calendar = Calendar;
+ exports.Draggable = ExternalDraggable;
+ exports.Internal = internal_esm;
+ exports.JsonRequestError = JsonRequestError;
+ exports.ThirdPartyDraggable = ThirdPartyDraggable;
+ exports.createPlugin = createPlugin;
+ exports.formatDate = formatDate;
+ exports.formatRange = formatRange;
+ exports.globalLocales = globalLocales;
+ exports.globalPlugins = globalPlugins;
+ exports.sliceEvents = sliceEvents;
+ exports.version = version;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+ return exports;
+
+})({});
diff --git a/library/fullcalendar/dist/index.global.min.js b/library/fullcalendar/dist/index.global.min.js
new file mode 100644
index 000000000..9d9afed22
--- /dev/null
+++ b/library/fullcalendar/dist/index.global.min.js
@@ -0,0 +1,6 @@
+/*!
+FullCalendar Standard Bundle v6.0.3
+Docs & License: https://fullcalendar.io/docs/initialize-globals
+(c) 2022 Adam Shaw
+*/
+var FullCalendar=function(e){"use strict";var t,n,r,i,s,o,a,l={},c=[],d=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function u(e,t){for(var n in t)e[n]=t[n];return e}function h(e){var t=e.parentNode;t&&t.removeChild(e)}function f(e,n,r){var i,s,o,a={};for(o in n)"key"==o?i=n[o]:"ref"==o?s=n[o]:a[o]=n[o];if(arguments.length>2&&(a.children=arguments.length>3?t.call(arguments,2):r),"function"==typeof e&&null!=e.defaultProps)for(o in e.defaultProps)void 0===a[o]&&(a[o]=e.defaultProps[o]);return g(e,a,i,s,null)}function g(e,t,i,s,o){var a={type:e,props:t,key:i,ref:s,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++r:o};return null==o&&null!=n.vnode&&n.vnode(a),a}function p(e){return e.children}function m(e,t){this.props=e,this.context=t}function v(e,t){if(null==t)return e.__?v(e.__,e.__.__k.indexOf(e)+1):null;for(var n;t<e.__k.length;t++)if(null!=(n=e.__k[t])&&null!=n.__e)return n.__e;return"function"==typeof e.type?v(e):null}function b(e){var t,n;if(null!=(e=e.__)&&null!=e.__c){for(e.__e=e.__c.base=null,t=0;t<e.__k.length;t++)if(null!=(n=e.__k[t])&&null!=n.__e){e.__e=e.__c.base=n.__e;break}return b(e)}}function y(e){(!e.__d&&(e.__d=!0)&&s.push(e)&&!E.__r++||o!==n.debounceRendering)&&((o=n.debounceRendering)||setTimeout)(E)}function E(){for(var e;E.__r=s.length;)e=s.sort((function(e,t){return e.__v.__b-t.__v.__b})),s=[],e.some((function(e){var t,n,r,i,s,o;e.__d&&(s=(i=(t=e).__v).__e,(o=t.__P)&&(n=[],(r=u({},i)).__v=i.__v+1,T(o,i,r,t.__n,void 0!==o.ownerSVGElement,null!=i.__h?[s]:null,n,null==s?v(i):s,i.__h),k(n,i),i.__e!=s&&b(i)))}))}function A(e,t,n,r,i,s,o,a,d,u){var h,f,m,b,y,E,A,S=r&&r.__k||c,C=S.length;for(n.__k=[],h=0;h<t.length;h++)if(null!=(b=n.__k[h]=null==(b=t[h])||"boolean"==typeof b?null:"string"==typeof b||"number"==typeof b||"bigint"==typeof b?g(null,b,null,null,b):Array.isArray(b)?g(p,{children:b},null,null,null):b.__b>0?g(b.type,b.props,b.key,b.ref?b.ref:null,b.__v):b)){if(b.__=n,b.__b=n.__b+1,null===(m=S[h])||m&&b.key==m.key&&b.type===m.type)S[h]=void 0;else for(f=0;f<C;f++){if((m=S[f])&&b.key==m.key&&b.type===m.type){S[f]=void 0;break}m=null}T(e,b,m=m||l,i,s,o,a,d,u),y=b.__e,(f=b.ref)&&m.ref!=f&&(A||(A=[]),m.ref&&A.push(m.ref,null,b),A.push(f,b.__c||y,b)),null!=y?(null==E&&(E=y),"function"==typeof b.type&&b.__k===m.__k?b.__d=d=D(b,d,e):d=w(e,b,m,S,y,d),"function"==typeof n.type&&(n.__d=d)):d&&m.__e==d&&d.parentNode!=e&&(d=v(m))}for(n.__e=E,h=C;h--;)null!=S[h]&&O(S[h],S[h]);if(A)for(h=0;h<A.length;h++)I(A[h],A[++h],A[++h])}function D(e,t,n){for(var r,i=e.__k,s=0;i&&s<i.length;s++)(r=i[s])&&(r.__=e,t="function"==typeof r.type?D(r,t,n):w(n,r,r,i,r.__e,t));return t}function S(e,t){return t=t||[],null==e||"boolean"==typeof e||(Array.isArray(e)?e.some((function(e){S(e,t)})):t.push(e)),t}function w(e,t,n,r,i,s){var o,a,l;if(void 0!==t.__d)o=t.__d,t.__d=void 0;else if(null==n||i!=s||null==i.parentNode)e:if(null==s||s.parentNode!==e)e.appendChild(i),o=null;else{for(a=s,l=0;(a=a.nextSibling)&&l<r.length;l+=1)if(a==i)break e;e.insertBefore(i,s),o=s}return void 0!==o?o:i.nextSibling}function C(e,t,n){"-"===t[0]?e.setProperty(t,n):e[t]=null==n?"":"number"!=typeof n||d.test(t)?n:n+"px"}function R(e,t,n,r,i){var s;e:if("style"===t)if("string"==typeof n)e.style.cssText=n;else{if("string"==typeof r&&(e.style.cssText=r=""),r)for(t in r)n&&t in n||C(e.style,t,"");if(n)for(t in n)r&&n[t]===r[t]||C(e.style,t,n[t])}else if("o"===t[0]&&"n"===t[1])s=t!==(t=t.replace(/Capture$/,"")),t=t.toLowerCase()in e?t.toLowerCase().slice(2):t.slice(2),e.l||(e.l={}),e.l[t+s]=n,n?r||e.addEventListener(t,s?_:x,s):e.removeEventListener(t,s?_:x,s);else if("dangerouslySetInnerHTML"!==t){if(i)t=t.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("href"!==t&&"list"!==t&&"form"!==t&&"tabIndex"!==t&&"download"!==t&&t in e)try{e[t]=null==n?"":n;break e}catch(e){}"function"==typeof n||(null==n||!1===n&&-1==t.indexOf("-")?e.removeAttribute(t):e.setAttribute(t,n))}}function x(e){this.l[e.type+!1](n.event?n.event(e):e)}function _(e){this.l[e.type+!0](n.event?n.event(e):e)}function T(e,t,r,i,s,o,a,l,c){var d,h,f,g,v,b,y,E,D,S,w,C,R,x,_,T=t.type;if(void 0!==t.constructor)return null;null!=r.__h&&(c=r.__h,l=t.__e=r.__e,t.__h=null,o=[l]),(d=n.__b)&&d(t);try{e:if("function"==typeof T){if(E=t.props,D=(d=T.contextType)&&i[d.__c],S=d?D?D.props.value:d.__:i,r.__c?y=(h=t.__c=r.__c).__=h.__E:("prototype"in T&&T.prototype.render?t.__c=h=new T(E,S):(t.__c=h=new m(E,S),h.constructor=T,h.render=N),D&&D.sub(h),h.props=E,h.state||(h.state={}),h.context=S,h.__n=i,f=h.__d=!0,h.__h=[],h._sb=[]),null==h.__s&&(h.__s=h.state),null!=T.getDerivedStateFromProps&&(h.__s==h.state&&(h.__s=u({},h.__s)),u(h.__s,T.getDerivedStateFromProps(E,h.__s))),g=h.props,v=h.state,f)null==T.getDerivedStateFromProps&&null!=h.componentWillMount&&h.componentWillMount(),null!=h.componentDidMount&&h.__h.push(h.componentDidMount);else{if(null==T.getDerivedStateFromProps&&E!==g&&null!=h.componentWillReceiveProps&&h.componentWillReceiveProps(E,S),!h.__e&&null!=h.shouldComponentUpdate&&!1===h.shouldComponentUpdate(E,h.__s,S)||t.__v===r.__v){for(h.props=E,h.state=h.__s,t.__v!==r.__v&&(h.__d=!1),h.__v=t,t.__e=r.__e,t.__k=r.__k,t.__k.forEach((function(e){e&&(e.__=t)})),w=0;w<h._sb.length;w++)h.__h.push(h._sb[w]);h._sb=[],h.__h.length&&a.push(h);break e}null!=h.componentWillUpdate&&h.componentWillUpdate(E,h.__s,S),null!=h.componentDidUpdate&&h.__h.push((function(){h.componentDidUpdate(g,v,b)}))}if(h.context=S,h.props=E,h.__v=t,h.__P=e,C=n.__r,R=0,"prototype"in T&&T.prototype.render){for(h.state=h.__s,h.__d=!1,C&&C(t),d=h.render(h.props,h.state,h.context),x=0;x<h._sb.length;x++)h.__h.push(h._sb[x]);h._sb=[]}else do{h.__d=!1,C&&C(t),d=h.render(h.props,h.state,h.context),h.state=h.__s}while(h.__d&&++R<25);h.state=h.__s,null!=h.getChildContext&&(i=u(u({},i),h.getChildContext())),f||null==h.getSnapshotBeforeUpdate||(b=h.getSnapshotBeforeUpdate(g,v)),_=null!=d&&d.type===p&&null==d.key?d.props.children:d,A(e,Array.isArray(_)?_:[_],t,r,i,s,o,a,l,c),h.base=t.__e,t.__h=null,h.__h.length&&a.push(h),y&&(h.__E=h.__=null),h.__e=!1}else null==o&&t.__v===r.__v?(t.__k=r.__k,t.__e=r.__e):t.__e=M(r.__e,t,r,i,s,o,a,c);(d=n.diffed)&&d(t)}catch(e){t.__v=null,(c||null!=o)&&(t.__e=l,t.__h=!!c,o[o.indexOf(l)]=null),n.__e(e,t,r)}}function k(e,t){n.__c&&n.__c(t,e),e.some((function(t){try{e=t.__h,t.__h=[],e.some((function(e){e.call(t)}))}catch(e){n.__e(e,t.__v)}}))}function M(e,n,r,i,s,o,a,c){var d,u,f,g=r.props,p=n.props,m=n.type,b=0;if("svg"===m&&(s=!0),null!=o)for(;b<o.length;b++)if((d=o[b])&&"setAttribute"in d==!!m&&(m?d.localName===m:3===d.nodeType)){e=d,o[b]=null;break}if(null==e){if(null===m)return document.createTextNode(p);e=s?document.createElementNS("http://www.w3.org/2000/svg",m):document.createElement(m,p.is&&p),o=null,c=!1}if(null===m)g===p||c&&e.data===p||(e.data=p);else{if(o=o&&t.call(e.childNodes),u=(g=r.props||l).dangerouslySetInnerHTML,f=p.dangerouslySetInnerHTML,!c){if(null!=o)for(g={},b=0;b<e.attributes.length;b++)g[e.attributes[b].name]=e.attributes[b].value;(f||u)&&(f&&(u&&f.__html==u.__html||f.__html===e.innerHTML)||(e.innerHTML=f&&f.__html||""))}if(function(e,t,n,r,i){var s;for(s in n)"children"===s||"key"===s||s in t||R(e,s,null,n[s],r);for(s in t)i&&"function"!=typeof t[s]||"children"===s||"key"===s||"value"===s||"checked"===s||n[s]===t[s]||R(e,s,t[s],n[s],r)}(e,p,g,s,c),f)n.__k=[];else if(b=n.props.children,A(e,Array.isArray(b)?b:[b],n,r,i,s&&"foreignObject"!==m,o,a,o?o[0]:r.__k&&v(r,0),c),null!=o)for(b=o.length;b--;)null!=o[b]&&h(o[b]);c||("value"in p&&void 0!==(b=p.value)&&(b!==e.value||"progress"===m&&!b||"option"===m&&b!==g.value)&&R(e,"value",b,g.value,!1),"checked"in p&&void 0!==(b=p.checked)&&b!==e.checked&&R(e,"checked",b,g.checked,!1))}return e}function I(e,t,r){try{"function"==typeof e?e(t):e.current=t}catch(e){n.__e(e,r)}}function O(e,t,r){var i,s;if(n.unmount&&n.unmount(e),(i=e.ref)&&(i.current&&i.current!==e.__e||I(i,null,t)),null!=(i=e.__c)){if(i.componentWillUnmount)try{i.componentWillUnmount()}catch(e){n.__e(e,t)}i.base=i.__P=null,e.__c=void 0}if(i=e.__k)for(s=0;s<i.length;s++)i[s]&&O(i[s],t,r||"function"!=typeof e.type);r||null==e.__e||h(e.__e),e.__=e.__e=e.__d=void 0}function N(e,t,n){return this.constructor(e,n)}function P(e,r,i){var s,o,a;n.__&&n.__(e,r),o=(s="function"==typeof i)?null:i&&i.__k||r.__k,a=[],T(r,e=(!s&&i||r).__k=f(p,null,[e]),o||l,l,void 0!==r.ownerSVGElement,!s&&i?[i]:o?null:r.firstChild?t.call(r.childNodes):null,a,!s&&i?i:o?o.__e:r.firstChild,s),k(a,e)}t=c.slice,n={__e:function(e,t,n,r){for(var i,s,o;t=t.__;)if((i=t.__c)&&!i.__)try{if((s=i.constructor)&&null!=s.getDerivedStateFromError&&(i.setState(s.getDerivedStateFromError(e)),o=i.__d),null!=i.componentDidCatch&&(i.componentDidCatch(e,r||{}),o=i.__d),o)return i.__E=i}catch(t){e=t}throw e}},r=0,i=function(e){return null!=e&&void 0===e.constructor},m.prototype.setState=function(e,t){var n;n=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=u({},this.state),"function"==typeof e&&(e=e(u({},n),this.props)),e&&u(n,e),null!=e&&this.__v&&(t&&this._sb.push(t),y(this))},m.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),y(this))},m.prototype.render=p,s=[],E.__r=0,a=0;var H,B,j,z=[],U=[],L=n.__b,W=n.__r,F=n.diffed,V=n.__c,G=n.unmount;function Q(){for(var e;e=z.shift();)if(e.__P&&e.__H)try{e.__H.__h.forEach(Z),e.__H.__h.forEach(X),e.__H.__h=[]}catch(t){e.__H.__h=[],n.__e(t,e.__v)}}n.__b=function(e){H=null,L&&L(e)},n.__r=function(e){W&&W(e);var t=(H=e.__c).__H;t&&(B===H?(t.__h=[],H.__h=[],t.__.forEach((function(e){e.__N&&(e.__=e.__N),e.__V=U,e.__N=e.i=void 0}))):(t.__h.forEach(Z),t.__h.forEach(X),t.__h=[])),B=H},n.diffed=function(e){F&&F(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(1!==z.push(t)&&j===n.requestAnimationFrame||((j=n.requestAnimationFrame)||Y)(Q)),t.__H.__.forEach((function(e){e.i&&(e.__H=e.i),e.__V!==U&&(e.__=e.__V),e.i=void 0,e.__V=U}))),B=H=null},n.__c=function(e,t){t.some((function(e){try{e.__h.forEach(Z),e.__h=e.__h.filter((function(e){return!e.__||X(e)}))}catch(r){t.some((function(e){e.__h&&(e.__h=[])})),t=[],n.__e(r,e.__v)}})),V&&V(e,t)},n.unmount=function(e){G&&G(e);var t,r=e.__c;r&&r.__H&&(r.__H.__.forEach((function(e){try{Z(e)}catch(e){t=e}})),r.__H=void 0,t&&n.__e(t,r.__v))};var q="function"==typeof requestAnimationFrame;function Y(e){var t,n=function(){clearTimeout(r),q&&cancelAnimationFrame(t),setTimeout(e)},r=setTimeout(n,100);q&&(t=requestAnimationFrame(n))}function Z(e){var t=H,n=e.__c;"function"==typeof n&&(e.__c=void 0,n()),H=t}function X(e){var t=H;e.__c=e.__(),H=t}function J(e,t){for(var n in e)if("__source"!==n&&!(n in t))return!0;for(var r in t)if("__source"!==r&&e[r]!==t[r])return!0;return!1}function $(e){this.props=e}($.prototype=new m).isPureReactComponent=!0,$.prototype.shouldComponentUpdate=function(e,t){return J(this.props,e)||J(this.state,t)};var K=n.__b;n.__b=function(e){e.type&&e.type.__f&&e.ref&&(e.props.ref=e.ref,e.ref=null),K&&K(e)};var ee=n.__e;n.__e=function(e,t,n,r){if(e.then)for(var i,s=t;s=s.__;)if((i=s.__c)&&i.__c)return null==t.__e&&(t.__e=n.__e,t.__k=n.__k),i.__c(e,t);ee(e,t,n,r)};var te=n.unmount;function ne(){this.__u=0,this.t=null,this.__b=null}function re(e){var t=e.__.__c;return t&&t.__a&&t.__a(e)}function ie(){this.u=null,this.o=null}n.unmount=function(e){var t=e.__c;t&&t.__R&&t.__R(),t&&!0===e.__h&&(e.type=null),te&&te(e)},(ne.prototype=new m).__c=function(e,t){var n=t.__c,r=this;null==r.t&&(r.t=[]),r.t.push(n);var i=re(r.__v),s=!1,o=function(){s||(s=!0,n.__R=null,i?i(a):a())};n.__R=o;var a=function(){if(!--r.__u){if(r.state.__a){var e=r.state.__a;r.__v.__k[0]=function e(t,n,r){return t&&(t.__v=null,t.__k=t.__k&&t.__k.map((function(t){return e(t,n,r)})),t.__c&&t.__c.__P===n&&(t.__e&&r.insertBefore(t.__e,t.__d),t.__c.__e=!0,t.__c.__P=r)),t}(e,e.__c.__P,e.__c.__O)}var t;for(r.setState({__a:r.__b=null});t=r.t.pop();)t.forceUpdate()}},l=!0===t.__h;r.__u++||l||r.setState({__a:r.__b=r.__v.__k[0]}),e.then(o,o)},ne.prototype.componentWillUnmount=function(){this.t=[]},ne.prototype.render=function(e,t){if(this.__b){if(this.__v.__k){var n=document.createElement("div"),r=this.__v.__k[0].__c;this.__v.__k[0]=function e(t,n,r){return t&&(t.__c&&t.__c.__H&&(t.__c.__H.__.forEach((function(e){"function"==typeof e.__c&&e.__c()})),t.__c.__H=null),null!=(t=function(e,t){for(var n in t)e[n]=t[n];return e}({},t)).__c&&(t.__c.__P===r&&(t.__c.__P=n),t.__c=null),t.__k=t.__k&&t.__k.map((function(t){return e(t,n,r)}))),t}(this.__b,n,r.__O=r.__P)}this.__b=null}var i=t.__a&&f(p,null,e.fallback);return i&&(i.__h=null),[f(p,null,t.__a?null:e.children),i]};var se=function(e,t,n){if(++n[1]===n[0]&&e.o.delete(t),e.props.revealOrder&&("t"!==e.props.revealOrder[0]||!e.o.size))for(n=e.u;n;){for(;n.length>3;)n.pop()();if(n[1]<n[0])break;e.u=n=n[2]}};function oe(e){return this.getChildContext=function(){return e.context},e.children}function ae(e){var t=this,n=e.i;t.componentWillUnmount=function(){P(null,t.l),t.l=null,t.i=null},t.i&&t.i!==n&&t.componentWillUnmount(),e.__v?(t.l||(t.i=n,t.l={nodeType:1,parentNode:n,childNodes:[],appendChild:function(e){this.childNodes.push(e),t.i.appendChild(e)},insertBefore:function(e,n){this.childNodes.push(e),t.i.appendChild(e)},removeChild:function(e){this.childNodes.splice(this.childNodes.indexOf(e)>>>1,1),t.i.removeChild(e)}}),P(f(oe,{context:t.context},e.__v),t.l)):t.l&&t.componentWillUnmount()}(ie.prototype=new m).__a=function(e){var t=this,n=re(t.__v),r=t.o.get(e);return r[0]++,function(i){var s=function(){t.props.revealOrder?(r.push(i),se(t,e,r)):i()};n?n(s):s()}},ie.prototype.render=function(e){this.u=null,this.o=new Map;var t=S(e.children);e.revealOrder&&"b"===e.revealOrder[0]&&t.reverse();for(var n=t.length;n--;)this.o.set(t[n],this.u=[1,0,this.u]);return e.children},ie.prototype.componentDidUpdate=ie.prototype.componentDidMount=function(){var e=this;this.o.forEach((function(t,n){se(e,n,t)}))};var le="undefined"!=typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103,ce=/^(?: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]/,de="undefined"!=typeof document,ue=function(e){return("undefined"!=typeof Symbol&&"symbol"==typeof Symbol()?/fil|che|rad/i:/fil|che|ra/i).test(e)};m.prototype.isReactComponent={},["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach((function(e){Object.defineProperty(m.prototype,e,{configurable:!0,get:function(){return this["UNSAFE_"+e]},set:function(t){Object.defineProperty(this,e,{configurable:!0,writable:!0,value:t})}})}));var he=n.event;function fe(){}function ge(){return this.cancelBubble}function pe(){return this.defaultPrevented}n.event=function(e){return he&&(e=he(e)),e.persist=fe,e.isPropagationStopped=ge,e.isDefaultPrevented=pe,e.nativeEvent=e};var me={configurable:!0,get:function(){return this.class}},ve=n.vnode;n.vnode=function(e){var t=e.type,n=e.props,r=n;if("string"==typeof t){var i=-1===t.indexOf("-");for(var s in r={},n){var o=n[s];de&&"children"===s&&"noscript"===t||"value"===s&&"defaultValue"in n&&null==o||("defaultValue"===s&&"value"in n&&null==n.value?s="value":"download"===s&&!0===o?o="":/ondoubleclick/i.test(s)?s="ondblclick":/^onchange(textarea|input)/i.test(s+t)&&!ue(n.type)?s="oninput":/^onfocus$/i.test(s)?s="onfocusin":/^onblur$/i.test(s)?s="onfocusout":/^on(Ani|Tra|Tou|BeforeInp|Compo)/.test(s)?s=s.toLowerCase():i&&ce.test(s)?s=s.replace(/[A-Z0-9]/g,"-$&").toLowerCase():null===o&&(o=void 0),/^oninput$/i.test(s)&&(s=s.toLowerCase(),r[s]&&(s="oninputCapture")),r[s]=o)}"select"==t&&r.multiple&&Array.isArray(r.value)&&(r.value=S(n.children).forEach((function(e){e.props.selected=-1!=r.value.indexOf(e.props.value)}))),"select"==t&&null!=r.defaultValue&&(r.value=S(n.children).forEach((function(e){e.props.selected=r.multiple?-1!=r.defaultValue.indexOf(e.props.value):r.defaultValue==e.props.value}))),e.props=r,n.class!=n.className&&(me.enumerable="className"in n,null!=n.className&&(r.class=n.className),Object.defineProperty(r,"className",me))}e.$$typeof=le,ve&&ve(e)};var be=n.__r;function ye(e){e.parentNode&&e.parentNode.removeChild(e)}function Ee(e,t){if(e.closest)return e.closest(t);if(!document.documentElement.contains(e))return null;do{if(Ae(e,t))return e;e=e.parentElement||e.parentNode}while(null!==e&&1===e.nodeType);return null}function Ae(e,t){return(e.matches||e.matchesSelector||e.msMatchesSelector).call(e,t)}function De(e,t){let n=e instanceof HTMLElement?[e]:e,r=[];for(let e=0;e<n.length;e+=1){let i=n[e].querySelectorAll(t);for(let e=0;e<i.length;e+=1)r.push(i[e])}return r}n.__r=function(e){be&&be(e),e.__c};const Se=/(top|left|right|bottom|width|height)$/i;function we(e,t){for(let n in t)Ce(e,n,t[n])}function Ce(e,t,n){null==n?e.style[t]="":"number"==typeof n&&Se.test(t)?e.style[t]=n+"px":e.style[t]=n}function Re(e){var t,n;return null!==(n=null===(t=e.composedPath)||void 0===t?void 0:t.call(e)[0])&&void 0!==n?n:e.target}function xe(e){return e.getRootNode?e.getRootNode():document}let _e=0;function Te(){return _e+=1,"fc-dom-"+_e}function ke(e){e.preventDefault()}function Me(e,t,n,r){let i=function(e,t){return n=>{let r=Ee(n.target,e);r&&t.call(r,n,r)}}(n,r);return e.addEventListener(t,i),()=>{e.removeEventListener(t,i)}}const Ie=["webkitTransitionEnd","otransitionend","oTransitionEnd","msTransitionEnd","transitionend"];function Oe(e,t){let n=r=>{t(r),Ie.forEach(t=>{e.removeEventListener(t,n)})};Ie.forEach(t=>{e.addEventListener(t,n)})}function Ne(e){return Object.assign({onClick:e},Pe(e))}function Pe(e){return{tabIndex:0,onKeyDown(t){"Enter"!==t.key&&" "!==t.key||(e(t),t.preventDefault())}}}let He=0;function Be(){return He+=1,String(He)}function je(){document.body.classList.add("fc-not-allowed")}function ze(){document.body.classList.remove("fc-not-allowed")}function Ue(e){e.classList.add("fc-unselectable"),e.addEventListener("selectstart",ke)}function Le(e){e.classList.remove("fc-unselectable"),e.removeEventListener("selectstart",ke)}function We(e){e.addEventListener("contextmenu",ke)}function Fe(e){e.removeEventListener("contextmenu",ke)}function Ve(e){let t,n,r=[],i=[];for("string"==typeof e?i=e.split(/\s*,\s*/):"function"==typeof e?i=[e]:Array.isArray(e)&&(i=e),t=0;t<i.length;t+=1)n=i[t],"string"==typeof n?r.push("-"===n.charAt(0)?{field:n.substring(1),order:-1}:{field:n,order:1}):"function"==typeof n&&r.push({func:n});return r}function Ge(e,t,n){let r,i;for(r=0;r<n.length;r+=1)if(i=Qe(e,t,n[r]),i)return i;return 0}function Qe(e,t,n){return n.func?n.func(e,t):qe(e[n.field],t[n.field])*(n.order||1)}function qe(e,t){return e||t?null==t?-1:null==e?1:"string"==typeof e||"string"==typeof t?String(e).localeCompare(String(t)):e-t:0}function Ye(e,t){let n=String(e);return"000".substr(0,t-n.length)+n}function Ze(e,t,n){return"function"==typeof e?e(...t):"string"==typeof e?t.reduce((e,t,n)=>e.replace("$"+n,t||""),e):n}function Xe(e,t){return e-t}function Je(e){return e%1==0}function $e(e){let t=e.querySelector(".fc-scrollgrid-shrink-frame"),n=e.querySelector(".fc-scrollgrid-shrink-cushion");if(!t)throw new Error("needs fc-scrollgrid-shrink-frame className");if(!n)throw new Error("needs fc-scrollgrid-shrink-cushion className");return e.getBoundingClientRect().width-t.getBoundingClientRect().width+n.getBoundingClientRect().width}const Ke=["years","months","days","milliseconds"],et=/^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/;function tt(e,t){return"string"==typeof e?function(e){let t=et.exec(e);if(t){let e=t[1]?-1:1;return{years:0,months:0,days:e*(t[2]?parseInt(t[2],10):0),milliseconds:e*(60*(t[3]?parseInt(t[3],10):0)*60*1e3+60*(t[4]?parseInt(t[4],10):0)*1e3+1e3*(t[5]?parseInt(t[5],10):0)+(t[6]?parseInt(t[6],10):0))}}return null}(e):"object"==typeof e&&e?nt(e):"number"==typeof e?nt({[t||"milliseconds"]:e}):null}function nt(e){let t={years:e.years||e.year||0,months:e.months||e.month||0,days:e.days||e.day||0,milliseconds:60*(e.hours||e.hour||0)*60*1e3+60*(e.minutes||e.minute||0)*1e3+1e3*(e.seconds||e.second||0)+(e.milliseconds||e.millisecond||e.ms||0)},n=e.weeks||e.week;return n&&(t.days+=7*n,t.specifiedWeeks=!0),t}function rt(e,t){return{years:e.years+t.years,months:e.months+t.months,days:e.days+t.days,milliseconds:e.milliseconds+t.milliseconds}}function it(e,t){return{years:e.years*t,months:e.months*t,days:e.days*t,milliseconds:e.milliseconds*t}}function st(e){return ot(e)/864e5}function ot(e){return 31536e6*e.years+2592e6*e.months+864e5*e.days+e.milliseconds}function at(e,t){let n=null;for(let r=0;r<Ke.length;r+=1){let i=Ke[r];if(t[i]){let r=e[i]/t[i];if(!Je(r)||null!==n&&n!==r)return null;n=r}else if(e[i])return null}return n}function lt(e){let t=e.milliseconds;if(t){if(t%1e3!=0)return{unit:"millisecond",value:t};if(t%6e4!=0)return{unit:"second",value:t/1e3};if(t%36e5!=0)return{unit:"minute",value:t/6e4};if(t)return{unit:"hour",value:t/36e5}}return e.days?e.specifiedWeeks&&e.days%7==0?{unit:"week",value:e.days/7}:{unit:"day",value:e.days}:e.months?{unit:"month",value:e.months}:e.years?{unit:"year",value:e.years}:{unit:"millisecond",value:0}}const{hasOwnProperty:ct}=Object.prototype;function dt(e,t){let n={};if(t)for(let r in t){let t=[];for(let i=e.length-1;i>=0;i-=1){let s=e[i][r];if("object"==typeof s&&s)t.unshift(s);else if(void 0!==s){n[r]=s;break}}t.length&&(n[r]=dt(t))}for(let t=e.length-1;t>=0;t-=1){let r=e[t];for(let e in r)e in n||(n[e]=r[e])}return n}function ut(e,t){let n={};for(let r in e)t(e[r],r)&&(n[r]=e[r]);return n}function ht(e,t){let n={};for(let r in e)n[r]=t(e[r],r);return n}function ft(e){let t={};for(let n of e)t[n]=!0;return t}function gt(e){let t=[];for(let n in e)t.push(e[n]);return t}function pt(e,t){if(e===t)return!0;for(let n in e)if(ct.call(e,n)&&!(n in t))return!1;for(let n in t)if(ct.call(t,n)&&e[n]!==t[n])return!1;return!0}const mt=/^on[A-Z]/;function vt(e,t){let n=[];for(let r in e)ct.call(e,r)&&(r in t||n.push(r));for(let r in t)ct.call(t,r)&&e[r]!==t[r]&&n.push(r);return n}function bt(e,t,n={}){if(e===t)return!0;for(let r in t)if(!(r in e)||!yt(e[r],t[r],n[r]))return!1;for(let n in e)if(!(n in t))return!1;return!0}function yt(e,t,n){return e===t||!0===n||!!n&&n(e,t)}function Et(e,t=0,n,r=1){let i=[];null==n&&(n=Object.keys(e).length);for(let s=t;s<n;s+=r){let t=e[s];void 0!==t&&i.push(t)}return i}const At=["sun","mon","tue","wed","thu","fri","sat"];function Dt(e,t){let n=Pt(e);return n[2]+=7*t,Ht(n)}function St(e,t){let n=Pt(e);return n[2]+=t,Ht(n)}function wt(e,t){let n=Pt(e);return n[6]+=t,Ht(n)}function Ct(e,t){return Rt(e,t)/7}function Rt(e,t){return(t.valueOf()-e.valueOf())/864e5}function xt(e,t){let n=kt(e),r=kt(t);return{years:0,months:0,days:Math.round(Rt(n,r)),milliseconds:t.valueOf()-r.valueOf()-(e.valueOf()-n.valueOf())}}function _t(e,t){let n=Tt(e,t);return null!==n&&n%7==0?n/7:null}function Tt(e,t){return jt(e)===jt(t)?Math.round(Rt(e,t)):null}function kt(e){return Ht([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()])}function Mt(e,t,n,r){let i=Ht([t,0,1+It(t,n,r)]),s=kt(e),o=Math.round(Rt(i,s));return Math.floor(o/7)+1}function It(e,t,n){let r=7+t-n;return-((7+Ht([e,0,r]).getUTCDay()-t)%7)+r-1}function Ot(e){return[e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),e.getMilliseconds()]}function Nt(e){return new Date(e[0],e[1]||0,null==e[2]?1:e[2],e[3]||0,e[4]||0,e[5]||0)}function Pt(e){return[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds(),e.getUTCMilliseconds()]}function Ht(e){return 1===e.length&&(e=e.concat([0])),new Date(Date.UTC(...e))}function Bt(e){return!isNaN(e.valueOf())}function jt(e){return 1e3*e.getUTCHours()*60*60+1e3*e.getUTCMinutes()*60+1e3*e.getUTCSeconds()+e.getUTCMilliseconds()}function zt(e,t,n=!1){let r=e.toISOString();return r=r.replace(".000",""),n&&(r=r.replace("T00:00:00Z","")),r.length>10&&(null==t?r=r.replace("Z",""):0!==t&&(r=r.replace("Z",Wt(t,!0)))),r}function Ut(e){return e.toISOString().replace(/T.*$/,"")}function Lt(e){return Ye(e.getUTCHours(),2)+":"+Ye(e.getUTCMinutes(),2)+":"+Ye(e.getUTCSeconds(),2)}function Wt(e,t=!1){let n=e<0?"-":"+",r=Math.abs(e),i=Math.floor(r/60),s=Math.round(r%60);return t?`${n+Ye(i,2)}:${Ye(s,2)}`:`GMT${n}${i}${s?":"+Ye(s,2):""}`}function Ft(e,t,n){if(e===t)return!0;let r,i=e.length;if(i!==t.length)return!1;for(r=0;r<i;r+=1)if(!(n?n(e[r],t[r]):e[r]===t[r]))return!1;return!0}function Vt(e,t,n){let r,i;return function(...s){if(r){if(!Ft(r,s)){n&&n(i);let r=e.apply(this,s);t&&t(r,i)||(i=r)}}else i=e.apply(this,s);return r=s,i}}function Gt(e,t,n){let r,i;return s=>{if(r){if(!pt(r,s)){n&&n(i);let r=e.call(this,s);t&&t(r,i)||(i=r)}}else i=e.call(this,s);return r=s,i}}const Qt={week:3,separator:0,omitZeroMinute:0,meridiem:0,omitCommas:0},qt={timeZoneName:7,era:6,year:5,month:4,day:2,weekday:2,hour:1,minute:1,second:1},Yt=/\s*([ap])\.?m\.?/i,Zt=/,/g,Xt=/\s+/g,Jt=/\u200e/g,$t=/UTC|GMT/;class Kt{constructor(e){let t={},n={},r=0;for(let i in e)i in Qt?(n[i]=e[i],r=Math.max(Qt[i],r)):(t[i]=e[i],i in qt&&(r=Math.max(qt[i],r)));this.standardDateProps=t,this.extendedSettings=n,this.severity=r,this.buildFormattingFunc=Vt(en)}format(e,t){return this.buildFormattingFunc(this.standardDateProps,this.extendedSettings,t)(e)}formatRange(e,t,n,r){let{standardDateProps:i,extendedSettings:s}=this,o=function(e,t,n){if(n.getMarkerYear(e)!==n.getMarkerYear(t))return 5;if(n.getMarkerMonth(e)!==n.getMarkerMonth(t))return 4;if(n.getMarkerDay(e)!==n.getMarkerDay(t))return 2;if(jt(e)!==jt(t))return 1;return 0}(e.marker,t.marker,n.calendarSystem);if(!o)return this.format(e,n);let a=o;!(a>1)||"numeric"!==i.year&&"2-digit"!==i.year||"numeric"!==i.month&&"2-digit"!==i.month||"numeric"!==i.day&&"2-digit"!==i.day||(a=1);let l=this.format(e,n),c=this.format(t,n);if(l===c)return l;let d=en(function(e,t){let n={};for(let r in e)(!(r in qt)||qt[r]<=t)&&(n[r]=e[r]);return n}(i,a),s,n),u=d(e),h=d(t),f=function(e,t,n,r){let i=0;for(;i<e.length;){let s=e.indexOf(t,i);if(-1===s)break;let o=e.substr(0,s);i=s+t.length;let a=e.substr(i),l=0;for(;l<n.length;){let e=n.indexOf(r,l);if(-1===e)break;let t=n.substr(0,e);l=e+r.length;let i=n.substr(l);if(o===t&&a===i)return{before:o,after:a}}}return null}(l,u,c,h),g=s.separator||r||n.defaultSeparator||"";return f?f.before+u+g+h+f.after:l+g+c}getLargestUnit(){switch(this.severity){case 7:case 6:case 5:return"year";case 4:return"month";case 3:return"week";case 2:return"day";default:return"time"}}}function en(e,t,n){let r=Object.keys(e).length;return 1===r&&"short"===e.timeZoneName?e=>Wt(e.timeZoneOffset):0===r&&t.week?e=>function(e,t,n,r,i){let s=[];"long"===i?s.push(n):"short"!==i&&"narrow"!==i||s.push(t);"long"!==i&&"short"!==i||s.push(" ");s.push(r.simpleNumberFormat.format(e)),"rtl"===r.options.direction&&s.reverse();return s.join("")}(n.computeWeekNumber(e.marker),n.weekText,n.weekTextLong,n.locale,t.week):function(e,t,n){e=Object.assign({},e),t=Object.assign({},t),function(e,t){e.timeZoneName&&(e.hour||(e.hour="2-digit"),e.minute||(e.minute="2-digit"));"long"===e.timeZoneName&&(e.timeZoneName="short");t.omitZeroMinute&&(e.second||e.millisecond)&&delete t.omitZeroMinute}(e,t),e.timeZone="UTC";let r,i=new Intl.DateTimeFormat(n.locale.codes,e);if(t.omitZeroMinute){let t=Object.assign({},e);delete t.minute,r=new Intl.DateTimeFormat(n.locale.codes,t)}return s=>{let o,{marker:a}=s;return o=r&&!a.getUTCMinutes()?r:i,function(e,t,n,r,i){e=e.replace(Jt,""),"short"===n.timeZoneName&&(e=function(e,t){let n=!1;e=e.replace($t,()=>(n=!0,t)),n||(e+=" "+t);return e}(e,"UTC"===i.timeZone||null==t.timeZoneOffset?"UTC":Wt(t.timeZoneOffset)));r.omitCommas&&(e=e.replace(Zt,"").trim());r.omitZeroMinute&&(e=e.replace(":00",""));!1===r.meridiem?e=e.replace(Yt,"").trim():"narrow"===r.meridiem?e=e.replace(Yt,(e,t)=>t.toLocaleLowerCase()):"short"===r.meridiem?e=e.replace(Yt,(e,t)=>t.toLocaleLowerCase()+"m"):"lowercase"===r.meridiem&&(e=e.replace(Yt,e=>e.toLocaleLowerCase()));return e=(e=e.replace(Xt," ")).trim()}(o.format(a),s,e,t,n)}}(e,t,n)}function tn(e,t){let n=t.markerToArray(e.marker);return{marker:e.marker,timeZoneOffset:e.timeZoneOffset,array:n,year:n[0],month:n[1],day:n[2],hour:n[3],minute:n[4],second:n[5],millisecond:n[6]}}function nn(e,t,n,r){let i=tn(e,n.calendarSystem);return{date:i,start:i,end:t?tn(t,n.calendarSystem):null,timeZone:n.timeZone,localeCodes:n.locale.codes,defaultSeparator:r||n.defaultSeparator}}class rn{constructor(e){this.cmdStr=e}format(e,t,n){return t.cmdFormatter(this.cmdStr,nn(e,null,t,n))}formatRange(e,t,n,r){return n.cmdFormatter(this.cmdStr,nn(e,t,n,r))}}class sn{constructor(e){this.func=e}format(e,t,n){return this.func(nn(e,null,t,n))}formatRange(e,t,n,r){return this.func(nn(e,t,n,r))}}function on(e){return"object"==typeof e&&e?new Kt(e):"string"==typeof e?new rn(e):"function"==typeof e?new sn(e):null}const an={navLinkDayClick:mn,navLinkWeekClick:mn,duration:tt,bootstrapFontAwesome:mn,buttonIcons:mn,customButtons:mn,defaultAllDayEventDuration:tt,defaultTimedEventDuration:tt,nextDayThreshold:tt,scrollTime:tt,scrollTimeReset:Boolean,slotMinTime:tt,slotMaxTime:tt,dayPopoverFormat:on,slotDuration:tt,snapDuration:tt,headerToolbar:mn,footerToolbar:mn,defaultRangeSeparator:String,titleRangeSeparator:String,forceEventDuration:Boolean,dayHeaders:Boolean,dayHeaderFormat:on,dayHeaderClassNames:mn,dayHeaderContent:mn,dayHeaderDidMount:mn,dayHeaderWillUnmount:mn,dayCellClassNames:mn,dayCellContent:mn,dayCellDidMount:mn,dayCellWillUnmount:mn,initialView:String,aspectRatio:Number,weekends:Boolean,weekNumberCalculation:mn,weekNumbers:Boolean,weekNumberClassNames:mn,weekNumberContent:mn,weekNumberDidMount:mn,weekNumberWillUnmount:mn,editable:Boolean,viewClassNames:mn,viewDidMount:mn,viewWillUnmount:mn,nowIndicator:Boolean,nowIndicatorClassNames:mn,nowIndicatorContent:mn,nowIndicatorDidMount:mn,nowIndicatorWillUnmount:mn,showNonCurrentDates:Boolean,lazyFetching:Boolean,startParam:String,endParam:String,timeZoneParam:String,timeZone:String,locales:mn,locale:mn,themeSystem:String,dragRevertDuration:Number,dragScroll:Boolean,allDayMaintainDuration:Boolean,unselectAuto:Boolean,dropAccept:mn,eventOrder:Ve,eventOrderStrict:Boolean,handleWindowResize:Boolean,windowResizeDelay:Number,longPressDelay:Number,eventDragMinDistance:Number,expandRows:Boolean,height:mn,contentHeight:mn,direction:String,weekNumberFormat:on,eventResizableFromStart:Boolean,displayEventTime:Boolean,displayEventEnd:Boolean,weekText:String,weekTextLong:String,progressiveEventRendering:Boolean,businessHours:mn,initialDate:mn,now:mn,eventDataTransform:mn,stickyHeaderDates:mn,stickyFooterScrollbar:mn,viewHeight:mn,defaultAllDay:Boolean,eventSourceFailure:mn,eventSourceSuccess:mn,eventDisplay:String,eventStartEditable:Boolean,eventDurationEditable:Boolean,eventOverlap:mn,eventConstraint:mn,eventAllow:mn,eventBackgroundColor:String,eventBorderColor:String,eventTextColor:String,eventColor:String,eventClassNames:mn,eventContent:mn,eventDidMount:mn,eventWillUnmount:mn,selectConstraint:mn,selectOverlap:mn,selectAllow:mn,droppable:Boolean,unselectCancel:String,slotLabelFormat:mn,slotLaneClassNames:mn,slotLaneContent:mn,slotLaneDidMount:mn,slotLaneWillUnmount:mn,slotLabelClassNames:mn,slotLabelContent:mn,slotLabelDidMount:mn,slotLabelWillUnmount:mn,dayMaxEvents:mn,dayMaxEventRows:mn,dayMinWidth:Number,slotLabelInterval:tt,allDayText:String,allDayClassNames:mn,allDayContent:mn,allDayDidMount:mn,allDayWillUnmount:mn,slotMinWidth:Number,navLinks:Boolean,eventTimeFormat:on,rerenderDelay:Number,moreLinkText:mn,moreLinkHint:mn,selectMinDistance:Number,selectable:Boolean,selectLongPressDelay:Number,eventLongPressDelay:Number,selectMirror:Boolean,eventMaxStack:Number,eventMinHeight:Number,eventMinWidth:Number,eventShortHeight:Number,slotEventOverlap:Boolean,plugins:mn,firstDay:Number,dayCount:Number,dateAlignment:String,dateIncrement:tt,hiddenDays:mn,monthMode:Boolean,fixedWeekCount:Boolean,validRange:mn,visibleRange:mn,titleFormat:mn,eventInteractive:Boolean,noEventsText:String,viewHint:mn,navLinkHint:mn,closeHint:String,timeHint:String,eventHint:String,moreLinkClick:mn,moreLinkClassNames:mn,moreLinkContent:mn,moreLinkDidMount:mn,moreLinkWillUnmount:mn,handleCustomRendering:mn,customRenderingMetaMap:mn,customRenderingReplacesEl:Boolean},ln={eventDisplay:"auto",defaultRangeSeparator:" - ",titleRangeSeparator:" – ",defaultTimedEventDuration:"01:00:00",defaultAllDayEventDuration:{day:1},forceEventDuration:!1,nextDayThreshold:"00:00:00",dayHeaders:!0,initialView:"",aspectRatio:1.35,headerToolbar:{start:"title",center:"",end:"today prev,next"},weekends:!0,weekNumbers:!1,weekNumberCalculation:"local",editable:!1,nowIndicator:!1,scrollTime:"06:00:00",scrollTimeReset:!0,slotMinTime:"00:00:00",slotMaxTime:"24:00:00",showNonCurrentDates:!0,lazyFetching:!0,startParam:"start",endParam:"end",timeZoneParam:"timeZone",timeZone:"local",locales:[],locale:"",themeSystem:"standard",dragRevertDuration:500,dragScroll:!0,allDayMaintainDuration:!1,unselectAuto:!0,dropAccept:"*",eventOrder:"start,-duration,allDay,title",dayPopoverFormat:{month:"long",day:"numeric",year:"numeric"},handleWindowResize:!0,windowResizeDelay:100,longPressDelay:1e3,eventDragMinDistance:5,expandRows:!1,navLinks:!1,selectable:!1,eventMinHeight:15,eventMinWidth:30,eventShortHeight:30},cn={datesSet:mn,eventsSet:mn,eventAdd:mn,eventChange:mn,eventRemove:mn,windowResize:mn,eventClick:mn,eventMouseEnter:mn,eventMouseLeave:mn,select:mn,unselect:mn,loading:mn,_unmount:mn,_beforeprint:mn,_afterprint:mn,_noEventDrop:mn,_noEventResize:mn,_resize:mn,_scrollRequest:mn},dn={buttonText:mn,buttonHints:mn,views:mn,plugins:mn,initialEvents:mn,events:mn,eventSources:mn},un={headerToolbar:hn,footerToolbar:hn,buttonText:hn,buttonHints:hn,buttonIcons:hn,dateIncrement:hn};function hn(e,t){return"object"==typeof e&&"object"==typeof t&&e&&t?pt(e,t):e===t}const fn={type:String,component:mn,buttonText:String,buttonTextKey:String,dateProfileGeneratorClass:mn,usesMinMaxTime:Boolean,classNames:mn,content:mn,didMount:mn,willUnmount:mn};function gn(e){return dt(e,un)}function pn(e,t){let n={},r={};for(let r in t)r in e&&(n[r]=t[r](e[r]));for(let n in e)n in t||(r[n]=e[n]);return{refined:n,extra:r}}function mn(e){return e}function vn(e,t,n,r){return{instanceId:Be(),defId:e,range:t,forcedStartTzo:null==n?null:n,forcedEndTzo:null==r?null:r}}function bn(e,t,n){let{dateEnv:r,pluginHooks:i,options:s}=n,{defs:o,instances:a}=e;a=ut(a,e=>!o[e.defId].recurringDef);for(let e in o){let n=o[e];if(n.recurringDef){let{duration:o}=n.recurringDef;o||(o=n.allDay?s.defaultAllDayEventDuration:s.defaultTimedEventDuration);let l=yn(n,o,t,r,i.recurringTypes);for(let t of l){let n=vn(e,{start:t,end:r.add(t,o)});a[n.instanceId]=n}}}return{defs:o,instances:a}}function yn(e,t,n,r,i){let s=i[e.recurringDef.typeId].expand(e.recurringDef.typeData,{start:r.subtract(n.start,t),end:n.end},r);return e.allDay&&(s=s.map(kt)),s}function En(e,t,n,r){let i={defs:{},instances:{}},s=Bn(n);for(let o of e){let e=Pn(o,t,n,r,s);e&&An(e,i)}return i}function An(e,t={defs:{},instances:{}}){return t.defs[e.def.defId]=e.def,e.instance&&(t.instances[e.instance.instanceId]=e.instance),t}function Dn(e,t){let n=e.instances[t];if(n){let t=e.defs[n.defId],r=Cn(e,e=>{return n=t,r=e,Boolean(n.groupId&&n.groupId===r.groupId);var n,r});return r.defs[t.defId]=t,r.instances[n.instanceId]=n,r}return{defs:{},instances:{}}}function Sn(){return{defs:{},instances:{}}}function wn(e,t){return{defs:Object.assign(Object.assign({},e.defs),t.defs),instances:Object.assign(Object.assign({},e.instances),t.instances)}}function Cn(e,t){let n=ut(e.defs,t),r=ut(e.instances,e=>n[e.defId]);return{defs:n,instances:r}}function Rn(e){return Array.isArray(e)?e:"string"==typeof e?e.split(/\s+/):[]}const xn={display:String,editable:Boolean,startEditable:Boolean,durationEditable:Boolean,constraint:mn,overlap:mn,allow:mn,className:Rn,classNames:Rn,color:String,backgroundColor:String,borderColor:String,textColor:String},_n={display:null,startEditable:null,durationEditable:null,constraints:[],overlap:null,allows:[],backgroundColor:"",borderColor:"",textColor:"",classNames:[]};function Tn(e,t){let n=function(e,t){return Array.isArray(e)?En(e,null,t,!0):"object"==typeof e&&e?En([e],null,t,!0):null!=e?String(e):null}(e.constraint,t);return{display:e.display||null,startEditable:null!=e.startEditable?e.startEditable:e.editable,durationEditable:null!=e.durationEditable?e.durationEditable:e.editable,constraints:null!=n?[n]:[],overlap:null!=e.overlap?e.overlap:null,allows:null!=e.allow?[e.allow]:[],backgroundColor:e.backgroundColor||e.color||"",borderColor:e.borderColor||e.color||"",textColor:e.textColor||"",classNames:(e.className||[]).concat(e.classNames||[])}}function kn(e){return e.reduce(Mn,_n)}function Mn(e,t){return{display:null!=t.display?t.display:e.display,startEditable:null!=t.startEditable?t.startEditable:e.startEditable,durationEditable:null!=t.durationEditable?t.durationEditable:e.durationEditable,constraints:e.constraints.concat(t.constraints),overlap:"boolean"==typeof t.overlap?t.overlap:e.overlap,allows:e.allows.concat(t.allows),backgroundColor:t.backgroundColor||e.backgroundColor,borderColor:t.borderColor||e.borderColor,textColor:t.textColor||e.textColor,classNames:e.classNames.concat(t.classNames)}}const In={id:String,groupId:String,title:String,url:String,interactive:Boolean},On={start:mn,end:mn,date:mn,allDay:Boolean},Nn=Object.assign(Object.assign(Object.assign({},In),On),{extendedProps:mn});function Pn(e,t,n,r,i=Bn(n)){let{refined:s,extra:o}=Hn(e,n,i),a=function(e,t){let n=null;e&&(n=e.defaultAllDay);null==n&&(n=t.options.defaultAllDay);return n}(t,n),l=function(e,t,n,r){for(let i=0;i<r.length;i+=1){let s=r[i].parse(e,n);if(s){let{allDay:n}=e;return null==n&&(n=t,null==n&&(n=s.allDayGuess,null==n&&(n=!1))),{allDay:n,duration:s.duration,typeData:s.typeData,typeId:i}}}return null}(s,a,n.dateEnv,n.pluginHooks.recurringTypes);if(l){let e=jn(s,o,t?t.sourceId:"",l.allDay,Boolean(l.duration),n);return e.recurringDef={typeId:l.typeId,typeData:l.typeData,duration:l.duration},{def:e,instance:null}}let c=function(e,t,n,r){let i,s,{allDay:o}=e,a=null,l=!1,c=null,d=null!=e.start?e.start:e.date;if(i=n.dateEnv.createMarkerMeta(d),i)a=i.marker;else if(!r)return null;null!=e.end&&(s=n.dateEnv.createMarkerMeta(e.end));null==o&&(o=null!=t?t:(!i||i.isTimeUnspecified)&&(!s||s.isTimeUnspecified));o&&a&&(a=kt(a));s&&(c=s.marker,o&&(c=kt(c)),a&&c<=a&&(c=null));c?l=!0:r||(l=n.options.forceEventDuration||!1,c=n.dateEnv.add(a,o?n.options.defaultAllDayEventDuration:n.options.defaultTimedEventDuration));return{allDay:o,hasEnd:l,range:{start:a,end:c},forcedStartTzo:i?i.forcedTzo:null,forcedEndTzo:s?s.forcedTzo:null}}(s,a,n,r);if(c){let e=jn(s,o,t?t.sourceId:"",c.allDay,c.hasEnd,n);return{def:e,instance:vn(e.defId,c.range,c.forcedStartTzo,c.forcedEndTzo)}}return null}function Hn(e,t,n=Bn(t)){return pn(e,n)}function Bn(e){return Object.assign(Object.assign(Object.assign({},xn),Nn),e.pluginHooks.eventRefiners)}function jn(e,t,n,r,i,s){let o={title:e.title||"",groupId:e.groupId||"",publicId:e.id||"",url:e.url||"",recurringDef:null,defId:Be(),sourceId:n,allDay:r,hasEnd:i,interactive:e.interactive,ui:Tn(e,s),extendedProps:Object.assign(Object.assign({},e.extendedProps||{}),t)};for(let t of s.pluginHooks.eventDefMemberAdders)Object.assign(o,t(e));return Object.freeze(o.ui.classNames),Object.freeze(o.extendedProps),o}const zn={startTime:"09:00",endTime:"17:00",daysOfWeek:[1,2,3,4,5],display:"inverse-background",classNames:"fc-non-business",groupId:"_businessHours"};function Un(e,t){return En(function(e){let t;t=!0===e?[{}]:Array.isArray(e)?e.filter(e=>e.daysOfWeek):"object"==typeof e&&e?[e]:[];return t=t.map(e=>Object.assign(Object.assign({},zn),e)),t}(e),null,t)}function Ln(e){let t=Math.floor(Rt(e.start,e.end))||1,n=kt(e.start);return{start:n,end:St(n,t)}}function Wn(e,t=tt(0)){let n=null,r=null;if(e.end){r=kt(e.end);let n=e.end.valueOf()-r.valueOf();n&&n>=ot(t)&&(r=St(r,1))}return e.start&&(n=kt(e.start),r&&r<=n&&(r=St(n,1))),{start:n,end:r}}function Fn(e){let t=Wn(e);return Rt(t.start,t.end)>1}function Vn(e,t,n,r){return"year"===r?tt(n.diffWholeYears(e,t),"year"):"month"===r?tt(n.diffWholeMonths(e,t),"month"):xt(e,t)}function Gn(e,t){return e.left>=t.left&&e.left<t.right&&e.top>=t.top&&e.top<t.bottom}function Qn(e,t){let n={left:Math.max(e.left,t.left),right:Math.min(e.right,t.right),top:Math.max(e.top,t.top),bottom:Math.min(e.bottom,t.bottom)};return n.left<n.right&&n.top<n.bottom&&n}function qn(e,t){return{left:Math.min(Math.max(e.left,t.left),t.right),top:Math.min(Math.max(e.top,t.top),t.bottom)}}function Yn(e){return{left:(e.left+e.right)/2,top:(e.top+e.bottom)/2}}function Zn(e,t){return{left:e.left-t.left,top:e.top-t.top}}let Xn;function Jn(){return null==Xn&&(Xn=function(){if("undefined"==typeof document)return!0;let e=document.createElement("div");e.style.position="absolute",e.style.top="0px",e.style.left="0px",e.innerHTML="<table><tr><td><div></div></td></tr></table>",e.querySelector("table").style.height="100px",e.querySelector("div").style.height="100%",document.body.appendChild(e);let t=e.querySelector("div").offsetHeight>0;return document.body.removeChild(e),t}()),Xn}const $n={defs:{},instances:{}};class Kn{constructor(){this.getKeysForEventDefs=Vt(this._getKeysForEventDefs),this.splitDateSelection=Vt(this._splitDateSpan),this.splitEventStore=Vt(this._splitEventStore),this.splitIndividualUi=Vt(this._splitIndividualUi),this.splitEventDrag=Vt(this._splitInteraction),this.splitEventResize=Vt(this._splitInteraction),this.eventUiBuilders={}}splitProps(e){let t=this.getKeyInfo(e),n=this.getKeysForEventDefs(e.eventStore),r=this.splitDateSelection(e.dateSelection),i=this.splitIndividualUi(e.eventUiBases,n),s=this.splitEventStore(e.eventStore,n),o=this.splitEventDrag(e.eventDrag),a=this.splitEventResize(e.eventResize),l={};this.eventUiBuilders=ht(t,(e,t)=>this.eventUiBuilders[t]||Vt(er));for(let n in t){let c=t[n],d=s[n]||$n,u=this.eventUiBuilders[n];l[n]={businessHours:c.businessHours||e.businessHours,dateSelection:r[n]||null,eventStore:d,eventUiBases:u(e.eventUiBases[""],c.ui,i[n]),eventSelection:d.instances[e.eventSelection]?e.eventSelection:"",eventDrag:o[n]||null,eventResize:a[n]||null}}return l}_splitDateSpan(e){let t={};if(e){let n=this.getKeysForDateSpan(e);for(let r of n)t[r]=e}return t}_getKeysForEventDefs(e){return ht(e.defs,e=>this.getKeysForEventDef(e))}_splitEventStore(e,t){let{defs:n,instances:r}=e,i={};for(let e in n)for(let r of t[e])i[r]||(i[r]={defs:{},instances:{}}),i[r].defs[e]=n[e];for(let e in r){let n=r[e];for(let r of t[n.defId])i[r]&&(i[r].instances[e]=n)}return i}_splitIndividualUi(e,t){let n={};for(let r in e)if(r)for(let i of t[r])n[i]||(n[i]={}),n[i][r]=e[r];return n}_splitInteraction(e){let t={};if(e){let n=this._splitEventStore(e.affectedEvents,this._getKeysForEventDefs(e.affectedEvents)),r=this._getKeysForEventDefs(e.mutatedEvents),i=this._splitEventStore(e.mutatedEvents,r),s=r=>{t[r]||(t[r]={affectedEvents:n[r]||$n,mutatedEvents:i[r]||$n,isEvent:e.isEvent})};for(let e in n)s(e);for(let e in i)s(e)}return t}}function er(e,t,n){let r=[];e&&r.push(e),t&&r.push(t);let i={"":kn(r)};return n&&Object.assign(i,n),i}function tr(e,t){let n,r,i=[],{start:s}=t;for(e.sort(nr),n=0;n<e.length;n+=1)r=e[n],r.start>s&&i.push({start:s,end:r.start}),r.end>s&&(s=r.end);return s<t.end&&i.push({start:s,end:t.end}),i}function nr(e,t){return e.start.valueOf()-t.start.valueOf()}function rr(e,t){let{start:n,end:r}=e,i=null;return null!==t.start&&(n=null===n?t.start:new Date(Math.max(n.valueOf(),t.start.valueOf()))),null!=t.end&&(r=null===r?t.end:new Date(Math.min(r.valueOf(),t.end.valueOf()))),(null===n||null===r||n<r)&&(i={start:n,end:r}),i}function ir(e,t){return(null===e.start?null:e.start.valueOf())===(null===t.start?null:t.start.valueOf())&&(null===e.end?null:e.end.valueOf())===(null===t.end?null:t.end.valueOf())}function sr(e,t){return(null===e.end||null===t.start||e.end>t.start)&&(null===e.start||null===t.end||e.start<t.end)}function or(e,t){return(null===e.start||null!==t.start&&t.start>=e.start)&&(null===e.end||null!==t.end&&t.end<=e.end)}function ar(e,t){return(null===e.start||t>=e.start)&&(null===e.end||t<e.end)}function lr(e,t,n,r){return{dow:e.getUTCDay(),isDisabled:Boolean(r&&!ar(r.activeRange,e)),isOther:Boolean(r&&!ar(r.currentRange,e)),isToday:Boolean(t&&ar(t,e)),isPast:Boolean(n?e<n:!!t&&e<t.start),isFuture:Boolean(n?e>n:!!t&&e>=t.end)}}function cr(e,t){let n=["fc-day","fc-day-"+At[e.dow]];return e.isDisabled?n.push("fc-day-disabled"):(e.isToday&&(n.push("fc-day-today"),n.push(t.getClass("today"))),e.isPast&&n.push("fc-day-past"),e.isFuture&&n.push("fc-day-future"),e.isOther&&n.push("fc-day-other")),n}const dr=on({year:"numeric",month:"long",day:"numeric"}),ur=on({week:"long"});function hr(e,t,n="day",r=!0){const{dateEnv:i,options:s,calendarApi:o}=e;let a=i.format(t,"week"===n?ur:dr);if(s.navLinks){let e=i.toDate(t);const l=e=>{let r="day"===n?s.navLinkDayClick:"week"===n?s.navLinkWeekClick:null;"function"==typeof r?r.call(o,i.toDate(t),e):("string"==typeof r&&(n=r),o.zoomTo(t,n))};return Object.assign({title:Ze(s.navLinkHint,[a,e],a),"data-navlink":""},r?Ne(l):{onClick:l})}return{"aria-label":a}}let fr,gr=null;function pr(){return null===gr&&(gr=function(){let e=document.createElement("div");we(e,{position:"absolute",top:-1e3,left:0,border:0,padding:0,overflow:"scroll",direction:"rtl"}),e.innerHTML="<div></div>",document.body.appendChild(e);let t=e.firstChild.getBoundingClientRect().left>e.getBoundingClientRect().left;return ye(e),t}()),gr}function mr(){return fr||(fr=function(){let e=document.createElement("div");e.style.overflow="scroll",e.style.position="absolute",e.style.top="-9999px",e.style.left="-9999px",document.body.appendChild(e);let t=vr(e);return document.body.removeChild(e),t}()),fr}function vr(e){return{x:e.offsetHeight-e.clientHeight,y:e.offsetWidth-e.clientWidth}}function br(e,t=!1){let n=window.getComputedStyle(e),r=parseInt(n.borderLeftWidth,10)||0,i=parseInt(n.borderRightWidth,10)||0,s=parseInt(n.borderTopWidth,10)||0,o=parseInt(n.borderBottomWidth,10)||0,a=vr(e),l=a.y-r-i,c={borderLeft:r,borderRight:i,borderTop:s,borderBottom:o,scrollbarBottom:a.x-s-o,scrollbarLeft:0,scrollbarRight:0};return pr()&&"rtl"===n.direction?c.scrollbarLeft=l:c.scrollbarRight=l,t&&(c.paddingLeft=parseInt(n.paddingLeft,10)||0,c.paddingRight=parseInt(n.paddingRight,10)||0,c.paddingTop=parseInt(n.paddingTop,10)||0,c.paddingBottom=parseInt(n.paddingBottom,10)||0),c}function yr(e,t=!1,n){let r=n?e.getBoundingClientRect():Er(e),i=br(e,t),s={left:r.left+i.borderLeft+i.scrollbarLeft,right:r.right-i.borderRight-i.scrollbarRight,top:r.top+i.borderTop,bottom:r.bottom-i.borderBottom-i.scrollbarBottom};return t&&(s.left+=i.paddingLeft,s.right-=i.paddingRight,s.top+=i.paddingTop,s.bottom-=i.paddingBottom),s}function Er(e){let t=e.getBoundingClientRect();return{left:t.left+window.pageXOffset,top:t.top+window.pageYOffset,right:t.right+window.pageXOffset,bottom:t.bottom+window.pageYOffset}}function Ar(e){let t=[];for(;e instanceof HTMLElement;){let n=window.getComputedStyle(e);if("fixed"===n.position)break;/(auto|scroll)/.test(n.overflow+n.overflowY+n.overflowX)&&t.push(e),e=e.parentNode}return t}function Dr(e,t,n){let r=!1,i=function(e){r||(r=!0,t(e))},s=function(e){r||(r=!0,n(e))},o=e(i,s);o&&"function"==typeof o.then&&o.then(i,s)}class Sr{constructor(){this.handlers={},this.thisContext=null}setThisContext(e){this.thisContext=e}setOptions(e){this.options=e}on(e,t){!function(e,t,n){(e[t]||(e[t]=[])).push(n)}(this.handlers,e,t)}off(e,t){!function(e,t,n){n?e[t]&&(e[t]=e[t].filter(e=>e!==n)):delete e[t]}(this.handlers,e,t)}trigger(e,...t){let n=this.handlers[e]||[],r=this.options&&this.options[e],i=[].concat(r||[],n);for(let e of i)e.apply(this.thisContext,t)}hasHandlers(e){return Boolean(this.handlers[e]&&this.handlers[e].length||this.options&&this.options[e])}}class wr{constructor(e,t,n,r){this.els=t;let i=this.originClientRect=e.getBoundingClientRect();n&&this.buildElHorizontals(i.left),r&&this.buildElVerticals(i.top)}buildElHorizontals(e){let t=[],n=[];for(let r of this.els){let i=r.getBoundingClientRect();t.push(i.left-e),n.push(i.right-e)}this.lefts=t,this.rights=n}buildElVerticals(e){let t=[],n=[];for(let r of this.els){let i=r.getBoundingClientRect();t.push(i.top-e),n.push(i.bottom-e)}this.tops=t,this.bottoms=n}leftToIndex(e){let t,{lefts:n,rights:r}=this,i=n.length;for(t=0;t<i;t+=1)if(e>=n[t]&&e<r[t])return t}topToIndex(e){let t,{tops:n,bottoms:r}=this,i=n.length;for(t=0;t<i;t+=1)if(e>=n[t]&&e<r[t])return t}getWidth(e){return this.rights[e]-this.lefts[e]}getHeight(e){return this.bottoms[e]-this.tops[e]}similarTo(e){return Cr(this.tops||[],e.tops||[])&&Cr(this.bottoms||[],e.bottoms||[])&&Cr(this.lefts||[],e.lefts||[])&&Cr(this.rights||[],e.rights||[])}}function Cr(e,t){const n=e.length;if(n!==t.length)return!1;for(let r=0;r<n;r++)if(Math.round(e[r])!==Math.round(t[r]))return!1;return!0}class Rr{getMaxScrollTop(){return this.getScrollHeight()-this.getClientHeight()}getMaxScrollLeft(){return this.getScrollWidth()-this.getClientWidth()}canScrollVertically(){return this.getMaxScrollTop()>0}canScrollHorizontally(){return this.getMaxScrollLeft()>0}canScrollUp(){return this.getScrollTop()>0}canScrollDown(){return this.getScrollTop()<this.getMaxScrollTop()}canScrollLeft(){return this.getScrollLeft()>0}canScrollRight(){return this.getScrollLeft()<this.getMaxScrollLeft()}}class xr extends Rr{constructor(e){super(),this.el=e}getScrollTop(){return this.el.scrollTop}getScrollLeft(){return this.el.scrollLeft}setScrollTop(e){this.el.scrollTop=e}setScrollLeft(e){this.el.scrollLeft=e}getScrollWidth(){return this.el.scrollWidth}getScrollHeight(){return this.el.scrollHeight}getClientHeight(){return this.el.clientHeight}getClientWidth(){return this.el.clientWidth}}class _r extends Rr{getScrollTop(){return window.pageYOffset}getScrollLeft(){return window.pageXOffset}setScrollTop(e){window.scroll(window.pageXOffset,e)}setScrollLeft(e){window.scroll(e,window.pageYOffset)}getScrollWidth(){return document.documentElement.scrollWidth}getScrollHeight(){return document.documentElement.scrollHeight}getClientHeight(){return document.documentElement.clientHeight}getClientWidth(){return document.documentElement.clientWidth}}class Tr{constructor(e){this.iconOverrideOption&&this.setIconOverride(e[this.iconOverrideOption])}setIconOverride(e){let t,n;if("object"==typeof e&&e){for(n in t=Object.assign({},this.iconClasses),e)t[n]=this.applyIconOverridePrefix(e[n]);this.iconClasses=t}else!1===e&&(this.iconClasses={})}applyIconOverridePrefix(e){let t=this.iconOverridePrefix;return t&&0!==e.indexOf(t)&&(e=t+e),e}getClass(e){return this.classes[e]||""}getIconClass(e,t){let n;return n=t&&this.rtlIconClasses&&this.rtlIconClasses[e]||this.iconClasses[e],n?`${this.baseIconClass} ${n}`:""}getCustomButtonIconClass(e){let t;return this.iconOverrideCustomButtonOption&&(t=e[this.iconOverrideCustomButtonOption],t)?`${this.baseIconClass} ${this.applyIconOverridePrefix(t)}`:""}}function kr(e){e();let t=n.debounceRendering,r=[];for(n.debounceRendering=function(e){r.push(e)},P(f(Mr,{}),document.createElement("div"));r.length;)r.shift()();n.debounceRendering=t}Tr.prototype.classes={},Tr.prototype.iconClasses={},Tr.prototype.baseIconClass="",Tr.prototype.iconOverridePrefix="";class Mr extends m{render(){return f("div",{})}componentDidMount(){this.setState({})}}function Ir(e){let t=function(e,t){var n={__c:t="__cC"+a++,__:e,Consumer:function(e,t){return e.children(t)},Provider:function(e){var n,r;return this.getChildContext||(n=[],(r={})[t]=this,this.getChildContext=function(){return r},this.shouldComponentUpdate=function(e){this.props.value!==e.value&&n.some(y)},this.sub=function(e){n.push(e);var t=e.componentWillUnmount;e.componentWillUnmount=function(){n.splice(n.indexOf(e),1),t&&t.call(e)}}),e.children}};return n.Provider.__=n.Consumer.contextType=n}(e),n=t.Provider;return t.Provider=function(){let e=!this.getChildContext,t=n.apply(this,arguments);if(e){let e=[];this.shouldComponentUpdate=t=>{this.props.value!==t.value&&e.forEach(e=>{e.context=t.value,e.forceUpdate()})},this.sub=t=>{e.push(t);let n=t.componentWillUnmount;t.componentWillUnmount=()=>{e.splice(e.indexOf(t),1),n&&n.call(t)}}}return t},t}class Or{constructor(e,t,n,r){this.execFunc=e,this.emitter=t,this.scrollTime=n,this.scrollTimeReset=r,this.handleScrollRequest=e=>{this.queuedRequest=Object.assign({},this.queuedRequest||{},e),this.drain()},t.on("_scrollRequest",this.handleScrollRequest),this.fireInitialScroll()}detach(){this.emitter.off("_scrollRequest",this.handleScrollRequest)}update(e){e&&this.scrollTimeReset?this.fireInitialScroll():this.drain()}fireInitialScroll(){this.handleScrollRequest({time:this.scrollTime})}drain(){this.queuedRequest&&this.execFunc(this.queuedRequest)&&(this.queuedRequest=null)}}const Nr=Ir({});function Pr(e,t,n,r,i,s,o,a,l,c,d,u,h){return{dateEnv:i,options:n,pluginHooks:o,emitter:c,dispatch:a,getCurrentData:l,calendarApi:d,viewSpec:e,viewApi:t,dateProfileGenerator:r,theme:s,isRtl:"rtl"===n.direction,addResizeHandler(e){c.on("_resize",e)},removeResizeHandler(e){c.off("_resize",e)},createScrollResponder:e=>new Or(e,c,tt(n.scrollTime),n.scrollTimeReset),registerInteractiveComponent:u,unregisterInteractiveComponent:h}}class Hr extends m{shouldComponentUpdate(e,t){return this.debug&&console.log(vt(e,this.props),vt(t,this.state)),!bt(this.props,e,this.propEquality)||!bt(this.state,t,this.stateEquality)}safeSetState(e){bt(this.state,Object.assign(Object.assign({},this.state),e),this.stateEquality)||this.setState(e)}}Hr.addPropsEquality=function(e){let t=Object.create(this.prototype.propEquality);Object.assign(t,e),this.prototype.propEquality=t},Hr.addStateEquality=function(e){let t=Object.create(this.prototype.stateEquality);Object.assign(t,e),this.prototype.stateEquality=t},Hr.contextType=Nr,Hr.prototype.propEquality={},Hr.prototype.stateEquality={};class Br extends Hr{}function jr(e,t){"function"==typeof e?e(t):e&&(e.current=t)}Br.contextType=Nr;class zr extends Br{constructor(){super(...arguments),this.uid=Be()}prepareHits(){}queryHit(e,t,n,r){return null}isValidSegDownEl(e){return!this.props.eventDrag&&!this.props.eventResize&&!Ee(e,".fc-event-mirror")}isValidDateDownEl(e){return!(Ee(e,".fc-event:not(.fc-bg-event)")||Ee(e,".fc-more-link")||Ee(e,"a[data-navlink]")||Ee(e,".fc-popover"))}}function Ur(e,t){return"function"==typeof e&&(e=e()),null==e?t.createNowMarker():t.createMarker(e)}class Lr{constructor(e){this.props=e,this.nowDate=Ur(e.nowInput,e.dateEnv),this.initHiddenDays()}buildPrev(e,t,n){let{dateEnv:r}=this.props,i=r.subtract(r.startOf(t,e.currentRangeUnit),e.dateIncrement);return this.build(i,-1,n)}buildNext(e,t,n){let{dateEnv:r}=this.props,i=r.add(r.startOf(t,e.currentRangeUnit),e.dateIncrement);return this.build(i,1,n)}build(e,t,n=!0){let r,i,s,o,a,l,{props:c}=this;var d,u;return r=this.buildValidRange(),r=this.trimHiddenDays(r),n&&(d=e,e=null!=(u=r).start&&d<u.start?u.start:null!=u.end&&d>=u.end?new Date(u.end.valueOf()-1):d),i=this.buildCurrentRangeInfo(e,t),s=/^(year|month|week|day)$/.test(i.unit),o=this.buildRenderRange(this.trimHiddenDays(i.range),i.unit,s),o=this.trimHiddenDays(o),a=o,c.showNonCurrentDates||(a=rr(a,i.range)),a=this.adjustActiveRange(a),a=rr(a,r),l=sr(i.range,r),{validRange:r,currentRange:i.range,currentRangeUnit:i.unit,isRangeAllDay:s,activeRange:a,renderRange:o,slotMinTime:c.slotMinTime,slotMaxTime:c.slotMaxTime,isValid:l,dateIncrement:this.buildDateIncrement(i.duration)}}buildValidRange(){let e=this.props.validRangeInput,t="function"==typeof e?e.call(this.props.calendarApi,this.nowDate):e;return this.refineRange(t)||{start:null,end:null}}buildCurrentRangeInfo(e,t){let n,{props:r}=this,i=null,s=null,o=null;return r.duration?(i=r.duration,s=r.durationUnit,o=this.buildRangeFromDuration(e,t,i,s)):(n=this.props.dayCount)?(s="day",o=this.buildRangeFromDayCount(e,t,n)):(o=this.buildCustomVisibleRange(e))?s=r.dateEnv.greatestWholeUnit(o.start,o.end).unit:(i=this.getFallbackDuration(),s=lt(i).unit,o=this.buildRangeFromDuration(e,t,i,s)),{duration:i,unit:s,range:o}}getFallbackDuration(){return tt({day:1})}adjustActiveRange(e){let{dateEnv:t,usesMinMaxTime:n,slotMinTime:r,slotMaxTime:i}=this.props,{start:s,end:o}=e;return n&&(st(r)<0&&(s=kt(s),s=t.add(s,r)),st(i)>1&&(o=kt(o),o=St(o,-1),o=t.add(o,i))),{start:s,end:o}}buildRangeFromDuration(e,t,n,r){let i,s,o,{dateEnv:a,dateAlignment:l}=this.props;if(!l){let{dateIncrement:e}=this.props;l=e&&ot(e)<ot(n)?lt(e).unit:r}function c(){i=a.startOf(e,l),s=a.add(i,n),o={start:i,end:s}}return st(n)<=1&&this.isHiddenDay(i)&&(i=this.skipHiddenDays(i,t),i=kt(i)),c(),this.trimHiddenDays(o)||(e=this.skipHiddenDays(e,t),c()),o}buildRangeFromDayCount(e,t,n){let r,{dateEnv:i,dateAlignment:s}=this.props,o=0,a=e;s&&(a=i.startOf(a,s)),a=kt(a),a=this.skipHiddenDays(a,t),r=a;do{r=St(r,1),this.isHiddenDay(r)||(o+=1)}while(o<n);return{start:a,end:r}}buildCustomVisibleRange(e){let{props:t}=this,n=t.visibleRangeInput,r="function"==typeof n?n.call(t.calendarApi,t.dateEnv.toDate(e)):n,i=this.refineRange(r);return!i||null!=i.start&&null!=i.end?i:null}buildRenderRange(e,t,n){return e}buildDateIncrement(e){let t,{dateIncrement:n}=this.props;return n||((t=this.props.dateAlignment)?tt(1,t):e||tt({days:1}))}refineRange(e){if(e){let t=function(e,t){let n=null,r=null;return e.start&&(n=t.createMarker(e.start)),e.end&&(r=t.createMarker(e.end)),n||r?n&&r&&r<n?null:{start:n,end:r}:null}(e,this.props.dateEnv);return t&&(t=Wn(t)),t}return null}initHiddenDays(){let e,t=this.props.hiddenDays||[],n=[],r=0;for(!1===this.props.weekends&&t.push(0,6),e=0;e<7;e+=1)(n[e]=-1!==t.indexOf(e))||(r+=1);if(!r)throw new Error("invalid hiddenDays");this.isHiddenDayHash=n}trimHiddenDays(e){let{start:t,end:n}=e;return t&&(t=this.skipHiddenDays(t)),n&&(n=this.skipHiddenDays(n,-1,!0)),null==t||null==n||t<n?{start:t,end:n}:null}isHiddenDay(e){return e instanceof Date&&(e=e.getUTCDay()),this.isHiddenDayHash[e]}skipHiddenDays(e,t=1,n=!1){for(;this.isHiddenDayHash[(e.getUTCDay()+(n?t:0)+7)%7];)e=St(e,t);return e}}function Wr(e,t,n){n.emitter.trigger("select",Object.assign(Object.assign({},Fr(e,n)),{jsEvent:t?t.origEvent:null,view:n.viewApi||n.calendarApi.view}))}function Fr(e,t){let n={};for(let r of t.pluginHooks.dateSpanTransforms)Object.assign(n,r(e,t));var r,i;return Object.assign(n,(r=e,i=t.dateEnv,Object.assign(Object.assign({},bi(r.range,i,r.allDay)),{allDay:r.allDay}))),n}function Vr(e,t,n){let{dateEnv:r,options:i}=n,s=t;return e?(s=kt(s),s=r.add(s,i.defaultAllDayEventDuration)):s=r.add(s,i.defaultTimedEventDuration),s}function Gr(e,t,n,r){let i=ni(e.defs,t),s={defs:{},instances:{}};for(let t in e.defs){let o=e.defs[t];s.defs[t]=Qr(o,i[t],n,r)}for(let t in e.instances){let o=e.instances[t],a=s.defs[o.defId];s.instances[t]=qr(o,a,i[o.defId],n,r)}return s}function Qr(e,t,n,r){let i=n.standardProps||{};null==i.hasEnd&&t.durationEditable&&(n.startDelta||n.endDelta)&&(i.hasEnd=!0);let s=Object.assign(Object.assign(Object.assign({},e),i),{ui:Object.assign(Object.assign({},e.ui),i.ui)});n.extendedProps&&(s.extendedProps=Object.assign(Object.assign({},s.extendedProps),n.extendedProps));for(let e of r.pluginHooks.eventDefMutationAppliers)e(s,n,r);return!s.hasEnd&&r.options.forceEventDuration&&(s.hasEnd=!0),s}function qr(e,t,n,r,i){let{dateEnv:s}=i,o=r.standardProps&&!0===r.standardProps.allDay,a=r.standardProps&&!1===r.standardProps.hasEnd,l=Object.assign({},e);return o&&(l.range=Ln(l.range)),r.datesDelta&&n.startEditable&&(l.range={start:s.add(l.range.start,r.datesDelta),end:s.add(l.range.end,r.datesDelta)}),r.startDelta&&n.durationEditable&&(l.range={start:s.add(l.range.start,r.startDelta),end:l.range.end}),r.endDelta&&n.durationEditable&&(l.range={start:l.range.start,end:s.add(l.range.end,r.endDelta)}),a&&(l.range={start:l.range.start,end:Vr(t.allDay,l.range.start,i)}),t.allDay&&(l.range={start:kt(l.range.start),end:kt(l.range.end)}),l.range.end<l.range.start&&(l.range.end=Vr(t.allDay,l.range.start,i)),l}class Yr{constructor(e,t){this.context=e,this.internalEventSource=t}remove(){this.context.dispatch({type:"REMOVE_EVENT_SOURCE",sourceId:this.internalEventSource.sourceId})}refetch(){this.context.dispatch({type:"FETCH_EVENT_SOURCES",sourceIds:[this.internalEventSource.sourceId],isRefetch:!0})}get id(){return this.internalEventSource.publicId}get url(){return this.internalEventSource.meta.url}get format(){return this.internalEventSource.meta.format}}class Zr{constructor(e,t,n){this._context=e,this._def=t,this._instance=n||null}setProp(e,t){if(e in On)console.warn("Could not set date-related prop 'name'. Use one of the date-related methods instead.");else if("id"===e)t=In[e](t),this.mutate({standardProps:{publicId:t}});else if(e in In)t=In[e](t),this.mutate({standardProps:{[e]:t}});else if(e in xn){let n=xn[e](t);n="color"===e?{backgroundColor:t,borderColor:t}:"editable"===e?{startEditable:t,durationEditable:t}:{[e]:t},this.mutate({standardProps:{ui:n}})}else console.warn(`Could not set prop '${e}'. Use setExtendedProp instead.`)}setExtendedProp(e,t){this.mutate({extendedProps:{[e]:t}})}setStart(e,t={}){let{dateEnv:n}=this._context,r=n.createMarker(e);if(r&&this._instance){let e=Vn(this._instance.range.start,r,n,t.granularity);t.maintainDuration?this.mutate({datesDelta:e}):this.mutate({startDelta:e})}}setEnd(e,t={}){let n,{dateEnv:r}=this._context;if((null==e||(n=r.createMarker(e),n))&&this._instance)if(n){let e=Vn(this._instance.range.end,n,r,t.granularity);this.mutate({endDelta:e})}else this.mutate({standardProps:{hasEnd:!1}})}setDates(e,t,n={}){let r,{dateEnv:i}=this._context,s={allDay:n.allDay},o=i.createMarker(e);var a,l;if(o&&((null==t||(r=i.createMarker(t),r))&&this._instance)){let e=this._instance.range;!0===n.allDay&&(e=Ln(e));let t=Vn(e.start,o,i,n.granularity);if(r){let o=Vn(e.end,r,i,n.granularity);l=o,(a=t).years===l.years&&a.months===l.months&&a.days===l.days&&a.milliseconds===l.milliseconds?this.mutate({datesDelta:t,standardProps:s}):this.mutate({startDelta:t,endDelta:o,standardProps:s})}else s.hasEnd=!1,this.mutate({datesDelta:t,standardProps:s})}}moveStart(e){let t=tt(e);t&&this.mutate({startDelta:t})}moveEnd(e){let t=tt(e);t&&this.mutate({endDelta:t})}moveDates(e){let t=tt(e);t&&this.mutate({datesDelta:t})}setAllDay(e,t={}){let n={allDay:e},{maintainDuration:r}=t;null==r&&(r=this._context.options.allDayMaintainDuration),this._def.allDay!==e&&(n.hasEnd=r),this.mutate({standardProps:n})}formatRange(e){let{dateEnv:t}=this._context,n=this._instance,r=on(e);return this._def.hasEnd?t.formatRange(n.range.start,n.range.end,r,{forcedStartTzo:n.forcedStartTzo,forcedEndTzo:n.forcedEndTzo}):t.format(n.range.start,r,{forcedTzo:n.forcedStartTzo})}mutate(e){let t=this._instance;if(t){let n=this._def,r=this._context,{eventStore:i}=r.getCurrentData(),s=Dn(i,t.instanceId);s=Gr(s,{"":{display:"",startEditable:!0,durationEditable:!0,constraints:[],overlap:null,allows:[],backgroundColor:"",borderColor:"",textColor:"",classNames:[]}},e,r);let o=new Zr(r,n,t);this._def=s.defs[n.defId],this._instance=s.instances[t.instanceId],r.dispatch({type:"MERGE_EVENTS",eventStore:s}),r.emitter.trigger("eventChange",{oldEvent:o,event:this,relatedEvents:Jr(s,r,t),revert(){r.dispatch({type:"RESET_EVENTS",eventStore:i})}})}}remove(){let e=this._context,t=Xr(this);e.dispatch({type:"REMOVE_EVENTS",eventStore:t}),e.emitter.trigger("eventRemove",{event:this,relatedEvents:[],revert(){e.dispatch({type:"MERGE_EVENTS",eventStore:t})}})}get source(){let{sourceId:e}=this._def;return e?new Yr(this._context,this._context.getCurrentData().eventSources[e]):null}get start(){return this._instance?this._context.dateEnv.toDate(this._instance.range.start):null}get end(){return this._instance&&this._def.hasEnd?this._context.dateEnv.toDate(this._instance.range.end):null}get startStr(){let e=this._instance;return e?this._context.dateEnv.formatIso(e.range.start,{omitTime:this._def.allDay,forcedTzo:e.forcedStartTzo}):""}get endStr(){let e=this._instance;return e&&this._def.hasEnd?this._context.dateEnv.formatIso(e.range.end,{omitTime:this._def.allDay,forcedTzo:e.forcedEndTzo}):""}get id(){return this._def.publicId}get groupId(){return this._def.groupId}get allDay(){return this._def.allDay}get title(){return this._def.title}get url(){return this._def.url}get display(){return this._def.ui.display||"auto"}get startEditable(){return this._def.ui.startEditable}get durationEditable(){return this._def.ui.durationEditable}get constraint(){return this._def.ui.constraints[0]||null}get overlap(){return this._def.ui.overlap}get allow(){return this._def.ui.allows[0]||null}get backgroundColor(){return this._def.ui.backgroundColor}get borderColor(){return this._def.ui.borderColor}get textColor(){return this._def.ui.textColor}get classNames(){return this._def.ui.classNames}get extendedProps(){return this._def.extendedProps}toPlainObject(e={}){let t=this._def,{ui:n}=t,{startStr:r,endStr:i}=this,s={};return t.title&&(s.title=t.title),r&&(s.start=r),i&&(s.end=i),t.publicId&&(s.id=t.publicId),t.groupId&&(s.groupId=t.groupId),t.url&&(s.url=t.url),n.display&&"auto"!==n.display&&(s.display=n.display),e.collapseColor&&n.backgroundColor&&n.backgroundColor===n.borderColor?s.color=n.backgroundColor:(n.backgroundColor&&(s.backgroundColor=n.backgroundColor),n.borderColor&&(s.borderColor=n.borderColor)),n.textColor&&(s.textColor=n.textColor),n.classNames.length&&(s.classNames=n.classNames),Object.keys(t.extendedProps).length&&(e.collapseExtendedProps?Object.assign(s,t.extendedProps):s.extendedProps=t.extendedProps),s}toJSON(){return this.toPlainObject()}}function Xr(e){let t=e._def,n=e._instance;return{defs:{[t.defId]:t},instances:n?{[n.instanceId]:n}:{}}}function Jr(e,t,n){let{defs:r,instances:i}=e,s=[],o=n?n.instanceId:"";for(let e in i){let n=i[e],a=r[n.defId];n.instanceId!==o&&s.push(new Zr(t,a,n))}return s}function $r(e,t,n,r){let i={},s={},o={},a=[],l=[],c=ni(e.defs,t);for(let t in e.defs){let n=e.defs[t];"inverse-background"===c[n.defId].display&&(n.groupId?(i[n.groupId]=[],o[n.groupId]||(o[n.groupId]=n)):s[t]=[])}for(let t in e.instances){let o=e.instances[t],d=e.defs[o.defId],u=c[d.defId],h=o.range,f=!d.allDay&&r?Wn(h,r):h,g=rr(f,n);g&&("inverse-background"===u.display?d.groupId?i[d.groupId].push(g):s[o.defId].push(g):"none"!==u.display&&("background"===u.display?a:l).push({def:d,ui:u,instance:o,range:g,isStart:f.start&&f.start.valueOf()===g.start.valueOf(),isEnd:f.end&&f.end.valueOf()===g.end.valueOf()}))}for(let e in i){let t=tr(i[e],n);for(let n of t){let t=o[e],r=c[t.defId];a.push({def:t,ui:r,instance:null,range:n,isStart:!1,isEnd:!1})}}for(let t in s){let r=tr(s[t],n);for(let n of r)a.push({def:e.defs[t],ui:c[t],instance:null,range:n,isStart:!1,isEnd:!1})}return{bg:a,fg:l}}function Kr(e){return"background"===e.ui.display||"inverse-background"===e.ui.display}function ei(e,t){e.fcSeg=t}function ti(e){return e.fcSeg||e.parentNode.fcSeg||null}function ni(e,t){return ht(e,e=>ri(e,t))}function ri(e,t){let n=[];return t[""]&&n.push(t[""]),t[e.defId]&&n.push(t[e.defId]),n.push(e.ui),kn(n)}function ii(e,t){let n=e.map(si);return n.sort((e,n)=>Ge(e,n,t)),n.map(e=>e._seg)}function si(e){let{eventRange:t}=e,n=t.def,r=t.instance?t.instance.range:t.range,i=r.start?r.start.valueOf():0,s=r.end?r.end.valueOf():0;return Object.assign(Object.assign(Object.assign({},n.extendedProps),n),{id:n.publicId,start:i,end:s,duration:s-i,allDay:Number(n.allDay),_seg:e})}function oi(e,t){let{pluginHooks:n}=t,r=n.isDraggableTransformers,{def:i,ui:s}=e.eventRange,o=s.startEditable;for(let e of r)o=e(o,i,s,t);return o}function ai(e,t){return e.isStart&&e.eventRange.ui.durationEditable&&t.options.eventResizableFromStart}function li(e,t){return e.isEnd&&e.eventRange.ui.durationEditable}function ci(e,t,n,r,i,s,o){let{dateEnv:a,options:l}=n,{displayEventTime:c,displayEventEnd:d}=l,u=e.eventRange.def,h=e.eventRange.instance;null==c&&(c=!1!==r),null==d&&(d=!1!==i);let f=h.range.start,g=h.range.end,p=s||e.start||e.eventRange.range.start,m=o||e.end||e.eventRange.range.end,v=kt(f).valueOf()===kt(p).valueOf(),b=kt(wt(g,-1)).valueOf()===kt(wt(m,-1)).valueOf();return c&&!u.allDay&&(v||b)?(p=v?f:p,m=b?g:m,d&&u.hasEnd?a.formatRange(p,m,t,{forcedStartTzo:s?null:h.forcedStartTzo,forcedEndTzo:o?null:h.forcedEndTzo}):a.format(p,t,{forcedTzo:s?null:h.forcedStartTzo})):""}function di(e,t,n){let r=e.eventRange.range;return{isPast:r.end<(n||t.start),isFuture:r.start>=(n||t.end),isToday:t&&ar(t,r.start)}}function ui(e){let t=["fc-event"];return e.isMirror&&t.push("fc-event-mirror"),e.isDraggable&&t.push("fc-event-draggable"),(e.isStartResizable||e.isEndResizable)&&t.push("fc-event-resizable"),e.isDragging&&t.push("fc-event-dragging"),e.isResizing&&t.push("fc-event-resizing"),e.isSelected&&t.push("fc-event-selected"),e.isStart&&t.push("fc-event-start"),e.isEnd&&t.push("fc-event-end"),e.isPast&&t.push("fc-event-past"),e.isToday&&t.push("fc-event-today"),e.isFuture&&t.push("fc-event-future"),t}function hi(e){return e.instance?e.instance.instanceId:`${e.def.defId}:${e.range.start.toISOString()}`}function fi(e,t){let{def:n,instance:r}=e.eventRange,{url:i}=n;if(i)return{href:i};let{emitter:s,options:o}=t,{eventInteractive:a}=o;return null==a&&(a=n.interactive,null==a&&(a=Boolean(s.hasHandlers("eventClick")))),a?Pe(e=>{s.trigger("eventClick",{el:e.target,event:new Zr(t,n,r),jsEvent:e,view:t.viewApi})}):{}}const gi={start:mn,end:mn,allDay:Boolean};function pi(e,t,n){let r=function(e,t){let{refined:n,extra:r}=pn(e,gi),i=n.start?t.createMarkerMeta(n.start):null,s=n.end?t.createMarkerMeta(n.end):null,{allDay:o}=n;null==o&&(o=i&&i.isTimeUnspecified&&(!s||s.isTimeUnspecified));return Object.assign({range:{start:i?i.marker:null,end:s?s.marker:null},allDay:o},r)}(e,t),{range:i}=r;if(!i.start)return null;if(!i.end){if(null==n)return null;i.end=t.add(i.start,n)}return r}function mi(e,t){return ir(e.range,t.range)&&e.allDay===t.allDay&&function(e,t){for(let n in t)if("range"!==n&&"allDay"!==n&&e[n]!==t[n])return!1;for(let n in e)if(!(n in t))return!1;return!0}(e,t)}function vi(e,t,n){return Object.assign(Object.assign({},bi(e,t,n)),{timeZone:t.timeZone})}function bi(e,t,n){return{start:t.toDate(e.start),end:t.toDate(e.end),startStr:t.formatIso(e.start,{omitTime:n}),endStr:t.formatIso(e.end,{omitTime:n})}}let yi={};var Ei,Ai;Ei="gregory",Ai=class{getMarkerYear(e){return e.getUTCFullYear()}getMarkerMonth(e){return e.getUTCMonth()}getMarkerDay(e){return e.getUTCDate()}arrayToMarker(e){return Ht(e)}markerToArray(e){return Pt(e)}},yi[Ei]=Ai;const Di=/^\s*(\d{4})(-?(\d{2})(-?(\d{2})([T ](\d{2}):?(\d{2})(:?(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/;function Si(e){let t=Di.exec(e);if(t){let e=new Date(Date.UTC(Number(t[1]),t[3]?Number(t[3])-1:0,Number(t[5]||1),Number(t[7]||0),Number(t[8]||0),Number(t[10]||0),t[12]?1e3*Number("0."+t[12]):0));if(Bt(e)){let n=null;return t[13]&&(n=("-"===t[15]?-1:1)*(60*Number(t[16]||0)+Number(t[18]||0))),{marker:e,isTimeUnspecified:!t[6],timeZoneOffset:n}}}return null}class wi{constructor(e){let t=this.timeZone=e.timeZone,n="local"!==t&&"UTC"!==t;e.namedTimeZoneImpl&&n&&(this.namedTimeZoneImpl=new e.namedTimeZoneImpl(t)),this.canComputeOffset=Boolean(!n||this.namedTimeZoneImpl),this.calendarSystem=function(e){return new yi[e]}(e.calendarSystem),this.locale=e.locale,this.weekDow=e.locale.week.dow,this.weekDoy=e.locale.week.doy,"ISO"===e.weekNumberCalculation&&(this.weekDow=1,this.weekDoy=4),"number"==typeof e.firstDay&&(this.weekDow=e.firstDay),"function"==typeof e.weekNumberCalculation&&(this.weekNumberFunc=e.weekNumberCalculation),this.weekText=null!=e.weekText?e.weekText:e.locale.options.weekText,this.weekTextLong=(null!=e.weekTextLong?e.weekTextLong:e.locale.options.weekTextLong)||this.weekText,this.cmdFormatter=e.cmdFormatter,this.defaultSeparator=e.defaultSeparator}createMarker(e){let t=this.createMarkerMeta(e);return null===t?null:t.marker}createNowMarker(){return this.canComputeOffset?this.timestampToMarker((new Date).valueOf()):Ht(Ot(new Date))}createMarkerMeta(e){if("string"==typeof e)return this.parse(e);let t=null;return"number"==typeof e?t=this.timestampToMarker(e):e instanceof Date?(e=e.valueOf(),isNaN(e)||(t=this.timestampToMarker(e))):Array.isArray(e)&&(t=Ht(e)),null!==t&&Bt(t)?{marker:t,isTimeUnspecified:!1,forcedTzo:null}:null}parse(e){let t=Si(e);if(null===t)return null;let{marker:n}=t,r=null;return null!==t.timeZoneOffset&&(this.canComputeOffset?n=this.timestampToMarker(n.valueOf()-60*t.timeZoneOffset*1e3):r=t.timeZoneOffset),{marker:n,isTimeUnspecified:t.isTimeUnspecified,forcedTzo:r}}getYear(e){return this.calendarSystem.getMarkerYear(e)}getMonth(e){return this.calendarSystem.getMarkerMonth(e)}add(e,t){let n=this.calendarSystem.markerToArray(e);return n[0]+=t.years,n[1]+=t.months,n[2]+=t.days,n[6]+=t.milliseconds,this.calendarSystem.arrayToMarker(n)}subtract(e,t){let n=this.calendarSystem.markerToArray(e);return n[0]-=t.years,n[1]-=t.months,n[2]-=t.days,n[6]-=t.milliseconds,this.calendarSystem.arrayToMarker(n)}addYears(e,t){let n=this.calendarSystem.markerToArray(e);return n[0]+=t,this.calendarSystem.arrayToMarker(n)}addMonths(e,t){let n=this.calendarSystem.markerToArray(e);return n[1]+=t,this.calendarSystem.arrayToMarker(n)}diffWholeYears(e,t){let{calendarSystem:n}=this;return jt(e)===jt(t)&&n.getMarkerDay(e)===n.getMarkerDay(t)&&n.getMarkerMonth(e)===n.getMarkerMonth(t)?n.getMarkerYear(t)-n.getMarkerYear(e):null}diffWholeMonths(e,t){let{calendarSystem:n}=this;return jt(e)===jt(t)&&n.getMarkerDay(e)===n.getMarkerDay(t)?n.getMarkerMonth(t)-n.getMarkerMonth(e)+12*(n.getMarkerYear(t)-n.getMarkerYear(e)):null}greatestWholeUnit(e,t){let n=this.diffWholeYears(e,t);return null!==n?{unit:"year",value:n}:(n=this.diffWholeMonths(e,t),null!==n?{unit:"month",value:n}:(n=_t(e,t),null!==n?{unit:"week",value:n}:(n=Tt(e,t),null!==n?{unit:"day",value:n}:(n=function(e,t){return(t.valueOf()-e.valueOf())/36e5}(e,t),Je(n)?{unit:"hour",value:n}:(n=function(e,t){return(t.valueOf()-e.valueOf())/6e4}(e,t),Je(n)?{unit:"minute",value:n}:(n=function(e,t){return(t.valueOf()-e.valueOf())/1e3}(e,t),Je(n)?{unit:"second",value:n}:{unit:"millisecond",value:t.valueOf()-e.valueOf()}))))))}countDurationsBetween(e,t,n){let r;return n.years&&(r=this.diffWholeYears(e,t),null!==r)?r/(st(n)/365):n.months&&(r=this.diffWholeMonths(e,t),null!==r)?r/function(e){return st(e)/30}(n):n.days&&(r=Tt(e,t),null!==r)?r/st(n):(t.valueOf()-e.valueOf())/ot(n)}startOf(e,t){return"year"===t?this.startOfYear(e):"month"===t?this.startOfMonth(e):"week"===t?this.startOfWeek(e):"day"===t?kt(e):"hour"===t?function(e){return Ht([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours()])}(e):"minute"===t?function(e){return Ht([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes()])}(e):"second"===t?function(e){return Ht([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds()])}(e):null}startOfYear(e){return this.calendarSystem.arrayToMarker([this.calendarSystem.getMarkerYear(e)])}startOfMonth(e){return this.calendarSystem.arrayToMarker([this.calendarSystem.getMarkerYear(e),this.calendarSystem.getMarkerMonth(e)])}startOfWeek(e){return this.calendarSystem.arrayToMarker([this.calendarSystem.getMarkerYear(e),this.calendarSystem.getMarkerMonth(e),e.getUTCDate()-(e.getUTCDay()-this.weekDow+7)%7])}computeWeekNumber(e){return this.weekNumberFunc?this.weekNumberFunc(this.toDate(e)):function(e,t,n){let r=e.getUTCFullYear(),i=Mt(e,r,t,n);if(i<1)return Mt(e,r-1,t,n);let s=Mt(e,r+1,t,n);return s>=1?Math.min(i,s):i}(e,this.weekDow,this.weekDoy)}format(e,t,n={}){return t.format({marker:e,timeZoneOffset:null!=n.forcedTzo?n.forcedTzo:this.offsetForMarker(e)},this)}formatRange(e,t,n,r={}){return r.isEndExclusive&&(t=wt(t,-1)),n.formatRange({marker:e,timeZoneOffset:null!=r.forcedStartTzo?r.forcedStartTzo:this.offsetForMarker(e)},{marker:t,timeZoneOffset:null!=r.forcedEndTzo?r.forcedEndTzo:this.offsetForMarker(t)},this,r.defaultSeparator)}formatIso(e,t={}){let n=null;return t.omitTimeZoneOffset||(n=null!=t.forcedTzo?t.forcedTzo:this.offsetForMarker(e)),zt(e,n,t.omitTime)}timestampToMarker(e){return"local"===this.timeZone?Ht(Ot(new Date(e))):"UTC"!==this.timeZone&&this.namedTimeZoneImpl?Ht(this.namedTimeZoneImpl.timestampToArray(e)):new Date(e)}offsetForMarker(e){return"local"===this.timeZone?-Nt(Pt(e)).getTimezoneOffset():"UTC"===this.timeZone?0:this.namedTimeZoneImpl?this.namedTimeZoneImpl.offsetForArray(Pt(e)):null}toDate(e,t){return"local"===this.timeZone?Nt(Pt(e)):"UTC"===this.timeZone?new Date(e.valueOf()):this.namedTimeZoneImpl?new Date(e.valueOf()-1e3*this.namedTimeZoneImpl.offsetForArray(Pt(e))*60):new Date(e.valueOf()-(t||0))}}class Ci{constructor(){this.strictOrder=!1,this.allowReslicing=!1,this.maxCoord=-1,this.maxStackCnt=-1,this.levelCoords=[],this.entriesByLevel=[],this.stackCnts={}}addSegs(e){let t=[];for(let n of e)this.insertEntry(n,t);return t}insertEntry(e,t){let n=this.findInsertion(e);return this.isInsertionValid(n,e)?(this.insertEntryAt(e,n),1):this.handleInvalidInsertion(n,e,t)}isInsertionValid(e,t){return(-1===this.maxCoord||e.levelCoord+t.thickness<=this.maxCoord)&&(-1===this.maxStackCnt||e.stackCnt<this.maxStackCnt)}handleInvalidInsertion(e,t,n){return this.allowReslicing&&e.touchingEntry?this.splitEntry(t,e.touchingEntry,n):(n.push(t),0)}splitEntry(e,t,n){let r=0,i=[],s=e.span,o=t.span;return s.start<o.start&&(r+=this.insertEntry({index:e.index,thickness:e.thickness,span:{start:s.start,end:o.start}},i)),s.end>o.end&&(r+=this.insertEntry({index:e.index,thickness:e.thickness,span:{start:o.end,end:s.end}},i)),r?(n.push({index:e.index,thickness:e.thickness,span:Ti(o,s)},...i),r):(n.push(e),0)}insertEntryAt(e,t){let{entriesByLevel:n,levelCoords:r}=this;-1===t.lateral?(ki(r,t.level,t.levelCoord),ki(n,t.level,[e])):ki(n[t.level],t.lateral,e),this.stackCnts[xi(e)]=t.stackCnt}findInsertion(e){let{levelCoords:t,entriesByLevel:n,strictOrder:r,stackCnts:i}=this,s=t.length,o=0,a=-1,l=-1,c=null,d=0;for(let u=0;u<s;u+=1){let s=t[u];if(!r&&s>=o+e.thickness)break;let h,f=n[u],g=Mi(f,e.span.start,Ri),p=g[0]+g[1];for(;(h=f[p])&&h.span.start<e.span.end;){let e=s+h.thickness;e>o&&(o=e,c=h,a=u,l=p),e===o&&(d=Math.max(d,i[xi(h)]+1)),p+=1}}let u=0;if(c)for(u=a+1;u<s&&t[u]<o;)u+=1;let h=-1;return u<s&&t[u]===o&&(h=Mi(n[u],e.span.end,Ri)[0]),{touchingLevel:a,touchingLateral:l,touchingEntry:c,stackCnt:d,levelCoord:o,level:u,lateral:h}}toRects(){let{entriesByLevel:e,levelCoords:t}=this,n=e.length,r=[];for(let i=0;i<n;i+=1){let n=e[i],s=t[i];for(let e of n)r.push(Object.assign(Object.assign({},e),{levelCoord:s}))}return r}}function Ri(e){return e.span.end}function xi(e){return e.index+":"+e.span.start}function _i(e){let t=[];for(let i of e){let e=[],s={span:i.span,entries:[i]};for(let i of t)Ti(i.span,s.span)?s={entries:i.entries.concat(s.entries),span:(n=i.span,r=s.span,{start:Math.min(n.start,r.start),end:Math.max(n.end,r.end)})}:e.push(i);e.push(s),t=e}var n,r;return t}function Ti(e,t){let n=Math.max(e.start,t.start),r=Math.min(e.end,t.end);return n<r?{start:n,end:r}:null}function ki(e,t,n){e.splice(t,0,n)}function Mi(e,t,n){let r=0,i=e.length;if(!i||t<n(e[r]))return[0,0];if(t>n(e[i-1]))return[i,0];for(;r<i;){let s=Math.floor(r+(i-r)/2),o=n(e[s]);if(t<o)i=s;else{if(!(t>o))return[s,1];r=s+1}}return[r,0]}class Ii{constructor(e){this.component=e.component,this.isHitComboAllowed=e.isHitComboAllowed||null}destroy(){}}function Oi(e){return{[e.component.uid]:e}}const Ni={};class Pi{constructor(e,t){this.emitter=new Sr}destroy(){}setMirrorIsVisible(e){}setMirrorNeedsRevert(e){}setAutoScrollEnabled(e){}}const Hi={},Bi={startTime:tt,duration:tt,create:Boolean,sourceId:String};function ji(e){let{refined:t,extra:n}=pn(e,Bi);return{startTime:t.startTime||null,duration:t.duration||null,create:null==t.create||t.create,sourceId:t.sourceId,leftoverProps:n}}class zi extends Br{constructor(){super(...arguments),this.state={forPrint:!1},this.handleBeforePrint=()=>{this.setState({forPrint:!0})},this.handleAfterPrint=()=>{this.setState({forPrint:!1})}}render(){let{props:e}=this,{options:t}=e,{forPrint:n}=this.state,r=n||"auto"===t.height||"auto"===t.contentHeight,i=r||null==t.height?"":t.height,s=["fc",n?"fc-media-print":"fc-media-screen","fc-direction-"+t.direction,e.theme.getClass("root")];return Jn()||s.push("fc-liquid-hack"),e.children(s,i,r,n)}componentDidMount(){let{emitter:e}=this.props;e.on("_beforeprint",this.handleBeforePrint),e.on("_afterprint",this.handleAfterPrint)}componentWillUnmount(){let{emitter:e}=this.props;e.off("_beforeprint",this.handleBeforePrint),e.off("_afterprint",this.handleAfterPrint)}}function Ui(e,t){return on(!e||t>10?{weekday:"short"}:t>1?{weekday:"short",month:"numeric",day:"numeric",omitCommas:!0}:{weekday:"long"})}const Li="fc-col-header-cell";function Wi(e){return e.text}class Fi extends Br{constructor(){super(...arguments),this.id=Be(),this.currentDomNodes=[],this.queuedDomNodes=[],this.handleEl=e=>{this.props.elRef&&jr(this.props.elRef,e)}}render(){const{props:e,context:t}=this,{options:n}=t,{generator:r,renderProps:s}=e,o=Gi(e);let a,l=[];if(Vi(e.generatorName,n))n.customRenderingReplacesEl&&delete o.elRef;else{const e="function"==typeof r?r(s,f):r;"string"==typeof e||i(e)||Array.isArray(e)?a=e:"object"==typeof e&&("html"in e?o.dangerouslySetInnerHTML={__html:e.html}:"domNodes"in e&&(l=Array.prototype.slice.call(e.domNodes)))}return this.queuedDomNodes=l,f(e.elTag,o,a)}componentDidMount(){this.applyQueueudDomNodes(),this.triggerCustomRendering(!0)}componentDidUpdate(){this.applyQueueudDomNodes(),this.triggerCustomRendering(!0)}componentWillUnmount(){this.triggerCustomRendering(!1)}triggerCustomRendering(e){const{props:t,context:n}=this,{handleCustomRendering:r,customRenderingMetaMap:i}=n.options;if(r){const n=null==i?void 0:i[t.generatorName];n&&r(Object.assign({id:this.id,isActive:e,containerEl:this.base,reportNewContainerEl:this.handleEl,generatorMeta:n},t))}}applyQueueudDomNodes(){const{queuedDomNodes:e,currentDomNodes:t}=this,n=this.base;if(!Ft(e,t)){t.forEach(ye);for(let t of e)n.appendChild(t);this.currentDomNodes=e}}}function Vi(e,t){var n;return Boolean(t.handleCustomRendering&&e&&(null===(n=t.customRenderingMetaMap)||void 0===n?void 0:n[e]))}function Gi(e,t){const n=Object.assign(Object.assign({},e.elAttrs),{ref:e.elRef});return(e.elClasses||t)&&(n.className=(e.elClasses||[]).concat(t||[]).concat(n.className||[]).filter(Boolean).join(" ")),e.elStyle&&(n.style=e.elStyle),n}Fi.addPropsEquality({elClasses:Ft,elStyle:pt,elAttrs:function(e,t){const n=vt(e,t);for(let e of n)if(!mt.test(e))return!1;return!0},renderProps:pt});const Qi=Ir(0);class qi extends m{constructor(){super(...arguments),this.InnerContent=Yi.bind(void 0,this)}render(){const{props:e}=this,t=function(e,t){const n="function"==typeof e?e(t):e||[];return"string"==typeof n?[n]:n}(e.classNameGenerator,e.renderProps);if(e.children){const n=Gi(e,t),r=e.children(this.InnerContent,e.renderProps,n);return e.elTag?f(e.elTag,n,r):r}return f(Fi,Object.assign(Object.assign({},e),{elTag:e.elTag||"div",elClasses:(e.elClasses||[]).concat(t),renderId:this.context}))}componentDidMount(){var e,t;null===(t=(e=this.props).didMount)||void 0===t||t.call(e,Object.assign(Object.assign({},this.props.renderProps),{el:this.base}))}componentWillUnmount(){var e,t;null===(t=(e=this.props).willUnmount)||void 0===t||t.call(e,Object.assign(Object.assign({},this.props.renderProps),{el:this.base}))}}function Yi(e,t){const n=e.props;return f(Fi,Object.assign({renderProps:n.renderProps,generatorName:n.generatorName,generator:n.generator,renderId:e.context},t))}qi.contextType=Qi;class Zi extends Br{render(){let{dateEnv:e,options:t,theme:n,viewApi:r}=this.context,{props:i}=this,{date:s,dateProfile:o}=i,a=lr(s,i.todayRange,null,o),l=[Li].concat(cr(a,n)),c=e.format(s,i.dayHeaderFormat),d=!a.isDisabled&&i.colCnt>1?hr(this.context,s):{},u=Object.assign(Object.assign(Object.assign({date:e.toDate(s),view:r},i.extraRenderProps),{text:c}),a);return f(qi,{elTag:"th",elClasses:l,elAttrs:Object.assign({role:"columnheader",colSpan:i.colSpan,"data-date":a.isDisabled?void 0:Ut(s)},i.extraDataAttrs),renderProps:u,generatorName:"dayHeaderContent",generator:t.dayHeaderContent||Wi,classNameGenerator:t.dayHeaderClassNames,didMount:t.dayHeaderDidMount,willUnmount:t.dayHeaderWillUnmount},e=>f("div",{className:"fc-scrollgrid-sync-inner"},!a.isDisabled&&f(e,{elTag:"a",elAttrs:d,elClasses:["fc-col-header-cell-cushion",i.isSticky&&"fc-sticky"]})))}}const Xi=on({weekday:"long"});class Ji extends Br{render(){let{props:e}=this,{dateEnv:t,theme:n,viewApi:r,options:i}=this.context,s=St(new Date(2592e5),e.dow),o={dow:e.dow,isDisabled:!1,isFuture:!1,isPast:!1,isToday:!1,isOther:!1},a=t.format(s,e.dayHeaderFormat),l=Object.assign(Object.assign(Object.assign(Object.assign({date:s},o),{view:r}),e.extraRenderProps),{text:a});return f(qi,{elTag:"th",elClasses:[Li,...cr(o,n),...e.extraClassNames||[]],elAttrs:Object.assign({role:"columnheader",colSpan:e.colSpan},e.extraDataAttrs),renderProps:l,generatorName:"dayHeaderContent",generator:i.dayHeaderContent||Wi,classNameGenerator:i.dayHeaderClassNames,didMount:i.dayHeaderDidMount,willUnmount:i.dayHeaderWillUnmount},n=>f("div",{className:"fc-scrollgrid-sync-inner"},f(n,{elTag:"a",elClasses:["fc-col-header-cell-cushion",e.isSticky&&"fc-sticky"],elAttrs:{"aria-label":t.format(s,Xi)}})))}}class $i extends m{constructor(e,t){super(e,t),this.initialNowDate=Ur(t.options.now,t.dateEnv),this.initialNowQueriedMs=(new Date).valueOf(),this.state=this.computeTiming().currentState}render(){let{props:e,state:t}=this;return e.children(t.nowDate,t.todayRange)}componentDidMount(){this.setTimeout()}componentDidUpdate(e){e.unit!==this.props.unit&&(this.clearTimeout(),this.setTimeout())}componentWillUnmount(){this.clearTimeout()}computeTiming(){let{props:e,context:t}=this,n=wt(this.initialNowDate,(new Date).valueOf()-this.initialNowQueriedMs),r=t.dateEnv.startOf(n,e.unit),i=t.dateEnv.add(r,tt(1,e.unit)),s=i.valueOf()-n.valueOf();return s=Math.min(864e5,s),{currentState:{nowDate:r,todayRange:Ki(r)},nextState:{nowDate:i,todayRange:Ki(i)},waitMs:s}}setTimeout(){let{nextState:e,waitMs:t}=this.computeTiming();this.timeoutId=setTimeout(()=>{this.setState(e,()=>{this.setTimeout()})},t)}clearTimeout(){this.timeoutId&&clearTimeout(this.timeoutId)}}function Ki(e){let t=kt(e);return{start:t,end:St(t,1)}}$i.contextType=Nr;class es extends Br{constructor(){super(...arguments),this.createDayHeaderFormatter=Vt(ts)}render(){let{context:e}=this,{dates:t,dateProfile:n,datesRepDistinctDays:r,renderIntro:i}=this.props,s=this.createDayHeaderFormatter(e.options.dayHeaderFormat,r,t.length);return f($i,{unit:"day"},(e,o)=>f("tr",{role:"row"},i&&i("day"),t.map(e=>r?f(Zi,{key:e.toISOString(),date:e,dateProfile:n,todayRange:o,colCnt:t.length,dayHeaderFormat:s}):f(Ji,{key:e.getUTCDay(),dow:e.getUTCDay(),dayHeaderFormat:s}))))}}function ts(e,t,n){return e||Ui(t,n)}class ns{constructor(e,t){let n=e.start,{end:r}=e,i=[],s=[],o=-1;for(;n<r;)t.isHiddenDay(n)?i.push(o+.5):(o+=1,i.push(o),s.push(n)),n=St(n,1);this.dates=s,this.indices=i,this.cnt=s.length}sliceRange(e){let t=this.getDateDayIndex(e.start),n=this.getDateDayIndex(St(e.end,-1)),r=Math.max(0,t),i=Math.min(this.cnt-1,n);return r=Math.ceil(r),i=Math.floor(i),r<=i?{firstIndex:r,lastIndex:i,isStart:t===r,isEnd:n===i}:null}getDateDayIndex(e){let{indices:t}=this,n=Math.floor(Rt(this.dates[0],e));return n<0?t[0]-1:n>=t.length?t[t.length-1]+1:t[n]}}class rs{constructor(e,t){let n,r,i,{dates:s}=e;if(t){for(r=s[0].getUTCDay(),n=1;n<s.length&&s[n].getUTCDay()!==r;n+=1);i=Math.ceil(s.length/n)}else i=1,n=s.length;this.rowCnt=i,this.colCnt=n,this.daySeries=e,this.cells=this.buildCells(),this.headerDates=this.buildHeaderDates()}buildCells(){let e=[];for(let t=0;t<this.rowCnt;t+=1){let n=[];for(let e=0;e<this.colCnt;e+=1)n.push(this.buildCell(t,e));e.push(n)}return e}buildCell(e,t){let n=this.daySeries.dates[e*this.colCnt+t];return{key:n.toISOString(),date:n}}buildHeaderDates(){let e=[];for(let t=0;t<this.colCnt;t+=1)e.push(this.cells[0][t].date);return e}sliceRange(e){let{colCnt:t}=this,n=this.daySeries.sliceRange(e),r=[];if(n){let{firstIndex:e,lastIndex:i}=n,s=e;for(;s<=i;){let o=Math.floor(s/t),a=Math.min((o+1)*t,i+1);r.push({row:o,firstCol:s%t,lastCol:(a-1)%t,isStart:n.isStart&&s===e,isEnd:n.isEnd&&a-1===i}),s=a}}return r}}class is{constructor(){this.sliceBusinessHours=Vt(this._sliceBusinessHours),this.sliceDateSelection=Vt(this._sliceDateSpan),this.sliceEventStore=Vt(this._sliceEventStore),this.sliceEventDrag=Vt(this._sliceInteraction),this.sliceEventResize=Vt(this._sliceInteraction),this.forceDayIfListItem=!1}sliceProps(e,t,n,r,...i){let{eventUiBases:s}=e,o=this.sliceEventStore(e.eventStore,s,t,n,...i);return{dateSelectionSegs:this.sliceDateSelection(e.dateSelection,s,r,...i),businessHourSegs:this.sliceBusinessHours(e.businessHours,t,n,r,...i),fgEventSegs:o.fg,bgEventSegs:o.bg,eventDrag:this.sliceEventDrag(e.eventDrag,s,t,n,...i),eventResize:this.sliceEventResize(e.eventResize,s,t,n,...i),eventSelection:e.eventSelection}}sliceNowDate(e,t,...n){return this._sliceDateSpan({range:{start:e,end:wt(e,1)},allDay:!1},{},t,...n)}_sliceBusinessHours(e,t,n,r,...i){return e?this._sliceEventStore(bn(e,ss(t,Boolean(n)),r),{},t,n,...i).bg:[]}_sliceEventStore(e,t,n,r,...i){if(e){let s=$r(e,t,ss(n,Boolean(r)),r);return{bg:this.sliceEventRanges(s.bg,i),fg:this.sliceEventRanges(s.fg,i)}}return{bg:[],fg:[]}}_sliceInteraction(e,t,n,r,...i){if(!e)return null;let s=$r(e.mutatedEvents,t,ss(n,Boolean(r)),r);return{segs:this.sliceEventRanges(s.fg,i),affectedInstances:e.affectedEvents.instances,isEvent:e.isEvent}}_sliceDateSpan(e,t,n,...r){if(!e)return[];let i=function(e,t,n){let r=Hn({editable:!1},n),i=jn(r.refined,r.extra,"",e.allDay,!0,n);return{def:i,ui:ri(i,t),instance:vn(i.defId,e.range),range:e.range,isStart:!0,isEnd:!0}}(e,t,n),s=this.sliceRange(e.range,...r);for(let e of s)e.eventRange=i;return s}sliceEventRanges(e,t){let n=[];for(let r of e)n.push(...this.sliceEventRange(r,t));return n}sliceEventRange(e,t){let n=e.range;this.forceDayIfListItem&&"list-item"===e.ui.display&&(n={start:n.start,end:St(n.start,1)});let r=this.sliceRange(n,...t);for(let t of r)t.eventRange=e,t.isStart=e.isStart&&t.isStart,t.isEnd=e.isEnd&&t.isEnd;return r}}function ss(e,t){let n=e.activeRange;return t?n:{start:wt(n.start,e.slotMinTime.milliseconds),end:wt(n.end,e.slotMaxTime.milliseconds-864e5)}}function os(e,t,n,r,i){switch(t.type){case"RECEIVE_EVENTS":return function(e,t,n,r,i,s){if(t&&n===t.latestFetchId){let n=En(function(e,t,n){let r=n.options.eventDataTransform,i=t?t.eventDataTransform:null;i&&(e=as(e,i));r&&(e=as(e,r));return e}(i,t,s),t,s);return r&&(n=bn(n,r,s)),wn(ls(e,t.sourceId),n)}return e}(e,n[t.sourceId],t.fetchId,t.fetchRange,t.rawEvents,i);case"ADD_EVENTS":return function(e,t,n,r){n&&(t=bn(t,n,r));return wn(e,t)}(e,t.eventStore,r?r.activeRange:null,i);case"RESET_EVENTS":return t.eventStore;case"MERGE_EVENTS":return wn(e,t.eventStore);case"PREV":case"NEXT":case"CHANGE_DATE":case"CHANGE_VIEW_TYPE":return r?bn(e,r.activeRange,i):e;case"REMOVE_EVENTS":return function(e,t){let{defs:n,instances:r}=e,i={},s={};for(let e in n)t.defs[e]||(i[e]=n[e]);for(let e in r)!t.instances[e]&&i[r[e].defId]&&(s[e]=r[e]);return{defs:i,instances:s}}(e,t.eventStore);case"REMOVE_EVENT_SOURCE":return ls(e,t.sourceId);case"REMOVE_ALL_EVENT_SOURCES":return Cn(e,e=>!e.sourceId);case"REMOVE_ALL_EVENTS":return{defs:{},instances:{}};default:return e}}function as(e,t){let n;if(t){n=[];for(let r of e){let e=t(r);e?n.push(e):null==e&&n.push(r)}}else n=e;return n}function ls(e,t){return Cn(e,e=>e.sourceId!==t)}function cs(e,t,n){let{instances:r}=e.mutatedEvents;for(let e in r)if(!or(t.validRange,r[e].range))return!1;return us({eventDrag:e},n)}function ds(e,t,n){return!!or(t.validRange,e.range)&&us({dateSelection:e},n)}function us(e,t){let n=t.getCurrentData(),r=Object.assign({businessHours:n.businessHours,dateSelection:"",eventStore:n.eventStore,eventUiBases:n.eventUiBases,eventSelection:"",eventDrag:null,eventResize:null},e);return(t.pluginHooks.isPropsValid||hs)(r,t)}function hs(e,t,n={},r){return!(e.eventDrag&&!function(e,t,n,r){let i=t.getCurrentData(),s=e.eventDrag,o=s.mutatedEvents,a=o.defs,l=o.instances,c=ni(a,s.isEvent?e.eventUiBases:{"":i.selectionConfig});r&&(c=ht(c,r));let d=(g=e.eventStore,p=s.affectedEvents.instances,{defs:g.defs,instances:ut(g.instances,e=>!p[e.instanceId])}),u=d.defs,h=d.instances,f=ni(u,e.eventUiBases);var g,p;for(let r in l){let o=l[r],g=o.range,p=c[o.defId],m=a[o.defId];if(!fs(p.constraints,g,d,e.businessHours,t))return!1;let{eventOverlap:v}=t.options,b="function"==typeof v?v:null;for(let e in h){let n=h[e];if(sr(g,n.range)){if(!1===f[n.defId].overlap&&s.isEvent)return!1;if(!1===p.overlap)return!1;if(b&&!b(new Zr(t,u[n.defId],n),new Zr(t,m,o)))return!1}}let y=i.eventStore;for(let e of p.allows){let i,s=Object.assign(Object.assign({},n),{range:o.range,allDay:m.allDay}),a=y.defs[m.defId],l=y.instances[r];if(i=a?new Zr(t,a,l):new Zr(t,m),!e(Fr(s,t),i))return!1}}return!0}(e,t,n,r))&&!(e.dateSelection&&!function(e,t,n,r){let i=e.eventStore,s=i.defs,o=i.instances,a=e.dateSelection,l=a.range,{selectionConfig:c}=t.getCurrentData();r&&(c=r(c));if(!fs(c.constraints,l,i,e.businessHours,t))return!1;let{selectOverlap:d}=t.options,u="function"==typeof d?d:null;for(let e in o){let n=o[e];if(sr(l,n.range)){if(!1===c.overlap)return!1;if(u&&!u(new Zr(t,s[n.defId],n),null))return!1}}for(let e of c.allows){let r=Object.assign(Object.assign({},n),a);if(!e(Fr(r,t),null))return!1}return!0}(e,t,n,r))}function fs(e,t,n,r,i){for(let s of e)if(!ms(gs(s,t,n,r,i),t))return!1;return!0}function gs(e,t,n,r,i){return"businessHours"===e?ps(bn(r,t,i)):"string"==typeof e?ps(Cn(n,t=>t.groupId===e)):"object"==typeof e&&e?ps(bn(e,t,i)):[]}function ps(e){let{instances:t}=e,n=[];for(let e in t)n.push(t[e].range);return n}function ms(e,t){for(let n of e)if(or(n,t))return!0;return!1}class vs extends Error{constructor(e,t){super(e),this.response=t}}function bs(e,t,n){const r={method:e=e.toUpperCase()};return"GET"===e?t+=(-1===t.indexOf("?")?"?":"&")+new URLSearchParams(n):(r.body=new URLSearchParams(n),r.headers={"Content-Type":"application/x-www-form-urlencoded"}),fetch(t,r).then(e=>{if(e.ok)return e.json().then(t=>[t,e],()=>{throw new vs("Failure parsing JSON",e)});throw new vs("Request failed",e)})}class ys{constructor(e){this.drainedOption=e,this.isRunning=!1,this.isDirty=!1,this.pauseDepths={},this.timeoutId=0}request(e){this.isDirty=!0,this.isPaused()||(this.clearTimeout(),null==e?this.tryDrain():this.timeoutId=setTimeout(this.tryDrain.bind(this),e))}pause(e=""){let{pauseDepths:t}=this;t[e]=(t[e]||0)+1,this.clearTimeout()}resume(e="",t){let{pauseDepths:n}=this;if(e in n){if(t)delete n[e];else{n[e]-=1,n[e]<=0&&delete n[e]}this.tryDrain()}}isPaused(){return Object.keys(this.pauseDepths).length}tryDrain(){if(!this.isRunning&&!this.isPaused()){for(this.isRunning=!0;this.isDirty;)this.isDirty=!1,this.drained();this.isRunning=!1}}clear(){this.clearTimeout(),this.isDirty=!1,this.pauseDepths={}}clearTimeout(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=0)}drained(){this.drainedOption&&this.drainedOption()}}const Es=/^(visible|hidden)$/;class As extends Br{constructor(){super(...arguments),this.handleEl=e=>{this.el=e,jr(this.props.elRef,e)}}render(){let{props:e}=this,{liquid:t,liquidIsAbsolute:n}=e,r=t&&n,i=["fc-scroller"];return t&&(n?i.push("fc-scroller-liquid-absolute"):i.push("fc-scroller-liquid")),f("div",{ref:this.handleEl,className:i.join(" "),style:{overflowX:e.overflowX,overflowY:e.overflowY,left:r&&-(e.overcomeLeft||0)||"",right:r&&-(e.overcomeRight||0)||"",bottom:r&&-(e.overcomeBottom||0)||"",marginLeft:!r&&-(e.overcomeLeft||0)||"",marginRight:!r&&-(e.overcomeRight||0)||"",marginBottom:!r&&-(e.overcomeBottom||0)||"",maxHeight:e.maxHeight||""}},e.children)}needsXScrolling(){if(Es.test(this.props.overflowX))return!1;let{el:e}=this,t=this.el.getBoundingClientRect().width-this.getYScrollbarWidth(),{children:n}=e;for(let e=0;e<n.length;e+=1){if(n[e].getBoundingClientRect().width>t)return!0}return!1}needsYScrolling(){if(Es.test(this.props.overflowY))return!1;let{el:e}=this,t=this.el.getBoundingClientRect().height-this.getXScrollbarWidth(),{children:n}=e;for(let e=0;e<n.length;e+=1){if(n[e].getBoundingClientRect().height>t)return!0}return!1}getXScrollbarWidth(){return Es.test(this.props.overflowX)?0:this.el.offsetHeight-this.el.clientHeight}getYScrollbarWidth(){return Es.test(this.props.overflowY)?0:this.el.offsetWidth-this.el.clientWidth}}class Ds{constructor(e){this.masterCallback=e,this.currentMap={},this.depths={},this.callbackMap={},this.handleValue=(e,t)=>{let{depths:n,currentMap:r}=this,i=!1,s=!1;null!==e?(i=t in r,r[t]=e,n[t]=(n[t]||0)+1,s=!0):(n[t]-=1,n[t]||(delete r[t],delete this.callbackMap[t],i=!0)),this.masterCallback&&(i&&this.masterCallback(null,String(t)),s&&this.masterCallback(e,String(t)))}}createRef(e){let t=this.callbackMap[e];return t||(t=this.callbackMap[e]=t=>{this.handleValue(t,String(e))}),t}collect(e,t,n){return Et(this.currentMap,e,t,n)}getAll(){return gt(this.currentMap)}}function Ss(e){let t=De(e,".fc-scrollgrid-shrink"),n=0;for(let e of t)n=Math.max(n,$e(e));return Math.ceil(n)}function ws(e,t){return e.liquid&&t.liquid}function Cs(e,t){return null!=t.maxHeight||ws(e,t)}function Rs(e,t,n,r){let{expandRows:i}=n;return"function"==typeof t.content?t.content(n):f("table",{role:"presentation",className:[t.tableClassName,e.syncRowHeights?"fc-scrollgrid-sync-table":""].join(" "),style:{minWidth:n.tableMinWidth,width:n.clientWidth,height:i?n.clientHeight:""}},n.tableColGroupNode,f(r?"thead":"tbody",{role:"presentation"},"function"==typeof t.rowContent?t.rowContent(n):t.rowContent))}function xs(e,t){return Ft(e,t,pt)}function _s(e,t){let n=[];for(let r of e){let e=r.span||1;for(let i=0;i<e;i+=1)n.push(f("col",{style:{width:"shrink"===r.width?Ts(t):r.width||"",minWidth:r.minWidth||""}}))}return f("colgroup",{},...n)}function Ts(e){return null==e?4:e}function ks(e){for(let t of e)if("shrink"===t.width)return!0;return!1}function Ms(e,t){let n=["fc-scrollgrid",t.theme.getClass("table")];return e&&n.push("fc-scrollgrid-liquid"),n}function Is(e,t){let n=["fc-scrollgrid-section","fc-scrollgrid-section-"+e.type,e.className];return t&&e.liquid&&null==e.maxHeight&&n.push("fc-scrollgrid-section-liquid"),e.isSticky&&n.push("fc-scrollgrid-section-sticky"),n}function Os(e){return f("div",{className:"fc-scrollgrid-sticky-shim",style:{width:e.clientWidth,minWidth:e.tableMinWidth}})}function Ns(e){let{stickyHeaderDates:t}=e;return null!=t&&"auto"!==t||(t="auto"===e.height||"auto"===e.viewHeight),t}function Ps(e){let{stickyFooterScrollbar:t}=e;return null!=t&&"auto"!==t||(t="auto"===e.height||"auto"===e.viewHeight),t}class Hs extends Br{constructor(){super(...arguments),this.processCols=Vt(e=>e,xs),this.renderMicroColGroup=Vt(_s),this.scrollerRefs=new Ds,this.scrollerElRefs=new Ds(this._handleScrollerEl.bind(this)),this.state={shrinkWidth:null,forceYScrollbars:!1,scrollerClientWidths:{},scrollerClientHeights:{}},this.handleSizing=()=>{this.safeSetState(Object.assign({shrinkWidth:this.computeShrinkWidth()},this.computeScrollerDims()))}}render(){let{props:e,state:t,context:n}=this,r=e.sections||[],i=this.processCols(e.cols),s=this.renderMicroColGroup(i,t.shrinkWidth),o=Ms(e.liquid,n);e.collapsibleWidth&&o.push("fc-scrollgrid-collapsible");let a,l=r.length,c=0,d=[],u=[],h=[];for(;c<l&&"header"===(a=r[c]).type;)d.push(this.renderSection(a,s,!0)),c+=1;for(;c<l&&"body"===(a=r[c]).type;)u.push(this.renderSection(a,s,!1)),c+=1;for(;c<l&&"footer"===(a=r[c]).type;)h.push(this.renderSection(a,s,!0)),c+=1;let g=!Jn();const p={role:"rowgroup"};return f("table",{role:"grid",className:o.join(" "),style:{height:e.height}},Boolean(!g&&d.length)&&f("thead",p,...d),Boolean(!g&&u.length)&&f("tbody",p,...u),Boolean(!g&&h.length)&&f("tfoot",p,...h),g&&f("tbody",p,...d,...u,...h))}renderSection(e,t,n){return"outerContent"in e?f(p,{key:e.key},e.outerContent):f("tr",{key:e.key,role:"presentation",className:Is(e,this.props.liquid).join(" ")},this.renderChunkTd(e,t,e.chunk,n))}renderChunkTd(e,t,n,r){if("outerContent"in n)return n.outerContent;let{props:i}=this,{forceYScrollbars:s,scrollerClientWidths:o,scrollerClientHeights:a}=this.state,l=Cs(i,e),c=ws(i,e),d=i.liquid?s?"scroll":l?"auto":"hidden":"visible",u=e.key,h=Rs(e,n,{tableColGroupNode:t,tableMinWidth:"",clientWidth:i.collapsibleWidth||void 0===o[u]?null:o[u],clientHeight:void 0!==a[u]?a[u]:null,expandRows:e.expandRows,syncRowHeights:!1,rowSyncHeights:[],reportRowHeightChange:()=>{}},r);return f(r?"th":"td",{ref:n.elRef,role:"presentation"},f("div",{className:"fc-scroller-harness"+(c?" fc-scroller-harness-liquid":"")},f(As,{ref:this.scrollerRefs.createRef(u),elRef:this.scrollerElRefs.createRef(u),overflowY:d,overflowX:i.liquid?"hidden":"visible",maxHeight:e.maxHeight,liquid:c,liquidIsAbsolute:!0},h)))}_handleScrollerEl(e,t){let n=function(e,t){for(let n of e)if(n.key===t)return n;return null}(this.props.sections,t);n&&jr(n.chunk.scrollerElRef,e)}componentDidMount(){this.handleSizing(),this.context.addResizeHandler(this.handleSizing)}componentDidUpdate(){this.handleSizing()}componentWillUnmount(){this.context.removeResizeHandler(this.handleSizing)}computeShrinkWidth(){return ks(this.props.cols)?Ss(this.scrollerElRefs.getAll()):0}computeScrollerDims(){let e=mr(),{scrollerRefs:t,scrollerElRefs:n}=this,r=!1,i={},s={};for(let e in t.currentMap){let n=t.currentMap[e];if(n&&n.needsYScrolling()){r=!0;break}}for(let t of this.props.sections){let o=t.key,a=n.currentMap[o];if(a){let t=a.parentNode;i[o]=Math.floor(t.getBoundingClientRect().width-(r?e.y:0)),s[o]=Math.floor(t.getBoundingClientRect().height)}}return{forceYScrollbars:r,scrollerClientWidths:i,scrollerClientHeights:s}}}Hs.addStateEquality({scrollerClientWidths:pt,scrollerClientHeights:pt});class Bs extends Br{constructor(){super(...arguments),this.handleEl=e=>{this.el=e,e&&ei(e,this.props.seg)}}render(){const{props:e,context:t}=this,{options:n}=t,{seg:r}=e,{eventRange:i}=r,{ui:s}=i,o={event:new Zr(t,i.def,i.instance),view:t.viewApi,timeText:e.timeText,textColor:s.textColor,backgroundColor:s.backgroundColor,borderColor:s.borderColor,isDraggable:!e.disableDragging&&oi(r,t),isStartResizable:!e.disableResizing&&ai(r,t),isEndResizable:!e.disableResizing&&li(r),isMirror:Boolean(e.isDragging||e.isResizing||e.isDateSelecting),isStart:Boolean(r.isStart),isEnd:Boolean(r.isEnd),isPast:Boolean(e.isPast),isFuture:Boolean(e.isFuture),isToday:Boolean(e.isToday),isSelected:Boolean(e.isSelected),isDragging:Boolean(e.isDragging),isResizing:Boolean(e.isResizing)};return f(qi,Object.assign({},e,{elRef:this.handleEl,elClasses:[...ui(o),...r.eventRange.ui.classNames,...e.elClasses||[]],renderProps:o,generatorName:"eventContent",generator:n.eventContent||e.defaultGenerator,classNameGenerator:n.eventClassNames,didMount:n.eventDidMount,willUnmount:n.eventWillUnmount}))}componentDidUpdate(e){this.el&&this.props.seg!==e.seg&&ei(this.el,this.props.seg)}}class js extends Br{render(){let{props:e,context:t}=this,{options:n}=t,{seg:r}=e,{ui:i}=r.eventRange,s=ci(r,n.eventTimeFormat||e.defaultTimeFormat,t,e.defaultDisplayEventTime,e.defaultDisplayEventEnd);return f(Bs,Object.assign({},e,{elTag:"a",elStyle:{borderColor:i.borderColor,backgroundColor:i.backgroundColor},elAttrs:fi(r,t),defaultGenerator:zs,timeText:s}),(e,t)=>f(p,null,f(e,{elTag:"div",elClasses:["fc-event-main"],elStyle:{color:t.textColor}}),Boolean(t.isStartResizable)&&f("div",{className:"fc-event-resizer fc-event-resizer-start"}),Boolean(t.isEndResizable)&&f("div",{className:"fc-event-resizer fc-event-resizer-end"})))}}function zs(e){return f("div",{className:"fc-event-main-frame"},e.timeText&&f("div",{className:"fc-event-time"},e.timeText),f("div",{className:"fc-event-title-container"},f("div",{className:"fc-event-title fc-sticky"},e.event.title||f(p,null," "))))}const Us=e=>f(Nr.Consumer,null,t=>{let{options:n}=t,r={isAxis:e.isAxis,date:t.dateEnv.toDate(e.date),view:t.viewApi};return f(qi,Object.assign({},e,{elTag:e.elTag||"div",renderProps:r,generatorName:"nowIndicatorContent",generator:n.nowIndicatorContent,classNameGenerator:n.nowIndicatorClassNames,didMount:n.nowIndicatorDidMount,willUnmount:n.nowIndicatorWillUnmount}))}),Ls=on({day:"numeric"});class Ws extends Br{constructor(){super(...arguments),this.refineRenderProps=Gt(Vs)}render(){let{props:e,context:t}=this,{options:n}=t,r=this.refineRenderProps({date:e.date,dateProfile:e.dateProfile,todayRange:e.todayRange,showDayNumber:e.showDayNumber,extraRenderProps:e.extraRenderProps,viewApi:t.viewApi,dateEnv:t.dateEnv});return f(qi,Object.assign({},e,{elClasses:[...cr(r,t.theme),...e.elClasses||[]],elAttrs:Object.assign(Object.assign({},e.elAttrs),r.isDisabled?{}:{"data-date":Ut(e.date)}),renderProps:r,generatorName:"dayCellContent",generator:n.dayCellContent||e.defaultGenerator,classNameGenerator:r.isDisabled?void 0:n.dayCellClassNames,didMount:n.dayCellDidMount,willUnmount:n.dayCellWillUnmount}))}}function Fs(e){return Boolean(e.dayCellContent||Vi("dayCellContent",e))}function Vs(e){let{date:t,dateEnv:n}=e,r=lr(t,e.todayRange,null,e.dateProfile);return Object.assign(Object.assign(Object.assign({date:n.toDate(t),view:e.viewApi},r),{dayNumberText:e.showDayNumber?n.format(t,Ls):""}),e.extraRenderProps)}class Gs extends Br{render(){let{props:e}=this,{seg:t}=e;return f(Bs,{elTag:"div",elClasses:["fc-bg-event"],elStyle:{backgroundColor:t.eventRange.ui.backgroundColor},defaultGenerator:Qs,seg:t,timeText:"",isDragging:!1,isResizing:!1,isDateSelecting:!1,isSelected:!1,isPast:e.isPast,isFuture:e.isFuture,isToday:e.isToday,disableDragging:!0,disableResizing:!0})}}function Qs(e){let{title:t}=e.event;return t&&f("div",{className:"fc-event-title"},e.event.title)}function qs(e){return f("div",{className:"fc-"+e})}const Ys=e=>f(Nr.Consumer,null,t=>{let{dateEnv:n,options:r}=t,{date:i}=e,s=r.weekNumberFormat||e.defaultFormat,o={num:n.computeWeekNumber(i),text:n.format(i,s),date:i};return f(qi,Object.assign({},e,{renderProps:o,generatorName:"weekNumberContent",generator:r.weekNumberContent||Zs,classNameGenerator:r.weekNumberClassNames,didMount:r.weekNumberDidMount,willUnmount:r.weekNumberWillUnmount}))});function Zs(e){return e.text}class Xs extends Br{constructor(){super(...arguments),this.state={titleId:Te()},this.handleRootEl=e=>{this.rootEl=e,this.props.elRef&&jr(this.props.elRef,e)},this.handleDocumentMouseDown=e=>{const t=Re(e);this.rootEl.contains(t)||this.handleCloseClick()},this.handleDocumentKeyDown=e=>{"Escape"===e.key&&this.handleCloseClick()},this.handleCloseClick=()=>{let{onClose:e}=this.props;e&&e()}}render(){let{theme:e,options:t}=this.context,{props:n,state:r}=this,i=["fc-popover",e.getClass("popover")].concat(n.extraClassNames||[]);return function(e,t){var n=f(ae,{__v:e,i:t});return n.containerInfo=t,n}(f("div",Object.assign({},n.extraAttrs,{id:n.id,className:i.join(" "),"aria-labelledby":r.titleId,ref:this.handleRootEl}),f("div",{className:"fc-popover-header "+e.getClass("popoverHeader")},f("span",{className:"fc-popover-title",id:r.titleId},n.title),f("span",{className:"fc-popover-close "+e.getIconClass("close"),title:t.closeHint,onClick:this.handleCloseClick})),f("div",{className:"fc-popover-body "+e.getClass("popoverContent")},n.children)),n.parentEl)}componentDidMount(){document.addEventListener("mousedown",this.handleDocumentMouseDown),document.addEventListener("keydown",this.handleDocumentKeyDown),this.updateSize()}componentWillUnmount(){document.removeEventListener("mousedown",this.handleDocumentMouseDown),document.removeEventListener("keydown",this.handleDocumentKeyDown)}updateSize(){let{isRtl:e}=this.context,{alignmentEl:t,alignGridTop:n}=this.props,{rootEl:r}=this,i=function(e){let t=Ar(e),n=e.getBoundingClientRect();for(let e of t){let t=Qn(n,e.getBoundingClientRect());if(!t)return null;n=t}return n}(t);if(i){let s=r.getBoundingClientRect(),o=n?Ee(t,".fc-scrollgrid").getBoundingClientRect().top:i.top,a=e?i.right-s.width:i.left;o=Math.max(o,10),a=Math.min(a,document.documentElement.clientWidth-10-s.width),a=Math.max(a,10);let l=r.offsetParent.getBoundingClientRect();we(r,{top:o-l.top,left:a-l.left})}}}class Js extends zr{constructor(){super(...arguments),this.handleRootEl=e=>{this.rootEl=e,e?this.context.registerInteractiveComponent(this,{el:e,useEventCenter:!1}):this.context.unregisterInteractiveComponent(this)}}render(){let{options:e,dateEnv:t}=this.context,{props:n}=this,{startDate:r,todayRange:i,dateProfile:s}=n,o=t.format(r,e.dayPopoverFormat);return f(Ws,{elRef:this.handleRootEl,date:r,dateProfile:s,todayRange:i},(t,r,i)=>f(Xs,{elRef:i.ref,id:n.id,title:o,extraClassNames:["fc-more-popover"].concat(i.className||[]),extraAttrs:i,parentEl:n.parentEl,alignmentEl:n.alignmentEl,alignGridTop:n.alignGridTop,onClose:n.onClose},Fs(e)&&f(t,{elTag:"div",elClasses:["fc-more-popover-misc"]}),n.children))}queryHit(e,t,n,r){let{rootEl:i,props:s}=this;return e>=0&&e<n&&t>=0&&t<r?{dateProfile:s.dateProfile,dateSpan:Object.assign({allDay:!0,range:{start:s.startDate,end:s.endDate}},s.extraDateSpan),dayEl:i,rect:{left:0,top:0,right:n,bottom:r},layer:1}:null}}class $s extends Br{constructor(){super(...arguments),this.state={isPopoverOpen:!1,popoverId:Te()},this.handleLinkEl=e=>{this.linkEl=e,this.props.elRef&&jr(this.props.elRef,e)},this.handleClick=e=>{let{props:t,context:n}=this,{moreLinkClick:r}=n.options,i=eo(t).start;function s(e){let{def:t,instance:r,range:i}=e.eventRange;return{event:new Zr(n,t,r),start:n.dateEnv.toDate(i.start),end:n.dateEnv.toDate(i.end),isStart:e.isStart,isEnd:e.isEnd}}"function"==typeof r&&(r=r({date:i,allDay:Boolean(t.allDayDate),allSegs:t.allSegs.map(s),hiddenSegs:t.hiddenSegs.map(s),jsEvent:e,view:n.viewApi})),r&&"popover"!==r?"string"==typeof r&&n.calendarApi.zoomTo(i,r):this.setState({isPopoverOpen:!0})},this.handlePopoverClose=()=>{this.setState({isPopoverOpen:!1})}}render(){let{props:e,state:t}=this;return f(Nr.Consumer,null,n=>{let{viewApi:r,options:i,calendarApi:s}=n,{moreLinkText:o}=i,{moreCnt:a}=e,l=eo(e),c="function"==typeof o?o.call(s,a):`+${a} ${o}`,d=Ze(i.moreLinkHint,[a],c),u={num:a,shortText:"+"+a,text:c,view:r};return f(p,null,Boolean(e.moreCnt)&&f(qi,{elTag:e.elTag||"a",elRef:this.handleLinkEl,elClasses:[...e.elClasses||[],"fc-more-link"],elStyle:e.elStyle,elAttrs:Object.assign(Object.assign(Object.assign({},e.elAttrs),Ne(this.handleClick)),{title:d,"aria-expanded":t.isPopoverOpen,"aria-controls":t.isPopoverOpen?t.popoverId:""}),renderProps:u,generatorName:"moreLinkContent",generator:i.moreLinkContent||e.defaultGenerator||Ks,classNameGenerator:i.moreLinkClassNames,didMount:i.moreLinkDidMount,willUnmount:i.moreLinkWillUnmount},e.children),t.isPopoverOpen&&f(Js,{id:t.popoverId,startDate:l.start,endDate:l.end,dateProfile:e.dateProfile,todayRange:e.todayRange,extraDateSpan:e.extraDateSpan,parentEl:this.parentEl,alignmentEl:e.alignmentElRef?e.alignmentElRef.current:this.linkEl,alignGridTop:e.alignGridTop,onClose:this.handlePopoverClose},e.popoverContent()))})}componentDidMount(){this.updateParentEl()}componentDidUpdate(){this.updateParentEl()}updateParentEl(){this.linkEl&&(this.parentEl=Ee(this.linkEl,".fc-view-harness"))}}function Ks(e){return e.text}function eo(e){if(e.allDayDate)return{start:e.allDayDate,end:St(e.allDayDate,1)};let{hiddenSegs:t}=e;return{start:to(t),end:(n=t,n.reduce(ro).eventRange.range.end)};var n}function to(e){return e.reduce(no).eventRange.range.start}function no(e,t){return e.eventRange.range.start<t.eventRange.range.start?e:t}function ro(e,t){return e.eventRange.range.end>t.eventRange.range.end?e:t}class io extends Br{render(){let{props:e,context:t}=this,{options:n}=t,r={view:t.viewApi};return f(qi,Object.assign({},e,{elTag:e.elTag||"div",elClasses:[...so(e.viewSpec),...e.elClasses||[]],renderProps:r,classNameGenerator:n.viewClassNames,generatorName:void 0,generator:void 0,didMount:n.viewDidMount,willUnmount:n.viewWillUnmount}),()=>e.children)}}function so(e){return[`fc-${e.type}-view`,"fc-view"]}function oo(e){if(!e||"undefined"==typeof document)return;const t=document.head||document.getElementsByTagName("head")[0],n=document.createElement("style");n.type="text/css",t.appendChild(n),n.styleSheet?n.styleSheet.cssText=e:n.appendChild(document.createTextNode(e))}const ao={id:String,defaultAllDay:Boolean,url:String,format:String,events:mn,eventDataTransform:mn,success:mn,failure:mn};function lo(e,t,n=co(t)){let r;if("string"==typeof e?r={url:e}:"function"==typeof e||Array.isArray(e)?r={events:e}:"object"==typeof e&&e&&(r=e),r){let{refined:i,extra:s}=pn(r,n),o=function(e,t){let n=t.pluginHooks.eventSourceDefs;for(let t=n.length-1;t>=0;t-=1){let r=n[t].parseMeta(e);if(r)return{sourceDefId:t,meta:r}}return null}(i,t);if(o)return{_raw:e,isFetching:!1,latestFetchId:"",fetchRange:null,defaultAllDay:i.defaultAllDay,eventDataTransform:i.eventDataTransform,success:i.success,failure:i.failure,publicId:i.id||"",sourceId:Be(),sourceDefId:o.sourceDefId,meta:o.meta,ui:Tn(i,t),extendedProps:s}}return null}function co(e){return Object.assign(Object.assign(Object.assign({},xn),ao),e.pluginHooks.eventSourceRefiners)}class uo{getCurrentData(){return this.currentDataManager.getCurrentData()}dispatch(e){this.currentDataManager.dispatch(e)}get view(){return this.getCurrentData().viewApi}batchRendering(e){e()}updateSize(){this.trigger("_resize",!0)}setOption(e,t){this.dispatch({type:"SET_OPTION",optionName:e,rawOptionValue:t})}getOption(e){return this.currentDataManager.currentCalendarOptionsInput[e]}getAvailableLocaleCodes(){return Object.keys(this.getCurrentData().availableRawLocales)}on(e,t){let{currentDataManager:n}=this;n.currentCalendarOptionsRefiners[e]?n.emitter.on(e,t):console.warn(`Unknown listener name '${e}'`)}off(e,t){this.currentDataManager.emitter.off(e,t)}trigger(e,...t){this.currentDataManager.emitter.trigger(e,...t)}changeView(e,t){this.batchRendering(()=>{if(this.unselect(),t)if(t.start&&t.end)this.dispatch({type:"CHANGE_VIEW_TYPE",viewType:e}),this.dispatch({type:"SET_OPTION",optionName:"visibleRange",rawOptionValue:t});else{let{dateEnv:n}=this.getCurrentData();this.dispatch({type:"CHANGE_VIEW_TYPE",viewType:e,dateMarker:n.createMarker(t)})}else this.dispatch({type:"CHANGE_VIEW_TYPE",viewType:e})})}zoomTo(e,t){let n;t=t||"day",n=this.getCurrentData().viewSpecs[t]||this.getUnitViewSpec(t),this.unselect(),n?this.dispatch({type:"CHANGE_VIEW_TYPE",viewType:n.type,dateMarker:e}):this.dispatch({type:"CHANGE_DATE",dateMarker:e})}getUnitViewSpec(e){let t,n,{viewSpecs:r,toolbarConfig:i}=this.getCurrentData(),s=[].concat(i.header?i.header.viewsWithButtons:[],i.footer?i.footer.viewsWithButtons:[]);for(let e in r)s.push(e);for(t=0;t<s.length;t+=1)if(n=r[s[t]],n&&n.singleUnit===e)return n;return null}prev(){this.unselect(),this.dispatch({type:"PREV"})}next(){this.unselect(),this.dispatch({type:"NEXT"})}prevYear(){let e=this.getCurrentData();this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:e.dateEnv.addYears(e.currentDate,-1)})}nextYear(){let e=this.getCurrentData();this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:e.dateEnv.addYears(e.currentDate,1)})}today(){let e=this.getCurrentData();this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:Ur(e.calendarOptions.now,e.dateEnv)})}gotoDate(e){let t=this.getCurrentData();this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:t.dateEnv.createMarker(e)})}incrementDate(e){let t=this.getCurrentData(),n=tt(e);n&&(this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:t.dateEnv.add(t.currentDate,n)}))}getDate(){let e=this.getCurrentData();return e.dateEnv.toDate(e.currentDate)}formatDate(e,t){let{dateEnv:n}=this.getCurrentData();return n.format(n.createMarker(e),on(t))}formatRange(e,t,n){let{dateEnv:r}=this.getCurrentData();return r.formatRange(r.createMarker(e),r.createMarker(t),on(n),n)}formatIso(e,t){let{dateEnv:n}=this.getCurrentData();return n.formatIso(n.createMarker(e),{omitTime:t})}select(e,t){let n;n=null==t?null!=e.start?e:{start:e,end:null}:{start:e,end:t};let r=this.getCurrentData(),i=pi(n,r.dateEnv,tt({days:1}));i&&(this.dispatch({type:"SELECT_DATES",selection:i}),Wr(i,null,r))}unselect(e){let t=this.getCurrentData();t.dateSelection&&(this.dispatch({type:"UNSELECT_DATES"}),function(e,t){t.emitter.trigger("unselect",{jsEvent:e?e.origEvent:null,view:t.viewApi||t.calendarApi.view})}(e,t))}addEvent(e,t){if(e instanceof Zr){let t=e._def,n=e._instance;return this.getCurrentData().eventStore.defs[t.defId]||(this.dispatch({type:"ADD_EVENTS",eventStore:An({def:t,instance:n})}),this.triggerEventAdd(e)),e}let n,r=this.getCurrentData();if(t instanceof Yr)n=t.internalEventSource;else if("boolean"==typeof t)t&&([n]=gt(r.eventSources));else if(null!=t){let e=this.getEventSourceById(t);if(!e)return console.warn(`Could not find an event source with ID "${t}"`),null;n=e.internalEventSource}let i=Pn(e,n,r,!1);if(i){let e=new Zr(r,i.def,i.def.recurringDef?null:i.instance);return this.dispatch({type:"ADD_EVENTS",eventStore:An(i)}),this.triggerEventAdd(e),e}return null}triggerEventAdd(e){let{emitter:t}=this.getCurrentData();t.trigger("eventAdd",{event:e,relatedEvents:[],revert:()=>{this.dispatch({type:"REMOVE_EVENTS",eventStore:Xr(e)})}})}getEventById(e){let t=this.getCurrentData(),{defs:n,instances:r}=t.eventStore;e=String(e);for(let i in n){let s=n[i];if(s.publicId===e){if(s.recurringDef)return new Zr(t,s,null);for(let e in r){let n=r[e];if(n.defId===s.defId)return new Zr(t,s,n)}}}return null}getEvents(){let e=this.getCurrentData();return Jr(e.eventStore,e)}removeAllEvents(){this.dispatch({type:"REMOVE_ALL_EVENTS"})}getEventSources(){let e=this.getCurrentData(),t=e.eventSources,n=[];for(let r in t)n.push(new Yr(e,t[r]));return n}getEventSourceById(e){let t=this.getCurrentData(),n=t.eventSources;e=String(e);for(let r in n)if(n[r].publicId===e)return new Yr(t,n[r]);return null}addEventSource(e){let t=this.getCurrentData();if(e instanceof Yr)return t.eventSources[e.internalEventSource.sourceId]||this.dispatch({type:"ADD_EVENT_SOURCES",sources:[e.internalEventSource]}),e;let n=lo(e,t);return n?(this.dispatch({type:"ADD_EVENT_SOURCES",sources:[n]}),new Yr(t,n)):null}removeAllEventSources(){this.dispatch({type:"REMOVE_ALL_EVENT_SOURCES"})}refetchEvents(){this.dispatch({type:"FETCH_EVENT_SOURCES",isRefetch:!0})}scrollToTime(e){let t=tt(e);t&&this.trigger("_scrollRequest",{time:t})}}var ho={__proto__:null,BASE_OPTION_DEFAULTS:ln,BaseComponent:Br,BgEvent:Gs,CalendarImpl:uo,CalendarRoot:zi,ContentContainer:qi,CustomRenderingStore:class extends class{constructor(){this.handlers=[]}set(e){this.currentValue=e;for(let t of this.handlers)t(e)}subscribe(e){this.handlers.push(e),void 0!==this.currentValue&&e(this.currentValue)}}{constructor(){super(...arguments),this.map=new Map}handle(e){const{map:t}=this;let n=!1;e.isActive?(t.set(e.id,e),n=!0):t.has(e.id)&&(t.delete(e.id),n=!0),n&&this.set(t)}},DateComponent:zr,DateEnv:wi,DateProfileGenerator:Lr,DayCellContainer:Ws,DayHeader:es,DaySeriesModel:ns,DayTableModel:rs,DelayedRunner:ys,ElementDragging:Pi,ElementScrollController:xr,Emitter:Sr,EventContainer:Bs,EventImpl:Zr,Interaction:Ii,MoreLinkContainer:$s,NamedTimeZoneImpl:class{constructor(e){this.timeZoneName=e}},NowIndicatorContainer:Us,NowTimer:$i,PositionCache:wr,RefMap:Ds,ScrollController:Rr,ScrollResponder:Or,Scroller:As,SegHierarchy:Ci,SimpleScrollGrid:Hs,Slicer:is,Splitter:Kn,StandardEvent:js,TableDateCell:Zi,TableDowCell:Ji,Theme:Tr,ViewContainer:io,ViewContextType:Nr,WeekNumberContainer:Ys,WindowScrollController:_r,addDays:St,addDurations:rt,addMs:wt,addWeeks:Dt,allowContextMenu:Fe,allowSelection:Le,applyMutationToEventStore:Gr,applyStyle:we,asCleanDays:function(e){return e.years||e.months||e.milliseconds?0:e.days},asRoughMinutes:function(e){return ot(e)/6e4},asRoughMs:ot,asRoughSeconds:function(e){return ot(e)/1e3},binarySearch:Mi,buildElAttrs:Gi,buildEntryKey:xi,buildEventApis:Jr,buildEventRangeKey:hi,buildIsoString:zt,buildNavLinkAttrs:hr,buildSegTimeText:ci,collectFromHash:Et,combineEventUis:kn,compareByFieldSpecs:Ge,compareNumbers:Xe,compareObjs:bt,computeEarliestSegStart:to,computeEdges:br,computeFallbackHeaderFormat:Ui,computeInnerRect:yr,computeRect:Er,computeShrinkWidth:Ss,computeVisibleDayRange:Wn,config:Hi,constrainPoint:qn,createDuration:tt,createEmptyEventStore:Sn,createEventInstance:vn,createEventUi:Tn,createFormatter:on,diffDates:Vn,diffDayAndTime:xt,diffDays:Rt,diffPoints:Zn,diffWeeks:Ct,diffWholeDays:Tt,diffWholeWeeks:_t,disableCursor:je,elementClosest:Ee,elementMatches:Ae,enableCursor:ze,eventTupleToStore:An,filterHash:ut,findDirectChildren:function(e,t){let n=e instanceof HTMLElement?[e]:e,r=[];for(let e=0;e<n.length;e+=1){let i=n[e].children;for(let e=0;e<i.length;e+=1){let n=i[e];t&&!Ae(n,t)||r.push(n)}}return r},findElements:De,flexibleCompare:qe,formatDayString:Ut,formatIsoTimeString:Lt,getAllowYScrolling:Cs,getCanVGrowWithinCell:Jn,getClippingParents:Ar,getDateMeta:lr,getDayClassNames:cr,getDefaultEventEnd:Vr,getElRoot:xe,getElSeg:ti,getEntrySpanEnd:Ri,getEventTargetViaRoot:Re,getIsRtlScrollbarOnLeft:pr,getRectCenter:Yn,getRelevantEvents:Dn,getScrollGridClassNames:Ms,getScrollbarWidths:mr,getSectionClassNames:Is,getSectionHasLiquidHeight:ws,getSegAnchorAttrs:fi,getSegMeta:di,getSlotClassNames:function(e,t){let n=["fc-slot","fc-slot-"+At[e.dow]];return e.isDisabled?n.push("fc-slot-disabled"):(e.isToday&&(n.push("fc-slot-today"),n.push(t.getClass("today"))),e.isPast&&n.push("fc-slot-past"),e.isFuture&&n.push("fc-slot-future")),n},getStickyFooterScrollbar:Ps,getStickyHeaderDates:Ns,getUniqueDomId:Te,greatestDurationDenominator:lt,groupIntersectingEntries:_i,guid:Be,hasBgRendering:Kr,hasCustomDayCellContent:Fs,hasShrinkWidth:ks,identity:mn,injectStyles:oo,interactionSettingsStore:Ni,interactionSettingsToStore:Oi,intersectRanges:rr,intersectRects:Qn,intersectSpans:Ti,isArraysEqual:Ft,isColPropsEqual:xs,isDateSelectionValid:ds,isDateSpansEqual:mi,isInt:Je,isInteractionValid:cs,isMultiDayRange:Fn,isPropsEqual:pt,isPropsValid:hs,isValidDate:Bt,mapHash:ht,memoize:Vt,memoizeArraylike:function(e,t,n){let r=[],i=[];return s=>{let o=r.length,a=s.length,l=0;for(;l<o;l+=1)if(s[l]){if(!Ft(r[l],s[l])){n&&n(i[l]);let r=e.apply(this,s[l]);t&&t(r,i[l])||(i[l]=r)}}else n&&n(i[l]);for(;l<a;l+=1)i[l]=e.apply(this,s[l]);return r=s,i.splice(a),i}},memoizeHashlike:function(e,t,n){let r={},i={};return s=>{let o={};for(let a in s)if(i[a])if(Ft(r[a],s[a]))o[a]=i[a];else{n&&n(i[a]);let r=e.apply(this,s[a]);o[a]=t&&t(r,i[a])?i[a]:r}else o[a]=e.apply(this,s[a]);return r=s,i=o,o}},memoizeObjArg:Gt,mergeEventStores:wn,multiplyDuration:it,padStart:Ye,parseBusinessHours:Un,parseClassNames:Rn,parseDragMeta:ji,parseEventDef:jn,parseFieldSpecs:Ve,parseMarker:Si,pointInsideRect:Gn,preventContextMenu:We,preventDefault:ke,preventSelection:Ue,rangeContainsMarker:ar,rangeContainsRange:or,rangesEqual:ir,rangesIntersect:sr,refineEventDef:Hn,refineProps:pn,removeElement:ye,removeExact:function(e,t){let n=0,r=0;for(;r<e.length;)e[r]===t?(e.splice(r,1),n+=1):r+=1;return n},renderChunkContent:Rs,renderFill:qs,renderMicroColGroup:_s,renderScrollShim:Os,requestJson:bs,sanitizeShrinkWidth:Ts,setRef:jr,sliceEventStore:$r,sortEventSegs:ii,startOfDay:kt,translateRect:function(e,t,n){return{left:e.left+t,right:e.right+t,top:e.top+n,bottom:e.bottom+n}},triggerDateSelect:Wr,unpromisify:Dr,whenTransitionDone:Oe,wholeDivideDurations:at};oo(':root{--fc-small-font-size:.85em;--fc-page-bg-color:#fff;--fc-neutral-bg-color:hsla(0,0%,82%,.3);--fc-neutral-text-color:grey;--fc-border-color:#ddd;--fc-button-text-color:#fff;--fc-button-bg-color:#2c3e50;--fc-button-border-color:#2c3e50;--fc-button-hover-bg-color:#1e2b37;--fc-button-hover-border-color:#1a252f;--fc-button-active-bg-color:#1a252f;--fc-button-active-border-color:#151e27;--fc-event-bg-color:#3788d8;--fc-event-border-color:#3788d8;--fc-event-text-color:#fff;--fc-event-selected-overlay-color:rgba(0,0,0,.25);--fc-more-link-bg-color:#d0d0d0;--fc-more-link-text-color:inherit;--fc-event-resizer-thickness:8px;--fc-event-resizer-dot-total-width:8px;--fc-event-resizer-dot-border-width:1px;--fc-non-business-color:hsla(0,0%,84%,.3);--fc-bg-event-color:#8fdf82;--fc-bg-event-opacity:0.3;--fc-highlight-color:rgba(188,232,241,.3);--fc-today-bg-color:rgba(255,220,40,.15);--fc-now-indicator-color:red}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc-unselectable{-webkit-touch-callout:none;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-moz-user-select:none;user-select:none}.fc{display:flex;flex-direction:column;font-size:1em}.fc,.fc *,.fc :after,.fc :before{box-sizing:border-box}.fc table{border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{padding:0;vertical-align:top}.fc a[data-navlink]{cursor:pointer}.fc a[data-navlink]:hover{text-decoration:underline}.fc-direction-ltr{direction:ltr;text-align:left}.fc-direction-rtl{direction:rtl;text-align:right}.fc-theme-standard td,.fc-theme-standard th{border:1px solid var(--fc-border-color)}.fc-liquid-hack td,.fc-liquid-hack th{position:relative}@font-face{font-family:fcicons;font-style:normal;font-weight:400;src:url("data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBfAAAAC8AAAAYGNtYXAXVtKNAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5ZgYydxIAAAF4AAAFNGhlYWQUJ7cIAAAGrAAAADZoaGVhB20DzAAABuQAAAAkaG10eCIABhQAAAcIAAAALGxvY2ED4AU6AAAHNAAAABhtYXhwAA8AjAAAB0wAAAAgbmFtZXsr690AAAdsAAABhnBvc3QAAwAAAAAI9AAAACAAAwPAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpBgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6Qb//f//AAAAAAAg6QD//f//AAH/4xcEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAWIAjQKeAskAEwAAJSc3NjQnJiIHAQYUFwEWMjc2NCcCnuLiDQ0MJAz/AA0NAQAMJAwNDcni4gwjDQwM/wANIwz/AA0NDCMNAAAAAQFiAI0CngLJABMAACUBNjQnASYiBwYUHwEHBhQXFjI3AZ4BAA0N/wAMJAwNDeLiDQ0MJAyNAQAMIw0BAAwMDSMM4uINIwwNDQAAAAIA4gC3Ax4CngATACcAACUnNzY0JyYiDwEGFB8BFjI3NjQnISc3NjQnJiIPAQYUHwEWMjc2NCcB87e3DQ0MIw3VDQ3VDSMMDQ0BK7e3DQ0MJAzVDQ3VDCQMDQ3zuLcMJAwNDdUNIwzWDAwNIwy4twwkDA0N1Q0jDNYMDA0jDAAAAgDiALcDHgKeABMAJwAAJTc2NC8BJiIHBhQfAQcGFBcWMjchNzY0LwEmIgcGFB8BBwYUFxYyNwJJ1Q0N1Q0jDA0Nt7cNDQwjDf7V1Q0N1QwkDA0Nt7cNDQwkDLfWDCMN1Q0NDCQMt7gMIw0MDNYMIw3VDQ0MJAy3uAwjDQwMAAADAFUAAAOrA1UAMwBoAHcAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMhMjY1NCYjISIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAAVYRGRkR/qoRGRkRA1UFBAUOCQkVDAsZDf2rDRkLDBUJCA4FBQUFBQUOCQgVDAsZDQJVDRkLDBUJCQ4FBAVVAgECBQMCBwQECAX9qwQJAwQHAwMFAQICAgIBBQMDBwQDCQQCVQUIBAQHAgMFAgEC/oAZEhEZGRESGQAAAAADAFUAAAOrA1UAMwBoAIkAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMzFRQWMzI2PQEzMjY1NCYrATU0JiMiBh0BIyIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAgBkSEhmAERkZEYAZEhIZgBEZGREDVQUEBQ4JCRUMCxkN/asNGQsMFQkIDgUFBQUFBQ4JCBUMCxkNAlUNGQsMFQkJDgUEBVUCAQIFAwIHBAQIBf2rBAkDBAcDAwUBAgICAgEFAwMHBAMJBAJVBQgEBAcCAwUCAQL+gIASGRkSgBkSERmAEhkZEoAZERIZAAABAOIAjQMeAskAIAAAExcHBhQXFjI/ARcWMjc2NC8BNzY0JyYiDwEnJiIHBhQX4uLiDQ0MJAzi4gwkDA0N4uINDQwkDOLiDCQMDQ0CjeLiDSMMDQ3h4Q0NDCMN4uIMIw0MDOLiDAwNIwwAAAABAAAAAQAAa5n0y18PPPUACwQAAAAAANivOVsAAAAA2K85WwAAAAADqwNVAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAAAAAOrAAEAAAAAAAAAAAAAAAAAAAALBAAAAAAAAAAAAAAAAgAAAAQAAWIEAAFiBAAA4gQAAOIEAABVBAAAVQQAAOIAAAAAAAoAFAAeAEQAagCqAOoBngJkApoAAQAAAAsAigADAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGZjaWNvbnMAZgBjAGkAYwBvAG4Ac1ZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGZjaWNvbnMAZgBjAGkAYwBvAG4Ac2ZjaWNvbnMAZgBjAGkAYwBvAG4Ac1JlZ3VsYXIAUgBlAGcAdQBsAGEAcmZjaWNvbnMAZgBjAGkAYwBvAG4Ac0ZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") format("truetype")}.fc-icon{speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font-family:fcicons!important;font-style:normal;font-variant:normal;font-weight:400;height:1em;line-height:1;text-align:center;text-transform:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:1em}.fc-icon-chevron-left:before{content:"\\e900"}.fc-icon-chevron-right:before{content:"\\e901"}.fc-icon-chevrons-left:before{content:"\\e902"}.fc-icon-chevrons-right:before{content:"\\e903"}.fc-icon-minus-square:before{content:"\\e904"}.fc-icon-plus-square:before{content:"\\e905"}.fc-icon-x:before{content:"\\e906"}.fc .fc-button{border-radius:0;font-family:inherit;font-size:inherit;line-height:inherit;margin:0;overflow:visible;text-transform:none}.fc .fc-button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.fc .fc-button{-webkit-appearance:button}.fc .fc-button:not(:disabled){cursor:pointer}.fc .fc-button::-moz-focus-inner{border-style:none;padding:0}.fc .fc-button{background-color:transparent;border:1px solid transparent;border-radius:.25em;display:inline-block;font-size:1em;font-weight:400;line-height:1.5;padding:.4em .65em;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}.fc .fc-button:hover{text-decoration:none}.fc .fc-button:focus{box-shadow:0 0 0 .2rem rgba(44,62,80,.25);outline:0}.fc .fc-button:disabled{opacity:.65}.fc .fc-button-primary{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:hover{background-color:var(--fc-button-hover-bg-color);border-color:var(--fc-button-hover-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:disabled{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button-primary:not(:disabled).fc-button-active,.fc .fc-button-primary:not(:disabled):active{background-color:var(--fc-button-active-bg-color);border-color:var(--fc-button-active-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:not(:disabled).fc-button-active:focus,.fc .fc-button-primary:not(:disabled):active:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button .fc-icon{font-size:1.5em;vertical-align:middle}.fc .fc-button-group{display:inline-flex;position:relative;vertical-align:middle}.fc .fc-button-group>.fc-button{flex:1 1 auto;position:relative}.fc .fc-button-group>.fc-button.fc-button-active,.fc .fc-button-group>.fc-button:active,.fc .fc-button-group>.fc-button:focus,.fc .fc-button-group>.fc-button:hover{z-index:1}.fc-direction-ltr .fc-button-group>.fc-button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;margin-left:-1px}.fc-direction-ltr .fc-button-group>.fc-button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.fc-direction-rtl .fc-button-group>.fc-button:not(:first-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.fc-direction-rtl .fc-button-group>.fc-button:not(:last-child){border-bottom-left-radius:0;border-top-left-radius:0}.fc .fc-toolbar{align-items:center;display:flex;justify-content:space-between}.fc .fc-toolbar.fc-header-toolbar{margin-bottom:1.5em}.fc .fc-toolbar.fc-footer-toolbar{margin-top:1.5em}.fc .fc-toolbar-title{font-size:1.75em;margin:0}.fc-direction-ltr .fc-toolbar>*>:not(:first-child){margin-left:.75em}.fc-direction-rtl .fc-toolbar>*>:not(:first-child){margin-right:.75em}.fc-direction-rtl .fc-toolbar-ltr{flex-direction:row-reverse}.fc .fc-scroller{-webkit-overflow-scrolling:touch;position:relative}.fc .fc-scroller-liquid{height:100%}.fc .fc-scroller-liquid-absolute{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-scroller-harness{direction:ltr;overflow:hidden;position:relative}.fc .fc-scroller-harness-liquid{height:100%}.fc-direction-rtl .fc-scroller-harness>.fc-scroller{direction:rtl}.fc-theme-standard .fc-scrollgrid{border:1px solid var(--fc-border-color)}.fc .fc-scrollgrid,.fc .fc-scrollgrid table{table-layout:fixed;width:100%}.fc .fc-scrollgrid table{border-left-style:hidden;border-right-style:hidden;border-top-style:hidden}.fc .fc-scrollgrid{border-bottom-width:0;border-collapse:separate;border-right-width:0}.fc .fc-scrollgrid-liquid{height:100%}.fc .fc-scrollgrid-section,.fc .fc-scrollgrid-section table,.fc .fc-scrollgrid-section>td{height:1px}.fc .fc-scrollgrid-section-liquid>td{height:100%}.fc .fc-scrollgrid-section>*{border-left-width:0;border-top-width:0}.fc .fc-scrollgrid-section-footer>*,.fc .fc-scrollgrid-section-header>*{border-bottom-width:0}.fc .fc-scrollgrid-section-body table,.fc .fc-scrollgrid-section-footer table{border-bottom-style:hidden}.fc .fc-scrollgrid-section-sticky>*{background:var(--fc-page-bg-color);position:sticky;z-index:3}.fc .fc-scrollgrid-section-header.fc-scrollgrid-section-sticky>*{top:0}.fc .fc-scrollgrid-section-footer.fc-scrollgrid-section-sticky>*{bottom:0}.fc .fc-scrollgrid-sticky-shim{height:1px;margin-bottom:-1px}.fc-sticky{position:sticky}.fc .fc-view-harness{flex-grow:1;position:relative}.fc .fc-view-harness-active>.fc-view{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-col-header-cell-cushion{display:inline-block;padding:2px 4px}.fc .fc-bg-event,.fc .fc-highlight,.fc .fc-non-business{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-non-business{background:var(--fc-non-business-color)}.fc .fc-bg-event{background:var(--fc-bg-event-color);opacity:var(--fc-bg-event-opacity)}.fc .fc-bg-event .fc-event-title{font-size:var(--fc-small-font-size);font-style:italic;margin:.5em}.fc .fc-highlight{background:var(--fc-highlight-color)}.fc .fc-cell-shaded,.fc .fc-day-disabled{background:var(--fc-neutral-bg-color)}a.fc-event,a.fc-event:hover{text-decoration:none}.fc-event.fc-event-draggable,.fc-event[href]{cursor:pointer}.fc-event .fc-event-main{position:relative;z-index:2}.fc-event-dragging:not(.fc-event-selected){opacity:.75}.fc-event-dragging.fc-event-selected{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-event .fc-event-resizer{display:none;position:absolute;z-index:4}.fc-event-selected .fc-event-resizer,.fc-event:hover .fc-event-resizer{display:block}.fc-event-selected .fc-event-resizer{background:var(--fc-page-bg-color);border-color:inherit;border-radius:calc(var(--fc-event-resizer-dot-total-width)/2);border-style:solid;border-width:var(--fc-event-resizer-dot-border-width);height:var(--fc-event-resizer-dot-total-width);width:var(--fc-event-resizer-dot-total-width)}.fc-event-selected .fc-event-resizer:before{bottom:-20px;content:"";left:-20px;position:absolute;right:-20px;top:-20px}.fc-event-selected,.fc-event:focus{box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event-selected:before,.fc-event:focus:before{bottom:0;content:"";left:0;position:absolute;right:0;top:0;z-index:3}.fc-event-selected:after,.fc-event:focus:after{background:var(--fc-event-selected-overlay-color);bottom:-1px;content:"";left:-1px;position:absolute;right:-1px;top:-1px;z-index:1}.fc-h-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-h-event .fc-event-main{color:var(--fc-event-text-color)}.fc-h-event .fc-event-main-frame{display:flex}.fc-h-event .fc-event-time{max-width:100%;overflow:hidden}.fc-h-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-width:0}.fc-h-event .fc-event-title{display:inline-block;left:0;max-width:100%;overflow:hidden;right:0;vertical-align:top}.fc-h-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-start),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-end){border-bottom-left-radius:0;border-left-width:0;border-top-left-radius:0}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-end),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-start){border-bottom-right-radius:0;border-right-width:0;border-top-right-radius:0}.fc-h-event:not(.fc-event-selected) .fc-event-resizer{bottom:0;top:0;width:var(--fc-event-resizer-thickness)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end{cursor:w-resize;left:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start{cursor:e-resize;right:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-h-event.fc-event-selected .fc-event-resizer{margin-top:calc(var(--fc-event-resizer-dot-total-width)*-.5);top:50%}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-start,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-end{left:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-end,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-start{right:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc .fc-popover{box-shadow:0 2px 6px rgba(0,0,0,.15);position:absolute;z-index:9999}.fc .fc-popover-header{align-items:center;display:flex;flex-direction:row;justify-content:space-between;padding:3px 4px}.fc .fc-popover-title{margin:0 2px}.fc .fc-popover-close{cursor:pointer;font-size:1.1em;opacity:.65}.fc-theme-standard .fc-popover{background:var(--fc-page-bg-color);border:1px solid var(--fc-border-color)}.fc-theme-standard .fc-popover-header{background:var(--fc-neutral-bg-color)}');const fo=[],go={code:"en",week:{dow:0,doy:4},direction:"ltr",buttonText:{prev:"prev",next:"next",prevYear:"prev year",nextYear:"next year",year:"year",today:"today",month:"month",week:"week",day:"day",list:"list"},weekText:"W",weekTextLong:"Week",closeHint:"Close",timeHint:"Time",eventHint:"Event",allDayText:"all-day",moreLinkText:"more",noEventsText:"No events to display"},po=Object.assign(Object.assign({},go),{buttonHints:{prev:"Previous $0",next:"Next $0",today:(e,t)=>"day"===t?"Today":"This "+e},viewHint:"$0 view",navLinkHint:"Go to $0",moreLinkHint:e=>`Show ${e} more event${1===e?"":"s"}`});function mo(e){let t=e.length>0?e[0].code:"en",n=fo.concat(e),r={en:po};for(let e of n)r[e.code]=e;return{map:r,defaultCode:t}}function vo(e,t){return"object"!=typeof e||Array.isArray(e)?function(e,t){let n=[].concat(e||[]),r=function(e,t){for(let n=0;n<e.length;n+=1){let r=e[n].toLocaleLowerCase().split("-");for(let e=r.length;e>0;e-=1){let n=r.slice(0,e).join("-");if(t[n])return t[n]}}return null}(n,t)||po;return bo(e,n,r)}(e,t):bo(e.code,[e.code],e)}function bo(e,t,n){let r=dt([go,n],["buttonText"]);delete r.code;let{week:i}=r;return delete r.week,{codeArg:e,codes:t,week:i,simpleNumberFormat:new Intl.NumberFormat(e),options:r}}function yo(e){return{id:Be(),name:e.name,premiumReleaseDate:e.premiumReleaseDate?new Date(e.premiumReleaseDate):void 0,deps:e.deps||[],reducers:e.reducers||[],isLoadingFuncs:e.isLoadingFuncs||[],contextInit:[].concat(e.contextInit||[]),eventRefiners:e.eventRefiners||{},eventDefMemberAdders:e.eventDefMemberAdders||[],eventSourceRefiners:e.eventSourceRefiners||{},isDraggableTransformers:e.isDraggableTransformers||[],eventDragMutationMassagers:e.eventDragMutationMassagers||[],eventDefMutationAppliers:e.eventDefMutationAppliers||[],dateSelectionTransformers:e.dateSelectionTransformers||[],datePointTransforms:e.datePointTransforms||[],dateSpanTransforms:e.dateSpanTransforms||[],views:e.views||{},viewPropsTransformers:e.viewPropsTransformers||[],isPropsValid:e.isPropsValid||null,externalDefTransforms:e.externalDefTransforms||[],viewContainerAppends:e.viewContainerAppends||[],eventDropTransformers:e.eventDropTransformers||[],componentInteractions:e.componentInteractions||[],calendarInteractions:e.calendarInteractions||[],themeClasses:e.themeClasses||{},eventSourceDefs:e.eventSourceDefs||[],cmdFormatter:e.cmdFormatter,recurringTypes:e.recurringTypes||[],namedTimeZonedImpl:e.namedTimeZonedImpl,initialView:e.initialView||"",elementDraggingImpl:e.elementDraggingImpl,optionChangeHandlers:e.optionChangeHandlers||{},scrollGridImpl:e.scrollGridImpl||null,listenerRefiners:e.listenerRefiners||{},optionRefiners:e.optionRefiners||{},propSetHandlers:e.propSetHandlers||{}}}function Eo(){let e,t=[],n=[];return(r,i)=>(e&&Ft(r,t)&&Ft(i,n)||(e=function(e,t){let n={},r={premiumReleaseDate:void 0,reducers:[],isLoadingFuncs:[],contextInit:[],eventRefiners:{},eventDefMemberAdders:[],eventSourceRefiners:{},isDraggableTransformers:[],eventDragMutationMassagers:[],eventDefMutationAppliers:[],dateSelectionTransformers:[],datePointTransforms:[],dateSpanTransforms:[],views:{},viewPropsTransformers:[],isPropsValid:null,externalDefTransforms:[],viewContainerAppends:[],eventDropTransformers:[],componentInteractions:[],calendarInteractions:[],themeClasses:{},eventSourceDefs:[],cmdFormatter:null,recurringTypes:[],namedTimeZonedImpl:null,initialView:"",elementDraggingImpl:null,optionChangeHandlers:{},scrollGridImpl:null,listenerRefiners:{},optionRefiners:{},propSetHandlers:{}};function i(e){for(let o of e){const e=o.name,a=n[e];void 0===a?(n[e]=o.id,i(o.deps),s=o,r={premiumReleaseDate:Ao((t=r).premiumReleaseDate,s.premiumReleaseDate),reducers:t.reducers.concat(s.reducers),isLoadingFuncs:t.isLoadingFuncs.concat(s.isLoadingFuncs),contextInit:t.contextInit.concat(s.contextInit),eventRefiners:Object.assign(Object.assign({},t.eventRefiners),s.eventRefiners),eventDefMemberAdders:t.eventDefMemberAdders.concat(s.eventDefMemberAdders),eventSourceRefiners:Object.assign(Object.assign({},t.eventSourceRefiners),s.eventSourceRefiners),isDraggableTransformers:t.isDraggableTransformers.concat(s.isDraggableTransformers),eventDragMutationMassagers:t.eventDragMutationMassagers.concat(s.eventDragMutationMassagers),eventDefMutationAppliers:t.eventDefMutationAppliers.concat(s.eventDefMutationAppliers),dateSelectionTransformers:t.dateSelectionTransformers.concat(s.dateSelectionTransformers),datePointTransforms:t.datePointTransforms.concat(s.datePointTransforms),dateSpanTransforms:t.dateSpanTransforms.concat(s.dateSpanTransforms),views:Object.assign(Object.assign({},t.views),s.views),viewPropsTransformers:t.viewPropsTransformers.concat(s.viewPropsTransformers),isPropsValid:s.isPropsValid||t.isPropsValid,externalDefTransforms:t.externalDefTransforms.concat(s.externalDefTransforms),viewContainerAppends:t.viewContainerAppends.concat(s.viewContainerAppends),eventDropTransformers:t.eventDropTransformers.concat(s.eventDropTransformers),calendarInteractions:t.calendarInteractions.concat(s.calendarInteractions),componentInteractions:t.componentInteractions.concat(s.componentInteractions),themeClasses:Object.assign(Object.assign({},t.themeClasses),s.themeClasses),eventSourceDefs:t.eventSourceDefs.concat(s.eventSourceDefs),cmdFormatter:s.cmdFormatter||t.cmdFormatter,recurringTypes:t.recurringTypes.concat(s.recurringTypes),namedTimeZonedImpl:s.namedTimeZonedImpl||t.namedTimeZonedImpl,initialView:t.initialView||s.initialView,elementDraggingImpl:t.elementDraggingImpl||s.elementDraggingImpl,optionChangeHandlers:Object.assign(Object.assign({},t.optionChangeHandlers),s.optionChangeHandlers),scrollGridImpl:s.scrollGridImpl||t.scrollGridImpl,listenerRefiners:Object.assign(Object.assign({},t.listenerRefiners),s.listenerRefiners),optionRefiners:Object.assign(Object.assign({},t.optionRefiners),s.optionRefiners),propSetHandlers:Object.assign(Object.assign({},t.propSetHandlers),s.propSetHandlers)}):a!==o.id&&console.warn(`Duplicate plugin '${e}'`)}var t,s}return e&&i(e),i(t),r}(r,i)),t=r,n=i,e)}function Ao(e,t){return void 0===e?t:void 0===t?e:new Date(Math.max(e.valueOf(),t.valueOf()))}class Do extends Tr{}function So(e,t,n,r){if(t[e])return t[e];let i=function(e,t,n,r){let i=n[e],s=r[e],o=e=>i&&null!==i[e]?i[e]:s&&null!==s[e]?s[e]:null,a=o("component"),l=o("superType"),c=null;if(l){if(l===e)throw new Error("Can't have a custom view type that references itself");c=So(l,t,n,r)}!a&&c&&(a=c.component);if(!a)return null;return{type:e,component:a,defaults:Object.assign(Object.assign({},c?c.defaults:{}),i?i.rawOptions:{}),overrides:Object.assign(Object.assign({},c?c.overrides:{}),s?s.rawOptions:{})}}(e,t,n,r);return i&&(t[e]=i),i}function wo(e){return ht(e,Co)}function Co(e){let t="function"==typeof e?{component:e}:e,{component:n}=t;var r;return t.content&&(r=t,n=e=>f(Nr.Consumer,null,t=>f(qi,{elTag:"div",elClasses:so(t.viewSpec),renderProps:Object.assign(Object.assign({},e),{nextDayThreshold:t.options.nextDayThreshold}),generatorName:void 0,generator:r.content,classNameGenerator:r.classNames,didMount:r.didMount,willUnmount:r.willUnmount}))),{superType:t.type,component:n,rawOptions:t}}function Ro(e,t,n,r){let i=wo(e),s=wo(t.views);return ht(function(e,t){let n,r={};for(n in e)So(n,r,e,t);for(n in t)So(n,r,e,t);return r}(i,s),e=>function(e,t,n,r,i){let s=e.overrides.duration||e.defaults.duration||r.duration||n.duration,o=null,a="",l="",c={};if(s&&(o=function(e){let t=JSON.stringify(e),n=xo[t];void 0===n&&(n=tt(e),xo[t]=n);return n}(s),o)){let e=lt(o);a=e.unit,1===e.value&&(l=a,c=t[a]?t[a].rawOptions:{})}let d=t=>{let n=t.buttonText||{},r=e.defaults.buttonTextKey;return null!=r&&null!=n[r]?n[r]:null!=n[e.type]?n[e.type]:null!=n[l]?n[l]:null},u=t=>{let n=t.buttonHints||{},r=e.defaults.buttonTextKey;return null!=r&&null!=n[r]?n[r]:null!=n[e.type]?n[e.type]:null!=n[l]?n[l]:null};return{type:e.type,component:e.component,duration:o,durationUnit:a,singleUnit:l,optionDefaults:e.defaults,optionOverrides:Object.assign(Object.assign({},c),e.overrides),buttonTextOverride:d(r)||d(n)||e.overrides.buttonText,buttonTextDefault:d(i)||e.defaults.buttonText||d(ln)||e.type,buttonTitleOverride:u(r)||u(n)||e.overrides.buttonHint,buttonTitleDefault:u(i)||e.defaults.buttonHint||u(ln)}}(e,s,t,n,r))}Do.prototype.classes={root:"fc-theme-standard",tableCellShaded:"fc-cell-shaded",buttonGroup:"fc-button-group",button:"fc-button fc-button-primary",buttonActive:"fc-button-active"},Do.prototype.baseIconClass="fc-icon",Do.prototype.iconClasses={close:"fc-icon-x",prev:"fc-icon-chevron-left",next:"fc-icon-chevron-right",prevYear:"fc-icon-chevrons-left",nextYear:"fc-icon-chevrons-right"},Do.prototype.rtlIconClasses={prev:"fc-icon-chevron-right",next:"fc-icon-chevron-left",prevYear:"fc-icon-chevrons-right",nextYear:"fc-icon-chevrons-left"},Do.prototype.iconOverrideOption="buttonIcons",Do.prototype.iconOverrideCustomButtonOption="icon",Do.prototype.iconOverridePrefix="fc-icon-";let xo={};function _o(e,t,n){let r=t?t.activeRange:null;return Mo({},function(e,t){let n=co(t),r=[].concat(e.eventSources||[]),i=[];e.initialEvents&&r.unshift(e.initialEvents);e.events&&r.unshift(e.events);for(let e of r){let r=lo(e,t,n);r&&i.push(r)}return i}(e,n),r,n)}function To(e,t,n,r){let i=n?n.activeRange:null;switch(t.type){case"ADD_EVENT_SOURCES":return Mo(e,t.sources,i,r);case"REMOVE_EVENT_SOURCE":return s=e,o=t.sourceId,ut(s,e=>e.sourceId!==o);case"PREV":case"NEXT":case"CHANGE_DATE":case"CHANGE_VIEW_TYPE":return n?Io(e,i,r):e;case"FETCH_EVENT_SOURCES":return Oo(e,t.sourceIds?ft(t.sourceIds):Po(e,r),i,t.isRefetch||!1,r);case"RECEIVE_EVENTS":case"RECEIVE_EVENT_ERROR":return function(e,t,n,r){let i=e[t];if(i&&n===i.latestFetchId)return Object.assign(Object.assign({},e),{[t]:Object.assign(Object.assign({},i),{isFetching:!1,fetchRange:r})});return e}(e,t.sourceId,t.fetchId,t.fetchRange);case"REMOVE_ALL_EVENT_SOURCES":return{};default:return e}var s,o}function ko(e){for(let t in e)if(e[t].isFetching)return!0;return!1}function Mo(e,t,n,r){let i={};for(let e of t)i[e.sourceId]=e;return n&&(i=Io(i,n,r)),Object.assign(Object.assign({},e),i)}function Io(e,t,n){return Oo(e,ut(e,e=>function(e,t,n){if(!Ho(e,n))return!e.latestFetchId;return!n.options.lazyFetching||!e.fetchRange||e.isFetching||t.start<e.fetchRange.start||t.end>e.fetchRange.end}(e,t,n)),t,!1,n)}function Oo(e,t,n,r,i){let s={};for(let o in e){let a=e[o];t[o]?s[o]=No(a,n,r,i):s[o]=a}return s}function No(e,t,n,r){let{options:i,calendarApi:s}=r,o=r.pluginHooks.eventSourceDefs[e.sourceDefId],a=Be();return o.fetch({eventSource:e,range:t,isRefetch:n,context:r},n=>{let{rawEvents:o}=n;i.eventSourceSuccess&&(o=i.eventSourceSuccess.call(s,o,n.response)||o),e.success&&(o=e.success.call(s,o,n.response)||o),r.dispatch({type:"RECEIVE_EVENTS",sourceId:e.sourceId,fetchId:a,fetchRange:t,rawEvents:o})},n=>{let o=!1;i.eventSourceFailure&&(i.eventSourceFailure.call(s,n),o=!0),e.failure&&(e.failure(n),o=!0),o||console.warn(n.message,n),r.dispatch({type:"RECEIVE_EVENT_ERROR",sourceId:e.sourceId,fetchId:a,fetchRange:t,error:n})}),Object.assign(Object.assign({},e),{isFetching:!0,latestFetchId:a})}function Po(e,t){return ut(e,e=>Ho(e,t))}function Ho(e,t){return!t.pluginHooks.eventSourceDefs[e.sourceDefId].ignoreRange}function Bo(e,t){switch(t.type){case"UNSELECT_DATES":return null;case"SELECT_DATES":return t.selection;default:return e}}function jo(e,t){switch(t.type){case"UNSELECT_EVENT":return"";case"SELECT_EVENT":return t.eventInstanceId;default:return e}}function zo(e,t){let n;switch(t.type){case"UNSET_EVENT_DRAG":return null;case"SET_EVENT_DRAG":return n=t.state,{affectedEvents:n.affectedEvents,mutatedEvents:n.mutatedEvents,isEvent:n.isEvent};default:return e}}function Uo(e,t){let n;switch(t.type){case"UNSET_EVENT_RESIZE":return null;case"SET_EVENT_RESIZE":return n=t.state,{affectedEvents:n.affectedEvents,mutatedEvents:n.mutatedEvents,isEvent:n.isEvent};default:return e}}function Lo(e,t,n,r,i){return{header:e.headerToolbar?Wo(e.headerToolbar,e,t,n,r,i):null,footer:e.footerToolbar?Wo(e.footerToolbar,e,t,n,r,i):null}}function Wo(e,t,n,r,i,s){let o={},a=[],l=!1;for(let c in e){let d=Fo(e[c],t,n,r,i,s);o[c]=d.widgets,a.push(...d.viewsWithButtons),l=l||d.hasTitle}return{sectionWidgets:o,viewsWithButtons:a,hasTitle:l}}function Fo(e,t,n,r,i,s){let o="rtl"===t.direction,a=t.customButtons||{},l=n.buttonText||{},c=t.buttonText||{},d=n.buttonHints||{},u=t.buttonHints||{},h=e?e.split(" "):[],f=[],g=!1;return{widgets:h.map(e=>e.split(",").map(e=>{if("title"===e)return g=!0,{buttonName:e};let n,h,p,m,v,b;if(n=a[e])p=e=>{n.click&&n.click.call(e.target,e,e.target)},(m=r.getCustomButtonIconClass(n))||(m=r.getIconClass(e,o))||(v=n.text),b=n.hint||n.text;else if(h=i[e]){f.push(e),p=()=>{s.changeView(e)},(v=h.buttonTextOverride)||(m=r.getIconClass(e,o))||(v=h.buttonTextDefault);let n=h.buttonTextOverride||h.buttonTextDefault;b=Ze(h.buttonTitleOverride||h.buttonTitleDefault||t.viewHint,[n,e],n)}else if(s[e])if(p=()=>{s[e]()},(v=l[e])||(m=r.getIconClass(e,o))||(v=c[e]),"prevYear"===e||"nextYear"===e){let t="prevYear"===e?"prev":"next";b=Ze(d[t]||u[t],[c.year||"year","year"],c[e])}else b=t=>Ze(d[e]||u[e],[c[t]||t,t],c[e]);return{buttonName:e,buttonClick:p,buttonIcon:m,buttonText:v,buttonHint:b}})),viewsWithButtons:f,hasTitle:g}}class Vo{constructor(e,t,n){this.type=e,this.getCurrentData=t,this.dateEnv=n}get calendar(){return this.getCurrentData().calendarApi}get title(){return this.getCurrentData().viewTitle}get activeStart(){return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.start)}get activeEnd(){return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.end)}get currentStart(){return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.start)}get currentEnd(){return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.end)}getOption(e){return this.getCurrentData().options[e]}}function Go(e,t){let n=gt(t.getCurrentData().eventSources),r=[];for(let t of e){let e=!1;for(let r=0;r<n.length;r+=1)if(n[r]._raw===t){n.splice(r,1),e=!0;break}e||r.push(t)}for(let e of n)t.dispatch({type:"REMOVE_EVENT_SOURCE",sourceId:e.sourceId});for(let e of r)t.calendarApi.addEventSource(e)}const Qo=[yo({name:"array-event-source",eventSourceDefs:[{ignoreRange:!0,parseMeta:e=>Array.isArray(e.events)?e.events:null,fetch(e,t){t({rawEvents:e.eventSource.meta})}}]}),yo({name:"func-event-source",eventSourceDefs:[{parseMeta:e=>"function"==typeof e.events?e.events:null,fetch(e,t,n){const{dateEnv:r}=e.context;Dr(e.eventSource.meta.bind(null,vi(e.range,r)),e=>t({rawEvents:e}),n)}}]}),yo({name:"json-event-source",eventSourceRefiners:{method:String,extraParams:mn,startParam:String,endParam:String,timeZoneParam:String},eventSourceDefs:[{parseMeta:e=>!e.url||"json"!==e.format&&e.format?null:{url:e.url,format:"json",method:(e.method||"GET").toUpperCase(),extraParams:e.extraParams,startParam:e.startParam,endParam:e.endParam,timeZoneParam:e.timeZoneParam},fetch(e,t,n){const{meta:r}=e.eventSource,i=function(e,t,n){let r,i,s,o,{dateEnv:a,options:l}=n,c={};r=e.startParam,null==r&&(r=l.startParam);i=e.endParam,null==i&&(i=l.endParam);s=e.timeZoneParam,null==s&&(s=l.timeZoneParam);o="function"==typeof e.extraParams?e.extraParams():e.extraParams||{};Object.assign(c,o),c[r]=a.formatIso(t.start),c[i]=a.formatIso(t.end),"local"!==a.timeZone&&(c[s]=a.timeZone);return c}(r,e.range,e.context);bs(r.method,r.url,i).then(([e,n])=>{t({rawEvents:e,response:n})},n)}}]}),yo({name:"simple-recurring-event",recurringTypes:[{parse(e,t){if(e.daysOfWeek||e.startTime||e.endTime||e.startRecur||e.endRecur){let i,s={daysOfWeek:e.daysOfWeek||null,startTime:e.startTime||null,endTime:e.endTime||null,startRecur:e.startRecur?t.createMarker(e.startRecur):null,endRecur:e.endRecur?t.createMarker(e.endRecur):null};return e.duration&&(i=e.duration),!i&&e.startTime&&e.endTime&&(n=e.endTime,r=e.startTime,i={years:n.years-r.years,months:n.months-r.months,days:n.days-r.days,milliseconds:n.milliseconds-r.milliseconds}),{allDayGuess:Boolean(!e.startTime&&!e.endTime),duration:i,typeData:s}}var n,r;return null},expand(e,t,n){let r=rr(t,{start:e.startRecur,end:e.endRecur});return r?function(e,t,n,r){let i=e?ft(e):null,s=kt(n.start),o=n.end,a=[];for(;s<o;){let e;i&&!i[s.getUTCDay()]||(e=t?r.add(s,t):s,a.push(e)),s=St(s,1)}return a}(e.daysOfWeek,e.startTime,r,n):[]}}],eventRefiners:{daysOfWeek:mn,startTime:tt,endTime:tt,duration:tt,startRecur:mn,endRecur:mn}}),yo({name:"change-handler",optionChangeHandlers:{events(e,t){Go([e],t)},eventSources:Go}}),yo({name:"misc",isLoadingFuncs:[e=>ko(e.eventSources)],propSetHandlers:{dateProfile:function(e,t){t.emitter.trigger("datesSet",Object.assign(Object.assign({},vi(e.activeRange,t.dateEnv)),{view:t.viewApi}))},eventStore:function(e,t){let{emitter:n}=t;n.hasHandlers("eventsSet")&&n.trigger("eventsSet",Jr(e,t))}}})];class qo{constructor(e,t){this.runTaskOption=e,this.drainedOption=t,this.queue=[],this.delayedRunner=new ys(this.drain.bind(this))}request(e,t){this.queue.push(e),this.delayedRunner.request(t)}pause(e){this.delayedRunner.pause(e)}resume(e,t){this.delayedRunner.resume(e,t)}drain(){let{queue:e}=this;for(;e.length;){let t,n=[];for(;t=e.shift();)this.runTask(t),n.push(t);this.drained(n)}}runTask(e){this.runTaskOption&&this.runTaskOption(e)}drained(e){this.drainedOption&&this.drainedOption(e)}}function Yo(e,t,n){let r;return r=/^(year|month)$/.test(e.currentRangeUnit)?e.currentRange:e.activeRange,n.formatRange(r.start,r.end,on(t.titleFormat||function(e){let{currentRangeUnit:t}=e;if("year"===t)return{year:"numeric"};if("month"===t)return{year:"numeric",month:"long"};let n=Tt(e.currentRange.start,e.currentRange.end);if(null!==n&&n>1)return{year:"numeric",month:"short",day:"numeric"};return{year:"numeric",month:"long",day:"numeric"}}(e)),{isEndExclusive:e.isRangeAllDay,defaultSeparator:t.titleRangeSeparator})}class Zo{constructor(e){this.computeOptionsData=Vt(this._computeOptionsData),this.computeCurrentViewData=Vt(this._computeCurrentViewData),this.organizeRawLocales=Vt(mo),this.buildLocale=Vt(vo),this.buildPluginHooks=Eo(),this.buildDateEnv=Vt(Xo),this.buildTheme=Vt(Jo),this.parseToolbars=Vt(Lo),this.buildViewSpecs=Vt(Ro),this.buildDateProfileGenerator=Gt($o),this.buildViewApi=Vt(Ko),this.buildViewUiProps=Gt(na),this.buildEventUiBySource=Vt(ea,pt),this.buildEventUiBases=Vt(ta),this.parseContextBusinessHours=Gt(ia),this.buildTitle=Vt(Yo),this.emitter=new Sr,this.actionRunner=new qo(this._handleAction.bind(this),this.updateData.bind(this)),this.currentCalendarOptionsInput={},this.currentCalendarOptionsRefined={},this.currentViewOptionsInput={},this.currentViewOptionsRefined={},this.currentCalendarOptionsRefiners={},this.getCurrentData=()=>this.data,this.dispatch=e=>{this.actionRunner.request(e)},this.props=e,this.actionRunner.pause();let t={},n=this.computeOptionsData(e.optionOverrides,t,e.calendarApi),r=n.calendarOptions.initialView||n.pluginHooks.initialView,i=this.computeCurrentViewData(r,n,e.optionOverrides,t);e.calendarApi.currentDataManager=this,this.emitter.setThisContext(e.calendarApi),this.emitter.setOptions(i.options);let s=function(e,t){let n=e.initialDate;return null!=n?t.createMarker(n):Ur(e.now,t)}(n.calendarOptions,n.dateEnv),o=i.dateProfileGenerator.build(s);ar(o.activeRange,s)||(s=o.currentRange.start);let a={dateEnv:n.dateEnv,options:n.calendarOptions,pluginHooks:n.pluginHooks,calendarApi:e.calendarApi,dispatch:this.dispatch,emitter:this.emitter,getCurrentData:this.getCurrentData};for(let e of n.pluginHooks.contextInit)e(a);let l=_o(n.calendarOptions,o,a),c={dynamicOptionOverrides:t,currentViewType:r,currentDate:s,dateProfile:o,businessHours:this.parseContextBusinessHours(a),eventSources:l,eventUiBases:{},eventStore:{defs:{},instances:{}},renderableEventStore:{defs:{},instances:{}},dateSelection:null,eventSelection:"",eventDrag:null,eventResize:null,selectionConfig:this.buildViewUiProps(a).selectionConfig},d=Object.assign(Object.assign({},a),c);for(let e of n.pluginHooks.reducers)Object.assign(c,e(null,null,d));ra(c,a)&&this.emitter.trigger("loading",!0),this.state=c,this.updateData(),this.actionRunner.resume()}resetOptions(e,t){let{props:n}=this;n.optionOverrides=t?Object.assign(Object.assign({},n.optionOverrides),e):e,this.actionRunner.request({type:"NOTHING"})}_handleAction(e){let{props:t,state:n,emitter:r}=this,i=function(e,t){switch(t.type){case"SET_OPTION":return Object.assign(Object.assign({},e),{[t.optionName]:t.rawOptionValue});default:return e}}(n.dynamicOptionOverrides,e),s=this.computeOptionsData(t.optionOverrides,i,t.calendarApi),o=function(e,t){switch(t.type){case"CHANGE_VIEW_TYPE":e=t.viewType}return e}(n.currentViewType,e),a=this.computeCurrentViewData(o,s,t.optionOverrides,i);t.calendarApi.currentDataManager=this,r.setThisContext(t.calendarApi),r.setOptions(a.options);let l={dateEnv:s.dateEnv,options:s.calendarOptions,pluginHooks:s.pluginHooks,calendarApi:t.calendarApi,dispatch:this.dispatch,emitter:r,getCurrentData:this.getCurrentData},{currentDate:c,dateProfile:d}=n;this.data&&this.data.dateProfileGenerator!==a.dateProfileGenerator&&(d=a.dateProfileGenerator.build(c)),c=function(e,t){switch(t.type){case"CHANGE_DATE":return t.dateMarker;default:return e}}(c,e),d=function(e,t,n,r){let i;switch(t.type){case"CHANGE_VIEW_TYPE":return r.build(t.dateMarker||n);case"CHANGE_DATE":return r.build(t.dateMarker);case"PREV":if(i=r.buildPrev(e,n),i.isValid)return i;break;case"NEXT":if(i=r.buildNext(e,n),i.isValid)return i}return e}(d,e,c,a.dateProfileGenerator),"PREV"!==e.type&&"NEXT"!==e.type&&ar(d.currentRange,c)||(c=d.currentRange.start);let u=To(n.eventSources,e,d,l),h=os(n.eventStore,e,u,d,l),f=ko(u)&&!a.options.progressiveEventRendering&&n.renderableEventStore||h,{eventUiSingleBase:g,selectionConfig:p}=this.buildViewUiProps(l),m=this.buildEventUiBySource(u),v={dynamicOptionOverrides:i,currentViewType:o,currentDate:c,dateProfile:d,eventSources:u,eventStore:h,renderableEventStore:f,selectionConfig:p,eventUiBases:this.buildEventUiBases(f.defs,g,m),businessHours:this.parseContextBusinessHours(l),dateSelection:Bo(n.dateSelection,e),eventSelection:jo(n.eventSelection,e),eventDrag:zo(n.eventDrag,e),eventResize:Uo(n.eventResize,e)},b=Object.assign(Object.assign({},l),v);for(let t of s.pluginHooks.reducers)Object.assign(v,t(n,e,b));let y=ra(n,l),E=ra(v,l);!y&&E?r.trigger("loading",!0):y&&!E&&r.trigger("loading",!1),this.state=v,t.onAction&&t.onAction(e)}updateData(){let{props:e,state:t}=this,n=this.data,r=this.computeOptionsData(e.optionOverrides,t.dynamicOptionOverrides,e.calendarApi),i=this.computeCurrentViewData(t.currentViewType,r,e.optionOverrides,t.dynamicOptionOverrides),s=this.data=Object.assign(Object.assign(Object.assign({viewTitle:this.buildTitle(t.dateProfile,i.options,r.dateEnv),calendarApi:e.calendarApi,dispatch:this.dispatch,emitter:this.emitter,getCurrentData:this.getCurrentData},r),i),t),o=r.pluginHooks.optionChangeHandlers,a=n&&n.calendarOptions,l=r.calendarOptions;if(a&&a!==l){a.timeZone!==l.timeZone&&(t.eventSources=s.eventSources=function(e,t,n){let r=t?t.activeRange:null;return Oo(e,Po(e,n),r,!0,n)}(s.eventSources,t.dateProfile,s),t.eventStore=s.eventStore=function(e,t,n){let{defs:r}=e,i=ht(e.instances,e=>{let i=r[e.defId];return i.allDay||i.recurringDef?e:Object.assign(Object.assign({},e),{range:{start:n.createMarker(t.toDate(e.range.start,e.forcedStartTzo)),end:n.createMarker(t.toDate(e.range.end,e.forcedEndTzo))},forcedStartTzo:n.canComputeOffset?null:e.forcedStartTzo,forcedEndTzo:n.canComputeOffset?null:e.forcedEndTzo})});return{defs:r,instances:i}}(s.eventStore,n.dateEnv,s.dateEnv));for(let e in o)a[e]!==l[e]&&o[e](l[e],s)}e.onData&&e.onData(s)}_computeOptionsData(e,t,n){let{refinedOptions:r,pluginHooks:i,localeDefaults:s,availableLocaleData:o,extra:a}=this.processRawCalendarOptions(e,t);sa(a);let l=this.buildDateEnv(r.timeZone,r.locale,r.weekNumberCalculation,r.firstDay,r.weekText,i,o,r.defaultRangeSeparator),c=this.buildViewSpecs(i.views,e,t,s),d=this.buildTheme(r,i);return{calendarOptions:r,pluginHooks:i,dateEnv:l,viewSpecs:c,theme:d,toolbarConfig:this.parseToolbars(r,e,d,c,n),localeDefaults:s,availableRawLocales:o.map}}processRawCalendarOptions(e,t){let{locales:n,locale:r}=gn([ln,e,t]),i=this.organizeRawLocales(n),s=i.map,o=this.buildLocale(r||i.defaultCode,s).options,a=this.buildPluginHooks(e.plugins||[],Qo),l=this.currentCalendarOptionsRefiners=Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},an),cn),dn),a.listenerRefiners),a.optionRefiners),c={},d=gn([ln,o,e,t]),u={},h=this.currentCalendarOptionsInput,f=this.currentCalendarOptionsRefined,g=!1;for(let e in d)"plugins"!==e&&(d[e]===h[e]||un[e]&&e in h&&un[e](h[e],d[e])?u[e]=f[e]:l[e]?(u[e]=l[e](d[e]),g=!0):c[e]=h[e]);return g&&(this.currentCalendarOptionsInput=d,this.currentCalendarOptionsRefined=u),{rawOptions:this.currentCalendarOptionsInput,refinedOptions:this.currentCalendarOptionsRefined,pluginHooks:a,availableLocaleData:i,localeDefaults:o,extra:c}}_computeCurrentViewData(e,t,n,r){let i=t.viewSpecs[e];if(!i)throw new Error(`viewType "${e}" is not available. Please make sure you've loaded all neccessary plugins`);let{refinedOptions:s,extra:o}=this.processRawViewOptions(i,t.pluginHooks,t.localeDefaults,n,r);return sa(o),{viewSpec:i,options:s,dateProfileGenerator:this.buildDateProfileGenerator({dateProfileGeneratorClass:i.optionDefaults.dateProfileGeneratorClass,duration:i.duration,durationUnit:i.durationUnit,usesMinMaxTime:i.optionDefaults.usesMinMaxTime,dateEnv:t.dateEnv,calendarApi:this.props.calendarApi,slotMinTime:s.slotMinTime,slotMaxTime:s.slotMaxTime,showNonCurrentDates:s.showNonCurrentDates,dayCount:s.dayCount,dateAlignment:s.dateAlignment,dateIncrement:s.dateIncrement,hiddenDays:s.hiddenDays,weekends:s.weekends,nowInput:s.now,validRangeInput:s.validRange,visibleRangeInput:s.visibleRange,monthMode:s.monthMode,fixedWeekCount:s.fixedWeekCount}),viewApi:this.buildViewApi(e,this.getCurrentData,t.dateEnv)}}processRawViewOptions(e,t,n,r,i){let s=gn([ln,e.optionDefaults,n,r,e.optionOverrides,i]),o=Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},an),cn),dn),fn),t.listenerRefiners),t.optionRefiners),a={},l=this.currentViewOptionsInput,c=this.currentViewOptionsRefined,d=!1,u={};for(let e in s)s[e]===l[e]||un[e]&&un[e](s[e],l[e])?a[e]=c[e]:(s[e]===this.currentCalendarOptionsInput[e]||un[e]&&un[e](s[e],this.currentCalendarOptionsInput[e])?e in this.currentCalendarOptionsRefined&&(a[e]=this.currentCalendarOptionsRefined[e]):o[e]?a[e]=o[e](s[e]):u[e]=s[e],d=!0);return d&&(this.currentViewOptionsInput=s,this.currentViewOptionsRefined=a),{rawOptions:this.currentViewOptionsInput,refinedOptions:this.currentViewOptionsRefined,extra:u}}}function Xo(e,t,n,r,i,s,o,a){let l=vo(t||o.defaultCode,o.map);return new wi({calendarSystem:"gregory",timeZone:e,namedTimeZoneImpl:s.namedTimeZonedImpl,locale:l,weekNumberCalculation:n,firstDay:r,weekText:i,cmdFormatter:s.cmdFormatter,defaultSeparator:a})}function Jo(e,t){return new(t.themeClasses[e.themeSystem]||Do)(e)}function $o(e){return new(e.dateProfileGeneratorClass||Lr)(e)}function Ko(e,t,n){return new Vo(e,t,n)}function ea(e){return ht(e,e=>e.ui)}function ta(e,t,n){let r={"":t};for(let t in e){let i=e[t];i.sourceId&&n[i.sourceId]&&(r[t]=n[i.sourceId])}return r}function na(e){let{options:t}=e;return{eventUiSingleBase:Tn({display:t.eventDisplay,editable:t.editable,startEditable:t.eventStartEditable,durationEditable:t.eventDurationEditable,constraint:t.eventConstraint,overlap:"boolean"==typeof t.eventOverlap?t.eventOverlap:void 0,allow:t.eventAllow,backgroundColor:t.eventBackgroundColor,borderColor:t.eventBorderColor,textColor:t.eventTextColor,color:t.eventColor},e),selectionConfig:Tn({constraint:t.selectConstraint,overlap:"boolean"==typeof t.selectOverlap?t.selectOverlap:void 0,allow:t.selectAllow},e)}}function ra(e,t){for(let n of t.pluginHooks.isLoadingFuncs)if(n(e))return!0;return!1}function ia(e){return Un(e.options.businessHours,e)}function sa(e,t){for(let n in e)console.warn(`Unknown option '${n}'`+(t?` for view '${t}'`:""))}class oa extends Br{render(){return f("div",{className:"fc-toolbar-chunk"},...this.props.widgetGroups.map(e=>this.renderWidgetGroup(e)))}renderWidgetGroup(e){let{props:t}=this,{theme:n}=this.context,r=[],i=!0;for(let s of e){let{buttonName:e,buttonClick:o,buttonText:a,buttonIcon:l,buttonHint:c}=s;if("title"===e)i=!1,r.push(f("h2",{className:"fc-toolbar-title",id:t.titleId},t.title));else{let i=e===t.activeButton,s=!t.isTodayEnabled&&"today"===e||!t.isPrevEnabled&&"prev"===e||!t.isNextEnabled&&"next"===e,d=[`fc-${e}-button`,n.getClass("button")];i&&d.push(n.getClass("buttonActive")),r.push(f("button",{type:"button",title:"function"==typeof c?c(t.navUnit):c,disabled:s,"aria-pressed":i,className:d.join(" "),onClick:o},a||(l?f("span",{className:l}):"")))}}if(r.length>1){return f("div",{className:i&&n.getClass("buttonGroup")||""},...r)}return r[0]}}class aa extends Br{render(){let e,t,{model:n,extraClassName:r}=this.props,i=!1,s=n.sectionWidgets,o=s.center;return s.left?(i=!0,e=s.left):e=s.start,s.right?(i=!0,t=s.right):t=s.end,f("div",{className:[r||"","fc-toolbar",i?"fc-toolbar-ltr":""].join(" ")},this.renderSection("start",e||[]),this.renderSection("center",o||[]),this.renderSection("end",t||[]))}renderSection(e,t){let{props:n}=this;return f(oa,{key:e,widgetGroups:t,title:n.title,navUnit:n.navUnit,activeButton:n.activeButton,isTodayEnabled:n.isTodayEnabled,isPrevEnabled:n.isPrevEnabled,isNextEnabled:n.isNextEnabled,titleId:n.titleId})}}class la extends Br{constructor(){super(...arguments),this.state={availableWidth:null},this.handleEl=e=>{this.el=e,jr(this.props.elRef,e),this.updateAvailableWidth()},this.handleResize=()=>{this.updateAvailableWidth()}}render(){let{props:e,state:t}=this,{aspectRatio:n}=e,r=["fc-view-harness",n||e.liquid||e.height?"fc-view-harness-active":"fc-view-harness-passive"],i="",s="";return n?null!==t.availableWidth?i=t.availableWidth/n:s=1/n*100+"%":i=e.height||"",f("div",{"aria-labelledby":e.labeledById,ref:this.handleEl,className:r.join(" "),style:{height:i,paddingBottom:s}},e.children)}componentDidMount(){this.context.addResizeHandler(this.handleResize)}componentWillUnmount(){this.context.removeResizeHandler(this.handleResize)}updateAvailableWidth(){this.el&&this.props.aspectRatio&&this.setState({availableWidth:this.el.offsetWidth})}}class ca extends Ii{constructor(e){super(e),this.handleSegClick=(e,t)=>{let{component:n}=this,{context:r}=n,i=ti(t);if(i&&n.isValidSegDownEl(e.target)){let s=Ee(e.target,".fc-event-forced-url"),o=s?s.querySelector("a[href]").href:"";r.emitter.trigger("eventClick",{el:t,event:new Zr(n.context,i.eventRange.def,i.eventRange.instance),jsEvent:e,view:r.viewApi}),o&&!e.defaultPrevented&&(window.location.href=o)}},this.destroy=Me(e.el,"click",".fc-event",this.handleSegClick)}}class da extends Ii{constructor(e){super(e),this.handleEventElRemove=e=>{e===this.currentSegEl&&this.handleSegLeave(null,this.currentSegEl)},this.handleSegEnter=(e,t)=>{ti(t)&&(this.currentSegEl=t,this.triggerEvent("eventMouseEnter",e,t))},this.handleSegLeave=(e,t)=>{this.currentSegEl&&(this.currentSegEl=null,this.triggerEvent("eventMouseLeave",e,t))},this.removeHoverListeners=function(e,t,n,r){let i;return Me(e,"mouseover",t,(e,t)=>{if(t!==i){i=t,n(e,t);let s=e=>{i=null,r(e,t),t.removeEventListener("mouseleave",s)};t.addEventListener("mouseleave",s)}})}(e.el,".fc-event",this.handleSegEnter,this.handleSegLeave)}destroy(){this.removeHoverListeners()}triggerEvent(e,t,n){let{component:r}=this,{context:i}=r,s=ti(n);t&&!r.isValidSegDownEl(t.target)||i.emitter.trigger(e,{el:n,event:new Zr(i,s.eventRange.def,s.eventRange.instance),jsEvent:t,view:i.viewApi})}}class ua extends Hr{constructor(){super(...arguments),this.buildViewContext=Vt(Pr),this.buildViewPropTransformers=Vt(fa),this.buildToolbarProps=Vt(ha),this.headerRef={current:null},this.footerRef={current:null},this.interactionsStore={},this.state={viewLabelId:Te()},this.registerInteractiveComponent=(e,t)=>{let n=function(e,t){return{component:e,el:t.el,useEventCenter:null==t.useEventCenter||t.useEventCenter,isHitComboAllowed:t.isHitComboAllowed||null}}(e,t),r=[ca,da].concat(this.props.pluginHooks.componentInteractions).map(e=>new e(n));this.interactionsStore[e.uid]=r,Ni[e.uid]=n},this.unregisterInteractiveComponent=e=>{let t=this.interactionsStore[e.uid];if(t){for(let e of t)e.destroy();delete this.interactionsStore[e.uid]}delete Ni[e.uid]},this.resizeRunner=new ys(()=>{this.props.emitter.trigger("_resize",!0),this.props.emitter.trigger("windowResize",{view:this.props.viewApi})}),this.handleWindowResize=e=>{let{options:t}=this.props;t.handleWindowResize&&e.target===window&&this.resizeRunner.request(t.windowResizeDelay)}}render(){let e,{props:t}=this,{toolbarConfig:n,options:r}=t,i=this.buildToolbarProps(t.viewSpec,t.dateProfile,t.dateProfileGenerator,t.currentDate,Ur(t.options.now,t.dateEnv),t.viewTitle),s=!1,o="";t.isHeightAuto||t.forPrint?o="":null!=r.height?s=!0:null!=r.contentHeight?o=r.contentHeight:e=Math.max(r.aspectRatio,.5);let a=this.buildViewContext(t.viewSpec,t.viewApi,t.options,t.dateProfileGenerator,t.dateEnv,t.theme,t.pluginHooks,t.dispatch,t.getCurrentData,t.emitter,t.calendarApi,this.registerInteractiveComponent,this.unregisterInteractiveComponent),l=n.header&&n.header.hasTitle?this.state.viewLabelId:"";return f(Nr.Provider,{value:a},n.header&&f(aa,Object.assign({ref:this.headerRef,extraClassName:"fc-header-toolbar",model:n.header,titleId:l},i)),f(la,{liquid:s,height:o,aspectRatio:e,labeledById:l},this.renderView(t),this.buildAppendContent()),n.footer&&f(aa,Object.assign({ref:this.footerRef,extraClassName:"fc-footer-toolbar",model:n.footer,titleId:""},i)))}componentDidMount(){let{props:e}=this;this.calendarInteractions=e.pluginHooks.calendarInteractions.map(t=>new t(e)),window.addEventListener("resize",this.handleWindowResize);let{propSetHandlers:t}=e.pluginHooks;for(let n in t)t[n](e[n],e)}componentDidUpdate(e){let{props:t}=this,{propSetHandlers:n}=t.pluginHooks;for(let r in n)t[r]!==e[r]&&n[r](t[r],t)}componentWillUnmount(){window.removeEventListener("resize",this.handleWindowResize),this.resizeRunner.clear();for(let e of this.calendarInteractions)e.destroy();this.props.emitter.trigger("_unmount")}buildAppendContent(){let{props:e}=this;return f(p,{},...e.pluginHooks.viewContainerAppends.map(t=>t(e)))}renderView(e){let{pluginHooks:t}=e,{viewSpec:n}=e,r={dateProfile:e.dateProfile,businessHours:e.businessHours,eventStore:e.renderableEventStore,eventUiBases:e.eventUiBases,dateSelection:e.dateSelection,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize,isHeightAuto:e.isHeightAuto,forPrint:e.forPrint},i=this.buildViewPropTransformers(t.viewPropsTransformers);for(let t of i)Object.assign(r,t.transform(r,e));return f(n.component,Object.assign({},r))}}function ha(e,t,n,r,i,s){let o=n.build(i,void 0,!1),a=n.buildPrev(t,r,!1),l=n.buildNext(t,r,!1);return{title:s,activeButton:e.type,navUnit:e.singleUnit,isTodayEnabled:o.isValid&&!ar(t.currentRange,i),isPrevEnabled:a.isValid,isNextEnabled:l.isValid}}function fa(e){return e.map(e=>new e)}function ga(e){let t=vo(e.locale||"en",mo([]).map);return new wi(Object.assign(Object.assign({timeZone:ln.timeZone,calendarSystem:"gregory"},e),{locale:t}))}Hi.touchMouseIgnoreWait=500;let pa=0,ma=0,va=!1;class ba{constructor(e){this.subjectEl=null,this.selector="",this.handleSelector="",this.shouldIgnoreMove=!1,this.shouldWatchScroll=!0,this.isDragging=!1,this.isTouchDragging=!1,this.wasTouchScroll=!1,this.handleMouseDown=e=>{if(!this.shouldIgnoreMouse()&&function(e){return 0===e.button&&!e.ctrlKey}(e)&&this.tryStart(e)){let t=this.createEventFromMouse(e,!0);this.emitter.trigger("pointerdown",t),this.initScrollWatch(t),this.shouldIgnoreMove||document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("mouseup",this.handleMouseUp)}},this.handleMouseMove=e=>{let t=this.createEventFromMouse(e);this.recordCoords(t),this.emitter.trigger("pointermove",t)},this.handleMouseUp=e=>{document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("mouseup",this.handleMouseUp),this.emitter.trigger("pointerup",this.createEventFromMouse(e)),this.cleanup()},this.handleTouchStart=e=>{if(this.tryStart(e)){this.isTouchDragging=!0;let t=this.createEventFromTouch(e,!0);this.emitter.trigger("pointerdown",t),this.initScrollWatch(t);let n=e.target;this.shouldIgnoreMove||n.addEventListener("touchmove",this.handleTouchMove),n.addEventListener("touchend",this.handleTouchEnd),n.addEventListener("touchcancel",this.handleTouchEnd),window.addEventListener("scroll",this.handleTouchScroll,!0)}},this.handleTouchMove=e=>{let t=this.createEventFromTouch(e);this.recordCoords(t),this.emitter.trigger("pointermove",t)},this.handleTouchEnd=e=>{if(this.isDragging){let t=e.target;t.removeEventListener("touchmove",this.handleTouchMove),t.removeEventListener("touchend",this.handleTouchEnd),t.removeEventListener("touchcancel",this.handleTouchEnd),window.removeEventListener("scroll",this.handleTouchScroll,!0),this.emitter.trigger("pointerup",this.createEventFromTouch(e)),this.cleanup(),this.isTouchDragging=!1,pa+=1,setTimeout(()=>{pa-=1},Hi.touchMouseIgnoreWait)}},this.handleTouchScroll=()=>{this.wasTouchScroll=!0},this.handleScroll=e=>{if(!this.shouldIgnoreMove){let t=window.pageXOffset-this.prevScrollX+this.prevPageX,n=window.pageYOffset-this.prevScrollY+this.prevPageY;this.emitter.trigger("pointermove",{origEvent:e,isTouch:this.isTouchDragging,subjectEl:this.subjectEl,pageX:t,pageY:n,deltaX:t-this.origPageX,deltaY:n-this.origPageY})}},this.containerEl=e,this.emitter=new Sr,e.addEventListener("mousedown",this.handleMouseDown),e.addEventListener("touchstart",this.handleTouchStart,{passive:!0}),ma+=1,1===ma&&window.addEventListener("touchmove",ya,{passive:!1})}destroy(){this.containerEl.removeEventListener("mousedown",this.handleMouseDown),this.containerEl.removeEventListener("touchstart",this.handleTouchStart,{passive:!0}),ma-=1,ma||window.removeEventListener("touchmove",ya,{passive:!1})}tryStart(e){let t=this.querySubjectEl(e),n=e.target;return!(!t||this.handleSelector&&!Ee(n,this.handleSelector))&&(this.subjectEl=t,this.isDragging=!0,this.wasTouchScroll=!1,!0)}cleanup(){va=!1,this.isDragging=!1,this.subjectEl=null,this.destroyScrollWatch()}querySubjectEl(e){return this.selector?Ee(e.target,this.selector):this.containerEl}shouldIgnoreMouse(){return pa||this.isTouchDragging}cancelTouchScroll(){this.isDragging&&(va=!0)}initScrollWatch(e){this.shouldWatchScroll&&(this.recordCoords(e),window.addEventListener("scroll",this.handleScroll,!0))}recordCoords(e){this.shouldWatchScroll&&(this.prevPageX=e.pageX,this.prevPageY=e.pageY,this.prevScrollX=window.pageXOffset,this.prevScrollY=window.pageYOffset)}destroyScrollWatch(){this.shouldWatchScroll&&window.removeEventListener("scroll",this.handleScroll,!0)}createEventFromMouse(e,t){let n=0,r=0;return t?(this.origPageX=e.pageX,this.origPageY=e.pageY):(n=e.pageX-this.origPageX,r=e.pageY-this.origPageY),{origEvent:e,isTouch:!1,subjectEl:this.subjectEl,pageX:e.pageX,pageY:e.pageY,deltaX:n,deltaY:r}}createEventFromTouch(e,t){let n,r,i=e.touches,s=0,o=0;return i&&i.length?(n=i[0].pageX,r=i[0].pageY):(n=e.pageX,r=e.pageY),t?(this.origPageX=n,this.origPageY=r):(s=n-this.origPageX,o=r-this.origPageY),{origEvent:e,isTouch:!0,subjectEl:this.subjectEl,pageX:n,pageY:r,deltaX:s,deltaY:o}}}function ya(e){va&&e.preventDefault()}class Ea{constructor(){this.isVisible=!1,this.sourceEl=null,this.mirrorEl=null,this.sourceElRect=null,this.parentNode=document.body,this.zIndex=9999,this.revertDuration=0}start(e,t,n){this.sourceEl=e,this.sourceElRect=this.sourceEl.getBoundingClientRect(),this.origScreenX=t-window.pageXOffset,this.origScreenY=n-window.pageYOffset,this.deltaX=0,this.deltaY=0,this.updateElPosition()}handleMove(e,t){this.deltaX=e-window.pageXOffset-this.origScreenX,this.deltaY=t-window.pageYOffset-this.origScreenY,this.updateElPosition()}setIsVisible(e){e?this.isVisible||(this.mirrorEl&&(this.mirrorEl.style.display=""),this.isVisible=e,this.updateElPosition()):this.isVisible&&(this.mirrorEl&&(this.mirrorEl.style.display="none"),this.isVisible=e)}stop(e,t){let n=()=>{this.cleanup(),t()};e&&this.mirrorEl&&this.isVisible&&this.revertDuration&&(this.deltaX||this.deltaY)?this.doRevertAnimation(n,this.revertDuration):setTimeout(n,0)}doRevertAnimation(e,t){let n=this.mirrorEl,r=this.sourceEl.getBoundingClientRect();n.style.transition="top "+t+"ms,left "+t+"ms",we(n,{left:r.left,top:r.top}),Oe(n,()=>{n.style.transition="",e()})}cleanup(){this.mirrorEl&&(ye(this.mirrorEl),this.mirrorEl=null),this.sourceEl=null}updateElPosition(){this.sourceEl&&this.isVisible&&we(this.getMirrorEl(),{left:this.sourceElRect.left+this.deltaX,top:this.sourceElRect.top+this.deltaY})}getMirrorEl(){let e=this.sourceElRect,t=this.mirrorEl;return t||(t=this.mirrorEl=this.sourceEl.cloneNode(!0),t.classList.add("fc-unselectable"),t.classList.add("fc-event-dragging"),we(t,{position:"fixed",zIndex:this.zIndex,visibility:"",boxSizing:"border-box",width:e.right-e.left,height:e.bottom-e.top,right:"auto",bottom:"auto",margin:0}),this.parentNode.appendChild(t)),t}}class Aa extends Rr{constructor(e,t){super(),this.handleScroll=()=>{this.scrollTop=this.scrollController.getScrollTop(),this.scrollLeft=this.scrollController.getScrollLeft(),this.handleScrollChange()},this.scrollController=e,this.doesListening=t,this.scrollTop=this.origScrollTop=e.getScrollTop(),this.scrollLeft=this.origScrollLeft=e.getScrollLeft(),this.scrollWidth=e.getScrollWidth(),this.scrollHeight=e.getScrollHeight(),this.clientWidth=e.getClientWidth(),this.clientHeight=e.getClientHeight(),this.clientRect=this.computeClientRect(),this.doesListening&&this.getEventTarget().addEventListener("scroll",this.handleScroll)}destroy(){this.doesListening&&this.getEventTarget().removeEventListener("scroll",this.handleScroll)}getScrollTop(){return this.scrollTop}getScrollLeft(){return this.scrollLeft}setScrollTop(e){this.scrollController.setScrollTop(e),this.doesListening||(this.scrollTop=Math.max(Math.min(e,this.getMaxScrollTop()),0),this.handleScrollChange())}setScrollLeft(e){this.scrollController.setScrollLeft(e),this.doesListening||(this.scrollLeft=Math.max(Math.min(e,this.getMaxScrollLeft()),0),this.handleScrollChange())}getClientWidth(){return this.clientWidth}getClientHeight(){return this.clientHeight}getScrollWidth(){return this.scrollWidth}getScrollHeight(){return this.scrollHeight}handleScrollChange(){}}class Da extends Aa{constructor(e,t){super(new xr(e),t)}getEventTarget(){return this.scrollController.el}computeClientRect(){return yr(this.scrollController.el)}}class Sa extends Aa{constructor(e){super(new _r,e)}getEventTarget(){return window}computeClientRect(){return{left:this.scrollLeft,right:this.scrollLeft+this.clientWidth,top:this.scrollTop,bottom:this.scrollTop+this.clientHeight}}handleScrollChange(){this.clientRect=this.computeClientRect()}}const wa="function"==typeof performance?performance.now:Date.now;class Ca{constructor(){this.isEnabled=!0,this.scrollQuery=[window,".fc-scroller"],this.edgeThreshold=50,this.maxVelocity=300,this.pointerScreenX=null,this.pointerScreenY=null,this.isAnimating=!1,this.scrollCaches=null,this.everMovedUp=!1,this.everMovedDown=!1,this.everMovedLeft=!1,this.everMovedRight=!1,this.animate=()=>{if(this.isAnimating){let e=this.computeBestEdge(this.pointerScreenX+window.pageXOffset,this.pointerScreenY+window.pageYOffset);if(e){let t=wa();this.handleSide(e,(t-this.msSinceRequest)/1e3),this.requestAnimation(t)}else this.isAnimating=!1}}}start(e,t,n){this.isEnabled&&(this.scrollCaches=this.buildCaches(n),this.pointerScreenX=null,this.pointerScreenY=null,this.everMovedUp=!1,this.everMovedDown=!1,this.everMovedLeft=!1,this.everMovedRight=!1,this.handleMove(e,t))}handleMove(e,t){if(this.isEnabled){let n=e-window.pageXOffset,r=t-window.pageYOffset,i=null===this.pointerScreenY?0:r-this.pointerScreenY,s=null===this.pointerScreenX?0:n-this.pointerScreenX;i<0?this.everMovedUp=!0:i>0&&(this.everMovedDown=!0),s<0?this.everMovedLeft=!0:s>0&&(this.everMovedRight=!0),this.pointerScreenX=n,this.pointerScreenY=r,this.isAnimating||(this.isAnimating=!0,this.requestAnimation(wa()))}}stop(){if(this.isEnabled){this.isAnimating=!1;for(let e of this.scrollCaches)e.destroy();this.scrollCaches=null}}requestAnimation(e){this.msSinceRequest=e,requestAnimationFrame(this.animate)}handleSide(e,t){let{scrollCache:n}=e,{edgeThreshold:r}=this,i=r-e.distance,s=i*i/(r*r)*this.maxVelocity*t,o=1;switch(e.name){case"left":o=-1;case"right":n.setScrollLeft(n.getScrollLeft()+s*o);break;case"top":o=-1;case"bottom":n.setScrollTop(n.getScrollTop()+s*o)}}computeBestEdge(e,t){let{edgeThreshold:n}=this,r=null,i=this.scrollCaches||[];for(let s of i){let i=s.clientRect,o=e-i.left,a=i.right-e,l=t-i.top,c=i.bottom-t;o>=0&&a>=0&&l>=0&&c>=0&&(l<=n&&this.everMovedUp&&s.canScrollUp()&&(!r||r.distance>l)&&(r={scrollCache:s,name:"top",distance:l}),c<=n&&this.everMovedDown&&s.canScrollDown()&&(!r||r.distance>c)&&(r={scrollCache:s,name:"bottom",distance:c}),o<=n&&this.everMovedLeft&&s.canScrollLeft()&&(!r||r.distance>o)&&(r={scrollCache:s,name:"left",distance:o}),a<=n&&this.everMovedRight&&s.canScrollRight()&&(!r||r.distance>a)&&(r={scrollCache:s,name:"right",distance:a}))}return r}buildCaches(e){return this.queryScrollEls(e).map(e=>e===window?new Sa(!1):new Da(e,!1))}queryScrollEls(e){let t=[];for(let n of this.scrollQuery)"object"==typeof n?t.push(n):t.push(...Array.prototype.slice.call(xe(e).querySelectorAll(n)));return t}}class Ra extends Pi{constructor(e,t){super(e),this.containerEl=e,this.delay=null,this.minDistance=0,this.touchScrollAllowed=!0,this.mirrorNeedsRevert=!1,this.isInteracting=!1,this.isDragging=!1,this.isDelayEnded=!1,this.isDistanceSurpassed=!1,this.delayTimeoutId=null,this.onPointerDown=e=>{this.isDragging||(this.isInteracting=!0,this.isDelayEnded=!1,this.isDistanceSurpassed=!1,Ue(document.body),We(document.body),e.isTouch||e.origEvent.preventDefault(),this.emitter.trigger("pointerdown",e),this.isInteracting&&!this.pointer.shouldIgnoreMove&&(this.mirror.setIsVisible(!1),this.mirror.start(e.subjectEl,e.pageX,e.pageY),this.startDelay(e),this.minDistance||this.handleDistanceSurpassed(e)))},this.onPointerMove=e=>{if(this.isInteracting){if(this.emitter.trigger("pointermove",e),!this.isDistanceSurpassed){let t,n=this.minDistance,{deltaX:r,deltaY:i}=e;t=r*r+i*i,t>=n*n&&this.handleDistanceSurpassed(e)}this.isDragging&&("scroll"!==e.origEvent.type&&(this.mirror.handleMove(e.pageX,e.pageY),this.autoScroller.handleMove(e.pageX,e.pageY)),this.emitter.trigger("dragmove",e))}},this.onPointerUp=e=>{this.isInteracting&&(this.isInteracting=!1,Le(document.body),Fe(document.body),this.emitter.trigger("pointerup",e),this.isDragging&&(this.autoScroller.stop(),this.tryStopDrag(e)),this.delayTimeoutId&&(clearTimeout(this.delayTimeoutId),this.delayTimeoutId=null))};let n=this.pointer=new ba(e);n.emitter.on("pointerdown",this.onPointerDown),n.emitter.on("pointermove",this.onPointerMove),n.emitter.on("pointerup",this.onPointerUp),t&&(n.selector=t),this.mirror=new Ea,this.autoScroller=new Ca}destroy(){this.pointer.destroy(),this.onPointerUp({})}startDelay(e){"number"==typeof this.delay?this.delayTimeoutId=setTimeout(()=>{this.delayTimeoutId=null,this.handleDelayEnd(e)},this.delay):this.handleDelayEnd(e)}handleDelayEnd(e){this.isDelayEnded=!0,this.tryStartDrag(e)}handleDistanceSurpassed(e){this.isDistanceSurpassed=!0,this.tryStartDrag(e)}tryStartDrag(e){this.isDelayEnded&&this.isDistanceSurpassed&&(this.pointer.wasTouchScroll&&!this.touchScrollAllowed||(this.isDragging=!0,this.mirrorNeedsRevert=!1,this.autoScroller.start(e.pageX,e.pageY,this.containerEl),this.emitter.trigger("dragstart",e),!1===this.touchScrollAllowed&&this.pointer.cancelTouchScroll()))}tryStopDrag(e){this.mirror.stop(this.mirrorNeedsRevert,this.stopDrag.bind(this,e))}stopDrag(e){this.isDragging=!1,this.emitter.trigger("dragend",e)}setIgnoreMove(e){this.pointer.shouldIgnoreMove=e}setMirrorIsVisible(e){this.mirror.setIsVisible(e)}setMirrorNeedsRevert(e){this.mirrorNeedsRevert=e}setAutoScrollEnabled(e){this.autoScroller.isEnabled=e}}class xa{constructor(e){this.origRect=Er(e),this.scrollCaches=Ar(e).map(e=>new Da(e,!0))}destroy(){for(let e of this.scrollCaches)e.destroy()}computeLeft(){let e=this.origRect.left;for(let t of this.scrollCaches)e+=t.origScrollLeft-t.getScrollLeft();return e}computeTop(){let e=this.origRect.top;for(let t of this.scrollCaches)e+=t.origScrollTop-t.getScrollTop();return e}isWithinClipping(e,t){let n={left:e,top:t};for(let e of this.scrollCaches)if(!_a(e.getEventTarget())&&!Gn(n,e.clientRect))return!1;return!0}}function _a(e){let t=e.tagName;return"HTML"===t||"BODY"===t}class Ta{constructor(e,t){this.useSubjectCenter=!1,this.requireInitial=!0,this.initialHit=null,this.movingHit=null,this.finalHit=null,this.handlePointerDown=e=>{let{dragging:t}=this;this.initialHit=null,this.movingHit=null,this.finalHit=null,this.prepareHits(),this.processFirstCoord(e),this.initialHit||!this.requireInitial?(t.setIgnoreMove(!1),this.emitter.trigger("pointerdown",e)):t.setIgnoreMove(!0)},this.handleDragStart=e=>{this.emitter.trigger("dragstart",e),this.handleMove(e,!0)},this.handleDragMove=e=>{this.emitter.trigger("dragmove",e),this.handleMove(e)},this.handlePointerUp=e=>{this.releaseHits(),this.emitter.trigger("pointerup",e)},this.handleDragEnd=e=>{this.movingHit&&this.emitter.trigger("hitupdate",null,!0,e),this.finalHit=this.movingHit,this.movingHit=null,this.emitter.trigger("dragend",e)},this.droppableStore=t,e.emitter.on("pointerdown",this.handlePointerDown),e.emitter.on("dragstart",this.handleDragStart),e.emitter.on("dragmove",this.handleDragMove),e.emitter.on("pointerup",this.handlePointerUp),e.emitter.on("dragend",this.handleDragEnd),this.dragging=e,this.emitter=new Sr}processFirstCoord(e){let t,n={left:e.pageX,top:e.pageY},r=n,i=e.subjectEl;i instanceof HTMLElement&&(t=Er(i),r=qn(r,t));let s=this.initialHit=this.queryHitForOffset(r.left,r.top);if(s){if(this.useSubjectCenter&&t){let e=Qn(t,s.rect);e&&(r=Yn(e))}this.coordAdjust=Zn(r,n)}else this.coordAdjust={left:0,top:0}}handleMove(e,t){let n=this.queryHitForOffset(e.pageX+this.coordAdjust.left,e.pageY+this.coordAdjust.top);!t&&ka(this.movingHit,n)||(this.movingHit=n,this.emitter.trigger("hitupdate",n,!1,e))}prepareHits(){this.offsetTrackers=ht(this.droppableStore,e=>(e.component.prepareHits(),new xa(e.el)))}releaseHits(){let{offsetTrackers:e}=this;for(let t in e)e[t].destroy();this.offsetTrackers={}}queryHitForOffset(e,t){let{droppableStore:n,offsetTrackers:r}=this,i=null;for(let s in n){let o=n[s].component,a=r[s];if(a&&a.isWithinClipping(e,t)){let n=a.computeLeft(),r=a.computeTop(),l=e-n,c=t-r,{origRect:d}=a,u=d.right-d.left,h=d.bottom-d.top;if(l>=0&&l<u&&c>=0&&c<h){let e=o.queryHit(l,c,u,h);e&&or(e.dateProfile.activeRange,e.dateSpan.range)&&(!i||e.layer>i.layer)&&(e.componentId=s,e.context=o.context,e.rect.left+=n,e.rect.right+=n,e.rect.top+=r,e.rect.bottom+=r,i=e)}}}return i}}function ka(e,t){return!e&&!t||Boolean(e)===Boolean(t)&&mi(e.dateSpan,t.dateSpan)}function Ma(e,t){let n={};for(let r of t.pluginHooks.datePointTransforms)Object.assign(n,r(e,t));var r,i;return Object.assign(n,(r=e,{date:(i=t.dateEnv).toDate(r.range.start),dateStr:i.formatIso(r.range.start,{omitTime:r.allDay}),allDay:r.allDay})),n}class Ia extends Ii{constructor(e){super(e),this.subjectEl=null,this.subjectSeg=null,this.isDragging=!1,this.eventRange=null,this.relevantEvents=null,this.receivingContext=null,this.validMutation=null,this.mutatedRelevantEvents=null,this.handlePointerDown=e=>{let t=e.origEvent.target,{component:n,dragging:r}=this,{mirror:i}=r,{options:s}=n.context,o=n.context;this.subjectEl=e.subjectEl;let a=this.subjectSeg=ti(e.subjectEl),l=(this.eventRange=a.eventRange).instance.instanceId;this.relevantEvents=Dn(o.getCurrentData().eventStore,l),r.minDistance=e.isTouch?0:s.eventDragMinDistance,r.delay=e.isTouch&&l!==n.props.eventSelection?function(e){let{options:t}=e.context,n=t.eventLongPressDelay;null==n&&(n=t.longPressDelay);return n}(n):null,s.fixedMirrorParent?i.parentNode=s.fixedMirrorParent:i.parentNode=Ee(t,".fc"),i.revertDuration=s.dragRevertDuration;let c=n.isValidSegDownEl(t)&&!Ee(t,".fc-event-resizer");r.setIgnoreMove(!c),this.isDragging=c&&e.subjectEl.classList.contains("fc-event-draggable")},this.handleDragStart=e=>{let t=this.component.context,n=this.eventRange,r=n.instance.instanceId;e.isTouch?r!==this.component.props.eventSelection&&t.dispatch({type:"SELECT_EVENT",eventInstanceId:r}):t.dispatch({type:"UNSELECT_EVENT"}),this.isDragging&&(t.calendarApi.unselect(e),t.emitter.trigger("eventDragStart",{el:this.subjectEl,event:new Zr(t,n.def,n.instance),jsEvent:e.origEvent,view:t.viewApi}))},this.handleHitUpdate=(e,t)=>{if(!this.isDragging)return;let n=this.relevantEvents,r=this.hitDragging.initialHit,i=this.component.context,s=null,o=null,a=null,l=!1,c={affectedEvents:n,mutatedEvents:{defs:{},instances:{}},isEvent:!0};if(e){s=e.context;let t=s.options;i===s||t.editable&&t.droppable?(o=function(e,t,n){let r=e.dateSpan,i=t.dateSpan,s=r.range.start,o=i.range.start,a={};r.allDay!==i.allDay&&(a.allDay=i.allDay,a.hasEnd=t.context.options.allDayMaintainDuration,i.allDay&&(s=kt(s)));let l=Vn(s,o,e.context.dateEnv,e.componentId===t.componentId?e.largeUnit:null);l.milliseconds&&(a.allDay=!1);let c={datesDelta:l,standardProps:a};for(let r of n)r(c,e,t);return c}(r,e,s.getCurrentData().pluginHooks.eventDragMutationMassagers),o&&(a=Gr(n,s.getCurrentData().eventUiBases,o,s),c.mutatedEvents=a,cs(c,e.dateProfile,s)||(l=!0,o=null,a=null,c.mutatedEvents={defs:{},instances:{}}))):s=null}this.displayDrag(s,c),l?je():ze(),t||(i===s&&ka(r,e)&&(o=null),this.dragging.setMirrorNeedsRevert(!o),this.dragging.setMirrorIsVisible(!e||!xe(this.subjectEl).querySelector(".fc-event-mirror")),this.receivingContext=s,this.validMutation=o,this.mutatedRelevantEvents=a)},this.handlePointerUp=()=>{this.isDragging||this.cleanup()},this.handleDragEnd=e=>{if(this.isDragging){let t=this.component.context,n=t.viewApi,{receivingContext:r,validMutation:i}=this,s=this.eventRange.def,o=this.eventRange.instance,a=new Zr(t,s,o),l=this.relevantEvents,c=this.mutatedRelevantEvents,{finalHit:d}=this.hitDragging;if(this.clearDrag(),t.emitter.trigger("eventDragStop",{el:this.subjectEl,event:a,jsEvent:e.origEvent,view:n}),i){if(r===t){let r=new Zr(t,c.defs[s.defId],o?c.instances[o.instanceId]:null);t.dispatch({type:"MERGE_EVENTS",eventStore:c});let d={oldEvent:a,event:r,relatedEvents:Jr(c,t,o),revert(){t.dispatch({type:"MERGE_EVENTS",eventStore:l})}},u={};for(let e of t.getCurrentData().pluginHooks.eventDropTransformers)Object.assign(u,e(i,t));t.emitter.trigger("eventDrop",Object.assign(Object.assign(Object.assign({},d),u),{el:e.subjectEl,delta:i.datesDelta,jsEvent:e.origEvent,view:n})),t.emitter.trigger("eventChange",d)}else if(r){let i={event:a,relatedEvents:Jr(l,t,o),revert(){t.dispatch({type:"MERGE_EVENTS",eventStore:l})}};t.emitter.trigger("eventLeave",Object.assign(Object.assign({},i),{draggedEl:e.subjectEl,view:n})),t.dispatch({type:"REMOVE_EVENTS",eventStore:l}),t.emitter.trigger("eventRemove",i);let u=c.defs[s.defId],h=c.instances[o.instanceId],f=new Zr(r,u,h);r.dispatch({type:"MERGE_EVENTS",eventStore:c});let g={event:f,relatedEvents:Jr(c,r,h),revert(){r.dispatch({type:"REMOVE_EVENTS",eventStore:c})}};r.emitter.trigger("eventAdd",g),e.isTouch&&r.dispatch({type:"SELECT_EVENT",eventInstanceId:o.instanceId}),r.emitter.trigger("drop",Object.assign(Object.assign({},Ma(d.dateSpan,r)),{draggedEl:e.subjectEl,jsEvent:e.origEvent,view:d.context.viewApi})),r.emitter.trigger("eventReceive",Object.assign(Object.assign({},g),{draggedEl:e.subjectEl,view:d.context.viewApi}))}}else t.emitter.trigger("_noEventDrop")}this.cleanup()};let{component:t}=this,{options:n}=t.context,r=this.dragging=new Ra(e.el);r.pointer.selector=Ia.SELECTOR,r.touchScrollAllowed=!1,r.autoScroller.isEnabled=n.dragScroll;let i=this.hitDragging=new Ta(this.dragging,Ni);i.useSubjectCenter=e.useEventCenter,i.emitter.on("pointerdown",this.handlePointerDown),i.emitter.on("dragstart",this.handleDragStart),i.emitter.on("hitupdate",this.handleHitUpdate),i.emitter.on("pointerup",this.handlePointerUp),i.emitter.on("dragend",this.handleDragEnd)}destroy(){this.dragging.destroy()}displayDrag(e,t){let n=this.component.context,r=this.receivingContext;r&&r!==e&&(r===n?r.dispatch({type:"SET_EVENT_DRAG",state:{affectedEvents:t.affectedEvents,mutatedEvents:{defs:{},instances:{}},isEvent:!0}}):r.dispatch({type:"UNSET_EVENT_DRAG"})),e&&e.dispatch({type:"SET_EVENT_DRAG",state:t})}clearDrag(){let e=this.component.context,{receivingContext:t}=this;t&&t.dispatch({type:"UNSET_EVENT_DRAG"}),e!==t&&e.dispatch({type:"UNSET_EVENT_DRAG"})}cleanup(){this.subjectSeg=null,this.isDragging=!1,this.eventRange=null,this.relevantEvents=null,this.receivingContext=null,this.validMutation=null,this.mutatedRelevantEvents=null}}Ia.SELECTOR=".fc-event-draggable, .fc-event-resizable";const Oa={fixedMirrorParent:mn},Na={dateClick:mn,eventDragStart:mn,eventDragStop:mn,eventDrop:mn,eventResizeStart:mn,eventResizeStop:mn,eventResize:mn,drop:mn,eventReceive:mn,eventLeave:mn};class Pa{constructor(e,t){this.receivingContext=null,this.droppableEvent=null,this.suppliedDragMeta=null,this.dragMeta=null,this.handleDragStart=e=>{this.dragMeta=this.buildDragMeta(e.subjectEl)},this.handleHitUpdate=(e,t,n)=>{let{dragging:r}=this.hitDragging,i=null,s=null,o=!1,a={affectedEvents:{defs:{},instances:{}},mutatedEvents:{defs:{},instances:{}},isEvent:this.dragMeta.create};e&&(i=e.context,this.canDropElOnCalendar(n.subjectEl,i)&&(s=function(e,t,n){let r=Object.assign({},t.leftoverProps);for(let i of n.pluginHooks.externalDefTransforms)Object.assign(r,i(e,t));let{refined:i,extra:s}=Hn(r,n),o=jn(i,s,t.sourceId,e.allDay,n.options.forceEventDuration||Boolean(t.duration),n),a=e.range.start;e.allDay&&t.startTime&&(a=n.dateEnv.add(a,t.startTime));let l=t.duration?n.dateEnv.add(a,t.duration):Vr(e.allDay,a,n),c=vn(o.defId,{start:a,end:l});return{def:o,instance:c}}(e.dateSpan,this.dragMeta,i),a.mutatedEvents=An(s),o=!cs(a,e.dateProfile,i),o&&(a.mutatedEvents={defs:{},instances:{}},s=null))),this.displayDrag(i,a),r.setMirrorIsVisible(t||!s||!document.querySelector(".fc-event-mirror")),o?je():ze(),t||(r.setMirrorNeedsRevert(!s),this.receivingContext=i,this.droppableEvent=s)},this.handleDragEnd=e=>{let{receivingContext:t,droppableEvent:n}=this;if(this.clearDrag(),t&&n){let r=this.hitDragging.finalHit,i=r.context.viewApi,s=this.dragMeta;if(t.emitter.trigger("drop",Object.assign(Object.assign({},Ma(r.dateSpan,t)),{draggedEl:e.subjectEl,jsEvent:e.origEvent,view:i})),s.create){let r=An(n);t.dispatch({type:"MERGE_EVENTS",eventStore:r}),e.isTouch&&t.dispatch({type:"SELECT_EVENT",eventInstanceId:n.instance.instanceId}),t.emitter.trigger("eventReceive",{event:new Zr(t,n.def,n.instance),relatedEvents:[],revert(){t.dispatch({type:"REMOVE_EVENTS",eventStore:r})},draggedEl:e.subjectEl,view:i})}}this.receivingContext=null,this.droppableEvent=null};let n=this.hitDragging=new Ta(e,Ni);n.requireInitial=!1,n.emitter.on("dragstart",this.handleDragStart),n.emitter.on("hitupdate",this.handleHitUpdate),n.emitter.on("dragend",this.handleDragEnd),this.suppliedDragMeta=t}buildDragMeta(e){return"object"==typeof this.suppliedDragMeta?ji(this.suppliedDragMeta):"function"==typeof this.suppliedDragMeta?ji(this.suppliedDragMeta(e)):function(e){let t=function(e,t){let n=Hi.dataAttrPrefix,r=(n?n+"-":"")+t;return e.getAttribute("data-"+r)||""}(e,"event");return ji(t?JSON.parse(t):{create:!1})}(e)}displayDrag(e,t){let n=this.receivingContext;n&&n!==e&&n.dispatch({type:"UNSET_EVENT_DRAG"}),e&&e.dispatch({type:"SET_EVENT_DRAG",state:t})}clearDrag(){this.receivingContext&&this.receivingContext.dispatch({type:"UNSET_EVENT_DRAG"})}canDropElOnCalendar(e,t){let n=t.options.dropAccept;return"function"==typeof n?n.call(t.calendarApi,e):"string"!=typeof n||!n||Boolean(Ae(e,n))}}Hi.dataAttrPrefix="";class Ha extends Pi{constructor(e){super(e),this.shouldIgnoreMove=!1,this.mirrorSelector="",this.currentMirrorEl=null,this.handlePointerDown=e=>{this.emitter.trigger("pointerdown",e),this.shouldIgnoreMove||this.emitter.trigger("dragstart",e)},this.handlePointerMove=e=>{this.shouldIgnoreMove||this.emitter.trigger("dragmove",e)},this.handlePointerUp=e=>{this.emitter.trigger("pointerup",e),this.shouldIgnoreMove||this.emitter.trigger("dragend",e)};let t=this.pointer=new ba(e);t.emitter.on("pointerdown",this.handlePointerDown),t.emitter.on("pointermove",this.handlePointerMove),t.emitter.on("pointerup",this.handlePointerUp)}destroy(){this.pointer.destroy()}setIgnoreMove(e){this.shouldIgnoreMove=e}setMirrorIsVisible(e){if(e)this.currentMirrorEl&&(this.currentMirrorEl.style.visibility="",this.currentMirrorEl=null);else{let e=this.mirrorSelector?document.querySelector(this.mirrorSelector):null;e&&(this.currentMirrorEl=e,e.style.visibility="hidden")}}}var Ba=yo({name:"@fullcalendar/interaction",componentInteractions:[class extends Ii{constructor(e){super(e),this.handlePointerDown=e=>{let{dragging:t}=this,n=e.origEvent.target;t.setIgnoreMove(!this.component.isValidDateDownEl(n))},this.handleDragEnd=e=>{let{component:t}=this,{pointer:n}=this.dragging;if(!n.wasTouchScroll){let{initialHit:n,finalHit:r}=this.hitDragging;if(n&&r&&ka(n,r)){let{context:r}=t,i=Object.assign(Object.assign({},Ma(n.dateSpan,r)),{dayEl:n.dayEl,jsEvent:e.origEvent,view:r.viewApi||r.calendarApi.view});r.emitter.trigger("dateClick",i)}}},this.dragging=new Ra(e.el),this.dragging.autoScroller.isEnabled=!1;let t=this.hitDragging=new Ta(this.dragging,Oi(e));t.emitter.on("pointerdown",this.handlePointerDown),t.emitter.on("dragend",this.handleDragEnd)}destroy(){this.dragging.destroy()}},class extends Ii{constructor(e){super(e),this.dragSelection=null,this.handlePointerDown=e=>{let{component:t,dragging:n}=this,{options:r}=t.context,i=r.selectable&&t.isValidDateDownEl(e.origEvent.target);n.setIgnoreMove(!i),n.delay=e.isTouch?function(e){let{options:t}=e.context,n=t.selectLongPressDelay;null==n&&(n=t.longPressDelay);return n}(t):null},this.handleDragStart=e=>{this.component.context.calendarApi.unselect(e)},this.handleHitUpdate=(e,t)=>{let{context:n}=this.component,r=null,i=!1;if(e){let t=this.hitDragging.initialHit;e.componentId===t.componentId&&this.isHitComboAllowed&&!this.isHitComboAllowed(t,e)||(r=function(e,t,n){let r=e.dateSpan,i=t.dateSpan,s=[r.range.start,r.range.end,i.range.start,i.range.end];s.sort(Xe);let o={};for(let r of n){let n=r(e,t);if(!1===n)return null;n&&Object.assign(o,n)}return o.range={start:s[0],end:s[3]},o.allDay=r.allDay,o}(t,e,n.pluginHooks.dateSelectionTransformers)),r&&ds(r,e.dateProfile,n)||(i=!0,r=null)}r?n.dispatch({type:"SELECT_DATES",selection:r}):t||n.dispatch({type:"UNSELECT_DATES"}),i?je():ze(),t||(this.dragSelection=r)},this.handlePointerUp=e=>{this.dragSelection&&(Wr(this.dragSelection,e,this.component.context),this.dragSelection=null)};let{component:t}=e,{options:n}=t.context,r=this.dragging=new Ra(e.el);r.touchScrollAllowed=!1,r.minDistance=n.selectMinDistance||0,r.autoScroller.isEnabled=n.dragScroll;let i=this.hitDragging=new Ta(this.dragging,Oi(e));i.emitter.on("pointerdown",this.handlePointerDown),i.emitter.on("dragstart",this.handleDragStart),i.emitter.on("hitupdate",this.handleHitUpdate),i.emitter.on("pointerup",this.handlePointerUp)}destroy(){this.dragging.destroy()}},Ia,class extends Ii{constructor(e){super(e),this.draggingSegEl=null,this.draggingSeg=null,this.eventRange=null,this.relevantEvents=null,this.validMutation=null,this.mutatedRelevantEvents=null,this.handlePointerDown=e=>{let{component:t}=this,n=ti(this.querySegEl(e)),r=this.eventRange=n.eventRange;this.dragging.minDistance=t.context.options.eventDragMinDistance,this.dragging.setIgnoreMove(!this.component.isValidSegDownEl(e.origEvent.target)||e.isTouch&&this.component.props.eventSelection!==r.instance.instanceId)},this.handleDragStart=e=>{let{context:t}=this.component,n=this.eventRange;this.relevantEvents=Dn(t.getCurrentData().eventStore,this.eventRange.instance.instanceId);let r=this.querySegEl(e);this.draggingSegEl=r,this.draggingSeg=ti(r),t.calendarApi.unselect(),t.emitter.trigger("eventResizeStart",{el:r,event:new Zr(t,n.def,n.instance),jsEvent:e.origEvent,view:t.viewApi})},this.handleHitUpdate=(e,t,n)=>{let{context:r}=this.component,i=this.relevantEvents,s=this.hitDragging.initialHit,o=this.eventRange.instance,a=null,l=null,c=!1,d={affectedEvents:i,mutatedEvents:{defs:{},instances:{}},isEvent:!0};if(e){e.componentId===s.componentId&&this.isHitComboAllowed&&!this.isHitComboAllowed(s,e)||(a=function(e,t,n,r){let i=e.context.dateEnv,s=e.dateSpan.range.start,o=t.dateSpan.range.start,a=Vn(s,o,i,e.largeUnit);if(n){if(i.add(r.start,a)<r.end)return{startDelta:a}}else if(i.add(r.end,a)>r.start)return{endDelta:a};return null}(s,e,n.subjectEl.classList.contains("fc-event-resizer-start"),o.range))}a&&(l=Gr(i,r.getCurrentData().eventUiBases,a,r),d.mutatedEvents=l,cs(d,e.dateProfile,r)||(c=!0,a=null,l=null,d.mutatedEvents=null)),l?r.dispatch({type:"SET_EVENT_RESIZE",state:d}):r.dispatch({type:"UNSET_EVENT_RESIZE"}),c?je():ze(),t||(a&&ka(s,e)&&(a=null),this.validMutation=a,this.mutatedRelevantEvents=l)},this.handleDragEnd=e=>{let{context:t}=this.component,n=this.eventRange.def,r=this.eventRange.instance,i=new Zr(t,n,r),s=this.relevantEvents,o=this.mutatedRelevantEvents;if(t.emitter.trigger("eventResizeStop",{el:this.draggingSegEl,event:i,jsEvent:e.origEvent,view:t.viewApi}),this.validMutation){let a=new Zr(t,o.defs[n.defId],r?o.instances[r.instanceId]:null);t.dispatch({type:"MERGE_EVENTS",eventStore:o});let l={oldEvent:i,event:a,relatedEvents:Jr(o,t,r),revert(){t.dispatch({type:"MERGE_EVENTS",eventStore:s})}};t.emitter.trigger("eventResize",Object.assign(Object.assign({},l),{el:this.draggingSegEl,startDelta:this.validMutation.startDelta||tt(0),endDelta:this.validMutation.endDelta||tt(0),jsEvent:e.origEvent,view:t.viewApi})),t.emitter.trigger("eventChange",l)}else t.emitter.trigger("_noEventResize");this.draggingSeg=null,this.relevantEvents=null,this.validMutation=null};let{component:t}=e,n=this.dragging=new Ra(e.el);n.pointer.selector=".fc-event-resizer",n.touchScrollAllowed=!1,n.autoScroller.isEnabled=t.context.options.dragScroll;let r=this.hitDragging=new Ta(this.dragging,Oi(e));r.emitter.on("pointerdown",this.handlePointerDown),r.emitter.on("dragstart",this.handleDragStart),r.emitter.on("hitupdate",this.handleHitUpdate),r.emitter.on("dragend",this.handleDragEnd)}destroy(){this.dragging.destroy()}querySegEl(e){return Ee(e.subjectEl,".fc-event")}}],calendarInteractions:[class{constructor(e){this.context=e,this.isRecentPointerDateSelect=!1,this.matchesCancel=!1,this.matchesEvent=!1,this.onSelect=e=>{e.jsEvent&&(this.isRecentPointerDateSelect=!0)},this.onDocumentPointerDown=e=>{let t=this.context.options.unselectCancel,n=Re(e.origEvent);this.matchesCancel=!!Ee(n,t),this.matchesEvent=!!Ee(n,Ia.SELECTOR)},this.onDocumentPointerUp=e=>{let{context:t}=this,{documentPointer:n}=this,r=t.getCurrentData();if(!n.wasTouchScroll){if(r.dateSelection&&!this.isRecentPointerDateSelect){let n=t.options.unselectAuto;!n||n&&this.matchesCancel||t.calendarApi.unselect(e)}r.eventSelection&&!this.matchesEvent&&t.dispatch({type:"UNSELECT_EVENT"})}this.isRecentPointerDateSelect=!1};let t=this.documentPointer=new ba(document);t.shouldIgnoreMove=!0,t.shouldWatchScroll=!1,t.emitter.on("pointerdown",this.onDocumentPointerDown),t.emitter.on("pointerup",this.onDocumentPointerUp),e.emitter.on("select",this.onSelect)}destroy(){this.context.emitter.off("select",this.onSelect),this.documentPointer.destroy()}}],elementDraggingImpl:Ra,optionRefiners:Oa,listenerRefiners:Na});class ja extends zr{constructor(){super(...arguments),this.headerElRef={current:null}}renderSimpleLayout(e,t){let{props:n,context:r}=this,i=[],s=Ns(r.options);return e&&i.push({type:"header",key:"header",isSticky:s,chunk:{elRef:this.headerElRef,tableClassName:"fc-col-header",rowContent:e}}),i.push({type:"body",key:"body",liquid:!0,chunk:{content:t}}),f(io,{elClasses:["fc-daygrid"],viewSpec:r.viewSpec},f(Hs,{liquid:!n.isHeightAuto&&!n.forPrint,collapsibleWidth:n.forPrint,cols:[],sections:i}))}renderHScrollLayout(e,t,n,r){let i=this.context.pluginHooks.scrollGridImpl;if(!i)throw new Error("No ScrollGrid implementation");let{props:s,context:o}=this,a=!s.forPrint&&Ns(o.options),l=!s.forPrint&&Ps(o.options),c=[];return e&&c.push({type:"header",key:"header",isSticky:a,chunks:[{key:"main",elRef:this.headerElRef,tableClassName:"fc-col-header",rowContent:e}]}),c.push({type:"body",key:"body",liquid:!0,chunks:[{key:"main",content:t}]}),l&&c.push({type:"footer",key:"footer",isSticky:!0,chunks:[{key:"main",content:Os}]}),f(io,{elClasses:["fc-daygrid"],viewSpec:o.viewSpec},f(i,{liquid:!s.isHeightAuto&&!s.forPrint,collapsibleWidth:s.forPrint,colGroups:[{cols:[{span:n,minWidth:r}]}],sections:c}))}}function za(e,t){let n=[];for(let e=0;e<t;e+=1)n[e]=[];for(let t of e)n[t.row].push(t);return n}function Ua(e,t){let n=[];for(let e=0;e<t;e+=1)n[e]=[];for(let t of e)n[t.firstCol].push(t);return n}function La(e,t){let n=[];if(e){for(let r=0;r<t;r+=1)n[r]={affectedInstances:e.affectedInstances,isEvent:e.isEvent,segs:[]};for(let t of e.segs)n[t.row].segs.push(t)}else for(let e=0;e<t;e+=1)n[e]=null;return n}const Wa=on({hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"narrow"});function Fa(e){let{display:t}=e.eventRange.ui;return"list-item"===t||"auto"===t&&!e.eventRange.def.allDay&&e.firstCol===e.lastCol&&e.isStart&&e.isEnd}class Va extends Br{render(){let{props:e}=this;return f(js,Object.assign({},e,{elClasses:["fc-daygrid-event","fc-daygrid-block-event","fc-h-event"],defaultTimeFormat:Wa,defaultDisplayEventEnd:e.defaultDisplayEventEnd,disableResizing:!e.seg.eventRange.def.allDay}))}}class Ga extends Br{render(){let{props:e,context:t}=this,{options:n}=t,{seg:r}=e,i=ci(r,n.eventTimeFormat||Wa,t,!0,e.defaultDisplayEventEnd);return f(Bs,Object.assign({},e,{elTag:"a",elClasses:["fc-daygrid-event","fc-daygrid-dot-event"],elAttrs:fi(e.seg,t),defaultGenerator:Qa,timeText:i,isResizing:!1,isDateSelecting:!1}))}}function Qa(e){return f(p,null,f("div",{className:"fc-daygrid-event-dot",style:{borderColor:e.borderColor||e.backgroundColor}}),e.timeText&&f("div",{className:"fc-event-time"},e.timeText),f("div",{className:"fc-event-title"},e.event.title||f(p,null," ")))}class qa extends Br{constructor(){super(...arguments),this.compileSegs=Vt(Ya)}render(){let{props:e}=this,{allSegs:t,invisibleSegs:n}=this.compileSegs(e.singlePlacements);return f($s,{elClasses:["fc-daygrid-more-link"],dateProfile:e.dateProfile,todayRange:e.todayRange,allDayDate:e.allDayDate,moreCnt:e.moreCnt,allSegs:t,hiddenSegs:n,alignmentElRef:e.alignmentElRef,alignGridTop:e.alignGridTop,extraDateSpan:e.extraDateSpan,popoverContent:()=>{let n=(e.eventDrag?e.eventDrag.affectedInstances:null)||(e.eventResize?e.eventResize.affectedInstances:null)||{};return f(p,null,t.map(t=>{let r=t.eventRange.instance.instanceId;return f("div",{className:"fc-daygrid-event-harness",key:r,style:{visibility:n[r]?"hidden":""}},Fa(t)?f(Ga,Object.assign({seg:t,isDragging:!1,isSelected:r===e.eventSelection,defaultDisplayEventEnd:!1},di(t,e.todayRange))):f(Va,Object.assign({seg:t,isDragging:!1,isResizing:!1,isDateSelecting:!1,isSelected:r===e.eventSelection,defaultDisplayEventEnd:!1},di(t,e.todayRange))))}))}})}}function Ya(e){let t=[],n=[];for(let r of e)t.push(r.seg),r.isVisible||n.push(r.seg);return{allSegs:t,invisibleSegs:n}}const Za=on({week:"narrow"});class Xa extends zr{constructor(){super(...arguments),this.rootElRef={current:null},this.state={dayNumberId:Te()},this.handleRootEl=e=>{jr(this.rootElRef,e),jr(this.props.elRef,e)}}render(){let{context:e,props:t,state:n,rootElRef:r}=this,{options:i}=e,{date:s,dateProfile:o}=t;return f(Ws,{elTag:"td",elRef:this.handleRootEl,elClasses:["fc-daygrid-day",...t.extraClassNames||[]],elAttrs:Object.assign(Object.assign(Object.assign({},t.extraDataAttrs),t.showDayNumber?{"aria-labelledby":n.dayNumberId}:{}),{role:"gridcell"}),defaultGenerator:Ja,date:s,dateProfile:o,todayRange:t.todayRange,showDayNumber:t.showDayNumber,extraRenderProps:t.extraRenderProps},(o,a)=>f("div",{className:"fc-daygrid-day-frame fc-scrollgrid-sync-inner",ref:t.innerElRef},t.showWeekNumber&&f(Ys,{elTag:"a",elClasses:["fc-daygrid-week-number"],elAttrs:hr(e,s,"week"),date:s,defaultFormat:Za}),Boolean(!a.isDisabled&&(t.showDayNumber||Fs(i)||t.forceDayTop))&&f("div",{className:"fc-daygrid-day-top"},f(o,{elTag:"a",elClasses:["fc-daygrid-day-number"],elAttrs:Object.assign(Object.assign({},hr(e,s)),{id:n.dayNumberId})})),f("div",{className:"fc-daygrid-day-events",ref:t.fgContentElRef},t.fgContent,f("div",{className:"fc-daygrid-day-bottom",style:{marginTop:t.moreMarginTop}},f(qa,{allDayDate:s,singlePlacements:t.singlePlacements,moreCnt:t.moreCnt,alignmentElRef:r,alignGridTop:!t.showDayNumber,extraDateSpan:t.extraDateSpan,dateProfile:t.dateProfile,eventSelection:t.eventSelection,eventDrag:t.eventDrag,eventResize:t.eventResize,todayRange:t.todayRange}))),f("div",{className:"fc-daygrid-day-bg"},t.bgContent)))}}function Ja(e){return e.dayNumberText||f(p,null," ")}function $a(e,t,n,r,i,s,o){let a=new el;a.allowReslicing=!0,a.strictOrder=r,!0===t||!0===n?(a.maxCoord=s,a.hiddenConsumes=!0):"number"==typeof t?a.maxStackCnt=t:"number"==typeof n&&(a.maxStackCnt=n,a.hiddenConsumes=!0);let l=[],c=[];for(let t=0;t<e.length;t+=1){let n=e[t],{instanceId:r}=n.eventRange.instance,s=i[r];null!=s?l.push({index:t,thickness:s,span:{start:n.firstCol,end:n.lastCol+1}}):c.push(n)}let d=a.addSegs(l),u=a.toRects(),{singleColPlacements:h,multiColPlacements:f,leftoverMargins:g}=function(e,t,n){let r=function(e,t){let n=[];for(let e=0;e<t;e+=1)n.push([]);for(let t of e)for(let e=t.span.start;e<t.span.end;e+=1)n[e].push(t);return n}(e,n.length),i=[],s=[],o=[];for(let e=0;e<n.length;e+=1){let a=r[e],l=[],c=0,d=0;for(let r of a){let i=t[r.index];l.push({seg:Ka(i,e,e+1,n),isVisible:!0,isAbsolute:!1,absoluteTop:r.levelCoord,marginTop:r.levelCoord-c}),c=r.levelCoord+r.thickness}let u=[];c=0,d=0;for(let r of a){let i=t[r.index],s=r.span.end-r.span.start>1,o=r.span.start===e;d+=r.levelCoord-c,c=r.levelCoord+r.thickness,s?(d+=r.thickness,o&&u.push({seg:Ka(i,r.span.start,r.span.end,n),isVisible:!0,isAbsolute:!0,absoluteTop:r.levelCoord,marginTop:0})):o&&(u.push({seg:Ka(i,r.span.start,r.span.end,n),isVisible:!0,isAbsolute:!1,absoluteTop:r.levelCoord,marginTop:d}),d=0)}i.push(l),s.push(u),o.push(d)}return{singleColPlacements:i,multiColPlacements:s,leftoverMargins:o}}(u,e,o),p=[],m=[];for(let e of c){f[e.firstCol].push({seg:e,isVisible:!1,isAbsolute:!0,absoluteTop:0,marginTop:0});for(let t=e.firstCol;t<=e.lastCol;t+=1)h[t].push({seg:Ka(e,t,t+1,o),isVisible:!1,isAbsolute:!1,absoluteTop:0,marginTop:0})}for(let e=0;e<o.length;e+=1)p.push(0);for(let t of d){let n=e[t.index],r=t.span;f[r.start].push({seg:Ka(n,r.start,r.end,o),isVisible:!1,isAbsolute:!0,absoluteTop:0,marginTop:0});for(let e=r.start;e<r.end;e+=1)p[e]+=1,h[e].push({seg:Ka(n,e,e+1,o),isVisible:!1,isAbsolute:!1,absoluteTop:0,marginTop:0})}for(let e=0;e<o.length;e+=1)m.push(g[e]);return{singleColPlacements:h,multiColPlacements:f,moreCnts:p,moreMarginTops:m}}function Ka(e,t,n,r){if(e.firstCol===t&&e.lastCol===n-1)return e;let i=e.eventRange,s=i.range,o=rr(s,{start:r[t].date,end:St(r[n-1].date,1)});return Object.assign(Object.assign({},e),{firstCol:t,lastCol:n-1,eventRange:{def:i.def,ui:Object.assign(Object.assign({},i.ui),{durationEditable:!1}),instance:i.instance,range:o},isStart:e.isStart&&o.start.valueOf()===s.start.valueOf(),isEnd:e.isEnd&&o.end.valueOf()===s.end.valueOf()})}class el extends Ci{constructor(){super(...arguments),this.hiddenConsumes=!1,this.forceHidden={}}addSegs(e){const t=super.addSegs(e),{entriesByLevel:n}=this,r=e=>!this.forceHidden[xi(e)];for(let e=0;e<n.length;e+=1)n[e]=n[e].filter(r);return t}handleInvalidInsertion(e,t,n){const{entriesByLevel:r,forceHidden:i}=this,{touchingEntry:s,touchingLevel:o,touchingLateral:a}=e;if(this.hiddenConsumes&&s){const e=xi(s);if(!i[e])if(this.allowReslicing){const e=Object.assign(Object.assign({},s),{span:Ti(s.span,t.span)});i[xi(e)]=!0,r[o][a]=e,this.splitEntry(s,t,n)}else i[e]=!0,n.push(s)}return super.handleInvalidInsertion(e,t,n)}}class tl extends zr{constructor(){super(...arguments),this.cellElRefs=new Ds,this.frameElRefs=new Ds,this.fgElRefs=new Ds,this.segHarnessRefs=new Ds,this.rootElRef={current:null},this.state={framePositions:null,maxContentHeight:null,eventInstanceHeights:{}},this.handleResize=e=>{e&&this.updateSizing(!0)}}render(){let{props:e,state:t,context:n}=this,{options:r}=n,i=e.cells.length,s=Ua(e.businessHourSegs,i),o=Ua(e.bgEventSegs,i),a=Ua(this.getHighlightSegs(),i),l=Ua(this.getMirrorSegs(),i),{singleColPlacements:c,multiColPlacements:d,moreCnts:u,moreMarginTops:h}=$a(ii(e.fgEventSegs,r.eventOrder),e.dayMaxEvents,e.dayMaxEventRows,r.eventOrderStrict,t.eventInstanceHeights,t.maxContentHeight,e.cells),g=e.eventDrag&&e.eventDrag.affectedInstances||e.eventResize&&e.eventResize.affectedInstances||{};return f("tr",{ref:this.rootElRef,role:"row"},e.renderIntro&&e.renderIntro(),e.cells.map((t,n)=>{let r=this.renderFgSegs(n,e.forPrint?c[n]:d[n],e.todayRange,g),i=this.renderFgSegs(n,function(e,t){if(!e.length)return[];let n=function(e){let t={};for(let n of e)for(let e of n)t[e.seg.eventRange.instance.instanceId]=e.absoluteTop;return t}(t);return e.map(e=>({seg:e,isVisible:!0,isAbsolute:!0,absoluteTop:n[e.eventRange.instance.instanceId],marginTop:0}))}(l[n],d),e.todayRange,{},Boolean(e.eventDrag),Boolean(e.eventResize),!1);return f(Xa,{key:t.key,elRef:this.cellElRefs.createRef(t.key),innerElRef:this.frameElRefs.createRef(t.key),dateProfile:e.dateProfile,date:t.date,showDayNumber:e.showDayNumbers,showWeekNumber:e.showWeekNumbers&&0===n,forceDayTop:e.showWeekNumbers,todayRange:e.todayRange,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize,extraRenderProps:t.extraRenderProps,extraDataAttrs:t.extraDataAttrs,extraClassNames:t.extraClassNames,extraDateSpan:t.extraDateSpan,moreCnt:u[n],moreMarginTop:h[n],singlePlacements:c[n],fgContentElRef:this.fgElRefs.createRef(t.key),fgContent:f(p,null,f(p,null,r),f(p,null,i)),bgContent:f(p,null,this.renderFillSegs(a[n],"highlight"),this.renderFillSegs(s[n],"non-business"),this.renderFillSegs(o[n],"bg-event"))})}))}componentDidMount(){this.updateSizing(!0),this.context.addResizeHandler(this.handleResize)}componentDidUpdate(e,t){let n=this.props;this.updateSizing(!pt(e,n))}componentWillUnmount(){this.context.removeResizeHandler(this.handleResize)}getHighlightSegs(){let{props:e}=this;return e.eventDrag&&e.eventDrag.segs.length?e.eventDrag.segs:e.eventResize&&e.eventResize.segs.length?e.eventResize.segs:e.dateSelectionSegs}getMirrorSegs(){let{props:e}=this;return e.eventResize&&e.eventResize.segs.length?e.eventResize.segs:[]}renderFgSegs(e,t,n,r,i,s,o){let{context:a}=this,{eventSelection:l}=this.props,{framePositions:c}=this.state,d=1===this.props.cells.length,u=i||s||o,h=[];if(c)for(let g of t){let{seg:t}=g,{instanceId:p}=t.eventRange.instance,m=p+":"+e,v=g.isVisible&&!r[p],b=g.isAbsolute,y="",E="";b&&(a.isRtl?(E=0,y=c.lefts[t.lastCol]-c.lefts[t.firstCol]):(y=0,E=c.rights[t.firstCol]-c.rights[t.lastCol])),h.push(f("div",{className:"fc-daygrid-event-harness"+(b?" fc-daygrid-event-harness-abs":""),key:m,ref:u?null:this.segHarnessRefs.createRef(m),style:{visibility:v?"":"hidden",marginTop:b?"":g.marginTop,top:b?g.absoluteTop:"",left:y,right:E}},Fa(t)?f(Ga,Object.assign({seg:t,isDragging:i,isSelected:p===l,defaultDisplayEventEnd:d},di(t,n))):f(Va,Object.assign({seg:t,isDragging:i,isResizing:s,isDateSelecting:o,isSelected:p===l,defaultDisplayEventEnd:d},di(t,n)))))}return h}renderFillSegs(e,t){let{isRtl:n}=this.context,{todayRange:r}=this.props,{framePositions:i}=this.state,s=[];if(i)for(let o of e){let e=n?{right:0,left:i.lefts[o.lastCol]-i.lefts[o.firstCol]}:{left:0,right:i.rights[o.firstCol]-i.rights[o.lastCol]};s.push(f("div",{key:hi(o.eventRange),className:"fc-daygrid-bg-harness",style:e},"bg-event"===t?f(Gs,Object.assign({seg:o},di(o,r))):qs(t)))}return f(p,{},...s)}updateSizing(e){let{props:t,state:n,frameElRefs:r}=this;if(!t.forPrint&&null!==t.clientWidth){if(e){let e=t.cells.map(e=>r.currentMap[e.key]);if(e.length){let t=this.rootElRef.current,r=new wr(t,e,!0,!1);n.framePositions&&n.framePositions.similarTo(r)||this.setState({framePositions:new wr(t,e,!0,!1)})}}const i=this.state.eventInstanceHeights,s=this.queryEventInstanceHeights(),o=!0===t.dayMaxEvents||!0===t.dayMaxEventRows;this.safeSetState({eventInstanceHeights:Object.assign(Object.assign({},i),s),maxContentHeight:o?this.computeMaxContentHeight():null})}}queryEventInstanceHeights(){let e=this.segHarnessRefs.currentMap,t={};for(let n in e){let r=Math.round(e[n].getBoundingClientRect().height),i=n.split(":")[0];t[i]=Math.max(t[i]||0,r)}return t}computeMaxContentHeight(){let e=this.props.cells[0].key,t=this.cellElRefs.currentMap[e],n=this.fgElRefs.currentMap[e];return t.getBoundingClientRect().bottom-n.getBoundingClientRect().top}getCellEls(){let e=this.cellElRefs.currentMap;return this.props.cells.map(t=>e[t.key])}}tl.addStateEquality({eventInstanceHeights:pt});class nl extends zr{constructor(){super(...arguments),this.splitBusinessHourSegs=Vt(za),this.splitBgEventSegs=Vt(za),this.splitFgEventSegs=Vt(za),this.splitDateSelectionSegs=Vt(za),this.splitEventDrag=Vt(La),this.splitEventResize=Vt(La),this.rowRefs=new Ds,this.handleRootEl=e=>{this.rootEl=e,e?this.context.registerInteractiveComponent(this,{el:e,isHitComboAllowed:this.props.isHitComboAllowed}):this.context.unregisterInteractiveComponent(this)}}render(){let{props:e}=this,{dateProfile:t,dayMaxEventRows:n,dayMaxEvents:r,expandRows:i}=e,s=e.cells.length,o=this.splitBusinessHourSegs(e.businessHourSegs,s),a=this.splitBgEventSegs(e.bgEventSegs,s),l=this.splitFgEventSegs(e.fgEventSegs,s),c=this.splitDateSelectionSegs(e.dateSelectionSegs,s),d=this.splitEventDrag(e.eventDrag,s),u=this.splitEventResize(e.eventResize,s),h=!0===r||!0===n;return h&&!i&&(h=!1,n=null,r=null),f("div",{className:["fc-daygrid-body",h?"fc-daygrid-body-balanced":"fc-daygrid-body-unbalanced",i?"":"fc-daygrid-body-natural"].join(" "),ref:this.handleRootEl,style:{width:e.clientWidth,minWidth:e.tableMinWidth}},f($i,{unit:"day"},(h,g)=>f(p,null,f("table",{role:"presentation",className:"fc-scrollgrid-sync-table",style:{width:e.clientWidth,minWidth:e.tableMinWidth,height:i?e.clientHeight:""}},e.colGroupNode,f("tbody",{role:"presentation"},e.cells.map((i,h)=>f(tl,{ref:this.rowRefs.createRef(h),key:i.length?i[0].date.toISOString():h,showDayNumbers:s>1,showWeekNumbers:e.showWeekNumbers,todayRange:g,dateProfile:t,cells:i,renderIntro:e.renderRowIntro,businessHourSegs:o[h],eventSelection:e.eventSelection,bgEventSegs:a[h].filter(rl),fgEventSegs:l[h],dateSelectionSegs:c[h],eventDrag:d[h],eventResize:u[h],dayMaxEvents:r,dayMaxEventRows:n,clientWidth:e.clientWidth,clientHeight:e.clientHeight,forPrint:e.forPrint})))))))}prepareHits(){this.rowPositions=new wr(this.rootEl,this.rowRefs.collect().map(e=>e.getCellEls()[0]),!1,!0),this.colPositions=new wr(this.rootEl,this.rowRefs.currentMap[0].getCellEls(),!0,!1)}queryHit(e,t){let{colPositions:n,rowPositions:r}=this,i=n.leftToIndex(e),s=r.topToIndex(t);if(null!=s&&null!=i){let e=this.props.cells[s][i];return{dateProfile:this.props.dateProfile,dateSpan:Object.assign({range:this.getCellRange(s,i),allDay:!0},e.extraDateSpan),dayEl:this.getCellEl(s,i),rect:{left:n.lefts[i],right:n.rights[i],top:r.tops[s],bottom:r.bottoms[s]},layer:0}}return null}getCellEl(e,t){return this.rowRefs.currentMap[e].getCellEls()[t]}getCellRange(e,t){let n=this.props.cells[e][t].date;return{start:n,end:St(n,1)}}}function rl(e){return e.eventRange.def.allDay}class il extends is{constructor(){super(...arguments),this.forceDayIfListItem=!0}sliceRange(e,t){return t.sliceRange(e)}}class sl extends zr{constructor(){super(...arguments),this.slicer=new il,this.tableRef={current:null}}render(){let{props:e,context:t}=this;return f(nl,Object.assign({ref:this.tableRef},this.slicer.sliceProps(e,e.dateProfile,e.nextDayThreshold,t,e.dayTableModel),{dateProfile:e.dateProfile,cells:e.dayTableModel.cells,colGroupNode:e.colGroupNode,tableMinWidth:e.tableMinWidth,renderRowIntro:e.renderRowIntro,dayMaxEvents:e.dayMaxEvents,dayMaxEventRows:e.dayMaxEventRows,showWeekNumbers:e.showWeekNumbers,expandRows:e.expandRows,headerAlignElRef:e.headerAlignElRef,clientWidth:e.clientWidth,clientHeight:e.clientHeight,forPrint:e.forPrint}))}}function ol(e,t){let n=new ns(e.renderRange,t);return new rs(n,/year|month|week/.test(e.currentRangeUnit))}oo(':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-day-events{margin-top:1px}.fc .fc-daygrid-body-balanced .fc-daygrid-day-events{left:0;position:absolute;right:0}.fc .fc-daygrid-body-unbalanced .fc-daygrid-day-events{min-height:2em;position:relative}.fc .fc-daygrid-body-natural .fc-daygrid-day-events{margin-bottom:1em}.fc .fc-daygrid-event-harness{position:relative}.fc .fc-daygrid-event-harness-abs{left:0;position:absolute;right:0;top:0}.fc .fc-daygrid-bg-harness{bottom:0;position:absolute;top:0}.fc .fc-daygrid-day-bg .fc-non-business{z-index:1}.fc .fc-daygrid-day-bg .fc-bg-event{z-index:2}.fc .fc-daygrid-day-bg .fc-highlight{z-index:3}.fc .fc-daygrid-event{margin-top:1px;z-index:6}.fc .fc-daygrid-event.fc-event-mirror{z-index:7}.fc .fc-daygrid-day-bottom{font-size:.85em;padding:2px 3px 0}.fc .fc-daygrid-day-bottom:before{clear:both;content:"";display:table}.fc .fc-daygrid-more-link{cursor:pointer;position:relative;z-index:4}.fc .fc-daygrid-week-number{background-color:var(--fc-neutral-bg-color);color:var(--fc-neutral-text-color);min-width:1.5em;padding:2px;position:absolute;text-align:center;top:0;z-index:5}.fc .fc-more-popover .fc-popover-body{min-width:220px;padding:10px}.fc-direction-ltr .fc-daygrid-event.fc-event-start,.fc-direction-rtl .fc-daygrid-event.fc-event-end{margin-left:2px}.fc-direction-ltr .fc-daygrid-event.fc-event-end,.fc-direction-rtl .fc-daygrid-event.fc-event-start{margin-right:2px}.fc-direction-ltr .fc-daygrid-week-number{border-radius:0 0 3px 0;left:0}.fc-direction-rtl .fc-daygrid-week-number{border-radius:0 0 0 3px;right:0}.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}');var al=yo({name:"@fullcalendar/daygrid",initialView:"dayGridMonth",views:{dayGrid:{component:class extends ja{constructor(){super(...arguments),this.buildDayTableModel=Vt(ol),this.headerRef={current:null},this.tableRef={current:null}}render(){let{options:e,dateProfileGenerator:t}=this.context,{props:n}=this,r=this.buildDayTableModel(n.dateProfile,t),i=e.dayHeaders&&f(es,{ref:this.headerRef,dateProfile:n.dateProfile,dates:r.headerDates,datesRepDistinctDays:1===r.rowCnt}),s=t=>f(sl,{ref:this.tableRef,dateProfile:n.dateProfile,dayTableModel:r,businessHours:n.businessHours,dateSelection:n.dateSelection,eventStore:n.eventStore,eventUiBases:n.eventUiBases,eventSelection:n.eventSelection,eventDrag:n.eventDrag,eventResize:n.eventResize,nextDayThreshold:e.nextDayThreshold,colGroupNode:t.tableColGroupNode,tableMinWidth:t.tableMinWidth,dayMaxEvents:e.dayMaxEvents,dayMaxEventRows:e.dayMaxEventRows,showWeekNumbers:e.weekNumbers,expandRows:!n.isHeightAuto,headerAlignElRef:this.headerElRef,clientWidth:t.clientWidth,clientHeight:t.clientHeight,forPrint:n.forPrint});return e.dayMinWidth?this.renderHScrollLayout(i,s,r.colCnt,e.dayMinWidth):this.renderSimpleLayout(i,s)}},dateProfileGeneratorClass:class extends Lr{buildRenderRange(e,t,n){let r,{dateEnv:i}=this.props,s=super.buildRenderRange(e,t,n),o=s.start,a=s.end;if(/^(year|month)$/.test(t)&&(o=i.startOfWeek(o),r=i.startOfWeek(a),r.valueOf()!==a.valueOf()&&(a=Dt(r,1))),this.props.monthMode&&this.props.fixedWeekCount){a=Dt(a,6-Math.ceil(Ct(o,a)))}return{start:o,end:a}}}},dayGridDay:{type:"dayGrid",duration:{days:1}},dayGridWeek:{type:"dayGrid",duration:{weeks:1}},dayGridMonth:{type:"dayGrid",duration:{months:1},monthMode:!0,fixedWeekCount:!0}}});class ll extends Kn{getKeyInfo(){return{allDay:{},timed:{}}}getKeysForDateSpan(e){return e.allDay?["allDay"]:["timed"]}getKeysForEventDef(e){return e.allDay?Kr(e)?["timed","allDay"]:["allDay"]:["timed"]}}const cl=on({hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"short"});function dl(e){let t=["fc-timegrid-slot","fc-timegrid-slot-label",e.isLabeled?"fc-scrollgrid-shrink":"fc-timegrid-slot-minor"];return f(Nr.Consumer,null,n=>{if(!e.isLabeled)return f("td",{className:t.join(" "),"data-time":e.isoTimeStr});let{dateEnv:r,options:i,viewApi:s}=n,o=null==i.slotLabelFormat?cl:Array.isArray(i.slotLabelFormat)?on(i.slotLabelFormat[0]):on(i.slotLabelFormat),a={level:0,time:e.time,date:r.toDate(e.date),view:s,text:r.format(e.date,o)};return f(qi,{elTag:"td",elClasses:t,elAttrs:{"data-time":e.isoTimeStr},renderProps:a,generatorName:"slotLabelContent",generator:i.slotLabelContent||ul,classNameGenerator:i.slotLabelClassNames,didMount:i.slotLabelDidMount,willUnmount:i.slotLabelWillUnmount},e=>f("div",{className:"fc-timegrid-slot-label-frame fc-scrollgrid-shrink-frame"},f(e,{elTag:"div",elClasses:["fc-timegrid-slot-label-cushion","fc-scrollgrid-shrink-cushion"]})))})}function ul(e){return e.text}class hl extends Br{render(){return this.props.slatMetas.map(e=>f("tr",{key:e.key},f(dl,Object.assign({},e))))}}const fl=on({week:"short"});class gl extends zr{constructor(){super(...arguments),this.allDaySplitter=new ll,this.headerElRef={current:null},this.rootElRef={current:null},this.scrollerElRef={current:null},this.state={slatCoords:null},this.handleScrollTopRequest=e=>{let t=this.scrollerElRef.current;t&&(t.scrollTop=e)},this.renderHeadAxis=(e,t="")=>{let{options:n}=this.context,{dateProfile:r}=this.props,i=r.renderRange,s=1===Rt(i.start,i.end)?hr(this.context,i.start,"week"):{};return n.weekNumbers&&"day"===e?f(Ys,{elTag:"th",elClasses:["fc-timegrid-axis","fc-scrollgrid-shrink"],elAttrs:{"aria-hidden":!0},date:i.start,defaultFormat:fl},e=>f("div",{className:["fc-timegrid-axis-frame","fc-scrollgrid-shrink-frame","fc-timegrid-axis-frame-liquid"].join(" "),style:{height:t}},f(e,{elTag:"a",elClasses:["fc-timegrid-axis-cushion","fc-scrollgrid-shrink-cushion","fc-scrollgrid-sync-inner"],elAttrs:s}))):f("th",{"aria-hidden":!0,className:"fc-timegrid-axis"},f("div",{className:"fc-timegrid-axis-frame",style:{height:t}}))},this.renderTableRowAxis=e=>{let{options:t,viewApi:n}=this.context,r={text:t.allDayText,view:n};return f(qi,{elTag:"td",elClasses:["fc-timegrid-axis","fc-scrollgrid-shrink"],elAttrs:{"aria-hidden":!0},renderProps:r,generatorName:"allDayContent",generator:t.allDayContent||pl,classNameGenerator:t.allDayClassNames,didMount:t.allDayDidMount,willUnmount:t.allDayWillUnmount},t=>f("div",{className:["fc-timegrid-axis-frame","fc-scrollgrid-shrink-frame",null==e?" fc-timegrid-axis-frame-liquid":""].join(" "),style:{height:e}},f(t,{elTag:"span",elClasses:["fc-timegrid-axis-cushion","fc-scrollgrid-shrink-cushion","fc-scrollgrid-sync-inner"]})))},this.handleSlatCoords=e=>{this.setState({slatCoords:e})}}renderSimpleLayout(e,t,n){let{context:r,props:i}=this,s=[],o=Ns(r.options);return e&&s.push({type:"header",key:"header",isSticky:o,chunk:{elRef:this.headerElRef,tableClassName:"fc-col-header",rowContent:e}}),t&&(s.push({type:"body",key:"all-day",chunk:{content:t}}),s.push({type:"body",key:"all-day-divider",outerContent:f("tr",{role:"presentation",className:"fc-scrollgrid-section"},f("td",{className:"fc-timegrid-divider "+r.theme.getClass("tableCellShaded")}))})),s.push({type:"body",key:"body",liquid:!0,expandRows:Boolean(r.options.expandRows),chunk:{scrollerElRef:this.scrollerElRef,content:n}}),f(io,{elRef:this.rootElRef,elClasses:["fc-timegrid"],viewSpec:r.viewSpec},f(Hs,{liquid:!i.isHeightAuto&&!i.forPrint,collapsibleWidth:i.forPrint,cols:[{width:"shrink"}],sections:s}))}renderHScrollLayout(e,t,n,r,i,s,o){let a=this.context.pluginHooks.scrollGridImpl;if(!a)throw new Error("No ScrollGrid implementation");let{context:l,props:c}=this,d=!c.forPrint&&Ns(l.options),u=!c.forPrint&&Ps(l.options),h=[];e&&h.push({type:"header",key:"header",isSticky:d,syncRowHeights:!0,chunks:[{key:"axis",rowContent:e=>f("tr",{role:"presentation"},this.renderHeadAxis("day",e.rowSyncHeights[0]))},{key:"cols",elRef:this.headerElRef,tableClassName:"fc-col-header",rowContent:e}]}),t&&(h.push({type:"body",key:"all-day",syncRowHeights:!0,chunks:[{key:"axis",rowContent:e=>f("tr",{role:"presentation"},this.renderTableRowAxis(e.rowSyncHeights[0]))},{key:"cols",content:t}]}),h.push({key:"all-day-divider",type:"body",outerContent:f("tr",{role:"presentation",className:"fc-scrollgrid-section"},f("td",{colSpan:2,className:"fc-timegrid-divider "+l.theme.getClass("tableCellShaded")}))}));let g=l.options.nowIndicator;return h.push({type:"body",key:"body",liquid:!0,expandRows:Boolean(l.options.expandRows),chunks:[{key:"axis",content:e=>f("div",{className:"fc-timegrid-axis-chunk"},f("table",{"aria-hidden":!0,style:{height:e.expandRows?e.clientHeight:""}},e.tableColGroupNode,f("tbody",null,f(hl,{slatMetas:s}))),f("div",{className:"fc-timegrid-now-indicator-container"},f($i,{unit:g?"minute":"day"},e=>{let t=g&&o&&o.safeComputeTop(e);return"number"==typeof t?f(Us,{elClasses:["fc-timegrid-now-indicator-arrow"],elStyle:{top:t},isAxis:!0,date:e}):null})))},{key:"cols",scrollerElRef:this.scrollerElRef,content:n}]}),u&&h.push({key:"footer",type:"footer",isSticky:!0,chunks:[{key:"axis",content:Os},{key:"cols",content:Os}]}),f(io,{elRef:this.rootElRef,elClasses:["fc-timegrid"],viewSpec:l.viewSpec},f(a,{liquid:!c.isHeightAuto&&!c.forPrint,collapsibleWidth:!1,colGroups:[{width:"shrink",cols:[{width:"shrink"}]},{cols:[{span:r,minWidth:i}]}],sections:h}))}getAllDayMaxEventProps(){let{dayMaxEvents:e,dayMaxEventRows:t}=this.context.options;return!0!==e&&!0!==t||(e=void 0,t=5),{dayMaxEvents:e,dayMaxEventRows:t}}}function pl(e){return e.text}class ml{constructor(e,t,n){this.positions=e,this.dateProfile=t,this.slotDuration=n}safeComputeTop(e){let{dateProfile:t}=this;if(ar(t.currentRange,e)){let n=kt(e),r=e.valueOf()-n.valueOf();if(r>=ot(t.slotMinTime)&&r<ot(t.slotMaxTime))return this.computeTimeTop(tt(r))}return null}computeDateTop(e,t){return t||(t=kt(e)),this.computeTimeTop(tt(e.valueOf()-t.valueOf()))}computeTimeTop(e){let t,n,{positions:r,dateProfile:i}=this,s=r.els.length,o=(e.milliseconds-ot(i.slotMinTime))/ot(this.slotDuration);return o=Math.max(0,o),o=Math.min(s,o),t=Math.floor(o),t=Math.min(t,s-1),n=o-t,r.tops[t]+r.getHeight(t)*n}}class vl extends Br{render(){let{props:e,context:t}=this,{options:n}=t,{slatElRefs:r}=e;return f("tbody",null,e.slatMetas.map((i,s)=>{let o={time:i.time,date:t.dateEnv.toDate(i.date),view:t.viewApi};return f("tr",{key:i.key,ref:r.createRef(i.key)},e.axis&&f(dl,Object.assign({},i)),f(qi,{elTag:"td",elClasses:["fc-timegrid-slot","fc-timegrid-slot-lane",!i.isLabeled&&"fc-timegrid-slot-minor"],elAttrs:{"data-time":i.isoTimeStr},renderProps:o,generatorName:"slotLaneContent",generator:n.slotLaneContent,classNameGenerator:n.slotLaneClassNames,didMount:n.slotLaneDidMount,willUnmount:n.slotLaneWillUnmount}))}))}}class bl extends Br{constructor(){super(...arguments),this.rootElRef={current:null},this.slatElRefs=new Ds}render(){let{props:e,context:t}=this;return f("div",{ref:this.rootElRef,className:"fc-timegrid-slots"},f("table",{"aria-hidden":!0,className:t.theme.getClass("table"),style:{minWidth:e.tableMinWidth,width:e.clientWidth,height:e.minHeight}},e.tableColGroupNode,f(vl,{slatElRefs:this.slatElRefs,axis:e.axis,slatMetas:e.slatMetas})))}componentDidMount(){this.updateSizing()}componentDidUpdate(){this.updateSizing()}componentWillUnmount(){this.props.onCoords&&this.props.onCoords(null)}updateSizing(){let{context:e,props:t}=this;if(t.onCoords&&null!==t.clientWidth){this.rootElRef.current.offsetHeight&&t.onCoords(new ml(new wr(this.rootElRef.current,(n=this.slatElRefs.currentMap,t.slatMetas.map(e=>n[e.key])),!1,!0),this.props.dateProfile,e.options.slotDuration))}var n}}function yl(e,t){let n,r=[];for(n=0;n<t;n+=1)r.push([]);if(e)for(n=0;n<e.length;n+=1)r[e[n].col].push(e[n]);return r}function El(e,t){let n=[];if(e){for(let r=0;r<t;r+=1)n[r]={affectedInstances:e.affectedInstances,isEvent:e.isEvent,segs:[]};for(let t of e.segs)n[t.col].segs.push(t)}else for(let e=0;e<t;e+=1)n[e]=null;return n}class Al extends Br{render(){let{props:e}=this;return f($s,{elClasses:["fc-timegrid-more-link"],elStyle:{top:e.top,bottom:e.bottom},allDayDate:null,moreCnt:e.hiddenSegs.length,allSegs:e.hiddenSegs,hiddenSegs:e.hiddenSegs,extraDateSpan:e.extraDateSpan,dateProfile:e.dateProfile,todayRange:e.todayRange,popoverContent:()=>Il(e.hiddenSegs,e),defaultGenerator:Dl},e=>f(e,{elTag:"div",elClasses:["fc-timegrid-more-link-inner","fc-sticky"]}))}}function Dl(e){return e.shortText}function Sl(e,t,n){let r=new Ci;null!=t&&(r.strictOrder=t),null!=n&&(r.maxStackCnt=n);let i=_i(r.addSegs(e)),s=function(e){const{entriesByLevel:t}=e,n=xl((e,t)=>e+":"+t,(r,i)=>{let s=wl(function(e,t,n){let{levelCoords:r,entriesByLevel:i}=e,s=i[t][n],o=r[t]+s.thickness,a=r.length,l=t;for(;l<a&&r[l]<o;l+=1);for(;l<a;l+=1){let e,t=i[l],n=Mi(t,s.span.start,Ri),r=n[0]+n[1],o=r;for(;(e=t[o])&&e.span.start<s.span.end;)o+=1;if(r<o)return{level:l,lateralStart:r,lateralEnd:o}}return null}(e,r,i),n),o=t[r][i];return[Object.assign(Object.assign({},o),{nextLevelNodes:s[0]}),o.thickness+s[1]]});return wl(t.length?{level:0,lateralStart:0,lateralEnd:t[0].length}:null,n)[0]}(r);return s=function(e,t){const n=xl((e,t,n)=>xi(e),(e,r,i)=>{let s,{nextLevelNodes:o,thickness:a}=e,l=a+i,c=a/l,d=[];if(o.length)for(let e of o)if(void 0===s){let t=n(e,r,l);s=t[0],d.push(t[1])}else{let t=n(e,s,0);d.push(t[1])}else s=t;let u=(s-r)*c;return[s-u,Object.assign(Object.assign({},e),{thickness:u,nextLevelNodes:d})]});return e.map(e=>n(e,0,0)[1])}(s,1),{segRects:function(e){let t=[];const n=xl((e,t,n)=>xi(e),(e,n,i)=>{let s=Object.assign(Object.assign({},e),{levelCoord:n,stackDepth:i,stackForward:0});return t.push(s),s.stackForward=r(e.nextLevelNodes,n+e.thickness,i+1)+1});function r(e,t,r){let i=0;for(let s of e)i=Math.max(n(s,t,r),i);return i}return r(e,0,0),t}(s),hiddenGroups:i}}function wl(e,t){if(!e)return[[],0];let{level:n,lateralStart:r,lateralEnd:i}=e,s=r,o=[];for(;s<i;)o.push(t(n,s)),s+=1;return o.sort(Cl),[o.map(Rl),o[0][1]]}function Cl(e,t){return t[1]-e[1]}function Rl(e){return e[0]}function xl(e,t){const n={};return(...r)=>{let i=e(...r);return i in n?n[i]:n[i]=t(...r)}}function _l(e,t,n=null,r=0){let i=[];if(n)for(let s=0;s<e.length;s+=1){let o=e[s],a=n.computeDateTop(o.start,t),l=Math.max(a+(r||0),n.computeDateTop(o.end,t));i.push({start:Math.round(a),end:Math.round(l)})}return i}const Tl=on({hour:"numeric",minute:"2-digit",meridiem:!1});class kl extends Br{render(){return f(js,Object.assign({},this.props,{elClasses:["fc-timegrid-event","fc-v-event",this.props.isShort&&"fc-timegrid-event-short"],defaultTimeFormat:Tl}))}}class Ml extends Br{constructor(){super(...arguments),this.sortEventSegs=Vt(ii)}render(){let{props:e,context:t}=this,{options:n}=t,r=n.selectMirror,i=e.eventDrag&&e.eventDrag.segs||e.eventResize&&e.eventResize.segs||r&&e.dateSelectionSegs||[],s=e.eventDrag&&e.eventDrag.affectedInstances||e.eventResize&&e.eventResize.affectedInstances||{},o=this.sortEventSegs(e.fgEventSegs,n.eventOrder);return f(Ws,{elTag:"td",elRef:e.elRef,elClasses:["fc-timegrid-col",...e.extraClassNames||[]],elAttrs:Object.assign({role:"gridcell"},e.extraDataAttrs),date:e.date,dateProfile:e.dateProfile,todayRange:e.todayRange,extraRenderProps:e.extraRenderProps},t=>f("div",{className:"fc-timegrid-col-frame"},f("div",{className:"fc-timegrid-col-bg"},this.renderFillSegs(e.businessHourSegs,"non-business"),this.renderFillSegs(e.bgEventSegs,"bg-event"),this.renderFillSegs(e.dateSelectionSegs,"highlight")),f("div",{className:"fc-timegrid-col-events"},this.renderFgSegs(o,s,!1,!1,!1)),f("div",{className:"fc-timegrid-col-events"},this.renderFgSegs(i,{},Boolean(e.eventDrag),Boolean(e.eventResize),Boolean(r))),f("div",{className:"fc-timegrid-now-indicator-container"},this.renderNowIndicator(e.nowIndicatorSegs)),Fs(n)&&f(t,{elTag:"div",elClasses:["fc-timegrid-col-misc"]})))}renderFgSegs(e,t,n,r,i){let{props:s}=this;return s.forPrint?Il(e,s):this.renderPositionedFgSegs(e,t,n,r,i)}renderPositionedFgSegs(e,t,n,r,i){let{eventMaxStack:s,eventShortHeight:o,eventOrderStrict:a,eventMinHeight:l}=this.context.options,{date:c,slatCoords:d,eventSelection:u,todayRange:h,nowDate:g}=this.props,m=n||r||i,v=_l(e,c,d,l),{segPlacements:b,hiddenGroups:y}=function(e,t,n,r){let i=[],s=[];for(let n=0;n<e.length;n+=1){let r=t[n];r?i.push({index:n,thickness:1,span:r}):s.push(e[n])}let{segRects:o,hiddenGroups:a}=Sl(i,n,r),l=[];for(let t of o)l.push({seg:e[t.index],rect:t});for(let e of s)l.push({seg:e,rect:null});return{segPlacements:l,hiddenGroups:a}}(e,v,a,s);return f(p,null,this.renderHiddenGroups(y,e),b.map(e=>{let{seg:s,rect:a}=e,l=s.eventRange.instance.instanceId,c=m||Boolean(!t[l]&&a),d=Ol(a&&a.span),p=!m&&a?this.computeSegHStyle(a):{left:0,right:0},v=Boolean(a)&&a.stackForward>0,b=Boolean(a)&&a.span.end-a.span.start<o;return f("div",{className:"fc-timegrid-event-harness"+(v?" fc-timegrid-event-harness-inset":""),key:l,style:Object.assign(Object.assign({visibility:c?"":"hidden"},d),p)},f(kl,Object.assign({seg:s,isDragging:n,isResizing:r,isDateSelecting:i,isSelected:l===u,isShort:b},di(s,h,g))))}))}renderHiddenGroups(e,t){let{extraDateSpan:n,dateProfile:r,todayRange:i,nowDate:s,eventSelection:o,eventDrag:a,eventResize:l}=this.props;return f(p,null,e.map(e=>{let c=Ol(e.span),d=(u=e.entries,h=t,u.map(e=>h[e.index]));var u,h;return f(Al,{key:zt(to(d)),hiddenSegs:d,top:c.top,bottom:c.bottom,extraDateSpan:n,dateProfile:r,todayRange:i,nowDate:s,eventSelection:o,eventDrag:a,eventResize:l})}))}renderFillSegs(e,t){let{props:n,context:r}=this,i=_l(e,n.date,n.slatCoords,r.options.eventMinHeight).map((r,i)=>{let s=e[i];return f("div",{key:hi(s.eventRange),className:"fc-timegrid-bg-harness",style:Ol(r)},"bg-event"===t?f(Gs,Object.assign({seg:s},di(s,n.todayRange,n.nowDate))):qs(t))});return f(p,null,i)}renderNowIndicator(e){let{slatCoords:t,date:n}=this.props;return t?e.map((e,r)=>f(Us,{key:r,elClasses:["fc-timegrid-now-indicator-line"],elStyle:{top:t.computeDateTop(e.start,n)},isAxis:!1,date:n})):null}computeSegHStyle(e){let t,n,{isRtl:r,options:i}=this.context,s=i.slotEventOverlap,o=e.levelCoord,a=e.levelCoord+e.thickness;s&&(a=Math.min(1,o+2*(a-o))),r?(t=1-a,n=o):(t=o,n=1-a);let l={zIndex:e.stackDepth+1,left:100*t+"%",right:100*n+"%"};return s&&!e.stackForward&&(l[r?"marginLeft":"marginRight"]=20),l}}function Il(e,{todayRange:t,nowDate:n,eventSelection:r,eventDrag:i,eventResize:s}){let o=(i?i.affectedInstances:null)||(s?s.affectedInstances:null)||{};return f(p,null,e.map(e=>{let i=e.eventRange.instance.instanceId;return f("div",{key:i,style:{visibility:o[i]?"hidden":""}},f(kl,Object.assign({seg:e,isDragging:!1,isResizing:!1,isDateSelecting:!1,isSelected:i===r,isShort:!1},di(e,t,n))))}))}function Ol(e){return e?{top:e.start,bottom:-e.end}:{top:"",bottom:""}}class Nl extends Br{constructor(){super(...arguments),this.splitFgEventSegs=Vt(yl),this.splitBgEventSegs=Vt(yl),this.splitBusinessHourSegs=Vt(yl),this.splitNowIndicatorSegs=Vt(yl),this.splitDateSelectionSegs=Vt(yl),this.splitEventDrag=Vt(El),this.splitEventResize=Vt(El),this.rootElRef={current:null},this.cellElRefs=new Ds}render(){let{props:e,context:t}=this,n=t.options.nowIndicator&&e.slatCoords&&e.slatCoords.safeComputeTop(e.nowDate),r=e.cells.length,i=this.splitFgEventSegs(e.fgEventSegs,r),s=this.splitBgEventSegs(e.bgEventSegs,r),o=this.splitBusinessHourSegs(e.businessHourSegs,r),a=this.splitNowIndicatorSegs(e.nowIndicatorSegs,r),l=this.splitDateSelectionSegs(e.dateSelectionSegs,r),c=this.splitEventDrag(e.eventDrag,r),d=this.splitEventResize(e.eventResize,r);return f("div",{className:"fc-timegrid-cols",ref:this.rootElRef},f("table",{role:"presentation",style:{minWidth:e.tableMinWidth,width:e.clientWidth}},e.tableColGroupNode,f("tbody",{role:"presentation"},f("tr",{role:"row"},e.axis&&f("td",{"aria-hidden":!0,className:"fc-timegrid-col fc-timegrid-axis"},f("div",{className:"fc-timegrid-col-frame"},f("div",{className:"fc-timegrid-now-indicator-container"},"number"==typeof n&&f(Us,{elClasses:["fc-timegrid-now-indicator-arrow"],elStyle:{top:n},isAxis:!0,date:e.nowDate})))),e.cells.map((t,n)=>f(Ml,{key:t.key,elRef:this.cellElRefs.createRef(t.key),dateProfile:e.dateProfile,date:t.date,nowDate:e.nowDate,todayRange:e.todayRange,extraRenderProps:t.extraRenderProps,extraDataAttrs:t.extraDataAttrs,extraClassNames:t.extraClassNames,extraDateSpan:t.extraDateSpan,fgEventSegs:i[n],bgEventSegs:s[n],businessHourSegs:o[n],nowIndicatorSegs:a[n],dateSelectionSegs:l[n],eventDrag:c[n],eventResize:d[n],slatCoords:e.slatCoords,eventSelection:e.eventSelection,forPrint:e.forPrint}))))))}componentDidMount(){this.updateCoords()}componentDidUpdate(){this.updateCoords()}updateCoords(){let{props:e}=this;var t;e.onColCoords&&null!==e.clientWidth&&e.onColCoords(new wr(this.rootElRef.current,(t=this.cellElRefs.currentMap,e.cells.map(e=>t[e.key])),!0,!1))}}class Pl extends zr{constructor(){super(...arguments),this.processSlotOptions=Vt(Hl),this.state={slatCoords:null},this.handleRootEl=e=>{e?this.context.registerInteractiveComponent(this,{el:e,isHitComboAllowed:this.props.isHitComboAllowed}):this.context.unregisterInteractiveComponent(this)},this.handleScrollRequest=e=>{let{onScrollTopRequest:t}=this.props,{slatCoords:n}=this.state;if(t&&n){if(e.time){let r=n.computeTimeTop(e.time);r=Math.ceil(r),r&&(r+=1),t(r)}return!0}return!1},this.handleColCoords=e=>{this.colCoords=e},this.handleSlatCoords=e=>{this.setState({slatCoords:e}),this.props.onSlatCoords&&this.props.onSlatCoords(e)}}render(){let{props:e,state:t}=this;return f("div",{className:"fc-timegrid-body",ref:this.handleRootEl,style:{width:e.clientWidth,minWidth:e.tableMinWidth}},f(bl,{axis:e.axis,dateProfile:e.dateProfile,slatMetas:e.slatMetas,clientWidth:e.clientWidth,minHeight:e.expandRows?e.clientHeight:"",tableMinWidth:e.tableMinWidth,tableColGroupNode:e.axis?e.tableColGroupNode:null,onCoords:this.handleSlatCoords}),f(Nl,{cells:e.cells,axis:e.axis,dateProfile:e.dateProfile,businessHourSegs:e.businessHourSegs,bgEventSegs:e.bgEventSegs,fgEventSegs:e.fgEventSegs,dateSelectionSegs:e.dateSelectionSegs,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize,todayRange:e.todayRange,nowDate:e.nowDate,nowIndicatorSegs:e.nowIndicatorSegs,clientWidth:e.clientWidth,tableMinWidth:e.tableMinWidth,tableColGroupNode:e.tableColGroupNode,slatCoords:t.slatCoords,onColCoords:this.handleColCoords,forPrint:e.forPrint}))}componentDidMount(){this.scrollResponder=this.context.createScrollResponder(this.handleScrollRequest)}componentDidUpdate(e){this.scrollResponder.update(e.dateProfile!==this.props.dateProfile)}componentWillUnmount(){this.scrollResponder.detach()}queryHit(e,t){let{dateEnv:n,options:r}=this.context,{colCoords:i}=this,{dateProfile:s}=this.props,{slatCoords:o}=this.state,{snapDuration:a,snapsPerSlot:l}=this.processSlotOptions(this.props.slotDuration,r.snapDuration),c=i.leftToIndex(e),d=o.positions.topToIndex(t);if(null!=c&&null!=d){let e=this.props.cells[c],r=o.positions.tops[d],u=o.positions.getHeight(d),h=(t-r)/u,f=d*l+Math.floor(h*l),g=this.props.cells[c].date,p=rt(s.slotMinTime,it(a,f)),m=n.add(g,p),v=n.add(m,a);return{dateProfile:s,dateSpan:Object.assign({range:{start:m,end:v},allDay:!1},e.extraDateSpan),dayEl:i.els[c],rect:{left:i.lefts[c],right:i.rights[c],top:r,bottom:r+u},layer:0}}return null}}function Hl(e,t){let n=t||e,r=at(e,n);return null===r&&(n=e,r=1),{snapDuration:n,snapsPerSlot:r}}class Bl extends is{sliceRange(e,t){let n=[];for(let r=0;r<t.length;r+=1){let i=rr(e,t[r]);i&&n.push({start:i.start,end:i.end,isStart:i.start.valueOf()===e.start.valueOf(),isEnd:i.end.valueOf()===e.end.valueOf(),col:r})}return n}}class jl extends zr{constructor(){super(...arguments),this.buildDayRanges=Vt(zl),this.slicer=new Bl,this.timeColsRef={current:null}}render(){let{props:e,context:t}=this,{dateProfile:n,dayTableModel:r}=e,i=t.options.nowIndicator,s=this.buildDayRanges(r,n,t.dateEnv);return f($i,{unit:i?"minute":"day"},(o,a)=>f(Pl,Object.assign({ref:this.timeColsRef},this.slicer.sliceProps(e,n,null,t,s),{forPrint:e.forPrint,axis:e.axis,dateProfile:n,slatMetas:e.slatMetas,slotDuration:e.slotDuration,cells:r.cells[0],tableColGroupNode:e.tableColGroupNode,tableMinWidth:e.tableMinWidth,clientWidth:e.clientWidth,clientHeight:e.clientHeight,expandRows:e.expandRows,nowDate:o,nowIndicatorSegs:i&&this.slicer.sliceNowDate(o,t,s),todayRange:a,onScrollTopRequest:e.onScrollTopRequest,onSlatCoords:e.onSlatCoords})))}}function zl(e,t,n){let r=[];for(let i of e.headerDates)r.push({start:n.add(i,t.slotMinTime),end:n.add(i,t.slotMaxTime)});return r}const Ul=[{hours:1},{minutes:30},{minutes:15},{seconds:30},{seconds:15}];function Ll(e,t,n,r,i){let s=new Date(0),o=e,a=tt(0),l=n||function(e){let t,n,r;for(t=Ul.length-1;t>=0;t-=1)if(n=tt(Ul[t]),r=at(n,e),null!==r&&r>1)return n;return e}(r),c=[];for(;ot(o)<ot(t);){let e=i.add(s,o),t=null!==at(a,l);c.push({date:e,time:o,key:e.toISOString(),isoTimeStr:Lt(e),isLabeled:t}),o=rt(o,r),a=rt(a,r)}return c}function Wl(e,t){let n=new ns(e.renderRange,t);return new rs(n,!1)}const Fl={allDaySlot:Boolean};oo('.fc-v-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-v-event .fc-event-main{color:var(--fc-event-text-color);height:100%}.fc-v-event .fc-event-main-frame{display:flex;flex-direction:column;height:100%}.fc-v-event .fc-event-time{flex-grow:0;flex-shrink:0;max-height:100%;overflow:hidden}.fc-v-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-height:0}.fc-v-event .fc-event-title{bottom:0;max-height:100%;overflow:hidden;top:0}.fc-v-event:not(.fc-event-start){border-top-left-radius:0;border-top-right-radius:0;border-top-width:0}.fc-v-event:not(.fc-event-end){border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-width:0}.fc-v-event.fc-event-selected:before{left:-10px;right:-10px}.fc-v-event .fc-event-resizer-start{cursor:n-resize}.fc-v-event .fc-event-resizer-end{cursor:s-resize}.fc-v-event:not(.fc-event-selected) .fc-event-resizer{height:var(--fc-event-resizer-thickness);left:0;right:0}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-start{top:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer{left:50%;margin-left:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-start{top:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc .fc-timegrid .fc-daygrid-body{z-index:2}.fc .fc-timegrid-divider{padding:0 0 2px}.fc .fc-timegrid-body{min-height:100%;position:relative;z-index:1}.fc .fc-timegrid-axis-chunk{position:relative}.fc .fc-timegrid-axis-chunk>table,.fc .fc-timegrid-slots{position:relative;z-index:1}.fc .fc-timegrid-slot{border-bottom:0;height:1.5em}.fc .fc-timegrid-slot:empty:before{content:"\\00a0"}.fc .fc-timegrid-slot-minor{border-top-style:dotted}.fc .fc-timegrid-slot-label-cushion{display:inline-block;white-space:nowrap}.fc .fc-timegrid-slot-label{vertical-align:middle}.fc .fc-timegrid-axis-cushion,.fc .fc-timegrid-slot-label-cushion{padding:0 4px}.fc .fc-timegrid-axis-frame-liquid{height:100%}.fc .fc-timegrid-axis-frame{align-items:center;display:flex;justify-content:flex-end;overflow:hidden}.fc .fc-timegrid-axis-cushion{flex-shrink:0;max-width:60px}.fc-direction-ltr .fc-timegrid-slot-label-frame{text-align:right}.fc-direction-rtl .fc-timegrid-slot-label-frame{text-align:left}.fc-liquid-hack .fc-timegrid-axis-frame-liquid{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-timegrid-col-frame{min-height:100%;position:relative}.fc-media-screen.fc-liquid-hack .fc-timegrid-col-frame{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols{bottom:0;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols>table{height:100%}.fc-media-screen .fc-timegrid-col-bg,.fc-media-screen .fc-timegrid-col-events,.fc-media-screen .fc-timegrid-now-indicator-container{left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col-bg{z-index:2}.fc .fc-timegrid-col-bg .fc-non-business{z-index:1}.fc .fc-timegrid-col-bg .fc-bg-event{z-index:2}.fc .fc-timegrid-col-bg .fc-highlight{z-index:3}.fc .fc-timegrid-bg-harness{left:0;position:absolute;right:0}.fc .fc-timegrid-col-events{z-index:3}.fc .fc-timegrid-now-indicator-container{bottom:0;overflow:hidden}.fc-direction-ltr .fc-timegrid-col-events{margin:0 2.5% 0 2px}.fc-direction-rtl .fc-timegrid-col-events{margin:0 2px 0 2.5%}.fc-timegrid-event-harness{position:absolute}.fc-timegrid-event-harness>.fc-timegrid-event{bottom:0;left:0;position:absolute;right:0;top:0}.fc-timegrid-event-harness-inset .fc-timegrid-event,.fc-timegrid-event.fc-event-mirror,.fc-timegrid-more-link{box-shadow:0 0 0 1px var(--fc-page-bg-color)}.fc-timegrid-event,.fc-timegrid-more-link{border-radius:3px;font-size:var(--fc-small-font-size)}.fc-timegrid-event{margin-bottom:1px}.fc-timegrid-event .fc-event-main{padding:1px 1px 0}.fc-timegrid-event .fc-event-time{font-size:var(--fc-small-font-size);margin-bottom:1px;white-space:nowrap}.fc-timegrid-event-short .fc-event-main-frame{flex-direction:row;overflow:hidden}.fc-timegrid-event-short .fc-event-time:after{content:"\\00a0-\\00a0"}.fc-timegrid-event-short .fc-event-title{font-size:var(--fc-small-font-size)}.fc-timegrid-more-link{background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;margin-bottom:1px;position:absolute;z-index:9999}.fc-timegrid-more-link-inner{padding:3px 2px;top:0}.fc-direction-ltr .fc-timegrid-more-link{right:0}.fc-direction-rtl .fc-timegrid-more-link{left:0}.fc .fc-timegrid-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;border-width:1px 0 0;left:0;position:absolute;right:0;z-index:4}.fc .fc-timegrid-now-indicator-arrow{border-color:var(--fc-now-indicator-color);border-style:solid;margin-top:-5px;position:absolute;z-index:4}.fc-direction-ltr .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 0 5px 6px;left:0}.fc-direction-rtl .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 6px 5px 0;right:0}');var Vl=yo({name:"@fullcalendar/timegrid",initialView:"timeGridWeek",optionRefiners:Fl,views:{timeGrid:{component:class extends gl{constructor(){super(...arguments),this.buildTimeColsModel=Vt(Wl),this.buildSlatMetas=Vt(Ll)}render(){let{options:e,dateEnv:t,dateProfileGenerator:n}=this.context,{props:r}=this,{dateProfile:i}=r,s=this.buildTimeColsModel(i,n),o=this.allDaySplitter.splitProps(r),a=this.buildSlatMetas(i.slotMinTime,i.slotMaxTime,e.slotLabelInterval,e.slotDuration,t),{dayMinWidth:l}=e,c=!l,d=l,u=e.dayHeaders&&f(es,{dates:s.headerDates,dateProfile:i,datesRepDistinctDays:!0,renderIntro:c?this.renderHeadAxis:null}),h=!1!==e.allDaySlot&&(t=>f(sl,Object.assign({},o.allDay,{dateProfile:i,dayTableModel:s,nextDayThreshold:e.nextDayThreshold,tableMinWidth:t.tableMinWidth,colGroupNode:t.tableColGroupNode,renderRowIntro:c?this.renderTableRowAxis:null,showWeekNumbers:!1,expandRows:!1,headerAlignElRef:this.headerElRef,clientWidth:t.clientWidth,clientHeight:t.clientHeight,forPrint:r.forPrint},this.getAllDayMaxEventProps()))),g=t=>f(jl,Object.assign({},o.timed,{dayTableModel:s,dateProfile:i,axis:c,slotDuration:e.slotDuration,slatMetas:a,forPrint:r.forPrint,tableColGroupNode:t.tableColGroupNode,tableMinWidth:t.tableMinWidth,clientWidth:t.clientWidth,clientHeight:t.clientHeight,onSlatCoords:this.handleSlatCoords,expandRows:t.expandRows,onScrollTopRequest:this.handleScrollTopRequest}));return d?this.renderHScrollLayout(u,h,g,s.colCnt,l,a,this.state.slatCoords):this.renderSimpleLayout(u,h,g)}},usesMinMaxTime:!0,allDaySlot:!0,slotDuration:"00:30:00",slotEventOverlap:!0},timeGridDay:{type:"timeGrid",duration:{days:1}},timeGridWeek:{type:"timeGrid",duration:{weeks:1}}}});class Gl extends Br{constructor(){super(...arguments),this.state={textId:Te()}}render(){let{theme:e,dateEnv:t,options:n,viewApi:r}=this.context,{cellId:i,dayDate:s,todayRange:o}=this.props,{textId:a}=this.state,l=lr(s,o),c=n.listDayFormat?t.format(s,n.listDayFormat):"",d=n.listDaySideFormat?t.format(s,n.listDaySideFormat):"",u=Object.assign({date:t.toDate(s),view:r,textId:a,text:c,sideText:d,navLinkAttrs:hr(this.context,s),sideNavLinkAttrs:hr(this.context,s,"day",!1)},l);return f(qi,{elTag:"tr",elClasses:["fc-list-day",...cr(l,e)],elAttrs:{"data-date":Ut(s)},renderProps:u,generatorName:"dayHeaderContent",generator:n.dayHeaderContent||Ql,classNameGenerator:n.dayHeaderClassNames,didMount:n.dayHeaderDidMount,willUnmount:n.dayHeaderWillUnmount},t=>f("th",{scope:"colgroup",colSpan:3,id:i,"aria-labelledby":a},f(t,{elTag:"div",elClasses:["fc-list-day-cushion",e.getClass("tableCellShaded")]})))}}function Ql(e){return f(p,null,e.text&&f("a",Object.assign({id:e.textId,className:"fc-list-day-text"},e.navLinkAttrs),e.text),e.sideText&&f("a",Object.assign({"aria-hidden":!0,className:"fc-list-day-side-text"},e.sideNavLinkAttrs),e.sideText))}const ql=on({hour:"numeric",minute:"2-digit",meridiem:"short"});class Yl extends Br{render(){let{props:e,context:t}=this,{options:n}=t,{seg:r,timeHeaderId:i,eventHeaderId:s,dateHeaderId:o}=e,a=n.eventTimeFormat||ql;return f(Bs,Object.assign({},e,{elTag:"tr",elClasses:["fc-list-event",r.eventRange.def.url&&"fc-event-forced-url"],defaultGenerator:()=>function(e,t){let n=fi(e,t);return f("a",Object.assign({},n),e.eventRange.def.title)}(r,t),seg:r,timeText:"",disableDragging:!0,disableResizing:!0}),(e,n)=>f(p,null,function(e,t,n,r,i){let{options:s}=n;if(!1!==s.displayEventTime){let o,a=e.eventRange.def,l=e.eventRange.instance,c=!1;if(a.allDay?c=!0:Fn(e.eventRange.range)?e.isStart?o=ci(e,t,n,null,null,l.range.start,e.end):e.isEnd?o=ci(e,t,n,null,null,e.start,l.range.end):c=!0:o=ci(e,t,n),c){let e={text:n.options.allDayText,view:n.viewApi};return f(qi,{elTag:"td",elClasses:["fc-list-event-time"],elAttrs:{headers:`${r} ${i}`},renderProps:e,generatorName:"allDayContent",generator:s.allDayContent||Zl,classNameGenerator:s.allDayClassNames,didMount:s.allDayDidMount,willUnmount:s.allDayWillUnmount})}return f("td",{className:"fc-list-event-time"},o)}return null}(r,a,t,i,o),f("td",{"aria-hidden":!0,className:"fc-list-event-graphic"},f("span",{className:"fc-list-event-dot",style:{borderColor:n.borderColor||n.backgroundColor}})),f(e,{elTag:"td",elClasses:["fc-list-event-title"],elAttrs:{headers:`${s} ${o}`}})))}}function Zl(e){return e.text}function Xl(e){return e.text}function Jl(e){let t=kt(e.renderRange.start),n=e.renderRange.end,r=[],i=[];for(;t<n;)r.push(t),i.push({start:t,end:St(t,1)}),t=St(t,1);return{dayDates:r,dayRanges:i}}const $l={listDayFormat:Kl,listDaySideFormat:Kl,noEventsClassNames:mn,noEventsContent:mn,noEventsDidMount:mn,noEventsWillUnmount:mn};function Kl(e){return!1===e?null:on(e)}oo(':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}');var ec=yo({name:"@fullcalendar/list",optionRefiners:$l,views:{list:{component:class extends zr{constructor(){super(...arguments),this.computeDateVars=Vt(Jl),this.eventStoreToSegs=Vt(this._eventStoreToSegs),this.state={timeHeaderId:Te(),eventHeaderId:Te(),dateHeaderIdRoot:Te()},this.setRootEl=e=>{e?this.context.registerInteractiveComponent(this,{el:e}):this.context.unregisterInteractiveComponent(this)}}render(){let{props:e,context:t}=this,{dayDates:n,dayRanges:r}=this.computeDateVars(e.dateProfile),i=this.eventStoreToSegs(e.eventStore,e.eventUiBases,r);return f(io,{elRef:this.setRootEl,elClasses:["fc-list",t.theme.getClass("table"),!1!==t.options.stickyHeaderDates?"fc-list-sticky":""],viewSpec:t.viewSpec},f(As,{liquid:!e.isHeightAuto,overflowX:e.isHeightAuto?"visible":"hidden",overflowY:e.isHeightAuto?"visible":"auto"},i.length>0?this.renderSegList(i,n):this.renderEmptyMessage()))}renderEmptyMessage(){let{options:e,viewApi:t}=this.context,n={text:e.noEventsText,view:t};return f(qi,{elTag:"div",elClasses:["fc-list-empty"],renderProps:n,generatorName:"noEventsContent",generator:e.noEventsContent||Xl,classNameGenerator:e.noEventsClassNames,didMount:e.noEventsDidMount,willUnmount:e.noEventsWillUnmount},e=>f(e,{elTag:"div",elClasses:["fc-list-empty-cushion"]}))}renderSegList(e,t){let{theme:n,options:r}=this.context,{timeHeaderId:i,eventHeaderId:s,dateHeaderIdRoot:o}=this.state,a=function(e){let t,n,r=[];for(t=0;t<e.length;t+=1)n=e[t],(r[n.dayIndex]||(r[n.dayIndex]=[])).push(n);return r}(e);return f($i,{unit:"day"},(e,l)=>{let c=[];for(let n=0;n<a.length;n+=1){let d=a[n];if(d){let a=Ut(t[n]),u=o+"-"+a;c.push(f(Gl,{key:a,cellId:u,dayDate:t[n],todayRange:l})),d=ii(d,r.eventOrder);for(let t of d)c.push(f(Yl,Object.assign({key:a+":"+t.eventRange.instance.instanceId,seg:t,isDragging:!1,isResizing:!1,isDateSelecting:!1,isSelected:!1,timeHeaderId:i,eventHeaderId:s,dateHeaderId:u},di(t,l,e))))}}return f("table",{className:"fc-list-table "+n.getClass("table")},f("thead",null,f("tr",null,f("th",{scope:"col",id:i},r.timeHint),f("th",{scope:"col","aria-hidden":!0}),f("th",{scope:"col",id:s},r.eventHint))),f("tbody",null,c))})}_eventStoreToSegs(e,t,n){return this.eventRangesToSegs($r(e,t,this.props.dateProfile.activeRange,this.context.options.nextDayThreshold).fg,n)}eventRangesToSegs(e,t){let n=[];for(let r of e)n.push(...this.eventRangeToSegs(r,t));return n}eventRangeToSegs(e,t){let n,r,i,{dateEnv:s}=this.context,{nextDayThreshold:o}=this.context.options,a=e.range,l=e.def.allDay,c=[];for(n=0;n<t.length;n+=1)if(r=rr(a,t[n]),r&&(i={component:this,eventRange:e,start:r.start,end:r.end,isStart:e.isStart&&r.start.valueOf()===a.start.valueOf(),isEnd:e.isEnd&&r.end.valueOf()===a.end.valueOf(),dayIndex:n},c.push(i),!i.isEnd&&!l&&n+1<t.length&&a.end<s.add(t[n+1].start,o))){i.end=a.end,i.isEnd=!0;break}return c}},buttonTextKey:"list",listDayFormat:{month:"long",day:"numeric",year:"numeric"}},listDay:{type:"list",duration:{days:1},listDayFormat:{weekday:"long"}},listWeek:{type:"list",duration:{weeks:1},listDayFormat:{weekday:"long"},listDaySideFormat:{month:"long",day:"numeric",year:"numeric"}},listMonth:{type:"list",duration:{month:1},listDaySideFormat:{weekday:"long"}},listYear:{type:"list",duration:{year:1},listDaySideFormat:{weekday:"long"}}}});return Qo.push(Ba,al,Vl,ec),e.Calendar=class extends uo{constructor(e,t={}){super(),this.isRendering=!1,this.isRendered=!1,this.currentClassNames=[],this.customContentRenderId=0,this.handleAction=e=>{switch(e.type){case"SET_EVENT_DRAG":case"SET_EVENT_RESIZE":this.renderRunner.tryDrain()}},this.handleData=e=>{this.currentData=e,this.renderRunner.request(e.calendarOptions.rerenderDelay)},this.handleRenderRequest=()=>{if(this.isRendering){this.isRendered=!0;let{currentData:e}=this;kr(()=>{P(f(zi,{options:e.calendarOptions,theme:e.theme,emitter:e.emitter},(t,n,r,i)=>(this.setClassNames(t),this.setHeight(n),f(Qi.Provider,{value:this.customContentRenderId},f(ua,Object.assign({isHeightAuto:r,forPrint:i},e))))),this.el)})}else this.isRendered&&(this.isRendered=!1,P(null,this.el),this.setClassNames([]),this.setHeight(""))},this.el=e,this.renderRunner=new ys(this.handleRenderRequest),new Zo({optionOverrides:t,calendarApi:this,onAction:this.handleAction,onData:this.handleData})}render(){let e=this.isRendering;e?this.customContentRenderId+=1:this.isRendering=!0,this.renderRunner.request(),e&&this.updateSize()}destroy(){this.isRendering&&(this.isRendering=!1,this.renderRunner.request())}updateSize(){kr(()=>{super.updateSize()})}batchRendering(e){this.renderRunner.pause("batchRendering"),e(),this.renderRunner.resume("batchRendering")}pauseRendering(){this.renderRunner.pause("pauseRendering")}resumeRendering(){this.renderRunner.resume("pauseRendering",!0)}resetOptions(e,t){this.currentDataManager.resetOptions(e,t)}setClassNames(e){if(!Ft(e,this.currentClassNames)){let{classList:t}=this.el;for(let e of this.currentClassNames)t.remove(e);for(let n of e)t.add(n);this.currentClassNames=e}}setHeight(e){Ce(this.el,"height",e)}},e.Draggable=class{constructor(e,t={}){this.handlePointerDown=e=>{let{dragging:t}=this,{minDistance:n,longPressDelay:r}=this.settings;t.minDistance=null!=n?n:e.isTouch?0:ln.eventDragMinDistance,t.delay=e.isTouch?null!=r?r:ln.longPressDelay:0},this.handleDragStart=e=>{e.isTouch&&this.dragging.delay&&e.subjectEl.classList.contains("fc-event")&&this.dragging.mirror.getMirrorEl().classList.add("fc-event-selected")},this.settings=t;let n=this.dragging=new Ra(e);n.touchScrollAllowed=!1,null!=t.itemSelector&&(n.pointer.selector=t.itemSelector),null!=t.appendTo&&(n.mirror.parentNode=t.appendTo),n.emitter.on("pointerdown",this.handlePointerDown),n.emitter.on("dragstart",this.handleDragStart),new Pa(n,t.eventData)}destroy(){this.dragging.destroy()}},e.Internal=ho,e.JsonRequestError=vs,e.ThirdPartyDraggable=class{constructor(e,t){let n=document;e===document||e instanceof Element?(n=e,t=t||{}):t=e||{};let r=this.dragging=new Ha(n);"string"==typeof t.itemSelector?r.pointer.selector=t.itemSelector:n===document&&(r.pointer.selector="[data-event]"),"string"==typeof t.mirrorSelector&&(r.mirrorSelector=t.mirrorSelector),new Pa(r,t.eventData)}destroy(){this.dragging.destroy()}},e.createPlugin=yo,e.formatDate=function(e,t={}){let n=ga(t),r=on(t),i=n.createMarkerMeta(e);return i?n.format(i.marker,r,{forcedTzo:i.forcedTzo}):""},e.formatRange=function(e,t,n){let r=ga("object"==typeof n&&n?n:{}),i=on(n),s=r.createMarkerMeta(e),o=r.createMarkerMeta(t);return s&&o?r.formatRange(s.marker,o.marker,i,{forcedStartTzo:s.forcedTzo,forcedEndTzo:o.forcedTzo,isEndExclusive:n.isEndExclusive,defaultSeparator:ln.defaultRangeSeparator}):""},e.globalLocales=fo,e.globalPlugins=Qo,e.sliceEvents=function(e,t){return $r(e.eventStore,e.eventUiBases,e.dateProfile.activeRange,t?e.nextDayThreshold:null).fg},e.version="6.0.3",Object.defineProperty(e,"__esModule",{value:!0}),e}({}); \ No newline at end of file