@fullcalendar/core 6.1.15 → 7.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs +48 -110
- package/index.d.ts +2 -1
- package/index.global.js +1558 -1794
- package/index.global.min.js +2 -2
- package/index.js +51 -113
- package/internal-common.cjs +1919 -2093
- package/internal-common.d.ts +176 -288
- package/internal-common.js +1905 -2073
- package/internal.cjs +16 -22
- package/internal.d.ts +2 -1
- package/internal.js +1 -1
- package/locales/af.global.js +1 -1
- package/locales/af.global.min.js +1 -1
- package/locales/ar-dz.global.js +1 -1
- package/locales/ar-dz.global.min.js +1 -1
- package/locales/ar-kw.global.js +1 -1
- package/locales/ar-kw.global.min.js +1 -1
- package/locales/ar-ly.global.js +1 -1
- package/locales/ar-ly.global.min.js +1 -1
- package/locales/ar-ma.global.js +1 -1
- package/locales/ar-ma.global.min.js +1 -1
- package/locales/ar-sa.global.js +1 -1
- package/locales/ar-sa.global.min.js +1 -1
- package/locales/ar-tn.global.js +1 -1
- package/locales/ar-tn.global.min.js +1 -1
- package/locales/ar.global.js +1 -1
- package/locales/ar.global.min.js +1 -1
- package/locales/az.global.js +1 -1
- package/locales/az.global.min.js +1 -1
- package/locales/bg.global.js +1 -1
- package/locales/bg.global.min.js +1 -1
- package/locales/bn.global.js +1 -1
- package/locales/bn.global.min.js +1 -1
- package/locales/bs.global.js +1 -1
- package/locales/bs.global.min.js +1 -1
- package/locales/ca.global.js +1 -1
- package/locales/ca.global.min.js +1 -1
- package/locales/cs.global.js +1 -1
- package/locales/cs.global.min.js +1 -1
- package/locales/cy.global.js +1 -1
- package/locales/cy.global.min.js +1 -1
- package/locales/da.global.js +1 -1
- package/locales/da.global.min.js +1 -1
- package/locales/de-at.global.js +1 -1
- package/locales/de-at.global.min.js +1 -1
- package/locales/de.global.js +1 -1
- package/locales/de.global.min.js +1 -1
- package/locales/el.global.js +1 -1
- package/locales/el.global.min.js +1 -1
- package/locales/en-au.global.js +1 -1
- package/locales/en-au.global.min.js +1 -1
- package/locales/en-gb.global.js +1 -1
- package/locales/en-gb.global.min.js +1 -1
- package/locales/en-nz.global.js +1 -1
- package/locales/en-nz.global.min.js +1 -1
- package/locales/eo.global.js +1 -1
- package/locales/eo.global.min.js +1 -1
- package/locales/es-us.global.js +1 -1
- package/locales/es-us.global.min.js +1 -1
- package/locales/es.global.js +1 -1
- package/locales/es.global.min.js +1 -1
- package/locales/et.global.js +1 -1
- package/locales/et.global.min.js +1 -1
- package/locales/eu.global.js +1 -1
- package/locales/eu.global.min.js +1 -1
- package/locales/fa.global.js +1 -1
- package/locales/fa.global.min.js +1 -1
- package/locales/fi.global.js +1 -1
- package/locales/fi.global.min.js +1 -1
- package/locales/fr-ca.global.js +1 -1
- package/locales/fr-ca.global.min.js +1 -1
- package/locales/fr-ch.global.js +1 -1
- package/locales/fr-ch.global.min.js +1 -1
- package/locales/fr.global.js +1 -1
- package/locales/fr.global.min.js +1 -1
- package/locales/gl.global.js +1 -1
- package/locales/gl.global.min.js +1 -1
- package/locales/he.global.js +1 -1
- package/locales/he.global.min.js +1 -1
- package/locales/hi.global.js +1 -1
- package/locales/hi.global.min.js +1 -1
- package/locales/hr.global.js +1 -1
- package/locales/hr.global.min.js +1 -1
- package/locales/hu.global.js +1 -1
- package/locales/hu.global.min.js +1 -1
- package/locales/hy-am.global.js +1 -1
- package/locales/hy-am.global.min.js +1 -1
- package/locales/id.global.js +1 -1
- package/locales/id.global.min.js +1 -1
- package/locales/is.global.js +1 -1
- package/locales/is.global.min.js +1 -1
- package/locales/it.global.js +1 -1
- package/locales/it.global.min.js +1 -1
- package/locales/ja.global.js +1 -1
- package/locales/ja.global.min.js +1 -1
- package/locales/ka.global.js +1 -1
- package/locales/ka.global.min.js +1 -1
- package/locales/kk.global.js +1 -1
- package/locales/kk.global.min.js +1 -1
- package/locales/km.global.js +1 -1
- package/locales/km.global.min.js +1 -1
- package/locales/ko.global.js +1 -1
- package/locales/ko.global.min.js +1 -1
- package/locales/ku.global.js +1 -1
- package/locales/ku.global.min.js +1 -1
- package/locales/lb.global.js +1 -1
- package/locales/lb.global.min.js +1 -1
- package/locales/lt.global.js +1 -1
- package/locales/lt.global.min.js +1 -1
- package/locales/lv.global.js +1 -1
- package/locales/lv.global.min.js +1 -1
- package/locales/mk.global.js +1 -1
- package/locales/mk.global.min.js +1 -1
- package/locales/ms.global.js +1 -1
- package/locales/ms.global.min.js +1 -1
- package/locales/nb.global.js +1 -1
- package/locales/nb.global.min.js +1 -1
- package/locales/ne.global.js +1 -1
- package/locales/ne.global.min.js +1 -1
- package/locales/nl.global.js +1 -1
- package/locales/nl.global.min.js +1 -1
- package/locales/nn.global.js +1 -1
- package/locales/nn.global.min.js +1 -1
- package/locales/pl.global.js +1 -1
- package/locales/pl.global.min.js +1 -1
- package/locales/pt-br.global.js +1 -1
- package/locales/pt-br.global.min.js +1 -1
- package/locales/pt.global.js +1 -1
- package/locales/pt.global.min.js +1 -1
- package/locales/ro.global.js +1 -1
- package/locales/ro.global.min.js +1 -1
- package/locales/ru.global.js +1 -1
- package/locales/ru.global.min.js +1 -1
- package/locales/si-lk.global.js +1 -1
- package/locales/si-lk.global.min.js +1 -1
- package/locales/sk.global.js +1 -1
- package/locales/sk.global.min.js +1 -1
- package/locales/sl.global.js +1 -1
- package/locales/sl.global.min.js +1 -1
- package/locales/sm.global.js +1 -1
- package/locales/sm.global.min.js +1 -1
- package/locales/sq.global.js +1 -1
- package/locales/sq.global.min.js +1 -1
- package/locales/sr-cyrl.global.js +1 -1
- package/locales/sr-cyrl.global.min.js +1 -1
- package/locales/sr.global.js +1 -1
- package/locales/sr.global.min.js +1 -1
- package/locales/sv.global.js +1 -1
- package/locales/sv.global.min.js +1 -1
- package/locales/ta-in.global.js +1 -1
- package/locales/ta-in.global.min.js +1 -1
- package/locales/th.global.js +1 -1
- package/locales/th.global.min.js +1 -1
- package/locales/tr.global.js +1 -1
- package/locales/tr.global.min.js +1 -1
- package/locales/ug.global.js +1 -1
- package/locales/ug.global.min.js +1 -1
- package/locales/uk.global.js +1 -1
- package/locales/uk.global.min.js +1 -1
- package/locales/uz-cy.global.js +1 -1
- package/locales/uz-cy.global.min.js +1 -1
- package/locales/uz.global.js +1 -1
- package/locales/uz.global.min.js +1 -1
- package/locales/vi.global.js +1 -1
- package/locales/vi.global.min.js +1 -1
- package/locales/zh-cn.global.js +1 -1
- package/locales/zh-cn.global.min.js +1 -1
- package/locales/zh-tw.global.js +1 -1
- package/locales/zh-tw.global.min.js +1 -1
- package/locales-all.global.js +1 -1
- package/locales-all.global.min.js +1 -1
- package/package.json +2 -2
- package/preact.d.ts +6 -0
- package/preact.js +1 -1
package/internal-common.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as preact from 'preact';
|
|
2
|
-
import { Component, createElement, isValidElement, Fragment } from 'preact';
|
|
2
|
+
import { Component, createElement, isValidElement, Fragment, createRef } from 'preact';
|
|
3
3
|
import { createPortal } from 'preact/compat';
|
|
4
4
|
|
|
5
5
|
const styleTexts = [];
|
|
@@ -82,7 +82,7 @@ if (typeof document !== 'undefined') {
|
|
|
82
82
|
registerStylesRoot(document);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
var css_248z = ":root{--fc-small-font-size:.85em;--fc-page-bg-color:#fff;--fc-neutral-bg-color:hsla(0,0%,82%,.3);--fc-neutral-text-color:grey;--fc-border-color:#ddd;--fc-button-text-color:#fff;--fc-button-bg-color:#2c3e50;--fc-button-border-color:#2c3e50;--fc-button-hover-bg-color:#1e2b37;--fc-button-hover-border-color:#1a252f;--fc-button-active-bg-color:#1a252f;--fc-button-active-border-color:#151e27;--fc-event-bg-color:#3788d8;--fc-event-border-color:#3788d8;--fc-event-text-color:#fff;--fc-event-selected-overlay-color:rgba(0,0,0,.25);--fc-more-link-bg-color:#d0d0d0;--fc-more-link-text-color:inherit;--fc-event-resizer-thickness:8px;--fc-event-resizer-dot-total-width:8px;--fc-event-resizer-dot-border-width:1px;--fc-non-business-color:hsla(0,0%,84%,.3);--fc-bg-event-color:#8fdf82;--fc-bg-event-opacity:0.3;--fc-highlight-color:rgba(188,232,241,.3);--fc-today-bg-color:rgba(255,220,40,.15);--fc-now-indicator-color:red}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc{display:flex;flex-direction:column;font-size:1em}.fc,.fc *,.fc :after,.fc :before{box-sizing:border-box}.fc table{border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{padding:0;vertical-align:top}.fc a[data-navlink]{cursor:pointer}.fc a[data-navlink]:hover{text-decoration:underline}.fc-direction-ltr{direction:ltr;text-align:left}.fc-direction-rtl{direction:rtl;text-align:right}.fc-theme-standard td,.fc-theme-standard th{border:1px solid var(--fc-border-color)}.fc-liquid-hack td,.fc-liquid-hack th{position:relative}@font-face{font-family:fcicons;font-style:normal;font-weight:400;src:url(\"data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBfAAAAC8AAAAYGNtYXAXVtKNAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5ZgYydxIAAAF4AAAFNGhlYWQUJ7cIAAAGrAAAADZoaGVhB20DzAAABuQAAAAkaG10eCIABhQAAAcIAAAALGxvY2ED4AU6AAAHNAAAABhtYXhwAA8AjAAAB0wAAAAgbmFtZXsr690AAAdsAAABhnBvc3QAAwAAAAAI9AAAACAAAwPAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpBgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6Qb//f//AAAAAAAg6QD//f//AAH/4xcEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAWIAjQKeAskAEwAAJSc3NjQnJiIHAQYUFwEWMjc2NCcCnuLiDQ0MJAz/AA0NAQAMJAwNDcni4gwjDQwM/wANIwz/AA0NDCMNAAAAAQFiAI0CngLJABMAACUBNjQnASYiBwYUHwEHBhQXFjI3AZ4BAA0N/wAMJAwNDeLiDQ0MJAyNAQAMIw0BAAwMDSMM4uINIwwNDQAAAAIA4gC3Ax4CngATACcAACUnNzY0JyYiDwEGFB8BFjI3NjQnISc3NjQnJiIPAQYUHwEWMjc2NCcB87e3DQ0MIw3VDQ3VDSMMDQ0BK7e3DQ0MJAzVDQ3VDCQMDQ3zuLcMJAwNDdUNIwzWDAwNIwy4twwkDA0N1Q0jDNYMDA0jDAAAAgDiALcDHgKeABMAJwAAJTc2NC8BJiIHBhQfAQcGFBcWMjchNzY0LwEmIgcGFB8BBwYUFxYyNwJJ1Q0N1Q0jDA0Nt7cNDQwjDf7V1Q0N1QwkDA0Nt7cNDQwkDLfWDCMN1Q0NDCQMt7gMIw0MDNYMIw3VDQ0MJAy3uAwjDQwMAAADAFUAAAOrA1UAMwBoAHcAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMhMjY1NCYjISIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAAVYRGRkR/qoRGRkRA1UFBAUOCQkVDAsZDf2rDRkLDBUJCA4FBQUFBQUOCQgVDAsZDQJVDRkLDBUJCQ4FBAVVAgECBQMCBwQECAX9qwQJAwQHAwMFAQICAgIBBQMDBwQDCQQCVQUIBAQHAgMFAgEC/oAZEhEZGRESGQAAAAADAFUAAAOrA1UAMwBoAIkAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMzFRQWMzI2PQEzMjY1NCYrATU0JiMiBh0BIyIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAgBkSEhmAERkZEYAZEhIZgBEZGREDVQUEBQ4JCRUMCxkN/asNGQsMFQkIDgUFBQUFBQ4JCBUMCxkNAlUNGQsMFQkJDgUEBVUCAQIFAwIHBAQIBf2rBAkDBAcDAwUBAgICAgEFAwMHBAMJBAJVBQgEBAcCAwUCAQL+gIASGRkSgBkSERmAEhkZEoAZERIZAAABAOIAjQMeAskAIAAAExcHBhQXFjI/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;-moz-user-select:none;user-select:none;width:1em}.fc-icon-chevron-left:before{content:\"\\e900\"}.fc-icon-chevron-right:before{content:\"\\e901\"}.fc-icon-chevrons-left:before{content:\"\\e902\"}.fc-icon-chevrons-right:before{content:\"\\e903\"}.fc-icon-minus-square:before{content:\"\\e904\"}.fc-icon-plus-square:before{content:\"\\e905\"}.fc-icon-x:before{content:\"\\e906\"}.fc .fc-button{border-radius:0;font-family:inherit;font-size:inherit;line-height:inherit;margin:0;overflow:visible;text-transform:none}.fc .fc-button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.fc .fc-button{-webkit-appearance:button}.fc .fc-button:not(:disabled){cursor:pointer}.fc .fc-button{background-color:transparent;border:1px solid transparent;border-radius:.25em;display:inline-block;font-size:1em;font-weight:400;line-height:1.5;padding:.4em .65em;text-align:center;-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)}";
|
|
85
|
+
var css_248z = ":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{display:flex;flex-direction:column;gap:1.5em}.fc,.fc *,.fc :after,.fc :before{box-sizing:border-box}.fc-direction-ltr{direction:ltr;text-align:left}.fc-direction-rtl{direction:rtl;text-align:right}.fc-flex-row{display:flex;flex-direction:row}.fc-flex-column{display:flex;flex-direction:column}.fc-grow{flex-grow:1}.fc-basis0,.fc-liquid{flex-basis:0}.fc-liquid{flex-grow:1;min-height:0;min-width:0}.fc-row{display:flex;flex-direction:row}.fc-rowgroup{display:flex;flex-direction:column}.fc-row,.fc-rowdivider,.fc-rowgroup{border-color:var(--fc-border-color);border-style:solid;border-width:1px 0 0}.fc-row:first-child:not(.fc-not-first),.fc-rowdivider+.fc-row,.fc-rowdivider+.fc-rowgroup,.fc-rowdivider:first-child,.fc-rowgroup:first-child,.fc-sticky-header+.fc-row,.fc-sticky-header+.fc-rowgroup{border-top-width:0}.fc-cell,.fc-celldivider{border:0 solid var(--fc-border-color)}.fc-cell{margin:0!important;padding:0!important}.fc-cell-inner{overflow:hidden;white-space:nowrap}.fc-direction-ltr .fc-cell,.fc-direction-ltr .fc-celldivider{border-left-width:1px}.fc-direction-ltr .fc-cell:first-child:not(.fc-not-first),.fc-direction-ltr .fc-celldivider+.fc-cell{border-left-width:0}.fc-direction-ltr .fc-celldivider,.fc-direction-rtl .fc-cell,.fc-direction-rtl .fc-celldivider{border-right-width:1px}.fc-direction-rtl .fc-cell:first-child:not(.fc-not-first),.fc-direction-rtl .fc-celldivider+.fc-cell{border-right-width:0}.fc-direction-rtl .fc-celldivider{border-left-width:1px}.fc-cell:only-child{flex-basis:0;flex-grow:1;min-width:0}.fc-celldivider,.fc-rowdivider{background:var(--fc-neutral-bg-color)}.fc-celldivider{padding-left:2px}.fc-rowdivider{padding-bottom:2px}.fc-rowdivider,.fc-sticky-header{border-bottom-width:1px}.fc-rel{position:relative}.fc-abs{position:absolute}.fc-fill{bottom:0;top:0}.fc-fill,.fc-fill-x{left:0;position:absolute;right:0}.fc-fill-y{bottom:0;position:absolute;top:0}.fc-sticky-y{bottom:0;position:sticky;top:0}.fc-sticky-x{left:0;position:sticky;right:0}.fc-sticky-header{background:var(--fc-page-bg-color);position:sticky;top:0;z-index:9999}.fc-sticky-footer{bottom:0;position:sticky;z-index:9999}.fc-content-box{box-sizing:content-box}.fc-border{border:1px solid var(--fc-border-color)}.fc-offscreen{left:-10000px;position:absolute}.fc-shaded{background-color:var(--fc-neutral-bg-color)}.fc-padding-sm{padding:2px 4px}.fc-padding-md{padding:4px 5px}.fc-padding-lg{padding:8px}.fc-justify-center{justify-content:center}.fc-align-center{align-items:center}.fc-align-start{align-items:flex-start}.fc a[data-navlink]{cursor:pointer}.fc a[data-navlink]:hover{text-decoration:underline}.fc-view-harness{position:relative}.fc-view-harness-fixedheight,.fc-view-harness-liquid{display:flex;flex-direction:column}.fc-view-harness-fixedheight>.fc-view,.fc-view-harness-liquid,.fc-view-harness-liquid>.fc-view{flex-basis:0;flex-grow:1;min-height:0}.fc-view-harness-aspectratio>.fc-view{bottom:0;left:0;position:absolute;right:0;top:0}a.fc-event,a.fc-event:hover{text-decoration:none}.fc-event.fc-event-draggable,.fc-event[href]{cursor:pointer}.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-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-event-inner{position:relative;z-index:2}.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-bg-event,.fc-highlight,.fc-non-business{bottom:0;left:0;position:absolute;right:0;top:0}.fc-non-business{background:var(--fc-non-business-color)}.fc-bg-event{background:var(--fc-bg-event-color);opacity:var(--fc-bg-event-opacity)}.fc-bg-event .fc-event-title{font-size:var(--fc-small-font-size);font-style:italic;margin:.5em}.fc-highlight{background:var(--fc-highlight-color)}.fc-day-disabled{background:var(--fc-neutral-bg-color)}.fc-h-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:flex;flex-direction:column;position:relative}.fc-h-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-h-event .fc-event-inner{color:var(--fc-event-text-color);display:flex;flex-direction:row;flex-grow:1;min-width:0}.fc-h-event .fc-event-time,.fc-h-event .fc-event-title{overflow:hidden;white-space:nowrap}.fc-h-event .fc-event-title-outer{display:flex;flex-basis:0;flex-direction:row;flex-grow:1;min-width:0}.fc-h-event .fc-event-title{left:0;position:sticky;right: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-popover{box-shadow:0 2px 6px rgba(0,0,0,.15);position:absolute;z-index:9999}.fc-popover-header{align-items:center;display:flex;flex-direction:row;justify-content:space-between;padding:3px 4px}.fc-popover-title{margin:0 2px}.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)}.fc-scroller-nobars{-ms-overflow-style:none;scrollbar-width:none}.fc-scroller-nobars::-webkit-scrollbar{display:none}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}@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;-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-button{border-radius:0;font-family:inherit;font-size:inherit;line-height:inherit;margin:0;overflow:visible;text-transform:none}.fc-button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.fc-button{-webkit-appearance:button}.fc-button:not(:disabled){cursor:pointer}.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;-moz-user-select:none;user-select:none;vertical-align:middle}.fc-button:hover{text-decoration:none}.fc-button:focus{box-shadow:0 0 0 .2rem rgba(44,62,80,.25);outline:0}.fc-button:disabled{opacity:.65}.fc-button-primary{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.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-button-primary:disabled{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc-button-primary:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc-button-primary:not(:disabled).fc-button-active,.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-button-primary:not(:disabled).fc-button-active:focus,.fc-button-primary:not(:disabled):active:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc-button .fc-icon{font-size:1.5em;vertical-align:middle}.fc-button-group{display:inline-flex;position:relative;vertical-align:middle}.fc-button-group>.fc-button{flex:1 1 auto;position:relative}.fc-button-group>.fc-button.fc-button-active,.fc-button-group>.fc-button:active,.fc-button-group>.fc-button:focus,.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-toolbar{align-items:center;display:flex;flex-direction:row;gap:.75em;justify-content:space-between}.fc-direction-rtl .fc-toolbar-ltr{flex-direction:row-reverse}.fc-toolbar-chunk{display:flex;flex-direction:row;flex-shrink:0;gap:.75em}.fc-toolbar-title{font-size:1.75em;margin:0;white-space:nowrap}";
|
|
86
86
|
injectStyles(css_248z);
|
|
87
87
|
|
|
88
88
|
class DelayedRunner {
|
|
@@ -444,20 +444,6 @@ function compareNumbers(a, b) {
|
|
|
444
444
|
function isInt(n) {
|
|
445
445
|
return n % 1 === 0;
|
|
446
446
|
}
|
|
447
|
-
/* FC-specific DOM dimension stuff
|
|
448
|
-
----------------------------------------------------------------------------------------------------------------------*/
|
|
449
|
-
function computeSmallestCellWidth(cellEl) {
|
|
450
|
-
let allWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-frame');
|
|
451
|
-
let contentWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-cushion');
|
|
452
|
-
if (!allWidthEl) {
|
|
453
|
-
throw new Error('needs fc-scrollgrid-shrink-frame className'); // TODO: use const
|
|
454
|
-
}
|
|
455
|
-
if (!contentWidthEl) {
|
|
456
|
-
throw new Error('needs fc-scrollgrid-shrink-cushion className');
|
|
457
|
-
}
|
|
458
|
-
return cellEl.getBoundingClientRect().width - allWidthEl.getBoundingClientRect().width + // the cell padding+border
|
|
459
|
-
contentWidthEl.getBoundingClientRect().width;
|
|
460
|
-
}
|
|
461
447
|
|
|
462
448
|
const INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];
|
|
463
449
|
const PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/;
|
|
@@ -1370,8 +1356,6 @@ const BASE_OPTION_REFINERS = {
|
|
|
1370
1356
|
dropAccept: identity,
|
|
1371
1357
|
eventOrder: parseFieldSpecs,
|
|
1372
1358
|
eventOrderStrict: Boolean,
|
|
1373
|
-
handleWindowResize: Boolean,
|
|
1374
|
-
windowResizeDelay: Number,
|
|
1375
1359
|
longPressDelay: Number,
|
|
1376
1360
|
eventDragMinDistance: Number,
|
|
1377
1361
|
expandRows: Boolean,
|
|
@@ -1521,8 +1505,6 @@ const BASE_OPTION_DEFAULTS = {
|
|
|
1521
1505
|
dropAccept: '*',
|
|
1522
1506
|
eventOrder: 'start,-duration,allDay,title',
|
|
1523
1507
|
dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' },
|
|
1524
|
-
handleWindowResize: true,
|
|
1525
|
-
windowResizeDelay: 100,
|
|
1526
1508
|
longPressDelay: 1000,
|
|
1527
1509
|
eventDragMinDistance: 5,
|
|
1528
1510
|
expandRows: false,
|
|
@@ -1541,7 +1523,6 @@ const CALENDAR_LISTENER_REFINERS = {
|
|
|
1541
1523
|
eventAdd: identity,
|
|
1542
1524
|
eventChange: identity,
|
|
1543
1525
|
eventRemove: identity,
|
|
1544
|
-
windowResize: identity,
|
|
1545
1526
|
eventClick: identity,
|
|
1546
1527
|
eventMouseEnter: identity,
|
|
1547
1528
|
eventMouseLeave: identity,
|
|
@@ -1554,8 +1535,7 @@ const CALENDAR_LISTENER_REFINERS = {
|
|
|
1554
1535
|
_afterprint: identity,
|
|
1555
1536
|
_noEventDrop: identity,
|
|
1556
1537
|
_noEventResize: identity,
|
|
1557
|
-
|
|
1558
|
-
_scrollRequest: identity,
|
|
1538
|
+
_timeScrollRequest: identity,
|
|
1559
1539
|
};
|
|
1560
1540
|
// calendar-specific options
|
|
1561
1541
|
// -------------------------
|
|
@@ -2225,6 +2205,9 @@ Theme.prototype.iconOverridePrefix = '';
|
|
|
2225
2205
|
NOTE: this can be a public API, especially createElement for hooks.
|
|
2226
2206
|
See examples/typescript-scheduler/src/index.ts
|
|
2227
2207
|
*/
|
|
2208
|
+
/*
|
|
2209
|
+
TODO: rethink this
|
|
2210
|
+
*/
|
|
2228
2211
|
function flushSync(runBeforeFlush) {
|
|
2229
2212
|
runBeforeFlush();
|
|
2230
2213
|
let oldDebounceRendering = preact.options.debounceRendering; // orig
|
|
@@ -2274,42 +2257,6 @@ function createContext(defaultValue) {
|
|
|
2274
2257
|
return ContextType;
|
|
2275
2258
|
}
|
|
2276
2259
|
|
|
2277
|
-
class ScrollResponder {
|
|
2278
|
-
constructor(execFunc, emitter, scrollTime, scrollTimeReset) {
|
|
2279
|
-
this.execFunc = execFunc;
|
|
2280
|
-
this.emitter = emitter;
|
|
2281
|
-
this.scrollTime = scrollTime;
|
|
2282
|
-
this.scrollTimeReset = scrollTimeReset;
|
|
2283
|
-
this.handleScrollRequest = (request) => {
|
|
2284
|
-
this.queuedRequest = Object.assign({}, this.queuedRequest || {}, request);
|
|
2285
|
-
this.drain();
|
|
2286
|
-
};
|
|
2287
|
-
emitter.on('_scrollRequest', this.handleScrollRequest);
|
|
2288
|
-
this.fireInitialScroll();
|
|
2289
|
-
}
|
|
2290
|
-
detach() {
|
|
2291
|
-
this.emitter.off('_scrollRequest', this.handleScrollRequest);
|
|
2292
|
-
}
|
|
2293
|
-
update(isDatesNew) {
|
|
2294
|
-
if (isDatesNew && this.scrollTimeReset) {
|
|
2295
|
-
this.fireInitialScroll(); // will drain
|
|
2296
|
-
}
|
|
2297
|
-
else {
|
|
2298
|
-
this.drain();
|
|
2299
|
-
}
|
|
2300
|
-
}
|
|
2301
|
-
fireInitialScroll() {
|
|
2302
|
-
this.handleScrollRequest({
|
|
2303
|
-
time: this.scrollTime,
|
|
2304
|
-
});
|
|
2305
|
-
}
|
|
2306
|
-
drain() {
|
|
2307
|
-
if (this.queuedRequest && this.execFunc(this.queuedRequest)) {
|
|
2308
|
-
this.queuedRequest = null;
|
|
2309
|
-
}
|
|
2310
|
-
}
|
|
2311
|
-
}
|
|
2312
|
-
|
|
2313
2260
|
const ViewContextType = createContext({}); // for Components
|
|
2314
2261
|
function buildViewContext(viewSpec, viewApi, viewOptions, dateProfileGenerator, dateEnv, theme, pluginHooks, dispatch, getCurrentData, emitter, calendarApi, registerInteractiveComponent, unregisterInteractiveComponent) {
|
|
2315
2262
|
return {
|
|
@@ -2325,15 +2272,6 @@ function buildViewContext(viewSpec, viewApi, viewOptions, dateProfileGenerator,
|
|
|
2325
2272
|
dateProfileGenerator,
|
|
2326
2273
|
theme,
|
|
2327
2274
|
isRtl: viewOptions.direction === 'rtl',
|
|
2328
|
-
addResizeHandler(handler) {
|
|
2329
|
-
emitter.on('_resize', handler);
|
|
2330
|
-
},
|
|
2331
|
-
removeResizeHandler(handler) {
|
|
2332
|
-
emitter.off('_resize', handler);
|
|
2333
|
-
},
|
|
2334
|
-
createScrollResponder(execFunc) {
|
|
2335
|
-
return new ScrollResponder(execFunc, emitter, createDuration(viewOptions.scrollTime), viewOptions.scrollTimeReset);
|
|
2336
|
-
},
|
|
2337
2275
|
registerInteractiveComponent,
|
|
2338
2276
|
unregisterInteractiveComponent,
|
|
2339
2277
|
};
|
|
@@ -3396,6 +3334,9 @@ function parseClassNames(raw) {
|
|
|
3396
3334
|
}
|
|
3397
3335
|
return [];
|
|
3398
3336
|
}
|
|
3337
|
+
function fracToCssDim(frac) {
|
|
3338
|
+
return frac * 100 + '%';
|
|
3339
|
+
}
|
|
3399
3340
|
|
|
3400
3341
|
// TODO: better called "EventSettings" or "EventConfig"
|
|
3401
3342
|
// TODO: move this file into structs
|
|
@@ -4335,12 +4276,12 @@ function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshol
|
|
|
4335
4276
|
function hasBgRendering(def) {
|
|
4336
4277
|
return def.ui.display === 'background' || def.ui.display === 'inverse-background';
|
|
4337
4278
|
}
|
|
4338
|
-
function
|
|
4339
|
-
el.
|
|
4279
|
+
function setElEventRange(el, eventRange) {
|
|
4280
|
+
el.fcEventRange = eventRange;
|
|
4340
4281
|
}
|
|
4341
|
-
function
|
|
4342
|
-
return el.
|
|
4343
|
-
el.parentNode.
|
|
4282
|
+
function getElEventRange(el) {
|
|
4283
|
+
return el.fcEventRange ||
|
|
4284
|
+
el.parentNode.fcEventRange || // for the harness
|
|
4344
4285
|
null;
|
|
4345
4286
|
}
|
|
4346
4287
|
// event ui computation
|
|
@@ -4360,7 +4301,7 @@ function compileEventUi(eventDef, eventUiBases) {
|
|
|
4360
4301
|
}
|
|
4361
4302
|
function sortEventSegs(segs, eventOrderSpecs) {
|
|
4362
4303
|
let objs = segs.map(buildSegCompareObj);
|
|
4363
|
-
objs.sort((obj0, obj1) => compareByFieldSpecs(obj0, obj1, eventOrderSpecs));
|
|
4304
|
+
objs.sort((obj0, obj1) => compareByFieldSpecs(obj0, obj1, eventOrderSpecs)); // !!!
|
|
4364
4305
|
return objs.map((c) => c._seg);
|
|
4365
4306
|
}
|
|
4366
4307
|
// returns a object with all primitive props that can be compared
|
|
@@ -4373,29 +4314,23 @@ function buildSegCompareObj(seg) {
|
|
|
4373
4314
|
return Object.assign(Object.assign(Object.assign({}, eventDef.extendedProps), eventDef), { id: eventDef.publicId, start,
|
|
4374
4315
|
end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg });
|
|
4375
4316
|
}
|
|
4376
|
-
function
|
|
4317
|
+
function computeEventRangeDraggable(eventRange, context) {
|
|
4377
4318
|
let { pluginHooks } = context;
|
|
4378
4319
|
let transformers = pluginHooks.isDraggableTransformers;
|
|
4379
|
-
let { def, ui } =
|
|
4320
|
+
let { def, ui } = eventRange;
|
|
4380
4321
|
let val = ui.startEditable;
|
|
4381
4322
|
for (let transformer of transformers) {
|
|
4382
4323
|
val = transformer(val, def, ui, context);
|
|
4383
4324
|
}
|
|
4384
4325
|
return val;
|
|
4385
4326
|
}
|
|
4386
|
-
function
|
|
4387
|
-
return seg.isStart && seg.eventRange.ui.durationEditable && context.options.eventResizableFromStart;
|
|
4388
|
-
}
|
|
4389
|
-
function computeSegEndResizable(seg, context) {
|
|
4390
|
-
return seg.isEnd && seg.eventRange.ui.durationEditable;
|
|
4391
|
-
}
|
|
4392
|
-
function buildSegTimeText(seg, timeFormat, context, defaultDisplayEventTime, // defaults to true
|
|
4327
|
+
function buildEventRangeTimeText(eventRange, timeFormat, context, defaultDisplayEventTime, // defaults to true
|
|
4393
4328
|
defaultDisplayEventEnd, // defaults to true
|
|
4394
4329
|
startOverride, endOverride) {
|
|
4395
4330
|
let { dateEnv, options } = context;
|
|
4396
4331
|
let { displayEventTime, displayEventEnd } = options;
|
|
4397
|
-
let eventDef =
|
|
4398
|
-
let eventInstance =
|
|
4332
|
+
let eventDef = eventRange.def;
|
|
4333
|
+
let eventInstance = eventRange.instance;
|
|
4399
4334
|
if (displayEventTime == null) {
|
|
4400
4335
|
displayEventTime = defaultDisplayEventTime !== false;
|
|
4401
4336
|
}
|
|
@@ -4404,8 +4339,8 @@ startOverride, endOverride) {
|
|
|
4404
4339
|
}
|
|
4405
4340
|
let wholeEventStart = eventInstance.range.start;
|
|
4406
4341
|
let wholeEventEnd = eventInstance.range.end;
|
|
4407
|
-
let segStart = startOverride ||
|
|
4408
|
-
let segEnd = endOverride ||
|
|
4342
|
+
let segStart = startOverride || eventRange.range.start;
|
|
4343
|
+
let segEnd = endOverride || eventRange.range.end;
|
|
4409
4344
|
let isStartDay = startOfDay(wholeEventStart).valueOf() === startOfDay(segStart).valueOf();
|
|
4410
4345
|
let isEndDay = startOfDay(addMs(wholeEventEnd, -1)).valueOf() === startOfDay(addMs(segEnd, -1)).valueOf();
|
|
4411
4346
|
if (displayEventTime && !eventDef.allDay && (isStartDay || isEndDay)) {
|
|
@@ -4423,8 +4358,8 @@ startOverride, endOverride) {
|
|
|
4423
4358
|
}
|
|
4424
4359
|
return '';
|
|
4425
4360
|
}
|
|
4426
|
-
function
|
|
4427
|
-
let segRange =
|
|
4361
|
+
function getEventRangeMeta(eventRange, todayRange, nowDate) {
|
|
4362
|
+
let segRange = eventRange.range;
|
|
4428
4363
|
return {
|
|
4429
4364
|
isPast: segRange.end <= (nowDate || todayRange.start),
|
|
4430
4365
|
isFuture: segRange.start >= (nowDate || todayRange.end),
|
|
@@ -4474,8 +4409,8 @@ function buildEventRangeKey(eventRange) {
|
|
|
4474
4409
|
: `${eventRange.def.defId}:${eventRange.range.start.toISOString()}`;
|
|
4475
4410
|
// inverse-background events don't have specific instances. TODO: better solution
|
|
4476
4411
|
}
|
|
4477
|
-
function
|
|
4478
|
-
let { def, instance } =
|
|
4412
|
+
function getEventRangeAnchorAttrs(eventRange, context) {
|
|
4413
|
+
let { def, instance } = eventRange;
|
|
4479
4414
|
let { url } = def;
|
|
4480
4415
|
if (url) {
|
|
4481
4416
|
return { href: url };
|
|
@@ -4655,33 +4590,6 @@ function requestJson(method, url, params) {
|
|
|
4655
4590
|
});
|
|
4656
4591
|
}
|
|
4657
4592
|
|
|
4658
|
-
let canVGrowWithinCell;
|
|
4659
|
-
function getCanVGrowWithinCell() {
|
|
4660
|
-
if (canVGrowWithinCell == null) {
|
|
4661
|
-
canVGrowWithinCell = computeCanVGrowWithinCell();
|
|
4662
|
-
}
|
|
4663
|
-
return canVGrowWithinCell;
|
|
4664
|
-
}
|
|
4665
|
-
function computeCanVGrowWithinCell() {
|
|
4666
|
-
// for SSR, because this function is call immediately at top-level
|
|
4667
|
-
// TODO: just make this logic execute top-level, immediately, instead of doing lazily
|
|
4668
|
-
if (typeof document === 'undefined') {
|
|
4669
|
-
return true;
|
|
4670
|
-
}
|
|
4671
|
-
let el = document.createElement('div');
|
|
4672
|
-
el.style.position = 'absolute';
|
|
4673
|
-
el.style.top = '0px';
|
|
4674
|
-
el.style.left = '0px';
|
|
4675
|
-
el.innerHTML = '<table><tr><td><div></div></td></tr></table>';
|
|
4676
|
-
el.querySelector('table').style.height = '100px';
|
|
4677
|
-
el.querySelector('div').style.height = '100%';
|
|
4678
|
-
document.body.appendChild(el);
|
|
4679
|
-
let div = el.querySelector('div');
|
|
4680
|
-
let possible = div.offsetHeight > 0;
|
|
4681
|
-
document.body.removeChild(el);
|
|
4682
|
-
return possible;
|
|
4683
|
-
}
|
|
4684
|
-
|
|
4685
4593
|
class CalendarRoot extends BaseComponent {
|
|
4686
4594
|
constructor() {
|
|
4687
4595
|
super(...arguments);
|
|
@@ -4700,21 +4608,16 @@ class CalendarRoot extends BaseComponent {
|
|
|
4700
4608
|
};
|
|
4701
4609
|
}
|
|
4702
4610
|
render() {
|
|
4703
|
-
let { props } = this;
|
|
4611
|
+
let { props, state } = this;
|
|
4704
4612
|
let { options } = props;
|
|
4705
|
-
let { forPrint } =
|
|
4706
|
-
let isHeightAuto = forPrint || options.height === 'auto' || options.contentHeight === 'auto';
|
|
4707
|
-
let height = (!isHeightAuto && options.height != null) ? options.height : '';
|
|
4613
|
+
let { forPrint } = state;
|
|
4708
4614
|
let classNames = [
|
|
4709
4615
|
'fc',
|
|
4710
4616
|
forPrint ? 'fc-media-print' : 'fc-media-screen',
|
|
4711
4617
|
`fc-direction-${options.direction}`,
|
|
4712
4618
|
props.theme.getClass('root'),
|
|
4713
4619
|
];
|
|
4714
|
-
|
|
4715
|
-
classNames.push('fc-liquid-hack');
|
|
4716
|
-
}
|
|
4717
|
-
return props.children(classNames, height, isHeightAuto, forPrint);
|
|
4620
|
+
return props.children(classNames, options.height, forPrint);
|
|
4718
4621
|
}
|
|
4719
4622
|
componentDidMount() {
|
|
4720
4623
|
let { emitter } = this.props;
|
|
@@ -4752,978 +4655,695 @@ function interactionSettingsToStore(settings) {
|
|
|
4752
4655
|
// global state
|
|
4753
4656
|
const interactionSettingsStore = {};
|
|
4754
4657
|
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
}
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
setOption(name, val) {
|
|
4772
|
-
this.dispatch({
|
|
4773
|
-
type: 'SET_OPTION',
|
|
4774
|
-
optionName: name,
|
|
4775
|
-
rawOptionValue: val,
|
|
4776
|
-
});
|
|
4777
|
-
}
|
|
4778
|
-
getOption(name) {
|
|
4779
|
-
return this.currentDataManager.currentCalendarOptionsInput[name];
|
|
4658
|
+
function pointInsideRect(point, rect) {
|
|
4659
|
+
return point.left >= rect.left &&
|
|
4660
|
+
point.left < rect.right &&
|
|
4661
|
+
point.top >= rect.top &&
|
|
4662
|
+
point.top < rect.bottom;
|
|
4663
|
+
}
|
|
4664
|
+
// Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false
|
|
4665
|
+
function intersectRects(rect1, rect2) {
|
|
4666
|
+
let res = {
|
|
4667
|
+
left: Math.max(rect1.left, rect2.left),
|
|
4668
|
+
right: Math.min(rect1.right, rect2.right),
|
|
4669
|
+
top: Math.max(rect1.top, rect2.top),
|
|
4670
|
+
bottom: Math.min(rect1.bottom, rect2.bottom),
|
|
4671
|
+
};
|
|
4672
|
+
if (res.left < res.right && res.top < res.bottom) {
|
|
4673
|
+
return res;
|
|
4780
4674
|
}
|
|
4781
|
-
|
|
4782
|
-
|
|
4675
|
+
return false;
|
|
4676
|
+
}
|
|
4677
|
+
function translateRect(rect, deltaX, deltaY) {
|
|
4678
|
+
return {
|
|
4679
|
+
left: rect.left + deltaX,
|
|
4680
|
+
right: rect.right + deltaX,
|
|
4681
|
+
top: rect.top + deltaY,
|
|
4682
|
+
bottom: rect.bottom + deltaY,
|
|
4683
|
+
};
|
|
4684
|
+
}
|
|
4685
|
+
// Returns a new point that will have been moved to reside within the given rectangle
|
|
4686
|
+
function constrainPoint(point, rect) {
|
|
4687
|
+
return {
|
|
4688
|
+
left: Math.min(Math.max(point.left, rect.left), rect.right),
|
|
4689
|
+
top: Math.min(Math.max(point.top, rect.top), rect.bottom),
|
|
4690
|
+
};
|
|
4691
|
+
}
|
|
4692
|
+
// Returns a point that is the center of the given rectangle
|
|
4693
|
+
function getRectCenter(rect) {
|
|
4694
|
+
return {
|
|
4695
|
+
left: (rect.left + rect.right) / 2,
|
|
4696
|
+
top: (rect.top + rect.bottom) / 2,
|
|
4697
|
+
};
|
|
4698
|
+
}
|
|
4699
|
+
// Subtracts point2's coordinates from point1's coordinates, returning a delta
|
|
4700
|
+
function diffPoints(point1, point2) {
|
|
4701
|
+
return {
|
|
4702
|
+
left: point1.left - point2.left,
|
|
4703
|
+
top: point1.top - point2.top,
|
|
4704
|
+
};
|
|
4705
|
+
}
|
|
4706
|
+
|
|
4707
|
+
const EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere
|
|
4708
|
+
class Splitter {
|
|
4709
|
+
constructor() {
|
|
4710
|
+
this.getKeysForEventDefs = memoize(this._getKeysForEventDefs);
|
|
4711
|
+
this.splitDateSelection = memoize(this._splitDateSpan);
|
|
4712
|
+
this.splitEventStore = memoize(this._splitEventStore);
|
|
4713
|
+
this.splitIndividualUi = memoize(this._splitIndividualUi);
|
|
4714
|
+
this.splitEventDrag = memoize(this._splitInteraction);
|
|
4715
|
+
this.splitEventResize = memoize(this._splitInteraction);
|
|
4716
|
+
this.eventUiBuilders = {}; // TODO: typescript protection
|
|
4783
4717
|
}
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
let
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4718
|
+
splitProps(props) {
|
|
4719
|
+
let keyInfos = this.getKeyInfo(props);
|
|
4720
|
+
let defKeys = this.getKeysForEventDefs(props.eventStore);
|
|
4721
|
+
let dateSelections = this.splitDateSelection(props.dateSelection);
|
|
4722
|
+
let individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases*
|
|
4723
|
+
let eventStores = this.splitEventStore(props.eventStore, defKeys);
|
|
4724
|
+
let eventDrags = this.splitEventDrag(props.eventDrag);
|
|
4725
|
+
let eventResizes = this.splitEventResize(props.eventResize);
|
|
4726
|
+
let splitProps = {};
|
|
4727
|
+
this.eventUiBuilders = mapHash(keyInfos, (info, key) => this.eventUiBuilders[key] || memoize(buildEventUiForKey));
|
|
4728
|
+
for (let key in keyInfos) {
|
|
4729
|
+
let keyInfo = keyInfos[key];
|
|
4730
|
+
let eventStore = eventStores[key] || EMPTY_EVENT_STORE;
|
|
4731
|
+
let buildEventUi = this.eventUiBuilders[key];
|
|
4732
|
+
splitProps[key] = {
|
|
4733
|
+
businessHours: keyInfo.businessHours || props.businessHours,
|
|
4734
|
+
dateSelection: dateSelections[key] || null,
|
|
4735
|
+
eventStore,
|
|
4736
|
+
eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]),
|
|
4737
|
+
eventDrag: eventDrags[key] || null,
|
|
4738
|
+
eventResize: eventResizes[key] || null,
|
|
4739
|
+
eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '',
|
|
4740
|
+
};
|
|
4793
4741
|
}
|
|
4742
|
+
return splitProps;
|
|
4794
4743
|
}
|
|
4795
|
-
|
|
4796
|
-
|
|
4744
|
+
_splitDateSpan(dateSpan) {
|
|
4745
|
+
let dateSpans = {};
|
|
4746
|
+
if (dateSpan) {
|
|
4747
|
+
let keys = this.getKeysForDateSpan(dateSpan);
|
|
4748
|
+
for (let key of keys) {
|
|
4749
|
+
dateSpans[key] = dateSpan;
|
|
4750
|
+
}
|
|
4751
|
+
}
|
|
4752
|
+
return dateSpans;
|
|
4797
4753
|
}
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
this.currentDataManager.emitter.trigger(handlerName, ...args);
|
|
4754
|
+
_getKeysForEventDefs(eventStore) {
|
|
4755
|
+
return mapHash(eventStore.defs, (eventDef) => this.getKeysForEventDef(eventDef));
|
|
4801
4756
|
}
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
this.dispatch({
|
|
4810
|
-
type: 'CHANGE_VIEW_TYPE',
|
|
4811
|
-
viewType,
|
|
4812
|
-
});
|
|
4813
|
-
this.dispatch({
|
|
4814
|
-
type: 'SET_OPTION',
|
|
4815
|
-
optionName: 'visibleRange',
|
|
4816
|
-
rawOptionValue: dateOrRange,
|
|
4817
|
-
});
|
|
4818
|
-
}
|
|
4819
|
-
else {
|
|
4820
|
-
let { dateEnv } = this.getCurrentData();
|
|
4821
|
-
this.dispatch({
|
|
4822
|
-
type: 'CHANGE_VIEW_TYPE',
|
|
4823
|
-
viewType,
|
|
4824
|
-
dateMarker: dateEnv.createMarker(dateOrRange),
|
|
4825
|
-
});
|
|
4757
|
+
_splitEventStore(eventStore, defKeys) {
|
|
4758
|
+
let { defs, instances } = eventStore;
|
|
4759
|
+
let splitStores = {};
|
|
4760
|
+
for (let defId in defs) {
|
|
4761
|
+
for (let key of defKeys[defId]) {
|
|
4762
|
+
if (!splitStores[key]) {
|
|
4763
|
+
splitStores[key] = createEmptyEventStore();
|
|
4826
4764
|
}
|
|
4765
|
+
splitStores[key].defs[defId] = defs[defId];
|
|
4827
4766
|
}
|
|
4828
|
-
else {
|
|
4829
|
-
this.dispatch({
|
|
4830
|
-
type: 'CHANGE_VIEW_TYPE',
|
|
4831
|
-
viewType,
|
|
4832
|
-
});
|
|
4833
|
-
}
|
|
4834
|
-
});
|
|
4835
|
-
}
|
|
4836
|
-
// Forces navigation to a view for the given date.
|
|
4837
|
-
// `viewType` can be a specific view name or a generic one like "week" or "day".
|
|
4838
|
-
// needs to change
|
|
4839
|
-
zoomTo(dateMarker, viewType) {
|
|
4840
|
-
let state = this.getCurrentData();
|
|
4841
|
-
let spec;
|
|
4842
|
-
viewType = viewType || 'day'; // day is default zoom
|
|
4843
|
-
spec = state.viewSpecs[viewType] || this.getUnitViewSpec(viewType);
|
|
4844
|
-
this.unselect();
|
|
4845
|
-
if (spec) {
|
|
4846
|
-
this.dispatch({
|
|
4847
|
-
type: 'CHANGE_VIEW_TYPE',
|
|
4848
|
-
viewType: spec.type,
|
|
4849
|
-
dateMarker,
|
|
4850
|
-
});
|
|
4851
|
-
}
|
|
4852
|
-
else {
|
|
4853
|
-
this.dispatch({
|
|
4854
|
-
type: 'CHANGE_DATE',
|
|
4855
|
-
dateMarker,
|
|
4856
|
-
});
|
|
4857
|
-
}
|
|
4858
|
-
}
|
|
4859
|
-
// Given a duration singular unit, like "week" or "day", finds a matching view spec.
|
|
4860
|
-
// Preference is given to views that have corresponding buttons.
|
|
4861
|
-
getUnitViewSpec(unit) {
|
|
4862
|
-
let { viewSpecs, toolbarConfig } = this.getCurrentData();
|
|
4863
|
-
let viewTypes = [].concat(toolbarConfig.header ? toolbarConfig.header.viewsWithButtons : [], toolbarConfig.footer ? toolbarConfig.footer.viewsWithButtons : []);
|
|
4864
|
-
let i;
|
|
4865
|
-
let spec;
|
|
4866
|
-
for (let viewType in viewSpecs) {
|
|
4867
|
-
viewTypes.push(viewType);
|
|
4868
4767
|
}
|
|
4869
|
-
for (
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
if (
|
|
4873
|
-
|
|
4768
|
+
for (let instanceId in instances) {
|
|
4769
|
+
let instance = instances[instanceId];
|
|
4770
|
+
for (let key of defKeys[instance.defId]) {
|
|
4771
|
+
if (splitStores[key]) { // must have already been created
|
|
4772
|
+
splitStores[key].instances[instanceId] = instance;
|
|
4874
4773
|
}
|
|
4875
4774
|
}
|
|
4876
4775
|
}
|
|
4877
|
-
return
|
|
4776
|
+
return splitStores;
|
|
4878
4777
|
}
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4778
|
+
_splitIndividualUi(eventUiBases, defKeys) {
|
|
4779
|
+
let splitHashes = {};
|
|
4780
|
+
for (let defId in eventUiBases) {
|
|
4781
|
+
if (defId) { // not the '' key
|
|
4782
|
+
for (let key of defKeys[defId]) {
|
|
4783
|
+
if (!splitHashes[key]) {
|
|
4784
|
+
splitHashes[key] = {};
|
|
4785
|
+
}
|
|
4786
|
+
splitHashes[key][defId] = eventUiBases[defId];
|
|
4787
|
+
}
|
|
4788
|
+
}
|
|
4789
|
+
}
|
|
4790
|
+
return splitHashes;
|
|
4884
4791
|
}
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4792
|
+
_splitInteraction(interaction) {
|
|
4793
|
+
let splitStates = {};
|
|
4794
|
+
if (interaction) {
|
|
4795
|
+
let affectedStores = this._splitEventStore(interaction.affectedEvents, this._getKeysForEventDefs(interaction.affectedEvents));
|
|
4796
|
+
// can't rely on defKeys because event data is mutated
|
|
4797
|
+
let mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents);
|
|
4798
|
+
let mutatedStores = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId);
|
|
4799
|
+
let populate = (key) => {
|
|
4800
|
+
if (!splitStates[key]) {
|
|
4801
|
+
splitStates[key] = {
|
|
4802
|
+
affectedEvents: affectedStores[key] || EMPTY_EVENT_STORE,
|
|
4803
|
+
mutatedEvents: mutatedStores[key] || EMPTY_EVENT_STORE,
|
|
4804
|
+
isEvent: interaction.isEvent,
|
|
4805
|
+
};
|
|
4806
|
+
}
|
|
4807
|
+
};
|
|
4808
|
+
for (let key in affectedStores) {
|
|
4809
|
+
populate(key);
|
|
4810
|
+
}
|
|
4811
|
+
for (let key in mutatedStores) {
|
|
4812
|
+
populate(key);
|
|
4813
|
+
}
|
|
4814
|
+
}
|
|
4815
|
+
return splitStates;
|
|
4888
4816
|
}
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
dateMarker: state.dateEnv.addYears(state.currentDate, -1),
|
|
4895
|
-
});
|
|
4817
|
+
}
|
|
4818
|
+
function buildEventUiForKey(allUi, eventUiForKey, individualUi) {
|
|
4819
|
+
let baseParts = [];
|
|
4820
|
+
if (allUi) {
|
|
4821
|
+
baseParts.push(allUi);
|
|
4896
4822
|
}
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
this.unselect();
|
|
4900
|
-
this.dispatch({
|
|
4901
|
-
type: 'CHANGE_DATE',
|
|
4902
|
-
dateMarker: state.dateEnv.addYears(state.currentDate, 1),
|
|
4903
|
-
});
|
|
4823
|
+
if (eventUiForKey) {
|
|
4824
|
+
baseParts.push(eventUiForKey);
|
|
4904
4825
|
}
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
dateMarker: getNow(state.calendarOptions.now, state.dateEnv),
|
|
4911
|
-
});
|
|
4826
|
+
let stuff = {
|
|
4827
|
+
'': combineEventUis(baseParts),
|
|
4828
|
+
};
|
|
4829
|
+
if (individualUi) {
|
|
4830
|
+
Object.assign(stuff, individualUi);
|
|
4912
4831
|
}
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4832
|
+
return stuff;
|
|
4833
|
+
}
|
|
4834
|
+
|
|
4835
|
+
function getDateMeta(date, todayRange, nowDate, dateProfile) {
|
|
4836
|
+
return {
|
|
4837
|
+
dow: date.getUTCDay(),
|
|
4838
|
+
isDisabled: Boolean(dateProfile && !rangeContainsMarker(dateProfile.activeRange, date)),
|
|
4839
|
+
isOther: Boolean(dateProfile && !rangeContainsMarker(dateProfile.currentRange, date)),
|
|
4840
|
+
isToday: Boolean(todayRange && rangeContainsMarker(todayRange, date)),
|
|
4841
|
+
isPast: Boolean(nowDate ? (date < nowDate) : todayRange ? (date < todayRange.start) : false),
|
|
4842
|
+
isFuture: Boolean(nowDate ? (date > nowDate) : todayRange ? (date >= todayRange.end) : false),
|
|
4843
|
+
};
|
|
4844
|
+
}
|
|
4845
|
+
function getDayClassNames(meta, theme) {
|
|
4846
|
+
let classNames = [
|
|
4847
|
+
'fc-day',
|
|
4848
|
+
`fc-day-${DAY_IDS[meta.dow]}`,
|
|
4849
|
+
];
|
|
4850
|
+
if (meta.isDisabled) {
|
|
4851
|
+
classNames.push('fc-day-disabled');
|
|
4920
4852
|
}
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4853
|
+
else {
|
|
4854
|
+
if (meta.isToday) {
|
|
4855
|
+
classNames.push('fc-day-today');
|
|
4856
|
+
}
|
|
4857
|
+
if (meta.isPast) {
|
|
4858
|
+
classNames.push('fc-day-past');
|
|
4859
|
+
}
|
|
4860
|
+
if (meta.isFuture) {
|
|
4861
|
+
classNames.push('fc-day-future');
|
|
4862
|
+
}
|
|
4863
|
+
if (meta.isOther) {
|
|
4864
|
+
classNames.push('fc-day-other');
|
|
4930
4865
|
}
|
|
4931
4866
|
}
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4867
|
+
return classNames;
|
|
4868
|
+
}
|
|
4869
|
+
function getSlotClassNames(meta, theme) {
|
|
4870
|
+
let classNames = [
|
|
4871
|
+
'fc-slot',
|
|
4872
|
+
`fc-slot-${DAY_IDS[meta.dow]}`,
|
|
4873
|
+
];
|
|
4874
|
+
if (meta.isDisabled) {
|
|
4875
|
+
classNames.push('fc-slot-disabled');
|
|
4941
4876
|
}
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4877
|
+
else {
|
|
4878
|
+
if (meta.isToday) {
|
|
4879
|
+
classNames.push('fc-slot-today');
|
|
4880
|
+
}
|
|
4881
|
+
if (meta.isPast) {
|
|
4882
|
+
classNames.push('fc-slot-past');
|
|
4883
|
+
}
|
|
4884
|
+
if (meta.isFuture) {
|
|
4885
|
+
classNames.push('fc-slot-future');
|
|
4886
|
+
}
|
|
4946
4887
|
}
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4888
|
+
return classNames;
|
|
4889
|
+
}
|
|
4890
|
+
|
|
4891
|
+
// TODO: kill Component::safeSetState
|
|
4892
|
+
// TODO: kill
|
|
4893
|
+
function setStateDimMap(component, key, newMap) {
|
|
4894
|
+
const currentMap = component.state[key];
|
|
4895
|
+
if (!currentMap || !isDimMapsEqual(currentMap, newMap)) {
|
|
4896
|
+
component.setState({ [key]: newMap });
|
|
4897
|
+
}
|
|
4898
|
+
}
|
|
4899
|
+
// TODO: kill
|
|
4900
|
+
function isDimMapsEqual(oldMap, newMap) {
|
|
4901
|
+
for (const key in newMap) {
|
|
4902
|
+
if (!isDimsEqual(oldMap[key], newMap[key])) {
|
|
4903
|
+
return false;
|
|
4904
|
+
}
|
|
4950
4905
|
}
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4906
|
+
return true;
|
|
4907
|
+
}
|
|
4908
|
+
// TODO: kill
|
|
4909
|
+
function isDimsEqual(v0, v1) {
|
|
4910
|
+
return v0 != null && (v0 === v1 || Math.abs(v0 - v1) < 0.01);
|
|
4911
|
+
}
|
|
4912
|
+
|
|
4913
|
+
const callbackMap = new Map();
|
|
4914
|
+
let flushedCallbackSet = new Set();
|
|
4915
|
+
let isHandling = false;
|
|
4916
|
+
/*
|
|
4917
|
+
Performant from multiple perspectives:
|
|
4918
|
+
- less memory with one ResizeObserver
|
|
4919
|
+
- batches firing
|
|
4920
|
+
*/
|
|
4921
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
4922
|
+
isHandling = true;
|
|
4923
|
+
for (let entry of entries) {
|
|
4924
|
+
const callback = callbackMap.get(entry.target);
|
|
4925
|
+
if (entry.contentBoxSize) {
|
|
4926
|
+
// The standard makes contentBoxSize an array...
|
|
4927
|
+
if (entry.contentBoxSize[0]) {
|
|
4928
|
+
callback(entry.contentBoxSize[0].inlineSize, entry.contentBoxSize[0].blockSize);
|
|
4958
4929
|
}
|
|
4959
4930
|
else {
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
end: null,
|
|
4963
|
-
};
|
|
4931
|
+
// ...but old versions of Firefox treat it as a single item
|
|
4932
|
+
callback(entry.contentBoxSize.inlineSize, entry.contentBoxSize.blockSize);
|
|
4964
4933
|
}
|
|
4965
4934
|
}
|
|
4966
4935
|
else {
|
|
4967
|
-
|
|
4968
|
-
start: dateOrObj,
|
|
4969
|
-
end: endDate,
|
|
4970
|
-
};
|
|
4971
|
-
}
|
|
4972
|
-
let state = this.getCurrentData();
|
|
4973
|
-
let selection = parseDateSpan(selectionInput, state.dateEnv, createDuration({ days: 1 }));
|
|
4974
|
-
if (selection) { // throw parse error otherwise?
|
|
4975
|
-
this.dispatch({ type: 'SELECT_DATES', selection });
|
|
4976
|
-
triggerDateSelect(selection, null, state);
|
|
4936
|
+
callback(entry.contentRect.width, entry.contentRect.height);
|
|
4977
4937
|
}
|
|
4978
4938
|
}
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
this.dispatch({ type: 'UNSELECT_DATES' });
|
|
4983
|
-
triggerDateUnselect(pev, state);
|
|
4984
|
-
}
|
|
4939
|
+
for (const flushedCallback of flushedCallbackSet.values()) {
|
|
4940
|
+
flushedCallback();
|
|
4941
|
+
flushedCallbackSet.delete(flushedCallback);
|
|
4985
4942
|
}
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
if (sourceInput) { // true. part of the first event source
|
|
5010
|
-
[eventSource] = hashValuesToArray(state.eventSources);
|
|
5011
|
-
}
|
|
5012
|
-
}
|
|
5013
|
-
else if (sourceInput != null) { // an ID. accepts a number too
|
|
5014
|
-
let sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function
|
|
5015
|
-
if (!sourceApi) {
|
|
5016
|
-
console.warn(`Could not find an event source with ID "${sourceInput}"`); // TODO: test
|
|
5017
|
-
return null;
|
|
5018
|
-
}
|
|
5019
|
-
eventSource = sourceApi.internalEventSource;
|
|
4943
|
+
isHandling = false;
|
|
4944
|
+
});
|
|
4945
|
+
/*
|
|
4946
|
+
PRECONDITIONS:
|
|
4947
|
+
- element can only have one listener attached ever
|
|
4948
|
+
- element cannot have border or padding
|
|
4949
|
+
|
|
4950
|
+
TODO:
|
|
4951
|
+
- always force border/padding on these elements to `0 !important` ???
|
|
4952
|
+
*/
|
|
4953
|
+
function watchSize(el, callback) {
|
|
4954
|
+
callbackMap.set(el, callback);
|
|
4955
|
+
resizeObserver.observe(el);
|
|
4956
|
+
return () => {
|
|
4957
|
+
callbackMap.delete(el);
|
|
4958
|
+
resizeObserver.unobserve(el);
|
|
4959
|
+
};
|
|
4960
|
+
}
|
|
4961
|
+
function watchWidth(el, callback) {
|
|
4962
|
+
let currentWidth;
|
|
4963
|
+
return watchSize(el, (width) => {
|
|
4964
|
+
if (currentWidth == null || currentWidth !== width) {
|
|
4965
|
+
callback(currentWidth = width);
|
|
5020
4966
|
}
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
this.triggerEventAdd(newEventApi);
|
|
5029
|
-
return newEventApi;
|
|
4967
|
+
});
|
|
4968
|
+
}
|
|
4969
|
+
function watchHeight(el, callback) {
|
|
4970
|
+
let currentHeight;
|
|
4971
|
+
return watchSize(el, (_width, height) => {
|
|
4972
|
+
if (currentHeight == null || currentHeight !== height) {
|
|
4973
|
+
callback(currentHeight = height);
|
|
5030
4974
|
}
|
|
5031
|
-
|
|
4975
|
+
});
|
|
4976
|
+
}
|
|
4977
|
+
function afterSize(callback) {
|
|
4978
|
+
if (isHandling) {
|
|
4979
|
+
flushedCallbackSet.add(callback);
|
|
5032
4980
|
}
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
emitter.trigger('eventAdd', {
|
|
5036
|
-
event: eventApi,
|
|
5037
|
-
relatedEvents: [],
|
|
5038
|
-
revert: () => {
|
|
5039
|
-
this.dispatch({
|
|
5040
|
-
type: 'REMOVE_EVENTS',
|
|
5041
|
-
eventStore: eventApiToStore(eventApi),
|
|
5042
|
-
});
|
|
5043
|
-
},
|
|
5044
|
-
});
|
|
5045
|
-
}
|
|
5046
|
-
// TODO: optimize
|
|
5047
|
-
getEventById(id) {
|
|
5048
|
-
let state = this.getCurrentData();
|
|
5049
|
-
let { defs, instances } = state.eventStore;
|
|
5050
|
-
id = String(id);
|
|
5051
|
-
for (let defId in defs) {
|
|
5052
|
-
let def = defs[defId];
|
|
5053
|
-
if (def.publicId === id) {
|
|
5054
|
-
if (def.recurringDef) {
|
|
5055
|
-
return new EventImpl(state, def, null);
|
|
5056
|
-
}
|
|
5057
|
-
for (let instanceId in instances) {
|
|
5058
|
-
let instance = instances[instanceId];
|
|
5059
|
-
if (instance.defId === def.defId) {
|
|
5060
|
-
return new EventImpl(state, def, instance);
|
|
5061
|
-
}
|
|
5062
|
-
}
|
|
5063
|
-
}
|
|
5064
|
-
}
|
|
5065
|
-
return null;
|
|
5066
|
-
}
|
|
5067
|
-
getEvents() {
|
|
5068
|
-
let currentData = this.getCurrentData();
|
|
5069
|
-
return buildEventApis(currentData.eventStore, currentData);
|
|
5070
|
-
}
|
|
5071
|
-
removeAllEvents() {
|
|
5072
|
-
this.dispatch({ type: 'REMOVE_ALL_EVENTS' });
|
|
5073
|
-
}
|
|
5074
|
-
// Public Event Sources API
|
|
5075
|
-
// -----------------------------------------------------------------------------------------------------------------
|
|
5076
|
-
getEventSources() {
|
|
5077
|
-
let state = this.getCurrentData();
|
|
5078
|
-
let sourceHash = state.eventSources;
|
|
5079
|
-
let sourceApis = [];
|
|
5080
|
-
for (let internalId in sourceHash) {
|
|
5081
|
-
sourceApis.push(new EventSourceImpl(state, sourceHash[internalId]));
|
|
5082
|
-
}
|
|
5083
|
-
return sourceApis;
|
|
4981
|
+
else {
|
|
4982
|
+
callback(); // TODO: should we queue microtask?
|
|
5084
4983
|
}
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
4984
|
+
}
|
|
4985
|
+
|
|
4986
|
+
const DAY_FORMAT = createFormatter({ year: 'numeric', month: 'long', day: 'numeric' });
|
|
4987
|
+
const WEEK_FORMAT = createFormatter({ week: 'long' });
|
|
4988
|
+
function buildNavLinkAttrs(context, dateMarker, viewType = 'day', isTabbable = true) {
|
|
4989
|
+
const { dateEnv, options, calendarApi } = context;
|
|
4990
|
+
let dateStr = dateEnv.format(dateMarker, viewType === 'week' ? WEEK_FORMAT : DAY_FORMAT);
|
|
4991
|
+
if (options.navLinks) {
|
|
4992
|
+
let zonedDate = dateEnv.toDate(dateMarker);
|
|
4993
|
+
const handleInteraction = (ev) => {
|
|
4994
|
+
let customAction = viewType === 'day' ? options.navLinkDayClick :
|
|
4995
|
+
viewType === 'week' ? options.navLinkWeekClick : null;
|
|
4996
|
+
if (typeof customAction === 'function') {
|
|
4997
|
+
customAction.call(calendarApi, dateEnv.toDate(dateMarker), ev);
|
|
5092
4998
|
}
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
if (sourceInput instanceof EventSourceImpl) {
|
|
5099
|
-
// not already present? don't want to add an old snapshot
|
|
5100
|
-
if (!state.eventSources[sourceInput.internalEventSource.sourceId]) {
|
|
5101
|
-
this.dispatch({
|
|
5102
|
-
type: 'ADD_EVENT_SOURCES',
|
|
5103
|
-
sources: [sourceInput.internalEventSource],
|
|
5104
|
-
});
|
|
4999
|
+
else {
|
|
5000
|
+
if (typeof customAction === 'string') {
|
|
5001
|
+
viewType = customAction;
|
|
5002
|
+
}
|
|
5003
|
+
calendarApi.zoomTo(dateMarker, viewType);
|
|
5105
5004
|
}
|
|
5106
|
-
|
|
5107
|
-
}
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] });
|
|
5111
|
-
return new EventSourceImpl(state, eventSource);
|
|
5112
|
-
}
|
|
5113
|
-
return null;
|
|
5114
|
-
}
|
|
5115
|
-
removeAllEventSources() {
|
|
5116
|
-
this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' });
|
|
5117
|
-
}
|
|
5118
|
-
refetchEvents() {
|
|
5119
|
-
this.dispatch({ type: 'FETCH_EVENT_SOURCES', isRefetch: true });
|
|
5120
|
-
}
|
|
5121
|
-
// Scroll
|
|
5122
|
-
// -----------------------------------------------------------------------------------------------------------------
|
|
5123
|
-
scrollToTime(timeInput) {
|
|
5124
|
-
let time = createDuration(timeInput);
|
|
5125
|
-
if (time) {
|
|
5126
|
-
this.trigger('_scrollRequest', { time });
|
|
5127
|
-
}
|
|
5005
|
+
};
|
|
5006
|
+
return Object.assign({ title: formatWithOrdinals(options.navLinkHint, [dateStr, zonedDate], dateStr), 'data-navlink': '' }, (isTabbable
|
|
5007
|
+
? createAriaClickAttrs(handleInteraction)
|
|
5008
|
+
: { onClick: handleInteraction }));
|
|
5128
5009
|
}
|
|
5010
|
+
return { 'aria-label': dateStr };
|
|
5129
5011
|
}
|
|
5130
5012
|
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5013
|
+
let _isRtlScrollbarOnLeft = null;
|
|
5014
|
+
function getIsRtlScrollbarOnLeft() {
|
|
5015
|
+
if (_isRtlScrollbarOnLeft === null) {
|
|
5016
|
+
_isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft();
|
|
5017
|
+
}
|
|
5018
|
+
return _isRtlScrollbarOnLeft;
|
|
5136
5019
|
}
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5020
|
+
function computeIsRtlScrollbarOnLeft() {
|
|
5021
|
+
let outerEl = document.createElement('div');
|
|
5022
|
+
applyStyle(outerEl, {
|
|
5023
|
+
position: 'absolute',
|
|
5024
|
+
top: -1000,
|
|
5025
|
+
left: 0,
|
|
5026
|
+
border: 0,
|
|
5027
|
+
padding: 0,
|
|
5028
|
+
overflow: 'scroll',
|
|
5029
|
+
direction: 'rtl',
|
|
5030
|
+
});
|
|
5031
|
+
outerEl.innerHTML = '<div></div>';
|
|
5032
|
+
document.body.appendChild(outerEl);
|
|
5033
|
+
let innerEl = outerEl.firstChild;
|
|
5034
|
+
let res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left;
|
|
5035
|
+
removeElement(outerEl);
|
|
5036
|
+
return res;
|
|
5037
|
+
}
|
|
5038
|
+
|
|
5039
|
+
let _scrollbarWidths;
|
|
5040
|
+
function getScrollbarWidths() {
|
|
5041
|
+
if (!_scrollbarWidths) {
|
|
5042
|
+
_scrollbarWidths = computeScrollbarWidths();
|
|
5147
5043
|
}
|
|
5148
|
-
return
|
|
5044
|
+
return _scrollbarWidths;
|
|
5149
5045
|
}
|
|
5150
|
-
function
|
|
5046
|
+
function computeScrollbarWidths() {
|
|
5047
|
+
let el = document.createElement('div');
|
|
5048
|
+
el.style.overflow = 'scroll';
|
|
5049
|
+
el.style.position = 'absolute';
|
|
5050
|
+
el.style.top = '-9999px';
|
|
5051
|
+
el.style.left = '-9999px';
|
|
5052
|
+
document.body.appendChild(el);
|
|
5053
|
+
let res = computeScrollbarWidthsForEl(el);
|
|
5054
|
+
document.body.removeChild(el);
|
|
5055
|
+
return res;
|
|
5056
|
+
}
|
|
5057
|
+
// WARNING: will include border
|
|
5058
|
+
function computeScrollbarWidthsForEl(el) {
|
|
5151
5059
|
return {
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
top: rect.top + deltaY,
|
|
5155
|
-
bottom: rect.bottom + deltaY,
|
|
5060
|
+
x: el.offsetHeight - el.clientHeight,
|
|
5061
|
+
y: el.offsetWidth - el.clientWidth,
|
|
5156
5062
|
};
|
|
5157
5063
|
}
|
|
5158
|
-
|
|
5159
|
-
function
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5064
|
+
|
|
5065
|
+
function computeEdges(el, getPadding = false) {
|
|
5066
|
+
let computedStyle = window.getComputedStyle(el);
|
|
5067
|
+
let borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0;
|
|
5068
|
+
let borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0;
|
|
5069
|
+
let borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0;
|
|
5070
|
+
let borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
|
|
5071
|
+
let badScrollbarWidths = computeScrollbarWidthsForEl(el); // includes border!
|
|
5072
|
+
let scrollbarLeftRight = badScrollbarWidths.y - borderLeft - borderRight;
|
|
5073
|
+
let scrollbarBottom = badScrollbarWidths.x - borderTop - borderBottom;
|
|
5074
|
+
let res = {
|
|
5075
|
+
borderLeft,
|
|
5076
|
+
borderRight,
|
|
5077
|
+
borderTop,
|
|
5078
|
+
borderBottom,
|
|
5079
|
+
scrollbarBottom,
|
|
5080
|
+
scrollbarLeft: 0,
|
|
5081
|
+
scrollbarRight: 0,
|
|
5163
5082
|
};
|
|
5083
|
+
if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side?
|
|
5084
|
+
res.scrollbarLeft = scrollbarLeftRight;
|
|
5085
|
+
}
|
|
5086
|
+
else {
|
|
5087
|
+
res.scrollbarRight = scrollbarLeftRight;
|
|
5088
|
+
}
|
|
5089
|
+
if (getPadding) {
|
|
5090
|
+
res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0;
|
|
5091
|
+
res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0;
|
|
5092
|
+
res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0;
|
|
5093
|
+
res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0;
|
|
5094
|
+
}
|
|
5095
|
+
return res;
|
|
5164
5096
|
}
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5097
|
+
function computeInnerRect(el, goWithinPadding = false, doFromWindowViewport) {
|
|
5098
|
+
let outerRect = doFromWindowViewport ? el.getBoundingClientRect() : computeRect(el);
|
|
5099
|
+
let edges = computeEdges(el, goWithinPadding);
|
|
5100
|
+
let res = {
|
|
5101
|
+
left: outerRect.left + edges.borderLeft + edges.scrollbarLeft,
|
|
5102
|
+
right: outerRect.right - edges.borderRight - edges.scrollbarRight,
|
|
5103
|
+
top: outerRect.top + edges.borderTop,
|
|
5104
|
+
bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom,
|
|
5170
5105
|
};
|
|
5106
|
+
if (goWithinPadding) {
|
|
5107
|
+
res.left += edges.paddingLeft;
|
|
5108
|
+
res.right -= edges.paddingRight;
|
|
5109
|
+
res.top += edges.paddingTop;
|
|
5110
|
+
res.bottom -= edges.paddingBottom;
|
|
5111
|
+
}
|
|
5112
|
+
return res;
|
|
5171
5113
|
}
|
|
5172
|
-
|
|
5173
|
-
|
|
5114
|
+
function computeRect(el) {
|
|
5115
|
+
let rect = el.getBoundingClientRect();
|
|
5174
5116
|
return {
|
|
5175
|
-
left:
|
|
5176
|
-
top:
|
|
5117
|
+
left: rect.left + window.scrollX,
|
|
5118
|
+
top: rect.top + window.scrollY,
|
|
5119
|
+
right: rect.right + window.scrollX,
|
|
5120
|
+
bottom: rect.bottom + window.scrollY,
|
|
5177
5121
|
};
|
|
5178
5122
|
}
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
this.eventUiBuilders = {}; // TODO: typescript protection
|
|
5190
|
-
}
|
|
5191
|
-
splitProps(props) {
|
|
5192
|
-
let keyInfos = this.getKeyInfo(props);
|
|
5193
|
-
let defKeys = this.getKeysForEventDefs(props.eventStore);
|
|
5194
|
-
let dateSelections = this.splitDateSelection(props.dateSelection);
|
|
5195
|
-
let individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases*
|
|
5196
|
-
let eventStores = this.splitEventStore(props.eventStore, defKeys);
|
|
5197
|
-
let eventDrags = this.splitEventDrag(props.eventDrag);
|
|
5198
|
-
let eventResizes = this.splitEventResize(props.eventResize);
|
|
5199
|
-
let splitProps = {};
|
|
5200
|
-
this.eventUiBuilders = mapHash(keyInfos, (info, key) => this.eventUiBuilders[key] || memoize(buildEventUiForKey));
|
|
5201
|
-
for (let key in keyInfos) {
|
|
5202
|
-
let keyInfo = keyInfos[key];
|
|
5203
|
-
let eventStore = eventStores[key] || EMPTY_EVENT_STORE;
|
|
5204
|
-
let buildEventUi = this.eventUiBuilders[key];
|
|
5205
|
-
splitProps[key] = {
|
|
5206
|
-
businessHours: keyInfo.businessHours || props.businessHours,
|
|
5207
|
-
dateSelection: dateSelections[key] || null,
|
|
5208
|
-
eventStore,
|
|
5209
|
-
eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]),
|
|
5210
|
-
eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '',
|
|
5211
|
-
eventDrag: eventDrags[key] || null,
|
|
5212
|
-
eventResize: eventResizes[key] || null,
|
|
5213
|
-
};
|
|
5123
|
+
function computeClippedClientRect(el) {
|
|
5124
|
+
let clippingParents = getClippingParents(el);
|
|
5125
|
+
let rect = el.getBoundingClientRect();
|
|
5126
|
+
for (let clippingParent of clippingParents) {
|
|
5127
|
+
let intersection = intersectRects(rect, clippingParent.getBoundingClientRect());
|
|
5128
|
+
if (intersection) {
|
|
5129
|
+
rect = intersection;
|
|
5130
|
+
}
|
|
5131
|
+
else {
|
|
5132
|
+
return null;
|
|
5214
5133
|
}
|
|
5215
|
-
return splitProps;
|
|
5216
5134
|
}
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5135
|
+
return rect;
|
|
5136
|
+
}
|
|
5137
|
+
// does not return window
|
|
5138
|
+
function getClippingParents(el) {
|
|
5139
|
+
let parents = [];
|
|
5140
|
+
while (el instanceof HTMLElement) { // will stop when gets to document or null
|
|
5141
|
+
let computedStyle = window.getComputedStyle(el);
|
|
5142
|
+
if (computedStyle.position === 'fixed') {
|
|
5143
|
+
break;
|
|
5224
5144
|
}
|
|
5225
|
-
|
|
5145
|
+
if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) {
|
|
5146
|
+
parents.push(el);
|
|
5147
|
+
}
|
|
5148
|
+
el = el.parentNode;
|
|
5226
5149
|
}
|
|
5227
|
-
|
|
5228
|
-
|
|
5150
|
+
return parents;
|
|
5151
|
+
}
|
|
5152
|
+
|
|
5153
|
+
/*
|
|
5154
|
+
Records offset information for a set of elements, relative to an origin element.
|
|
5155
|
+
Can record the left/right OR the top/bottom OR both.
|
|
5156
|
+
Provides methods for querying the cache by position.
|
|
5157
|
+
*/
|
|
5158
|
+
class PositionCache {
|
|
5159
|
+
constructor(originEl, els, isHorizontal, isVertical) {
|
|
5160
|
+
this.els = els;
|
|
5161
|
+
let originClientRect = this.originClientRect = originEl.getBoundingClientRect(); // relative to viewport top-left
|
|
5162
|
+
if (isHorizontal) {
|
|
5163
|
+
this.buildElHorizontals(originClientRect.left);
|
|
5164
|
+
}
|
|
5165
|
+
if (isVertical) {
|
|
5166
|
+
this.buildElVerticals(originClientRect.top);
|
|
5167
|
+
}
|
|
5229
5168
|
}
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
let
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
splitStores[key].defs[defId] = defs[defId];
|
|
5239
|
-
}
|
|
5169
|
+
// Populates the left/right internal coordinate arrays
|
|
5170
|
+
buildElHorizontals(originClientLeft) {
|
|
5171
|
+
let lefts = [];
|
|
5172
|
+
let rights = [];
|
|
5173
|
+
for (let el of this.els) {
|
|
5174
|
+
let rect = el.getBoundingClientRect();
|
|
5175
|
+
lefts.push(rect.left - originClientLeft);
|
|
5176
|
+
rights.push(rect.right - originClientLeft);
|
|
5240
5177
|
}
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5178
|
+
this.lefts = lefts;
|
|
5179
|
+
this.rights = rights;
|
|
5180
|
+
}
|
|
5181
|
+
// Populates the top/bottom internal coordinate arrays
|
|
5182
|
+
buildElVerticals(originClientTop) {
|
|
5183
|
+
let tops = [];
|
|
5184
|
+
let bottoms = [];
|
|
5185
|
+
for (let el of this.els) {
|
|
5186
|
+
let rect = el.getBoundingClientRect();
|
|
5187
|
+
tops.push(rect.top - originClientTop);
|
|
5188
|
+
bottoms.push(rect.bottom - originClientTop);
|
|
5248
5189
|
}
|
|
5249
|
-
|
|
5190
|
+
this.tops = tops;
|
|
5191
|
+
this.bottoms = bottoms;
|
|
5250
5192
|
}
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
}
|
|
5193
|
+
// Given a left offset (from document left), returns the index of the el that it horizontally intersects.
|
|
5194
|
+
// If no intersection is made, returns undefined.
|
|
5195
|
+
leftToIndex(leftPosition) {
|
|
5196
|
+
let { lefts, rights } = this;
|
|
5197
|
+
let len = lefts.length;
|
|
5198
|
+
let i;
|
|
5199
|
+
for (i = 0; i < len; i += 1) {
|
|
5200
|
+
if (leftPosition >= lefts[i] && leftPosition < rights[i]) {
|
|
5201
|
+
return i;
|
|
5261
5202
|
}
|
|
5262
5203
|
}
|
|
5263
|
-
return
|
|
5204
|
+
return undefined; // TODO: better
|
|
5264
5205
|
}
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
splitStates[key] = {
|
|
5275
|
-
affectedEvents: affectedStores[key] || EMPTY_EVENT_STORE,
|
|
5276
|
-
mutatedEvents: mutatedStores[key] || EMPTY_EVENT_STORE,
|
|
5277
|
-
isEvent: interaction.isEvent,
|
|
5278
|
-
};
|
|
5279
|
-
}
|
|
5280
|
-
};
|
|
5281
|
-
for (let key in affectedStores) {
|
|
5282
|
-
populate(key);
|
|
5283
|
-
}
|
|
5284
|
-
for (let key in mutatedStores) {
|
|
5285
|
-
populate(key);
|
|
5206
|
+
// Given a top offset (from document top), returns the index of the el that it vertically intersects.
|
|
5207
|
+
// If no intersection is made, returns undefined.
|
|
5208
|
+
topToIndex(topPosition) {
|
|
5209
|
+
let { tops, bottoms } = this;
|
|
5210
|
+
let len = tops.length;
|
|
5211
|
+
let i;
|
|
5212
|
+
for (i = 0; i < len; i += 1) {
|
|
5213
|
+
if (topPosition >= tops[i] && topPosition < bottoms[i]) {
|
|
5214
|
+
return i;
|
|
5286
5215
|
}
|
|
5287
5216
|
}
|
|
5288
|
-
return
|
|
5289
|
-
}
|
|
5290
|
-
}
|
|
5291
|
-
function buildEventUiForKey(allUi, eventUiForKey, individualUi) {
|
|
5292
|
-
let baseParts = [];
|
|
5293
|
-
if (allUi) {
|
|
5294
|
-
baseParts.push(allUi);
|
|
5295
|
-
}
|
|
5296
|
-
if (eventUiForKey) {
|
|
5297
|
-
baseParts.push(eventUiForKey);
|
|
5217
|
+
return undefined; // TODO: better
|
|
5298
5218
|
}
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
if (individualUi) {
|
|
5303
|
-
Object.assign(stuff, individualUi);
|
|
5219
|
+
// Gets the width of the element at the given index
|
|
5220
|
+
getWidth(leftIndex) {
|
|
5221
|
+
return this.rights[leftIndex] - this.lefts[leftIndex];
|
|
5304
5222
|
}
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
function getDateMeta(date, todayRange, nowDate, dateProfile) {
|
|
5309
|
-
return {
|
|
5310
|
-
dow: date.getUTCDay(),
|
|
5311
|
-
isDisabled: Boolean(dateProfile && !rangeContainsMarker(dateProfile.activeRange, date)),
|
|
5312
|
-
isOther: Boolean(dateProfile && !rangeContainsMarker(dateProfile.currentRange, date)),
|
|
5313
|
-
isToday: Boolean(todayRange && rangeContainsMarker(todayRange, date)),
|
|
5314
|
-
isPast: Boolean(nowDate ? (date < nowDate) : todayRange ? (date < todayRange.start) : false),
|
|
5315
|
-
isFuture: Boolean(nowDate ? (date > nowDate) : todayRange ? (date >= todayRange.end) : false),
|
|
5316
|
-
};
|
|
5317
|
-
}
|
|
5318
|
-
function getDayClassNames(meta, theme) {
|
|
5319
|
-
let classNames = [
|
|
5320
|
-
'fc-day',
|
|
5321
|
-
`fc-day-${DAY_IDS[meta.dow]}`,
|
|
5322
|
-
];
|
|
5323
|
-
if (meta.isDisabled) {
|
|
5324
|
-
classNames.push('fc-day-disabled');
|
|
5223
|
+
// Gets the height of the element at the given index
|
|
5224
|
+
getHeight(topIndex) {
|
|
5225
|
+
return this.bottoms[topIndex] - this.tops[topIndex];
|
|
5325
5226
|
}
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
if (meta.isPast) {
|
|
5332
|
-
classNames.push('fc-day-past');
|
|
5333
|
-
}
|
|
5334
|
-
if (meta.isFuture) {
|
|
5335
|
-
classNames.push('fc-day-future');
|
|
5336
|
-
}
|
|
5337
|
-
if (meta.isOther) {
|
|
5338
|
-
classNames.push('fc-day-other');
|
|
5339
|
-
}
|
|
5227
|
+
similarTo(otherCache) {
|
|
5228
|
+
return similarNumArrays(this.tops || [], otherCache.tops || []) &&
|
|
5229
|
+
similarNumArrays(this.bottoms || [], otherCache.bottoms || []) &&
|
|
5230
|
+
similarNumArrays(this.lefts || [], otherCache.lefts || []) &&
|
|
5231
|
+
similarNumArrays(this.rights || [], otherCache.rights || []);
|
|
5340
5232
|
}
|
|
5341
|
-
return classNames;
|
|
5342
5233
|
}
|
|
5343
|
-
function
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
];
|
|
5348
|
-
if (meta.isDisabled) {
|
|
5349
|
-
classNames.push('fc-slot-disabled');
|
|
5234
|
+
function similarNumArrays(a, b) {
|
|
5235
|
+
const len = a.length;
|
|
5236
|
+
if (len !== b.length) {
|
|
5237
|
+
return false;
|
|
5350
5238
|
}
|
|
5351
|
-
|
|
5352
|
-
if (
|
|
5353
|
-
|
|
5354
|
-
classNames.push(theme.getClass('today'));
|
|
5355
|
-
}
|
|
5356
|
-
if (meta.isPast) {
|
|
5357
|
-
classNames.push('fc-slot-past');
|
|
5358
|
-
}
|
|
5359
|
-
if (meta.isFuture) {
|
|
5360
|
-
classNames.push('fc-slot-future');
|
|
5239
|
+
for (let i = 0; i < len; i++) {
|
|
5240
|
+
if (Math.round(a[i]) !== Math.round(b[i])) {
|
|
5241
|
+
return false;
|
|
5361
5242
|
}
|
|
5362
5243
|
}
|
|
5363
|
-
return
|
|
5244
|
+
return true;
|
|
5364
5245
|
}
|
|
5365
5246
|
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
viewType === 'week' ? options.navLinkWeekClick : null;
|
|
5376
|
-
if (typeof customAction === 'function') {
|
|
5377
|
-
customAction.call(calendarApi, dateEnv.toDate(dateMarker), ev);
|
|
5378
|
-
}
|
|
5379
|
-
else {
|
|
5380
|
-
if (typeof customAction === 'string') {
|
|
5381
|
-
viewType = customAction;
|
|
5382
|
-
}
|
|
5383
|
-
calendarApi.zoomTo(dateMarker, viewType);
|
|
5384
|
-
}
|
|
5385
|
-
};
|
|
5386
|
-
return Object.assign({ title: formatWithOrdinals(options.navLinkHint, [dateStr, zonedDate], dateStr), 'data-navlink': '' }, (isTabbable
|
|
5387
|
-
? createAriaClickAttrs(handleInteraction)
|
|
5388
|
-
: { onClick: handleInteraction }));
|
|
5247
|
+
/* eslint max-classes-per-file: "off" */
|
|
5248
|
+
/*
|
|
5249
|
+
An object for getting/setting scroll-related information for an element.
|
|
5250
|
+
Internally, this is done very differently for window versus DOM element,
|
|
5251
|
+
so this object serves as a common interface.
|
|
5252
|
+
*/
|
|
5253
|
+
class ScrollController {
|
|
5254
|
+
getMaxScrollTop() {
|
|
5255
|
+
return this.getScrollHeight() - this.getClientHeight();
|
|
5389
5256
|
}
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
let _isRtlScrollbarOnLeft = null;
|
|
5394
|
-
function getIsRtlScrollbarOnLeft() {
|
|
5395
|
-
if (_isRtlScrollbarOnLeft === null) {
|
|
5396
|
-
_isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft();
|
|
5257
|
+
getMaxScrollLeft() {
|
|
5258
|
+
return this.getScrollWidth() - this.getClientWidth();
|
|
5397
5259
|
}
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
function computeIsRtlScrollbarOnLeft() {
|
|
5401
|
-
let outerEl = document.createElement('div');
|
|
5402
|
-
applyStyle(outerEl, {
|
|
5403
|
-
position: 'absolute',
|
|
5404
|
-
top: -1000,
|
|
5405
|
-
left: 0,
|
|
5406
|
-
border: 0,
|
|
5407
|
-
padding: 0,
|
|
5408
|
-
overflow: 'scroll',
|
|
5409
|
-
direction: 'rtl',
|
|
5410
|
-
});
|
|
5411
|
-
outerEl.innerHTML = '<div></div>';
|
|
5412
|
-
document.body.appendChild(outerEl);
|
|
5413
|
-
let innerEl = outerEl.firstChild;
|
|
5414
|
-
let res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left;
|
|
5415
|
-
removeElement(outerEl);
|
|
5416
|
-
return res;
|
|
5417
|
-
}
|
|
5418
|
-
|
|
5419
|
-
let _scrollbarWidths;
|
|
5420
|
-
function getScrollbarWidths() {
|
|
5421
|
-
if (!_scrollbarWidths) {
|
|
5422
|
-
_scrollbarWidths = computeScrollbarWidths();
|
|
5260
|
+
canScrollVertically() {
|
|
5261
|
+
return this.getMaxScrollTop() > 0;
|
|
5423
5262
|
}
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
function computeScrollbarWidths() {
|
|
5427
|
-
let el = document.createElement('div');
|
|
5428
|
-
el.style.overflow = 'scroll';
|
|
5429
|
-
el.style.position = 'absolute';
|
|
5430
|
-
el.style.top = '-9999px';
|
|
5431
|
-
el.style.left = '-9999px';
|
|
5432
|
-
document.body.appendChild(el);
|
|
5433
|
-
let res = computeScrollbarWidthsForEl(el);
|
|
5434
|
-
document.body.removeChild(el);
|
|
5435
|
-
return res;
|
|
5436
|
-
}
|
|
5437
|
-
// WARNING: will include border
|
|
5438
|
-
function computeScrollbarWidthsForEl(el) {
|
|
5439
|
-
return {
|
|
5440
|
-
x: el.offsetHeight - el.clientHeight,
|
|
5441
|
-
y: el.offsetWidth - el.clientWidth,
|
|
5442
|
-
};
|
|
5443
|
-
}
|
|
5444
|
-
|
|
5445
|
-
function computeEdges(el, getPadding = false) {
|
|
5446
|
-
let computedStyle = window.getComputedStyle(el);
|
|
5447
|
-
let borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0;
|
|
5448
|
-
let borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0;
|
|
5449
|
-
let borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0;
|
|
5450
|
-
let borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
|
|
5451
|
-
let badScrollbarWidths = computeScrollbarWidthsForEl(el); // includes border!
|
|
5452
|
-
let scrollbarLeftRight = badScrollbarWidths.y - borderLeft - borderRight;
|
|
5453
|
-
let scrollbarBottom = badScrollbarWidths.x - borderTop - borderBottom;
|
|
5454
|
-
let res = {
|
|
5455
|
-
borderLeft,
|
|
5456
|
-
borderRight,
|
|
5457
|
-
borderTop,
|
|
5458
|
-
borderBottom,
|
|
5459
|
-
scrollbarBottom,
|
|
5460
|
-
scrollbarLeft: 0,
|
|
5461
|
-
scrollbarRight: 0,
|
|
5462
|
-
};
|
|
5463
|
-
if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side?
|
|
5464
|
-
res.scrollbarLeft = scrollbarLeftRight;
|
|
5263
|
+
canScrollHorizontally() {
|
|
5264
|
+
return this.getMaxScrollLeft() > 0;
|
|
5465
5265
|
}
|
|
5466
|
-
|
|
5467
|
-
|
|
5266
|
+
canScrollUp() {
|
|
5267
|
+
return this.getScrollTop() > 0;
|
|
5468
5268
|
}
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0;
|
|
5472
|
-
res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0;
|
|
5473
|
-
res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0;
|
|
5269
|
+
canScrollDown() {
|
|
5270
|
+
return this.getScrollTop() < this.getMaxScrollTop();
|
|
5474
5271
|
}
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
let res = {
|
|
5481
|
-
left: outerRect.left + edges.borderLeft + edges.scrollbarLeft,
|
|
5482
|
-
right: outerRect.right - edges.borderRight - edges.scrollbarRight,
|
|
5483
|
-
top: outerRect.top + edges.borderTop,
|
|
5484
|
-
bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom,
|
|
5485
|
-
};
|
|
5486
|
-
if (goWithinPadding) {
|
|
5487
|
-
res.left += edges.paddingLeft;
|
|
5488
|
-
res.right -= edges.paddingRight;
|
|
5489
|
-
res.top += edges.paddingTop;
|
|
5490
|
-
res.bottom -= edges.paddingBottom;
|
|
5272
|
+
canScrollLeft() {
|
|
5273
|
+
return this.getScrollLeft() > 0;
|
|
5274
|
+
}
|
|
5275
|
+
canScrollRight() {
|
|
5276
|
+
return this.getScrollLeft() < this.getMaxScrollLeft();
|
|
5491
5277
|
}
|
|
5492
|
-
return res;
|
|
5493
|
-
}
|
|
5494
|
-
function computeRect(el) {
|
|
5495
|
-
let rect = el.getBoundingClientRect();
|
|
5496
|
-
return {
|
|
5497
|
-
left: rect.left + window.scrollX,
|
|
5498
|
-
top: rect.top + window.scrollY,
|
|
5499
|
-
right: rect.right + window.scrollX,
|
|
5500
|
-
bottom: rect.bottom + window.scrollY,
|
|
5501
|
-
};
|
|
5502
5278
|
}
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5279
|
+
class ElementScrollController extends ScrollController {
|
|
5280
|
+
constructor(el) {
|
|
5281
|
+
super();
|
|
5282
|
+
this.el = el;
|
|
5283
|
+
}
|
|
5284
|
+
getScrollTop() {
|
|
5285
|
+
return this.el.scrollTop;
|
|
5286
|
+
}
|
|
5287
|
+
getScrollLeft() {
|
|
5288
|
+
return this.el.scrollLeft;
|
|
5289
|
+
}
|
|
5290
|
+
setScrollTop(top) {
|
|
5291
|
+
this.el.scrollTop = top;
|
|
5292
|
+
}
|
|
5293
|
+
setScrollLeft(left) {
|
|
5294
|
+
this.el.scrollLeft = left;
|
|
5295
|
+
}
|
|
5296
|
+
getScrollWidth() {
|
|
5297
|
+
return this.el.scrollWidth;
|
|
5298
|
+
}
|
|
5299
|
+
getScrollHeight() {
|
|
5300
|
+
return this.el.scrollHeight;
|
|
5301
|
+
}
|
|
5302
|
+
getClientHeight() {
|
|
5303
|
+
return this.el.clientHeight;
|
|
5304
|
+
}
|
|
5305
|
+
getClientWidth() {
|
|
5306
|
+
return this.el.clientWidth;
|
|
5514
5307
|
}
|
|
5515
|
-
return rect;
|
|
5516
5308
|
}
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5309
|
+
class WindowScrollController extends ScrollController {
|
|
5310
|
+
getScrollTop() {
|
|
5311
|
+
return window.scrollY;
|
|
5312
|
+
}
|
|
5313
|
+
getScrollLeft() {
|
|
5314
|
+
return window.scrollX;
|
|
5315
|
+
}
|
|
5316
|
+
setScrollTop(n) {
|
|
5317
|
+
window.scroll(window.scrollX, n);
|
|
5318
|
+
}
|
|
5319
|
+
setScrollLeft(n) {
|
|
5320
|
+
window.scroll(n, window.scrollY);
|
|
5321
|
+
}
|
|
5322
|
+
getScrollWidth() {
|
|
5323
|
+
return document.documentElement.scrollWidth;
|
|
5324
|
+
}
|
|
5325
|
+
getScrollHeight() {
|
|
5326
|
+
return document.documentElement.scrollHeight;
|
|
5327
|
+
}
|
|
5328
|
+
getClientHeight() {
|
|
5329
|
+
return document.documentElement.clientHeight;
|
|
5330
|
+
}
|
|
5331
|
+
getClientWidth() {
|
|
5332
|
+
return document.documentElement.clientWidth;
|
|
5529
5333
|
}
|
|
5530
|
-
return parents;
|
|
5531
5334
|
}
|
|
5532
5335
|
|
|
5533
5336
|
/*
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5337
|
+
an INTERACTABLE date component
|
|
5338
|
+
|
|
5339
|
+
PURPOSES:
|
|
5340
|
+
- hook up to fg, fill, and mirror renderers
|
|
5341
|
+
- interface for dragging and hits
|
|
5537
5342
|
*/
|
|
5538
|
-
class
|
|
5539
|
-
constructor(
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
if (isHorizontal) {
|
|
5543
|
-
this.buildElHorizontals(originClientRect.left);
|
|
5544
|
-
}
|
|
5545
|
-
if (isVertical) {
|
|
5546
|
-
this.buildElVerticals(originClientRect.top);
|
|
5547
|
-
}
|
|
5548
|
-
}
|
|
5549
|
-
// Populates the left/right internal coordinate arrays
|
|
5550
|
-
buildElHorizontals(originClientLeft) {
|
|
5551
|
-
let lefts = [];
|
|
5552
|
-
let rights = [];
|
|
5553
|
-
for (let el of this.els) {
|
|
5554
|
-
let rect = el.getBoundingClientRect();
|
|
5555
|
-
lefts.push(rect.left - originClientLeft);
|
|
5556
|
-
rights.push(rect.right - originClientLeft);
|
|
5557
|
-
}
|
|
5558
|
-
this.lefts = lefts;
|
|
5559
|
-
this.rights = rights;
|
|
5560
|
-
}
|
|
5561
|
-
// Populates the top/bottom internal coordinate arrays
|
|
5562
|
-
buildElVerticals(originClientTop) {
|
|
5563
|
-
let tops = [];
|
|
5564
|
-
let bottoms = [];
|
|
5565
|
-
for (let el of this.els) {
|
|
5566
|
-
let rect = el.getBoundingClientRect();
|
|
5567
|
-
tops.push(rect.top - originClientTop);
|
|
5568
|
-
bottoms.push(rect.bottom - originClientTop);
|
|
5569
|
-
}
|
|
5570
|
-
this.tops = tops;
|
|
5571
|
-
this.bottoms = bottoms;
|
|
5572
|
-
}
|
|
5573
|
-
// Given a left offset (from document left), returns the index of the el that it horizontally intersects.
|
|
5574
|
-
// If no intersection is made, returns undefined.
|
|
5575
|
-
leftToIndex(leftPosition) {
|
|
5576
|
-
let { lefts, rights } = this;
|
|
5577
|
-
let len = lefts.length;
|
|
5578
|
-
let i;
|
|
5579
|
-
for (i = 0; i < len; i += 1) {
|
|
5580
|
-
if (leftPosition >= lefts[i] && leftPosition < rights[i]) {
|
|
5581
|
-
return i;
|
|
5582
|
-
}
|
|
5583
|
-
}
|
|
5584
|
-
return undefined; // TODO: better
|
|
5585
|
-
}
|
|
5586
|
-
// Given a top offset (from document top), returns the index of the el that it vertically intersects.
|
|
5587
|
-
// If no intersection is made, returns undefined.
|
|
5588
|
-
topToIndex(topPosition) {
|
|
5589
|
-
let { tops, bottoms } = this;
|
|
5590
|
-
let len = tops.length;
|
|
5591
|
-
let i;
|
|
5592
|
-
for (i = 0; i < len; i += 1) {
|
|
5593
|
-
if (topPosition >= tops[i] && topPosition < bottoms[i]) {
|
|
5594
|
-
return i;
|
|
5595
|
-
}
|
|
5596
|
-
}
|
|
5597
|
-
return undefined; // TODO: better
|
|
5598
|
-
}
|
|
5599
|
-
// Gets the width of the element at the given index
|
|
5600
|
-
getWidth(leftIndex) {
|
|
5601
|
-
return this.rights[leftIndex] - this.lefts[leftIndex];
|
|
5602
|
-
}
|
|
5603
|
-
// Gets the height of the element at the given index
|
|
5604
|
-
getHeight(topIndex) {
|
|
5605
|
-
return this.bottoms[topIndex] - this.tops[topIndex];
|
|
5606
|
-
}
|
|
5607
|
-
similarTo(otherCache) {
|
|
5608
|
-
return similarNumArrays(this.tops || [], otherCache.tops || []) &&
|
|
5609
|
-
similarNumArrays(this.bottoms || [], otherCache.bottoms || []) &&
|
|
5610
|
-
similarNumArrays(this.lefts || [], otherCache.lefts || []) &&
|
|
5611
|
-
similarNumArrays(this.rights || [], otherCache.rights || []);
|
|
5612
|
-
}
|
|
5613
|
-
}
|
|
5614
|
-
function similarNumArrays(a, b) {
|
|
5615
|
-
const len = a.length;
|
|
5616
|
-
if (len !== b.length) {
|
|
5617
|
-
return false;
|
|
5618
|
-
}
|
|
5619
|
-
for (let i = 0; i < len; i++) {
|
|
5620
|
-
if (Math.round(a[i]) !== Math.round(b[i])) {
|
|
5621
|
-
return false;
|
|
5622
|
-
}
|
|
5623
|
-
}
|
|
5624
|
-
return true;
|
|
5625
|
-
}
|
|
5626
|
-
|
|
5627
|
-
/* eslint max-classes-per-file: "off" */
|
|
5628
|
-
/*
|
|
5629
|
-
An object for getting/setting scroll-related information for an element.
|
|
5630
|
-
Internally, this is done very differently for window versus DOM element,
|
|
5631
|
-
so this object serves as a common interface.
|
|
5632
|
-
*/
|
|
5633
|
-
class ScrollController {
|
|
5634
|
-
getMaxScrollTop() {
|
|
5635
|
-
return this.getScrollHeight() - this.getClientHeight();
|
|
5636
|
-
}
|
|
5637
|
-
getMaxScrollLeft() {
|
|
5638
|
-
return this.getScrollWidth() - this.getClientWidth();
|
|
5639
|
-
}
|
|
5640
|
-
canScrollVertically() {
|
|
5641
|
-
return this.getMaxScrollTop() > 0;
|
|
5642
|
-
}
|
|
5643
|
-
canScrollHorizontally() {
|
|
5644
|
-
return this.getMaxScrollLeft() > 0;
|
|
5645
|
-
}
|
|
5646
|
-
canScrollUp() {
|
|
5647
|
-
return this.getScrollTop() > 0;
|
|
5648
|
-
}
|
|
5649
|
-
canScrollDown() {
|
|
5650
|
-
return this.getScrollTop() < this.getMaxScrollTop();
|
|
5651
|
-
}
|
|
5652
|
-
canScrollLeft() {
|
|
5653
|
-
return this.getScrollLeft() > 0;
|
|
5654
|
-
}
|
|
5655
|
-
canScrollRight() {
|
|
5656
|
-
return this.getScrollLeft() < this.getMaxScrollLeft();
|
|
5657
|
-
}
|
|
5658
|
-
}
|
|
5659
|
-
class ElementScrollController extends ScrollController {
|
|
5660
|
-
constructor(el) {
|
|
5661
|
-
super();
|
|
5662
|
-
this.el = el;
|
|
5663
|
-
}
|
|
5664
|
-
getScrollTop() {
|
|
5665
|
-
return this.el.scrollTop;
|
|
5666
|
-
}
|
|
5667
|
-
getScrollLeft() {
|
|
5668
|
-
return this.el.scrollLeft;
|
|
5669
|
-
}
|
|
5670
|
-
setScrollTop(top) {
|
|
5671
|
-
this.el.scrollTop = top;
|
|
5672
|
-
}
|
|
5673
|
-
setScrollLeft(left) {
|
|
5674
|
-
this.el.scrollLeft = left;
|
|
5675
|
-
}
|
|
5676
|
-
getScrollWidth() {
|
|
5677
|
-
return this.el.scrollWidth;
|
|
5678
|
-
}
|
|
5679
|
-
getScrollHeight() {
|
|
5680
|
-
return this.el.scrollHeight;
|
|
5681
|
-
}
|
|
5682
|
-
getClientHeight() {
|
|
5683
|
-
return this.el.clientHeight;
|
|
5684
|
-
}
|
|
5685
|
-
getClientWidth() {
|
|
5686
|
-
return this.el.clientWidth;
|
|
5687
|
-
}
|
|
5688
|
-
}
|
|
5689
|
-
class WindowScrollController extends ScrollController {
|
|
5690
|
-
getScrollTop() {
|
|
5691
|
-
return window.scrollY;
|
|
5692
|
-
}
|
|
5693
|
-
getScrollLeft() {
|
|
5694
|
-
return window.scrollX;
|
|
5695
|
-
}
|
|
5696
|
-
setScrollTop(n) {
|
|
5697
|
-
window.scroll(window.scrollX, n);
|
|
5698
|
-
}
|
|
5699
|
-
setScrollLeft(n) {
|
|
5700
|
-
window.scroll(n, window.scrollY);
|
|
5701
|
-
}
|
|
5702
|
-
getScrollWidth() {
|
|
5703
|
-
return document.documentElement.scrollWidth;
|
|
5704
|
-
}
|
|
5705
|
-
getScrollHeight() {
|
|
5706
|
-
return document.documentElement.scrollHeight;
|
|
5707
|
-
}
|
|
5708
|
-
getClientHeight() {
|
|
5709
|
-
return document.documentElement.clientHeight;
|
|
5710
|
-
}
|
|
5711
|
-
getClientWidth() {
|
|
5712
|
-
return document.documentElement.clientWidth;
|
|
5713
|
-
}
|
|
5714
|
-
}
|
|
5715
|
-
|
|
5716
|
-
/*
|
|
5717
|
-
an INTERACTABLE date component
|
|
5718
|
-
|
|
5719
|
-
PURPOSES:
|
|
5720
|
-
- hook up to fg, fill, and mirror renderers
|
|
5721
|
-
- interface for dragging and hits
|
|
5722
|
-
*/
|
|
5723
|
-
class DateComponent extends BaseComponent {
|
|
5724
|
-
constructor() {
|
|
5725
|
-
super(...arguments);
|
|
5726
|
-
this.uid = guid();
|
|
5343
|
+
class DateComponent extends BaseComponent {
|
|
5344
|
+
constructor() {
|
|
5345
|
+
super(...arguments);
|
|
5346
|
+
this.uid = guid();
|
|
5727
5347
|
}
|
|
5728
5348
|
// Hit System
|
|
5729
5349
|
// -----------------------------------------------------------------------------------------------------------------
|
|
@@ -5753,440 +5373,603 @@ class NamedTimeZoneImpl {
|
|
|
5753
5373
|
}
|
|
5754
5374
|
}
|
|
5755
5375
|
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
this.getEntryThickness = getEntryThickness;
|
|
5762
|
-
// settings
|
|
5763
|
-
this.strictOrder = false;
|
|
5764
|
-
this.allowReslicing = false;
|
|
5765
|
-
this.maxCoord = -1; // -1 means no max
|
|
5766
|
-
this.maxStackCnt = -1; // -1 means no max
|
|
5767
|
-
this.levelCoords = []; // ordered
|
|
5768
|
-
this.entriesByLevel = []; // parallel with levelCoords
|
|
5769
|
-
this.stackCnts = {}; // TODO: use better technique!?
|
|
5770
|
-
}
|
|
5771
|
-
addSegs(inputs) {
|
|
5772
|
-
let hiddenEntries = [];
|
|
5773
|
-
for (let input of inputs) {
|
|
5774
|
-
this.insertEntry(input, hiddenEntries);
|
|
5775
|
-
}
|
|
5776
|
-
return hiddenEntries;
|
|
5777
|
-
}
|
|
5778
|
-
insertEntry(entry, hiddenEntries) {
|
|
5779
|
-
let insertion = this.findInsertion(entry);
|
|
5780
|
-
if (this.isInsertionValid(insertion, entry)) {
|
|
5781
|
-
this.insertEntryAt(entry, insertion);
|
|
5782
|
-
}
|
|
5783
|
-
else {
|
|
5784
|
-
this.handleInvalidInsertion(insertion, entry, hiddenEntries);
|
|
5785
|
-
}
|
|
5786
|
-
}
|
|
5787
|
-
isInsertionValid(insertion, entry) {
|
|
5788
|
-
return (this.maxCoord === -1 || insertion.levelCoord + this.getEntryThickness(entry) <= this.maxCoord) &&
|
|
5789
|
-
(this.maxStackCnt === -1 || insertion.stackCnt < this.maxStackCnt);
|
|
5790
|
-
}
|
|
5791
|
-
handleInvalidInsertion(insertion, entry, hiddenEntries) {
|
|
5792
|
-
if (this.allowReslicing && insertion.touchingEntry) {
|
|
5793
|
-
const hiddenEntry = Object.assign(Object.assign({}, entry), { span: intersectSpans(entry.span, insertion.touchingEntry.span) });
|
|
5794
|
-
hiddenEntries.push(hiddenEntry);
|
|
5795
|
-
this.splitEntry(entry, insertion.touchingEntry, hiddenEntries);
|
|
5796
|
-
}
|
|
5797
|
-
else {
|
|
5798
|
-
hiddenEntries.push(entry);
|
|
5799
|
-
}
|
|
5376
|
+
const DAY_NUM_FORMAT = createFormatter({ day: 'numeric' });
|
|
5377
|
+
class DayCellContainer extends BaseComponent {
|
|
5378
|
+
constructor() {
|
|
5379
|
+
super(...arguments);
|
|
5380
|
+
this.refineRenderProps = memoizeObjArg(refineRenderProps);
|
|
5800
5381
|
}
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5382
|
+
render() {
|
|
5383
|
+
let { props, context } = this;
|
|
5384
|
+
let { options } = context;
|
|
5385
|
+
let renderProps = this.refineRenderProps({
|
|
5386
|
+
date: props.date,
|
|
5387
|
+
dateProfile: props.dateProfile,
|
|
5388
|
+
todayRange: props.todayRange,
|
|
5389
|
+
isMonthStart: props.isMonthStart || false,
|
|
5390
|
+
showDayNumber: props.showDayNumber,
|
|
5391
|
+
extraRenderProps: props.extraRenderProps,
|
|
5392
|
+
viewApi: context.viewApi,
|
|
5393
|
+
dateEnv: context.dateEnv,
|
|
5394
|
+
monthStartFormat: options.monthStartFormat,
|
|
5395
|
+
});
|
|
5396
|
+
return (createElement(ContentContainer, Object.assign({}, props /* includes children */, { elClasses: [
|
|
5397
|
+
...getDayClassNames(renderProps, context.theme),
|
|
5398
|
+
...(props.elClasses || []),
|
|
5399
|
+
], elAttrs: Object.assign(Object.assign({}, props.elAttrs), (renderProps.isDisabled ? {} : { 'data-date': formatDayString(props.date) })), renderProps: renderProps, generatorName: "dayCellContent", customGenerator: options.dayCellContent, defaultGenerator: props.defaultGenerator, classNameGenerator:
|
|
5400
|
+
// don't use custom classNames if disabled
|
|
5401
|
+
renderProps.isDisabled ? undefined : options.dayCellClassNames, didMount: options.dayCellDidMount, willUnmount: options.dayCellWillUnmount })));
|
|
5821
5402
|
}
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
let stackCnt = 0;
|
|
5846
|
-
for (let trackingLevel = 0; trackingLevel < levelCnt; trackingLevel += 1) {
|
|
5847
|
-
const trackingCoord = levelCoords[trackingLevel];
|
|
5848
|
-
// if the current level is past the placed entry, we have found a good empty space and can stop.
|
|
5849
|
-
// if strictOrder, keep finding more lateral intersections.
|
|
5850
|
-
if (!strictOrder && trackingCoord >= candidateCoord + this.getEntryThickness(newEntry)) {
|
|
5851
|
-
break;
|
|
5403
|
+
}
|
|
5404
|
+
function hasCustomDayCellContent(options) {
|
|
5405
|
+
return Boolean(options.dayCellContent || hasCustomRenderingHandler('dayCellContent', options));
|
|
5406
|
+
}
|
|
5407
|
+
function refineRenderProps(raw) {
|
|
5408
|
+
let { date, dateEnv, dateProfile, isMonthStart } = raw;
|
|
5409
|
+
let dayMeta = getDateMeta(date, raw.todayRange, null, dateProfile);
|
|
5410
|
+
let dayNumberText = raw.showDayNumber ? (dateEnv.format(date, isMonthStart ? raw.monthStartFormat : DAY_NUM_FORMAT)) : '';
|
|
5411
|
+
return Object.assign(Object.assign(Object.assign({ date: dateEnv.toDate(date), view: raw.viewApi }, dayMeta), { isMonthStart,
|
|
5412
|
+
dayNumberText }), raw.extraRenderProps);
|
|
5413
|
+
}
|
|
5414
|
+
|
|
5415
|
+
const PADDING_FROM_VIEWPORT = 10;
|
|
5416
|
+
class Popover extends BaseComponent {
|
|
5417
|
+
constructor() {
|
|
5418
|
+
super(...arguments);
|
|
5419
|
+
this.state = {
|
|
5420
|
+
titleId: getUniqueDomId(),
|
|
5421
|
+
};
|
|
5422
|
+
this.handleRootEl = (el) => {
|
|
5423
|
+
this.rootEl = el;
|
|
5424
|
+
if (this.props.elRef) {
|
|
5425
|
+
setRef(this.props.elRef, el);
|
|
5852
5426
|
}
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
(
|
|
5859
|
-
|
|
5860
|
-
) {
|
|
5861
|
-
let trackingEntryBottom = trackingCoord + this.getEntryThickness(trackingEntry);
|
|
5862
|
-
// intersects into the top of the candidate?
|
|
5863
|
-
if (trackingEntryBottom > candidateCoord) {
|
|
5864
|
-
candidateCoord = trackingEntryBottom;
|
|
5865
|
-
touchingEntry = trackingEntry;
|
|
5866
|
-
touchingLevel = trackingLevel;
|
|
5867
|
-
touchingLateral = lateralIndex;
|
|
5868
|
-
}
|
|
5869
|
-
// butts up against top of candidate? (will happen if just intersected as well)
|
|
5870
|
-
if (trackingEntryBottom === candidateCoord) {
|
|
5871
|
-
// accumulate the highest possible stackCnt of the trackingEntries that butt up
|
|
5872
|
-
stackCnt = Math.max(stackCnt, stackCnts[buildEntryKey(trackingEntry)] + 1);
|
|
5873
|
-
}
|
|
5874
|
-
lateralIndex += 1;
|
|
5427
|
+
};
|
|
5428
|
+
// Triggered when the user clicks *anywhere* in the document, for the autoHide feature
|
|
5429
|
+
this.handleDocumentMouseDown = (ev) => {
|
|
5430
|
+
// only hide the popover if the click happened outside the popover
|
|
5431
|
+
const target = getEventTargetViaRoot(ev);
|
|
5432
|
+
if (!this.rootEl.contains(target)) {
|
|
5433
|
+
this.handleCloseClick();
|
|
5875
5434
|
}
|
|
5876
|
-
}
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5435
|
+
};
|
|
5436
|
+
this.handleDocumentKeyDown = (ev) => {
|
|
5437
|
+
if (ev.key === 'Escape') {
|
|
5438
|
+
this.handleCloseClick();
|
|
5439
|
+
}
|
|
5440
|
+
};
|
|
5441
|
+
this.handleCloseClick = () => {
|
|
5442
|
+
let { onClose } = this.props;
|
|
5443
|
+
if (onClose) {
|
|
5444
|
+
onClose();
|
|
5883
5445
|
}
|
|
5884
|
-
}
|
|
5885
|
-
// if adding to an existing level, find where to insert
|
|
5886
|
-
let destLateral = -1;
|
|
5887
|
-
if (destLevel < levelCnt && levelCoords[destLevel] === candidateCoord) {
|
|
5888
|
-
destLateral = binarySearch(entriesByLevel[destLevel], newEntry.span.end, getEntrySpanEnd)[0];
|
|
5889
|
-
}
|
|
5890
|
-
return {
|
|
5891
|
-
touchingLevel,
|
|
5892
|
-
touchingLateral,
|
|
5893
|
-
touchingEntry,
|
|
5894
|
-
stackCnt,
|
|
5895
|
-
levelCoord: candidateCoord,
|
|
5896
|
-
level: destLevel,
|
|
5897
|
-
lateral: destLateral,
|
|
5898
5446
|
};
|
|
5899
5447
|
}
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
let {
|
|
5903
|
-
let
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5448
|
+
render() {
|
|
5449
|
+
let { theme, options } = this.context;
|
|
5450
|
+
let { props, state } = this;
|
|
5451
|
+
let classNames = [
|
|
5452
|
+
'fc-popover',
|
|
5453
|
+
theme.getClass('popover'),
|
|
5454
|
+
].concat(props.extraClassNames || []);
|
|
5455
|
+
return createPortal(createElement("div", Object.assign({}, props.extraAttrs, { id: props.id, className: classNames.join(' '), "aria-labelledby": state.titleId, ref: this.handleRootEl }),
|
|
5456
|
+
createElement("div", { className: 'fc-popover-header ' + theme.getClass('popoverHeader') },
|
|
5457
|
+
createElement("span", { className: "fc-popover-title", id: state.titleId }, props.title),
|
|
5458
|
+
createElement("span", { className: 'fc-popover-close ' + theme.getIconClass('close'), title: options.closeHint, onClick: this.handleCloseClick })),
|
|
5459
|
+
createElement("div", { className: 'fc-popover-body ' + theme.getClass('popoverContent') }, props.children)), props.parentEl);
|
|
5460
|
+
}
|
|
5461
|
+
componentDidMount() {
|
|
5462
|
+
document.addEventListener('mousedown', this.handleDocumentMouseDown);
|
|
5463
|
+
document.addEventListener('keydown', this.handleDocumentKeyDown);
|
|
5464
|
+
this.updateSize();
|
|
5465
|
+
}
|
|
5466
|
+
componentWillUnmount() {
|
|
5467
|
+
document.removeEventListener('mousedown', this.handleDocumentMouseDown);
|
|
5468
|
+
document.removeEventListener('keydown', this.handleDocumentKeyDown);
|
|
5469
|
+
}
|
|
5470
|
+
updateSize() {
|
|
5471
|
+
let { isRtl } = this.context;
|
|
5472
|
+
let { alignmentEl, alignGridTop } = this.props;
|
|
5473
|
+
let { rootEl } = this;
|
|
5474
|
+
let alignmentRect = computeClippedClientRect(alignmentEl);
|
|
5475
|
+
if (alignmentRect) {
|
|
5476
|
+
let popoverDims = rootEl.getBoundingClientRect();
|
|
5477
|
+
if (alignGridTop) {
|
|
5478
|
+
throw new Error('alignGridTop not supported yet');
|
|
5910
5479
|
}
|
|
5480
|
+
// position relative to viewport
|
|
5481
|
+
let popoverTop = alignGridTop
|
|
5482
|
+
? elementClosest(alignmentEl, '.fc-scrollgrid').getBoundingClientRect().top // BAD!!!
|
|
5483
|
+
: alignmentRect.top;
|
|
5484
|
+
let popoverLeft = isRtl ? alignmentRect.right - popoverDims.width : alignmentRect.left;
|
|
5485
|
+
// constrain
|
|
5486
|
+
popoverTop = Math.max(popoverTop, PADDING_FROM_VIEWPORT);
|
|
5487
|
+
popoverLeft = Math.min(popoverLeft, document.documentElement.clientWidth - PADDING_FROM_VIEWPORT - popoverDims.width);
|
|
5488
|
+
popoverLeft = Math.max(popoverLeft, PADDING_FROM_VIEWPORT);
|
|
5489
|
+
let origin = rootEl.offsetParent.getBoundingClientRect();
|
|
5490
|
+
applyStyle(rootEl, {
|
|
5491
|
+
top: popoverTop - origin.top,
|
|
5492
|
+
left: popoverLeft - origin.left,
|
|
5493
|
+
});
|
|
5911
5494
|
}
|
|
5912
|
-
return rects;
|
|
5913
5495
|
}
|
|
5914
5496
|
}
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
let hungryMerge = {
|
|
5927
|
-
span: entry.span,
|
|
5928
|
-
entries: [entry],
|
|
5929
|
-
};
|
|
5930
|
-
for (let merge of merges) {
|
|
5931
|
-
if (intersectSpans(merge.span, hungryMerge.span)) {
|
|
5932
|
-
hungryMerge = {
|
|
5933
|
-
entries: merge.entries.concat(hungryMerge.entries),
|
|
5934
|
-
span: joinSpans(merge.span, hungryMerge.span),
|
|
5935
|
-
};
|
|
5497
|
+
|
|
5498
|
+
class MorePopover extends DateComponent {
|
|
5499
|
+
constructor() {
|
|
5500
|
+
super(...arguments);
|
|
5501
|
+
this.handleRootEl = (rootEl) => {
|
|
5502
|
+
this.rootEl = rootEl;
|
|
5503
|
+
if (rootEl) {
|
|
5504
|
+
this.context.registerInteractiveComponent(this, {
|
|
5505
|
+
el: rootEl,
|
|
5506
|
+
useEventCenter: false,
|
|
5507
|
+
});
|
|
5936
5508
|
}
|
|
5937
5509
|
else {
|
|
5938
|
-
|
|
5510
|
+
this.context.unregisterInteractiveComponent(this);
|
|
5939
5511
|
}
|
|
5940
|
-
}
|
|
5941
|
-
filteredMerges.push(hungryMerge);
|
|
5942
|
-
merges = filteredMerges;
|
|
5943
|
-
}
|
|
5944
|
-
return merges;
|
|
5945
|
-
}
|
|
5946
|
-
function joinSpans(span0, span1) {
|
|
5947
|
-
return {
|
|
5948
|
-
start: Math.min(span0.start, span1.start),
|
|
5949
|
-
end: Math.max(span0.end, span1.end),
|
|
5950
|
-
};
|
|
5951
|
-
}
|
|
5952
|
-
function intersectSpans(span0, span1) {
|
|
5953
|
-
let start = Math.max(span0.start, span1.start);
|
|
5954
|
-
let end = Math.min(span0.end, span1.end);
|
|
5955
|
-
if (start < end) {
|
|
5956
|
-
return { start, end };
|
|
5512
|
+
};
|
|
5957
5513
|
}
|
|
5958
|
-
|
|
5959
|
-
}
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
}
|
|
5965
|
-
|
|
5966
|
-
let startIndex = 0;
|
|
5967
|
-
let endIndex = a.length; // exclusive
|
|
5968
|
-
if (!endIndex || searchVal < getItemVal(a[startIndex])) { // no items OR before first item
|
|
5969
|
-
return [0, 0];
|
|
5514
|
+
render() {
|
|
5515
|
+
let { options, dateEnv } = this.context;
|
|
5516
|
+
let { props } = this;
|
|
5517
|
+
let { startDate, todayRange, dateProfile } = props;
|
|
5518
|
+
let title = dateEnv.format(startDate, options.dayPopoverFormat);
|
|
5519
|
+
return (createElement(DayCellContainer, { elRef: this.handleRootEl, date: startDate, dateProfile: dateProfile, todayRange: todayRange }, (InnerContent, renderProps, elAttrs) => (createElement(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 },
|
|
5520
|
+
hasCustomDayCellContent(options) && (createElement(InnerContent, { elTag: "div", elClasses: ['fc-more-popover-misc'] })),
|
|
5521
|
+
props.children))));
|
|
5970
5522
|
}
|
|
5971
|
-
|
|
5972
|
-
|
|
5523
|
+
queryHit(positionLeft, positionTop, elWidth, elHeight) {
|
|
5524
|
+
let { rootEl, props } = this;
|
|
5525
|
+
if (positionLeft >= 0 && positionLeft < elWidth &&
|
|
5526
|
+
positionTop >= 0 && positionTop < elHeight) {
|
|
5527
|
+
return {
|
|
5528
|
+
dateProfile: props.dateProfile,
|
|
5529
|
+
dateSpan: Object.assign({ allDay: !props.forceTimed, range: {
|
|
5530
|
+
start: props.startDate,
|
|
5531
|
+
end: props.endDate,
|
|
5532
|
+
} }, props.extraDateSpan),
|
|
5533
|
+
dayEl: rootEl,
|
|
5534
|
+
rect: {
|
|
5535
|
+
left: 0,
|
|
5536
|
+
top: 0,
|
|
5537
|
+
right: elWidth,
|
|
5538
|
+
bottom: elHeight,
|
|
5539
|
+
},
|
|
5540
|
+
layer: 1, // important when comparing with hits from other components
|
|
5541
|
+
};
|
|
5542
|
+
}
|
|
5543
|
+
return null;
|
|
5973
5544
|
}
|
|
5974
|
-
while (startIndex < endIndex) {
|
|
5975
|
-
let middleIndex = Math.floor(startIndex + (endIndex - startIndex) / 2);
|
|
5976
|
-
let middleVal = getItemVal(a[middleIndex]);
|
|
5977
|
-
if (searchVal < middleVal) {
|
|
5978
|
-
endIndex = middleIndex;
|
|
5979
|
-
}
|
|
5980
|
-
else if (searchVal > middleVal) {
|
|
5981
|
-
startIndex = middleIndex + 1;
|
|
5982
|
-
}
|
|
5983
|
-
else { // equal!
|
|
5984
|
-
return [middleIndex, 1];
|
|
5985
|
-
}
|
|
5986
|
-
}
|
|
5987
|
-
return [startIndex, 0];
|
|
5988
5545
|
}
|
|
5989
5546
|
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
5547
|
+
class MoreLinkContainer extends BaseComponent {
|
|
5548
|
+
constructor() {
|
|
5549
|
+
super(...arguments);
|
|
5550
|
+
this.state = {
|
|
5551
|
+
isPopoverOpen: false,
|
|
5552
|
+
popoverId: getUniqueDomId(),
|
|
5553
|
+
};
|
|
5554
|
+
this.handleLinkEl = (linkEl) => {
|
|
5555
|
+
this.linkEl = linkEl;
|
|
5556
|
+
if (this.props.elRef) {
|
|
5557
|
+
setRef(this.props.elRef, linkEl);
|
|
5558
|
+
}
|
|
5559
|
+
};
|
|
5560
|
+
this.handleClick = (ev) => {
|
|
5561
|
+
let { props, context } = this;
|
|
5562
|
+
let { moreLinkClick } = context.options;
|
|
5563
|
+
let date = computeRange(props).start;
|
|
5564
|
+
function buildPublicSeg(seg) {
|
|
5565
|
+
let { def, instance, range } = seg.eventRange;
|
|
5566
|
+
return {
|
|
5567
|
+
event: new EventImpl(context, def, instance),
|
|
5568
|
+
start: context.dateEnv.toDate(range.start),
|
|
5569
|
+
end: context.dateEnv.toDate(range.end),
|
|
5570
|
+
isStart: seg.isStart,
|
|
5571
|
+
isEnd: seg.isEnd,
|
|
5572
|
+
};
|
|
5573
|
+
}
|
|
5574
|
+
if (typeof moreLinkClick === 'function') {
|
|
5575
|
+
moreLinkClick = moreLinkClick({
|
|
5576
|
+
date,
|
|
5577
|
+
allDay: Boolean(props.allDayDate),
|
|
5578
|
+
allSegs: props.segs.map(buildPublicSeg),
|
|
5579
|
+
hiddenSegs: props.hiddenSegs.map(buildPublicSeg),
|
|
5580
|
+
jsEvent: ev,
|
|
5581
|
+
view: context.viewApi,
|
|
5582
|
+
});
|
|
5583
|
+
}
|
|
5584
|
+
if (!moreLinkClick || moreLinkClick === 'popover') {
|
|
5585
|
+
this.setState({ isPopoverOpen: true });
|
|
5586
|
+
}
|
|
5587
|
+
else if (typeof moreLinkClick === 'string') { // a view name
|
|
5588
|
+
context.calendarApi.zoomTo(date, moreLinkClick);
|
|
5589
|
+
}
|
|
5590
|
+
};
|
|
5591
|
+
this.handlePopoverClose = () => {
|
|
5592
|
+
this.setState({ isPopoverOpen: false });
|
|
5593
|
+
};
|
|
6006
5594
|
}
|
|
6007
|
-
|
|
5595
|
+
render() {
|
|
5596
|
+
let { props, state } = this;
|
|
5597
|
+
return (createElement(ViewContextType.Consumer, null, (context) => {
|
|
5598
|
+
let { viewApi, options, calendarApi } = context;
|
|
5599
|
+
let { moreLinkText } = options;
|
|
5600
|
+
let moreCnt = props.hiddenSegs.length;
|
|
5601
|
+
let range = computeRange(props);
|
|
5602
|
+
let text = typeof moreLinkText === 'function' // TODO: eventually use formatWithOrdinals
|
|
5603
|
+
? moreLinkText.call(calendarApi, moreCnt)
|
|
5604
|
+
: `+${moreCnt} ${moreLinkText}`;
|
|
5605
|
+
let hint = formatWithOrdinals(options.moreLinkHint, [moreCnt], text);
|
|
5606
|
+
let renderProps = {
|
|
5607
|
+
num: moreCnt,
|
|
5608
|
+
shortText: `+${moreCnt}`,
|
|
5609
|
+
text,
|
|
5610
|
+
view: viewApi,
|
|
5611
|
+
};
|
|
5612
|
+
return (createElement(Fragment, null,
|
|
5613
|
+
Boolean(moreCnt) && (createElement(ContentContainer, { elTag: props.elTag || 'a', elRef: this.handleLinkEl, elClasses: [
|
|
5614
|
+
...(props.elClasses || []),
|
|
5615
|
+
'fc-more-link',
|
|
5616
|
+
], elStyle: props.elStyle, elAttrs: Object.assign(Object.assign(Object.assign({}, props.elAttrs), createAriaClickAttrs(this.handleClick)), { title: hint, 'aria-expanded': state.isPopoverOpen, 'aria-controls': state.isPopoverOpen ? state.popoverId : '' }), renderProps: renderProps, generatorName: "moreLinkContent", customGenerator: options.moreLinkContent, defaultGenerator: props.defaultGenerator || renderMoreLinkInner, classNameGenerator: options.moreLinkClassNames, didMount: options.moreLinkDidMount, willUnmount: options.moreLinkWillUnmount }, props.children)),
|
|
5617
|
+
state.isPopoverOpen && (createElement(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 ?
|
|
5618
|
+
props.alignmentElRef.current :
|
|
5619
|
+
this.linkEl, alignGridTop: props.alignGridTop, forceTimed: props.forceTimed, onClose: this.handlePopoverClose }, props.popoverContent()))));
|
|
5620
|
+
}));
|
|
6008
5621
|
}
|
|
6009
|
-
|
|
6010
|
-
|
|
5622
|
+
componentDidMount() {
|
|
5623
|
+
this.updateParentEl();
|
|
6011
5624
|
}
|
|
6012
|
-
|
|
6013
|
-
|
|
5625
|
+
componentDidUpdate() {
|
|
5626
|
+
this.updateParentEl();
|
|
6014
5627
|
}
|
|
6015
|
-
|
|
6016
|
-
|
|
5628
|
+
updateParentEl() {
|
|
5629
|
+
if (this.linkEl) {
|
|
5630
|
+
this.parentEl = elementClosest(this.linkEl, '.fc-view-harness'); // HACK. reconsider
|
|
5631
|
+
}
|
|
6017
5632
|
}
|
|
6018
5633
|
}
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
startTime: createDuration,
|
|
6030
|
-
duration: createDuration,
|
|
6031
|
-
create: Boolean,
|
|
6032
|
-
sourceId: String,
|
|
6033
|
-
};
|
|
6034
|
-
function parseDragMeta(raw) {
|
|
6035
|
-
let { refined, extra } = refineProps(raw, DRAG_META_REFINERS);
|
|
5634
|
+
function renderMoreLinkInner(props) {
|
|
5635
|
+
return props.text;
|
|
5636
|
+
}
|
|
5637
|
+
function computeRange(props) {
|
|
5638
|
+
if (props.allDayDate) {
|
|
5639
|
+
return {
|
|
5640
|
+
start: props.allDayDate,
|
|
5641
|
+
end: addDays(props.allDayDate, 1),
|
|
5642
|
+
};
|
|
5643
|
+
}
|
|
6036
5644
|
return {
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
create: refined.create != null ? refined.create : true,
|
|
6040
|
-
sourceId: refined.sourceId,
|
|
6041
|
-
leftoverProps: extra,
|
|
5645
|
+
start: computeEarliestSegStart(props.hiddenSegs),
|
|
5646
|
+
end: computeLatestSegEnd(props.hiddenSegs),
|
|
6042
5647
|
};
|
|
6043
5648
|
}
|
|
6044
|
-
|
|
6045
|
-
|
|
6046
|
-
function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
|
|
6047
|
-
// if more than one week row, or if there are a lot of columns with not much space,
|
|
6048
|
-
// put just the day numbers will be in each cell
|
|
6049
|
-
if (!datesRepDistinctDays || dayCnt > 10) {
|
|
6050
|
-
return createFormatter({ weekday: 'short' }); // "Sat"
|
|
6051
|
-
}
|
|
6052
|
-
if (dayCnt > 1) {
|
|
6053
|
-
return createFormatter({ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }); // "Sat 11/12"
|
|
6054
|
-
}
|
|
6055
|
-
return createFormatter({ weekday: 'long' }); // "Saturday"
|
|
5649
|
+
function computeEarliestSegStart(segs) {
|
|
5650
|
+
return segs.reduce(pickEarliestStart).eventRange.range.start;
|
|
6056
5651
|
}
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
function renderInner$1(renderProps) {
|
|
6060
|
-
return renderProps.text;
|
|
5652
|
+
function pickEarliestStart(seg0, seg1) {
|
|
5653
|
+
return seg0.eventRange.range.start < seg1.eventRange.range.start ? seg0 : seg1;
|
|
6061
5654
|
}
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
class TableDateCell extends BaseComponent {
|
|
6065
|
-
render() {
|
|
6066
|
-
let { dateEnv, options, theme, viewApi } = this.context;
|
|
6067
|
-
let { props } = this;
|
|
6068
|
-
let { date, dateProfile } = props;
|
|
6069
|
-
let dayMeta = getDateMeta(date, props.todayRange, null, dateProfile);
|
|
6070
|
-
let classNames = [CLASS_NAME].concat(getDayClassNames(dayMeta, theme));
|
|
6071
|
-
let text = dateEnv.format(date, props.dayHeaderFormat);
|
|
6072
|
-
// if colCnt is 1, we are already in a day-view and don't need a navlink
|
|
6073
|
-
let navLinkAttrs = (!dayMeta.isDisabled && props.colCnt > 1)
|
|
6074
|
-
? buildNavLinkAttrs(this.context, date)
|
|
6075
|
-
: {};
|
|
6076
|
-
let renderProps = Object.assign(Object.assign(Object.assign({ date: dateEnv.toDate(date), view: viewApi }, props.extraRenderProps), { text }), dayMeta);
|
|
6077
|
-
return (createElement(ContentContainer, { elTag: "th", elClasses: classNames, elAttrs: Object.assign({ role: 'columnheader', colSpan: props.colSpan, 'data-date': !dayMeta.isDisabled ? formatDayString(date) : undefined }, props.extraDataAttrs), renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner$1, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContainer) => (createElement("div", { className: "fc-scrollgrid-sync-inner" }, !dayMeta.isDisabled && (createElement(InnerContainer, { elTag: "a", elAttrs: navLinkAttrs, elClasses: [
|
|
6078
|
-
'fc-col-header-cell-cushion',
|
|
6079
|
-
props.isSticky && 'fc-sticky',
|
|
6080
|
-
] }))))));
|
|
6081
|
-
}
|
|
5655
|
+
function computeLatestSegEnd(segs) {
|
|
5656
|
+
return segs.reduce(pickLatestEnd).eventRange.range.end;
|
|
6082
5657
|
}
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
class TableDowCell extends BaseComponent {
|
|
6086
|
-
render() {
|
|
6087
|
-
let { props } = this;
|
|
6088
|
-
let { dateEnv, theme, viewApi, options } = this.context;
|
|
6089
|
-
let date = addDays(new Date(259200000), props.dow); // start with Sun, 04 Jan 1970 00:00:00 GMT
|
|
6090
|
-
let dateMeta = {
|
|
6091
|
-
dow: props.dow,
|
|
6092
|
-
isDisabled: false,
|
|
6093
|
-
isFuture: false,
|
|
6094
|
-
isPast: false,
|
|
6095
|
-
isToday: false,
|
|
6096
|
-
isOther: false,
|
|
6097
|
-
};
|
|
6098
|
-
let text = dateEnv.format(date, props.dayHeaderFormat);
|
|
6099
|
-
let renderProps = Object.assign(Object.assign(Object.assign(Object.assign({ // TODO: make this public?
|
|
6100
|
-
date }, dateMeta), { view: viewApi }), props.extraRenderProps), { text });
|
|
6101
|
-
return (createElement(ContentContainer, { elTag: "th", elClasses: [
|
|
6102
|
-
CLASS_NAME,
|
|
6103
|
-
...getDayClassNames(dateMeta, theme),
|
|
6104
|
-
...(props.extraClassNames || []),
|
|
6105
|
-
], elAttrs: Object.assign({ role: 'columnheader', colSpan: props.colSpan }, props.extraDataAttrs), renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner$1, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => (createElement("div", { className: "fc-scrollgrid-sync-inner" },
|
|
6106
|
-
createElement(InnerContent, { elTag: "a", elClasses: [
|
|
6107
|
-
'fc-col-header-cell-cushion',
|
|
6108
|
-
props.isSticky && 'fc-sticky',
|
|
6109
|
-
], elAttrs: {
|
|
6110
|
-
'aria-label': dateEnv.format(date, WEEKDAY_FORMAT),
|
|
6111
|
-
} })))));
|
|
6112
|
-
}
|
|
5658
|
+
function pickLatestEnd(seg0, seg1) {
|
|
5659
|
+
return seg0.eventRange.range.end > seg1.eventRange.range.end ? seg0 : seg1;
|
|
6113
5660
|
}
|
|
6114
5661
|
|
|
6115
|
-
class
|
|
6116
|
-
constructor(
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
this.
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
this.
|
|
5662
|
+
class SegHierarchy {
|
|
5663
|
+
constructor(getEntryThickness = (entry) => {
|
|
5664
|
+
// if no thickness known, assume 1 (if 0, so small it always fits)
|
|
5665
|
+
return entry.thickness;
|
|
5666
|
+
}) {
|
|
5667
|
+
this.getEntryThickness = getEntryThickness;
|
|
5668
|
+
// settings
|
|
5669
|
+
this.strictOrder = false;
|
|
5670
|
+
this.allowReslicing = false;
|
|
5671
|
+
this.maxCoord = -1; // -1 means no max
|
|
5672
|
+
this.maxStackCnt = -1; // -1 means no max
|
|
5673
|
+
this.levelCoords = []; // ordered
|
|
5674
|
+
this.entriesByLevel = []; // parallel with levelCoords
|
|
5675
|
+
this.stackCnts = {}; // TODO: use better technique!?
|
|
6128
5676
|
}
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
this.
|
|
5677
|
+
addSegs(inputs) {
|
|
5678
|
+
let hiddenEntries = [];
|
|
5679
|
+
for (let input of inputs) {
|
|
5680
|
+
this.insertEntry(input, hiddenEntries);
|
|
6133
5681
|
}
|
|
5682
|
+
return hiddenEntries;
|
|
6134
5683
|
}
|
|
6135
|
-
|
|
6136
|
-
this.
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
nextState: { nowDate: nextUnitStart, todayRange: buildDayRange(nextUnitStart) },
|
|
6150
|
-
waitMs,
|
|
6151
|
-
};
|
|
5684
|
+
insertEntry(entry, hiddenEntries) {
|
|
5685
|
+
let entryThickness = this.getEntryThickness(entry);
|
|
5686
|
+
if (entryThickness == null) {
|
|
5687
|
+
hiddenEntries.push(entry);
|
|
5688
|
+
}
|
|
5689
|
+
else {
|
|
5690
|
+
let insertion = this.findInsertion(entry, entryThickness);
|
|
5691
|
+
if (this.isInsertionValid(insertion, entry, entryThickness)) {
|
|
5692
|
+
this.insertEntryAt(entry, insertion);
|
|
5693
|
+
}
|
|
5694
|
+
else {
|
|
5695
|
+
this.handleInvalidInsertion(insertion, entry, hiddenEntries);
|
|
5696
|
+
}
|
|
5697
|
+
}
|
|
6152
5698
|
}
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
this.setState(nextState, () => {
|
|
6157
|
-
this.setTimeout();
|
|
6158
|
-
});
|
|
6159
|
-
}, waitMs);
|
|
5699
|
+
isInsertionValid(insertion, entry, entryThickness) {
|
|
5700
|
+
return (this.maxCoord === -1 || insertion.levelCoord + entryThickness <= this.maxCoord) &&
|
|
5701
|
+
(this.maxStackCnt === -1 || insertion.stackCnt < this.maxStackCnt);
|
|
6160
5702
|
}
|
|
6161
|
-
|
|
6162
|
-
if (this.
|
|
6163
|
-
|
|
5703
|
+
handleInvalidInsertion(insertion, entry, hiddenEntries) {
|
|
5704
|
+
if (this.allowReslicing && insertion.touchingEntry) {
|
|
5705
|
+
const hiddenEntry = Object.assign(Object.assign({}, entry), { span: intersectSpans(entry.span, insertion.touchingEntry.span) });
|
|
5706
|
+
hiddenEntries.push(hiddenEntry);
|
|
5707
|
+
this.splitEntry(entry, insertion.touchingEntry, hiddenEntries);
|
|
5708
|
+
}
|
|
5709
|
+
else {
|
|
5710
|
+
hiddenEntries.push(entry);
|
|
6164
5711
|
}
|
|
6165
5712
|
}
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
5713
|
+
/*
|
|
5714
|
+
Does NOT add what hit the `barrier` into hiddenEntries. Should already be done.
|
|
5715
|
+
*/
|
|
5716
|
+
splitEntry(entry, barrier, hiddenEntries) {
|
|
5717
|
+
let entrySpan = entry.span;
|
|
5718
|
+
let barrierSpan = barrier.span;
|
|
5719
|
+
if (entrySpan.start < barrierSpan.start) {
|
|
5720
|
+
this.insertEntry({
|
|
5721
|
+
index: entry.index,
|
|
5722
|
+
seg: entry.seg,
|
|
5723
|
+
thickness: entry.thickness,
|
|
5724
|
+
span: { start: entrySpan.start, end: barrierSpan.start },
|
|
5725
|
+
}, hiddenEntries);
|
|
5726
|
+
}
|
|
5727
|
+
if (entrySpan.end > barrierSpan.end) {
|
|
5728
|
+
this.insertEntry({
|
|
5729
|
+
index: entry.index,
|
|
5730
|
+
seg: entry.seg,
|
|
5731
|
+
thickness: entry.thickness,
|
|
5732
|
+
span: { start: barrierSpan.end, end: entrySpan.end },
|
|
5733
|
+
}, hiddenEntries);
|
|
5734
|
+
}
|
|
5735
|
+
}
|
|
5736
|
+
insertEntryAt(entry, insertion) {
|
|
5737
|
+
let { entriesByLevel, levelCoords } = this;
|
|
5738
|
+
if (insertion.lateral === -1) {
|
|
5739
|
+
// create a new level
|
|
5740
|
+
insertAt(levelCoords, insertion.level, insertion.levelCoord);
|
|
5741
|
+
insertAt(entriesByLevel, insertion.level, [entry]);
|
|
5742
|
+
}
|
|
5743
|
+
else {
|
|
5744
|
+
// insert into existing level
|
|
5745
|
+
insertAt(entriesByLevel[insertion.level], insertion.lateral, entry);
|
|
5746
|
+
}
|
|
5747
|
+
this.stackCnts[buildEntryKey(entry)] = insertion.stackCnt;
|
|
5748
|
+
}
|
|
5749
|
+
/*
|
|
5750
|
+
does not care about limits
|
|
5751
|
+
*/
|
|
5752
|
+
findInsertion(newEntry, newEntryThickness) {
|
|
5753
|
+
let { levelCoords, entriesByLevel, strictOrder, stackCnts } = this;
|
|
5754
|
+
let levelCnt = levelCoords.length;
|
|
5755
|
+
let candidateCoord = 0;
|
|
5756
|
+
let touchingLevel = -1;
|
|
5757
|
+
let touchingLateral = -1;
|
|
5758
|
+
let touchingEntry = null;
|
|
5759
|
+
let stackCnt = 0;
|
|
5760
|
+
for (let trackingLevel = 0; trackingLevel < levelCnt; trackingLevel += 1) {
|
|
5761
|
+
const trackingCoord = levelCoords[trackingLevel];
|
|
5762
|
+
// if the current level is past the placed entry, we have found a good empty space and can stop.
|
|
5763
|
+
// if strictOrder, keep finding more lateral intersections.
|
|
5764
|
+
if (!strictOrder && trackingCoord >= candidateCoord + newEntryThickness) {
|
|
5765
|
+
break;
|
|
5766
|
+
}
|
|
5767
|
+
let trackingEntries = entriesByLevel[trackingLevel];
|
|
5768
|
+
let trackingEntry;
|
|
5769
|
+
let searchRes = binarySearch(trackingEntries, newEntry.span.start, getEntrySpanEnd); // find first entry after newEntry's end
|
|
5770
|
+
let lateralIndex = searchRes[0] + searchRes[1]; // if exact match (which doesn't collide), go to next one
|
|
5771
|
+
while ( // loop through entries that horizontally intersect
|
|
5772
|
+
(trackingEntry = trackingEntries[lateralIndex]) && // but not past the whole entry list
|
|
5773
|
+
trackingEntry.span.start < newEntry.span.end // and not entirely past newEntry
|
|
5774
|
+
) {
|
|
5775
|
+
let trackingEntryBottom = trackingCoord + this.getEntryThickness(trackingEntry);
|
|
5776
|
+
// intersects into the top of the candidate?
|
|
5777
|
+
if (trackingEntryBottom > candidateCoord) {
|
|
5778
|
+
candidateCoord = trackingEntryBottom;
|
|
5779
|
+
touchingEntry = trackingEntry;
|
|
5780
|
+
touchingLevel = trackingLevel;
|
|
5781
|
+
touchingLateral = lateralIndex;
|
|
5782
|
+
}
|
|
5783
|
+
// butts up against top of candidate? (will happen if just intersected as well)
|
|
5784
|
+
if (trackingEntryBottom === candidateCoord) {
|
|
5785
|
+
// accumulate the highest possible stackCnt of the trackingEntries that butt up
|
|
5786
|
+
stackCnt = Math.max(stackCnt, stackCnts[buildEntryKey(trackingEntry)] + 1);
|
|
5787
|
+
}
|
|
5788
|
+
lateralIndex += 1;
|
|
5789
|
+
}
|
|
5790
|
+
}
|
|
5791
|
+
// the destination level will be after touchingEntry's level. find it
|
|
5792
|
+
let destLevel = 0;
|
|
5793
|
+
if (touchingEntry) {
|
|
5794
|
+
destLevel = touchingLevel + 1;
|
|
5795
|
+
while (destLevel < levelCnt && levelCoords[destLevel] < candidateCoord) {
|
|
5796
|
+
destLevel += 1;
|
|
5797
|
+
}
|
|
5798
|
+
}
|
|
5799
|
+
// if adding to an existing level, find where to insert
|
|
5800
|
+
let destLateral = -1;
|
|
5801
|
+
if (destLevel < levelCnt && levelCoords[destLevel] === candidateCoord) {
|
|
5802
|
+
destLateral = binarySearch(entriesByLevel[destLevel], newEntry.span.end, getEntrySpanEnd)[0];
|
|
5803
|
+
}
|
|
5804
|
+
return {
|
|
5805
|
+
touchingLevel,
|
|
5806
|
+
touchingLateral,
|
|
5807
|
+
touchingEntry,
|
|
5808
|
+
stackCnt,
|
|
5809
|
+
levelCoord: candidateCoord,
|
|
5810
|
+
level: destLevel,
|
|
5811
|
+
lateral: destLateral,
|
|
5812
|
+
};
|
|
5813
|
+
}
|
|
5814
|
+
// sorted by levelCoord (lowest to highest)
|
|
5815
|
+
toRects() {
|
|
5816
|
+
let { entriesByLevel, levelCoords } = this;
|
|
5817
|
+
let levelCnt = entriesByLevel.length;
|
|
5818
|
+
let rects = [];
|
|
5819
|
+
for (let level = 0; level < levelCnt; level += 1) {
|
|
5820
|
+
let entries = entriesByLevel[level];
|
|
5821
|
+
let levelCoord = levelCoords[level];
|
|
5822
|
+
for (let entry of entries) {
|
|
5823
|
+
rects.push(Object.assign(Object.assign({}, entry), { thickness: this.getEntryThickness(entry), levelCoord }));
|
|
5824
|
+
}
|
|
5825
|
+
}
|
|
5826
|
+
return rects;
|
|
5827
|
+
}
|
|
5828
|
+
}
|
|
5829
|
+
function getEntrySpanEnd(entry) {
|
|
5830
|
+
return entry.span.end;
|
|
5831
|
+
}
|
|
5832
|
+
/*
|
|
5833
|
+
Generates a unique ID whose lifespan is a single run of SegHierarchy, so can be really specific
|
|
5834
|
+
without fear of accidentally busting the cache on subsequent rerenders
|
|
5835
|
+
*/
|
|
5836
|
+
function buildEntryKey(entry) {
|
|
5837
|
+
return entry.index + ':' + entry.span.start;
|
|
5838
|
+
}
|
|
5839
|
+
/*
|
|
5840
|
+
returns groups with entries sorted by input order
|
|
5841
|
+
*/
|
|
5842
|
+
function groupIntersectingEntries(entries) {
|
|
5843
|
+
let merges = [];
|
|
5844
|
+
for (let entry of entries) {
|
|
5845
|
+
let filteredMerges = [];
|
|
5846
|
+
let hungryMerge = {
|
|
5847
|
+
span: entry.span,
|
|
5848
|
+
entries: [entry],
|
|
5849
|
+
};
|
|
5850
|
+
for (let merge of merges) {
|
|
5851
|
+
if (intersectSpans(merge.span, hungryMerge.span)) {
|
|
5852
|
+
hungryMerge = {
|
|
5853
|
+
span: joinSpans(merge.span, hungryMerge.span),
|
|
5854
|
+
entries: merge.entries.concat(hungryMerge.entries), // keep preexisting merge's items first. maintains order
|
|
5855
|
+
};
|
|
5856
|
+
}
|
|
5857
|
+
else {
|
|
5858
|
+
filteredMerges.push(merge);
|
|
5859
|
+
}
|
|
5860
|
+
}
|
|
5861
|
+
filteredMerges.push(hungryMerge);
|
|
5862
|
+
merges = filteredMerges;
|
|
5863
|
+
}
|
|
5864
|
+
return merges.map((merge) => {
|
|
5865
|
+
const segs = merge.entries.map(extractEntrySeg);
|
|
5866
|
+
return {
|
|
5867
|
+
key: buildIsoString(computeEarliestSegStart(segs)),
|
|
5868
|
+
span: merge.span,
|
|
5869
|
+
segs,
|
|
5870
|
+
};
|
|
5871
|
+
});
|
|
5872
|
+
}
|
|
5873
|
+
function extractEntrySeg(entry) {
|
|
5874
|
+
return entry.seg;
|
|
5875
|
+
}
|
|
5876
|
+
function joinSpans(span0, span1) {
|
|
5877
|
+
return {
|
|
5878
|
+
start: Math.min(span0.start, span1.start),
|
|
5879
|
+
end: Math.max(span0.end, span1.end),
|
|
5880
|
+
};
|
|
5881
|
+
}
|
|
5882
|
+
function intersectSpans(span0, span1) {
|
|
5883
|
+
let start = Math.max(span0.start, span1.start);
|
|
5884
|
+
let end = Math.min(span0.end, span1.end);
|
|
5885
|
+
if (start < end) {
|
|
5886
|
+
return { start, end };
|
|
5887
|
+
}
|
|
5888
|
+
return null;
|
|
5889
|
+
}
|
|
5890
|
+
// general util
|
|
5891
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
5892
|
+
function insertAt(arr, index, item) {
|
|
5893
|
+
arr.splice(index, 0, item);
|
|
5894
|
+
}
|
|
5895
|
+
function binarySearch(a, searchVal, getItemVal) {
|
|
5896
|
+
let startIndex = 0;
|
|
5897
|
+
let endIndex = a.length; // exclusive
|
|
5898
|
+
if (!endIndex || searchVal < getItemVal(a[startIndex])) { // no items OR before first item
|
|
5899
|
+
return [0, 0];
|
|
5900
|
+
}
|
|
5901
|
+
if (searchVal > getItemVal(a[endIndex - 1])) { // after last item
|
|
5902
|
+
return [endIndex, 0];
|
|
5903
|
+
}
|
|
5904
|
+
while (startIndex < endIndex) {
|
|
5905
|
+
let middleIndex = Math.floor(startIndex + (endIndex - startIndex) / 2);
|
|
5906
|
+
let middleVal = getItemVal(a[middleIndex]);
|
|
5907
|
+
if (searchVal < middleVal) {
|
|
5908
|
+
endIndex = middleIndex;
|
|
5909
|
+
}
|
|
5910
|
+
else if (searchVal > middleVal) {
|
|
5911
|
+
startIndex = middleIndex + 1;
|
|
5912
|
+
}
|
|
5913
|
+
else { // equal!
|
|
5914
|
+
return [middleIndex, 1];
|
|
5915
|
+
}
|
|
5916
|
+
}
|
|
5917
|
+
return [startIndex, 0];
|
|
5918
|
+
}
|
|
5919
|
+
|
|
5920
|
+
/*
|
|
5921
|
+
An abstraction for a dragging interaction originating on an event.
|
|
5922
|
+
Does higher-level things than PointerDragger, such as possibly:
|
|
5923
|
+
- a "mirror" that moves with the pointer
|
|
5924
|
+
- a minimum number of pixels or other criteria for a true drag to begin
|
|
5925
|
+
|
|
5926
|
+
subclasses must emit:
|
|
5927
|
+
- pointerdown
|
|
5928
|
+
- dragstart
|
|
5929
|
+
- dragmove
|
|
5930
|
+
- pointerup
|
|
5931
|
+
- dragend
|
|
5932
|
+
*/
|
|
5933
|
+
class ElementDragging {
|
|
5934
|
+
constructor(el, selector) {
|
|
5935
|
+
this.emitter = new Emitter();
|
|
5936
|
+
}
|
|
5937
|
+
destroy() {
|
|
5938
|
+
}
|
|
5939
|
+
setMirrorIsVisible(bool) {
|
|
5940
|
+
// optional if subclass doesn't want to support a mirror
|
|
5941
|
+
}
|
|
5942
|
+
setMirrorNeedsRevert(bool) {
|
|
5943
|
+
// optional if subclass doesn't want to support a mirror
|
|
5944
|
+
}
|
|
5945
|
+
setAutoScrollEnabled(bool) {
|
|
5946
|
+
// optional
|
|
6186
5947
|
}
|
|
6187
5948
|
}
|
|
6188
|
-
|
|
6189
|
-
|
|
5949
|
+
|
|
5950
|
+
// TODO: get rid of this in favor of options system,
|
|
5951
|
+
// tho it's really easy to access this globally rather than pass thru options.
|
|
5952
|
+
const config = {};
|
|
5953
|
+
|
|
5954
|
+
/*
|
|
5955
|
+
Information about what will happen when an external element is dragged-and-dropped
|
|
5956
|
+
onto a calendar. Contains information for creating an event.
|
|
5957
|
+
*/
|
|
5958
|
+
const DRAG_META_REFINERS = {
|
|
5959
|
+
startTime: createDuration,
|
|
5960
|
+
duration: createDuration,
|
|
5961
|
+
create: Boolean,
|
|
5962
|
+
sourceId: String,
|
|
5963
|
+
};
|
|
5964
|
+
function parseDragMeta(raw) {
|
|
5965
|
+
let { refined, extra } = refineProps(raw, DRAG_META_REFINERS);
|
|
5966
|
+
return {
|
|
5967
|
+
startTime: refined.startTime || null,
|
|
5968
|
+
duration: refined.duration || null,
|
|
5969
|
+
create: refined.create != null ? refined.create : true,
|
|
5970
|
+
sourceId: refined.sourceId,
|
|
5971
|
+
leftoverProps: extra,
|
|
5972
|
+
};
|
|
6190
5973
|
}
|
|
6191
5974
|
|
|
6192
5975
|
class DaySeriesModel {
|
|
@@ -6270,7 +6053,7 @@ class DayTableModel {
|
|
|
6270
6053
|
this.rowCnt = rowCnt;
|
|
6271
6054
|
this.colCnt = daysPerRow;
|
|
6272
6055
|
this.daySeries = daySeries;
|
|
6273
|
-
this.
|
|
6056
|
+
this.cellRows = this.buildCells();
|
|
6274
6057
|
this.headerDates = this.buildHeaderDates();
|
|
6275
6058
|
}
|
|
6276
6059
|
buildCells() {
|
|
@@ -6294,7 +6077,7 @@ class DayTableModel {
|
|
|
6294
6077
|
buildHeaderDates() {
|
|
6295
6078
|
let dates = [];
|
|
6296
6079
|
for (let col = 0; col < this.colCnt; col += 1) {
|
|
6297
|
-
dates.push(this.
|
|
6080
|
+
dates.push(this.cellRows[0][col].date);
|
|
6298
6081
|
}
|
|
6299
6082
|
return dates;
|
|
6300
6083
|
}
|
|
@@ -6322,18 +6105,272 @@ class DayTableModel {
|
|
|
6322
6105
|
}
|
|
6323
6106
|
}
|
|
6324
6107
|
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6108
|
+
const WHEEL_EVENT_NAMES = 'wheel mousewheel DomMouseScroll MozMousePixelScroll'.split(' ');
|
|
6109
|
+
/*
|
|
6110
|
+
Fires:
|
|
6111
|
+
- scrollStart (always user)
|
|
6112
|
+
- scroll
|
|
6113
|
+
- scrollEnd (always user)
|
|
6114
|
+
|
|
6115
|
+
NOTE: detection is complicated (w/ touch and wheel) because ScrollerSyncer needs to know about it,
|
|
6116
|
+
but are we sure we can't just ignore programmatic scrollTo() calls with a flag? and determine the
|
|
6117
|
+
the scroll-master simply by who was the newest scroller? Does passive:true do things asynchronously?
|
|
6118
|
+
*/
|
|
6119
|
+
class ScrollListener {
|
|
6120
|
+
constructor(el) {
|
|
6121
|
+
this.el = el;
|
|
6122
|
+
this.emitter = new Emitter();
|
|
6123
|
+
this.isScrolling = false;
|
|
6124
|
+
this.isTouching = false; // user currently has finger down?
|
|
6125
|
+
this.isRecentlyWheeled = false;
|
|
6126
|
+
this.isRecentlyScrolled = false;
|
|
6127
|
+
this.wheelWaiter = new DelayedRunner(this._handleWheelWaited.bind(this));
|
|
6128
|
+
this.scrollWaiter = new DelayedRunner(this._handleScrollWaited.bind(this));
|
|
6129
|
+
// Handlers
|
|
6130
|
+
// ----------------------------------------------------------------------------------------------
|
|
6131
|
+
this.handleScroll = () => {
|
|
6132
|
+
this.startScroll();
|
|
6133
|
+
this.emitter.trigger('scroll', this.isRecentlyWheeled, this.isTouching);
|
|
6134
|
+
this.isRecentlyScrolled = true;
|
|
6135
|
+
this.scrollWaiter.request(500);
|
|
6136
|
+
};
|
|
6137
|
+
// will fire *before* the scroll event is fired (might not cause a scroll)
|
|
6138
|
+
this.handleWheel = () => {
|
|
6139
|
+
this.isRecentlyWheeled = true;
|
|
6140
|
+
this.wheelWaiter.request(500);
|
|
6141
|
+
};
|
|
6142
|
+
// will fire *before* the scroll event is fired (might not cause a scroll)
|
|
6143
|
+
this.handleTouchStart = () => {
|
|
6144
|
+
this.isTouching = true;
|
|
6145
|
+
};
|
|
6146
|
+
this.handleTouchEnd = () => {
|
|
6147
|
+
this.isTouching = false;
|
|
6148
|
+
// if the user ended their touch, and the scroll area wasn't moving,
|
|
6149
|
+
// we consider this to be the end of the scroll.
|
|
6150
|
+
if (!this.isRecentlyScrolled) {
|
|
6151
|
+
this.endScroll(); // won't fire if already ended
|
|
6152
|
+
}
|
|
6153
|
+
};
|
|
6154
|
+
el.addEventListener('scroll', this.handleScroll);
|
|
6155
|
+
el.addEventListener('touchstart', this.handleTouchStart, { passive: true });
|
|
6156
|
+
el.addEventListener('touchend', this.handleTouchEnd);
|
|
6157
|
+
for (let eventName of WHEEL_EVENT_NAMES) {
|
|
6158
|
+
el.addEventListener(eventName, this.handleWheel, { passive: true });
|
|
6159
|
+
}
|
|
6160
|
+
}
|
|
6161
|
+
destroy() {
|
|
6162
|
+
let { el } = this;
|
|
6163
|
+
el.removeEventListener('scroll', this.handleScroll);
|
|
6164
|
+
el.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
|
|
6165
|
+
el.removeEventListener('touchend', this.handleTouchEnd);
|
|
6166
|
+
for (let eventName of WHEEL_EVENT_NAMES) {
|
|
6167
|
+
el.removeEventListener(eventName, this.handleWheel, { passive: true });
|
|
6168
|
+
}
|
|
6169
|
+
}
|
|
6170
|
+
// Start / Stop
|
|
6171
|
+
// ----------------------------------------------------------------------------------------------
|
|
6172
|
+
startScroll() {
|
|
6173
|
+
if (!this.isScrolling) {
|
|
6174
|
+
this.isScrolling = true;
|
|
6175
|
+
this.emitter.trigger('scrollStart', this.isRecentlyWheeled, this.isTouching);
|
|
6176
|
+
}
|
|
6177
|
+
}
|
|
6178
|
+
endScroll() {
|
|
6179
|
+
if (this.isScrolling) {
|
|
6180
|
+
this.emitter.trigger('scrollEnd');
|
|
6181
|
+
this.isScrolling = false;
|
|
6182
|
+
this.isRecentlyScrolled = true;
|
|
6183
|
+
this.isRecentlyWheeled = false;
|
|
6184
|
+
this.scrollWaiter.clear();
|
|
6185
|
+
this.wheelWaiter.clear();
|
|
6186
|
+
}
|
|
6187
|
+
}
|
|
6188
|
+
_handleScrollWaited() {
|
|
6189
|
+
this.isRecentlyScrolled = false;
|
|
6190
|
+
// only end the scroll if not currently touching.
|
|
6191
|
+
// if touching, the scrolling will end later, on touchend.
|
|
6192
|
+
if (!this.isTouching) {
|
|
6193
|
+
this.endScroll(); // won't fire if already ended
|
|
6194
|
+
}
|
|
6195
|
+
}
|
|
6196
|
+
_handleWheelWaited() {
|
|
6197
|
+
this.isRecentlyWheeled = false;
|
|
6198
|
+
}
|
|
6199
|
+
}
|
|
6200
|
+
|
|
6201
|
+
class Scroller extends DateComponent {
|
|
6202
|
+
constructor() {
|
|
6203
|
+
super(...arguments);
|
|
6204
|
+
// ref
|
|
6205
|
+
this.elRef = createRef();
|
|
6206
|
+
}
|
|
6207
|
+
render() {
|
|
6208
|
+
const { props } = this;
|
|
6209
|
+
// if there's only one axis that needs scrolling, the other axis will unintentionally have
|
|
6210
|
+
// scrollbars too, so we must force to 'hidden'
|
|
6211
|
+
const fallbackOverflow = (props.horizontal || props.vertical) ? 'hidden' : '';
|
|
6212
|
+
return (createElement("div", { ref: this.elRef, className: [
|
|
6213
|
+
'fc-scroller',
|
|
6214
|
+
props.hideScrollbars ? 'fc-scroller-nobars' : '',
|
|
6215
|
+
...(props.elClassNames || []),
|
|
6216
|
+
].join(' '), style: Object.assign(Object.assign({}, props.elStyle), { overflowX: props.horizontal ? 'auto' : fallbackOverflow, overflowY: props.vertical ? 'auto' : fallbackOverflow }) }, props.children));
|
|
6217
|
+
}
|
|
6218
|
+
componentDidMount() {
|
|
6219
|
+
const el = this.elRef.current; // TODO: make dynamic with useEffect
|
|
6220
|
+
this.listener = new ScrollListener(el);
|
|
6221
|
+
this.disconnectSize = watchSize(el, (contentWidth, contentHeight) => {
|
|
6222
|
+
const { props, context } = this;
|
|
6223
|
+
const bottomScrollbarWidth = el.offsetHeight - el.clientHeight;
|
|
6224
|
+
const horizontalScrollbarWidth = el.offsetWidth - el.clientWidth;
|
|
6225
|
+
let rightScrollbarWidth = 0;
|
|
6226
|
+
let leftScrollbarWidth = 0;
|
|
6227
|
+
if (context.isRtl && getRtlScrollerConfig().leftScrollbars) {
|
|
6228
|
+
leftScrollbarWidth = horizontalScrollbarWidth;
|
|
6229
|
+
}
|
|
6230
|
+
else {
|
|
6231
|
+
rightScrollbarWidth = horizontalScrollbarWidth;
|
|
6232
|
+
}
|
|
6233
|
+
if (!isDimsEqual(this.currentWidth, contentWidth)) {
|
|
6234
|
+
setRef(props.widthRef, this.currentWidth = contentWidth);
|
|
6235
|
+
}
|
|
6236
|
+
if (!isDimsEqual(this.currentHeight, contentHeight)) {
|
|
6237
|
+
setRef(props.heightRef, this.currentHeight = contentHeight);
|
|
6238
|
+
}
|
|
6239
|
+
if (!isDimsEqual(this.currentBottomScrollbarWidth, bottomScrollbarWidth)) {
|
|
6240
|
+
setRef(props.bottomScrollbarWidthRef, this.currentBottomScrollbarWidth = bottomScrollbarWidth);
|
|
6241
|
+
}
|
|
6242
|
+
if (!isDimsEqual(this.currentRightScrollbarWidth, rightScrollbarWidth)) {
|
|
6243
|
+
setRef(props.rightScrollbarWidthRef, this.currentRightScrollbarWidth = rightScrollbarWidth);
|
|
6244
|
+
}
|
|
6245
|
+
if (!isDimsEqual(this.currentLeftScrollbarWidth, leftScrollbarWidth)) {
|
|
6246
|
+
setRef(props.leftScrollbarWidthRef, this.currentLeftScrollbarWidth = leftScrollbarWidth);
|
|
6247
|
+
}
|
|
6248
|
+
});
|
|
6249
|
+
}
|
|
6250
|
+
componentWillUnmount() {
|
|
6251
|
+
const { props } = this;
|
|
6252
|
+
this.disconnectSize();
|
|
6253
|
+
this.listener.destroy();
|
|
6254
|
+
setRef(props.widthRef, null);
|
|
6255
|
+
setRef(props.heightRef, null);
|
|
6256
|
+
setRef(props.bottomScrollbarWidthRef, null);
|
|
6257
|
+
setRef(props.rightScrollbarWidthRef, null);
|
|
6258
|
+
setRef(props.leftScrollbarWidthRef, null);
|
|
6259
|
+
}
|
|
6260
|
+
endScroll() {
|
|
6261
|
+
this.listener.endScroll();
|
|
6262
|
+
}
|
|
6263
|
+
// Public API
|
|
6264
|
+
// -----------------------------------------------------------------------------------------------
|
|
6265
|
+
get x() {
|
|
6266
|
+
const { isRtl } = this.context;
|
|
6267
|
+
const el = this.elRef.current;
|
|
6268
|
+
return getNormalizedScrollX(el, isRtl);
|
|
6269
|
+
}
|
|
6270
|
+
get y() {
|
|
6271
|
+
const el = this.elRef.current;
|
|
6272
|
+
return el.scrollTop;
|
|
6273
|
+
}
|
|
6274
|
+
scrollTo({ x, y }) {
|
|
6275
|
+
const { isRtl } = this.context;
|
|
6276
|
+
const el = this.elRef.current;
|
|
6277
|
+
if (y != null) {
|
|
6278
|
+
el.scrollTop = y;
|
|
6279
|
+
}
|
|
6280
|
+
if (x != null) {
|
|
6281
|
+
setNormalizedScrollX(el, isRtl, x);
|
|
6282
|
+
}
|
|
6283
|
+
}
|
|
6284
|
+
addScrollEndListener(handler) {
|
|
6285
|
+
this.listener.emitter.on('scrollEnd', handler);
|
|
6286
|
+
}
|
|
6287
|
+
removeScrollEndListener(handler) {
|
|
6288
|
+
this.listener.emitter.off('scrollEnd', handler);
|
|
6289
|
+
}
|
|
6290
|
+
}
|
|
6291
|
+
// Public API
|
|
6292
|
+
// -------------------------------------------------------------------------------------------------
|
|
6293
|
+
// TODO: consolidate with scroll-left-norm.ts
|
|
6294
|
+
function getNormalizedScrollX(el, isRtl) {
|
|
6295
|
+
const { scrollLeft } = el;
|
|
6296
|
+
return isRtl ? getNormalizedRtlScrollX(scrollLeft, el) : scrollLeft;
|
|
6297
|
+
}
|
|
6298
|
+
function setNormalizedScrollX(el, isRtl, x) {
|
|
6299
|
+
el.scrollLeft = isRtl ? getNormalizedRtlScrollLeft(x, el) : x;
|
|
6300
|
+
}
|
|
6301
|
+
/*
|
|
6302
|
+
Returns a value in the 'reverse' system
|
|
6303
|
+
*/
|
|
6304
|
+
function getNormalizedRtlScrollX(scrollLeft, el) {
|
|
6305
|
+
switch (getRtlScrollerConfig().system) {
|
|
6306
|
+
case 'positive':
|
|
6307
|
+
return el.scrollWidth - el.clientWidth - scrollLeft;
|
|
6308
|
+
case 'negative':
|
|
6309
|
+
return -scrollLeft;
|
|
6310
|
+
}
|
|
6311
|
+
return scrollLeft;
|
|
6312
|
+
}
|
|
6313
|
+
/*
|
|
6314
|
+
Receives a value in the 'reverse' system
|
|
6315
|
+
TODO: is this really the same equations as getNormalizedRtlScrollX??? I think so
|
|
6316
|
+
If so, consolidate. With isRtl check too
|
|
6317
|
+
*/
|
|
6318
|
+
function getNormalizedRtlScrollLeft(x, el) {
|
|
6319
|
+
switch (getRtlScrollerConfig().system) {
|
|
6320
|
+
case 'positive':
|
|
6321
|
+
return el.scrollWidth - el.clientWidth - x;
|
|
6322
|
+
case 'negative':
|
|
6323
|
+
return -x;
|
|
6324
|
+
}
|
|
6325
|
+
return x;
|
|
6326
|
+
}
|
|
6327
|
+
let _rtlScrollerConfig;
|
|
6328
|
+
function getRtlScrollerConfig() {
|
|
6329
|
+
return _rtlScrollerConfig || (_rtlScrollerConfig = detectRtlScrollerConfig());
|
|
6330
|
+
}
|
|
6331
|
+
function detectRtlScrollerConfig() {
|
|
6332
|
+
let el = document.createElement('div');
|
|
6333
|
+
el.style.position = 'absolute';
|
|
6334
|
+
el.style.top = '-1000px';
|
|
6335
|
+
el.style.width = '100px'; // must be at least the side of scrollbars or you get inaccurate values (#7335)
|
|
6336
|
+
el.style.height = '100px'; // "
|
|
6337
|
+
el.style.overflow = 'scroll';
|
|
6338
|
+
el.style.direction = 'rtl';
|
|
6339
|
+
let innerEl = document.createElement('div');
|
|
6340
|
+
innerEl.style.width = '200px';
|
|
6341
|
+
innerEl.style.height = '200px';
|
|
6342
|
+
el.appendChild(innerEl);
|
|
6343
|
+
document.body.appendChild(el);
|
|
6344
|
+
let system;
|
|
6345
|
+
if (el.scrollLeft > 0) {
|
|
6346
|
+
system = 'positive'; // scroll is a positive number from the left edge
|
|
6347
|
+
}
|
|
6348
|
+
else {
|
|
6349
|
+
el.scrollLeft = 50;
|
|
6350
|
+
if (el.scrollLeft > 0) {
|
|
6351
|
+
system = 'reverse'; // scroll is a positive number from the right edge
|
|
6352
|
+
}
|
|
6353
|
+
else {
|
|
6354
|
+
system = 'negative'; // scroll is a negative number from the right edge
|
|
6355
|
+
}
|
|
6356
|
+
}
|
|
6357
|
+
let rightScrollbars = innerEl.getBoundingClientRect().right < el.getBoundingClientRect().right;
|
|
6358
|
+
removeElement(el);
|
|
6359
|
+
return { system, leftScrollbars: !rightScrollbars };
|
|
6360
|
+
}
|
|
6361
|
+
|
|
6362
|
+
class Slicer {
|
|
6363
|
+
constructor() {
|
|
6364
|
+
this.sliceBusinessHours = memoize(this._sliceBusinessHours);
|
|
6365
|
+
this.sliceDateSelection = memoize(this._sliceDateSpan);
|
|
6366
|
+
this.sliceEventStore = memoize(this._sliceEventStore);
|
|
6367
|
+
this.sliceEventDrag = memoize(this._sliceInteraction);
|
|
6368
|
+
this.sliceEventResize = memoize(this._sliceInteraction);
|
|
6369
|
+
this.forceDayIfListItem = false; // hack
|
|
6370
|
+
}
|
|
6371
|
+
sliceProps(props, dateProfile, nextDayThreshold, context, ...extraArgs) {
|
|
6372
|
+
let { eventUiBases } = props;
|
|
6373
|
+
let eventSegs = this.sliceEventStore(props.eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs);
|
|
6337
6374
|
return {
|
|
6338
6375
|
dateSelectionSegs: this.sliceDateSelection(props.dateSelection, dateProfile, nextDayThreshold, eventUiBases, context, ...extraArgs),
|
|
6339
6376
|
businessHourSegs: this.sliceBusinessHours(props.businessHours, dateProfile, nextDayThreshold, context, ...extraArgs),
|
|
@@ -6624,423 +6661,124 @@ function anyRangesContainRange(outerRanges, innerRange) {
|
|
|
6624
6661
|
return false;
|
|
6625
6662
|
}
|
|
6626
6663
|
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
};
|
|
6635
|
-
}
|
|
6636
|
-
render() {
|
|
6637
|
-
let { props } = this;
|
|
6638
|
-
let { liquid, liquidIsAbsolute } = props;
|
|
6639
|
-
let isAbsolute = liquid && liquidIsAbsolute;
|
|
6640
|
-
let className = ['fc-scroller'];
|
|
6641
|
-
if (liquid) {
|
|
6642
|
-
if (liquidIsAbsolute) {
|
|
6643
|
-
className.push('fc-scroller-liquid-absolute');
|
|
6644
|
-
}
|
|
6645
|
-
else {
|
|
6646
|
-
className.push('fc-scroller-liquid');
|
|
6647
|
-
}
|
|
6648
|
-
}
|
|
6649
|
-
return (createElement("div", { ref: this.handleEl, className: className.join(' '), style: {
|
|
6650
|
-
overflowX: props.overflowX,
|
|
6651
|
-
overflowY: props.overflowY,
|
|
6652
|
-
left: (isAbsolute && -(props.overcomeLeft || 0)) || '',
|
|
6653
|
-
right: (isAbsolute && -(props.overcomeRight || 0)) || '',
|
|
6654
|
-
bottom: (isAbsolute && -(props.overcomeBottom || 0)) || '',
|
|
6655
|
-
marginLeft: (!isAbsolute && -(props.overcomeLeft || 0)) || '',
|
|
6656
|
-
marginRight: (!isAbsolute && -(props.overcomeRight || 0)) || '',
|
|
6657
|
-
marginBottom: (!isAbsolute && -(props.overcomeBottom || 0)) || '',
|
|
6658
|
-
maxHeight: props.maxHeight || '',
|
|
6659
|
-
} }, props.children));
|
|
6660
|
-
}
|
|
6661
|
-
needsXScrolling() {
|
|
6662
|
-
if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {
|
|
6663
|
-
return false;
|
|
6664
|
-
}
|
|
6665
|
-
// testing scrollWidth>clientWidth is unreliable cross-browser when pixel heights aren't integers.
|
|
6666
|
-
// much more reliable to see if children are taller than the scroller, even tho doesn't account for
|
|
6667
|
-
// inner-child margins and absolute positioning
|
|
6668
|
-
let { el } = this;
|
|
6669
|
-
let realClientWidth = this.el.getBoundingClientRect().width - this.getYScrollbarWidth();
|
|
6670
|
-
let { children } = el;
|
|
6671
|
-
for (let i = 0; i < children.length; i += 1) {
|
|
6672
|
-
let childEl = children[i];
|
|
6673
|
-
if (childEl.getBoundingClientRect().width > realClientWidth) {
|
|
6674
|
-
return true;
|
|
6675
|
-
}
|
|
6676
|
-
}
|
|
6677
|
-
return false;
|
|
6678
|
-
}
|
|
6679
|
-
needsYScrolling() {
|
|
6680
|
-
if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {
|
|
6681
|
-
return false;
|
|
6682
|
-
}
|
|
6683
|
-
// testing scrollHeight>clientHeight is unreliable cross-browser when pixel heights aren't integers.
|
|
6684
|
-
// much more reliable to see if children are taller than the scroller, even tho doesn't account for
|
|
6685
|
-
// inner-child margins and absolute positioning
|
|
6686
|
-
let { el } = this;
|
|
6687
|
-
let realClientHeight = this.el.getBoundingClientRect().height - this.getXScrollbarWidth();
|
|
6688
|
-
let { children } = el;
|
|
6689
|
-
for (let i = 0; i < children.length; i += 1) {
|
|
6690
|
-
let childEl = children[i];
|
|
6691
|
-
if (childEl.getBoundingClientRect().height > realClientHeight) {
|
|
6692
|
-
return true;
|
|
6693
|
-
}
|
|
6694
|
-
}
|
|
6695
|
-
return false;
|
|
6664
|
+
function getIsHeightAuto(options) {
|
|
6665
|
+
return options.height === 'auto' || options.viewHeight === 'auto';
|
|
6666
|
+
}
|
|
6667
|
+
function getStickyHeaderDates(options) {
|
|
6668
|
+
let { stickyHeaderDates } = options;
|
|
6669
|
+
if (stickyHeaderDates == null || stickyHeaderDates === 'auto') {
|
|
6670
|
+
stickyHeaderDates = getIsHeightAuto(options);
|
|
6696
6671
|
}
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6672
|
+
return stickyHeaderDates;
|
|
6673
|
+
}
|
|
6674
|
+
function getStickyFooterScrollbar(options) {
|
|
6675
|
+
let { stickyFooterScrollbar } = options;
|
|
6676
|
+
if (stickyFooterScrollbar == null || stickyFooterScrollbar === 'auto') {
|
|
6677
|
+
stickyFooterScrollbar = getIsHeightAuto(options);
|
|
6702
6678
|
}
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6679
|
+
return stickyFooterScrollbar;
|
|
6680
|
+
}
|
|
6681
|
+
function getScrollerSyncerClass(pluginHooks) {
|
|
6682
|
+
const ScrollerSyncer = pluginHooks.scrollerSyncerClass;
|
|
6683
|
+
if (!ScrollerSyncer) {
|
|
6684
|
+
throw new RangeError('Must import @fullcalendar/scrollgrid');
|
|
6708
6685
|
}
|
|
6686
|
+
return ScrollerSyncer;
|
|
6709
6687
|
}
|
|
6710
6688
|
|
|
6711
6689
|
/*
|
|
6712
|
-
TODO:
|
|
6713
|
-
TODO: infer RefType from masterCallback if provided
|
|
6690
|
+
TODO: make API where createRefMap() called
|
|
6714
6691
|
*/
|
|
6715
6692
|
class RefMap {
|
|
6716
6693
|
constructor(masterCallback) {
|
|
6717
6694
|
this.masterCallback = masterCallback;
|
|
6718
|
-
this.
|
|
6719
|
-
this.
|
|
6720
|
-
this.
|
|
6695
|
+
this.rev = '';
|
|
6696
|
+
this.current = new Map();
|
|
6697
|
+
this.callbacks = new Map;
|
|
6721
6698
|
this.handleValue = (val, key) => {
|
|
6722
|
-
let {
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
// for bug... ACTUALLY: can probably do away with this now that callers don't share numeric indices anymore
|
|
6727
|
-
removed = (key in currentMap);
|
|
6728
|
-
currentMap[key] = val;
|
|
6729
|
-
depths[key] = (depths[key] || 0) + 1;
|
|
6730
|
-
added = true;
|
|
6699
|
+
let { current, callbacks } = this;
|
|
6700
|
+
if (val === null) {
|
|
6701
|
+
current.delete(key);
|
|
6702
|
+
callbacks.delete(key);
|
|
6731
6703
|
}
|
|
6732
6704
|
else {
|
|
6733
|
-
|
|
6734
|
-
if (!depths[key]) {
|
|
6735
|
-
delete currentMap[key];
|
|
6736
|
-
delete this.callbackMap[key];
|
|
6737
|
-
removed = true;
|
|
6738
|
-
}
|
|
6705
|
+
current.set(key, val);
|
|
6739
6706
|
}
|
|
6707
|
+
this.rev = guid();
|
|
6740
6708
|
if (this.masterCallback) {
|
|
6741
|
-
|
|
6742
|
-
this.masterCallback(null, String(key));
|
|
6743
|
-
}
|
|
6744
|
-
if (added) {
|
|
6745
|
-
this.masterCallback(val, String(key));
|
|
6746
|
-
}
|
|
6709
|
+
this.masterCallback(val, key);
|
|
6747
6710
|
}
|
|
6748
6711
|
};
|
|
6749
6712
|
}
|
|
6750
6713
|
createRef(key) {
|
|
6751
|
-
let refCallback = this.
|
|
6714
|
+
let refCallback = this.callbacks.get(key);
|
|
6752
6715
|
if (!refCallback) {
|
|
6753
|
-
refCallback =
|
|
6754
|
-
this.handleValue(val,
|
|
6716
|
+
refCallback = (val) => {
|
|
6717
|
+
this.handleValue(val, key);
|
|
6755
6718
|
};
|
|
6719
|
+
this.callbacks.set(key, refCallback);
|
|
6756
6720
|
}
|
|
6757
6721
|
return refCallback;
|
|
6758
6722
|
}
|
|
6759
|
-
// TODO: check callers that don't care about order. should use getAll instead
|
|
6760
|
-
// NOTE: this method has become less valuable now that we are encouraged to map order by some other index
|
|
6761
|
-
// TODO: provide ONE array-export function, buildArray, which fails on non-numeric indexes. caller can manipulate and "collect"
|
|
6762
|
-
collect(startIndex, endIndex, step) {
|
|
6763
|
-
return collectFromHash(this.currentMap, startIndex, endIndex, step);
|
|
6764
|
-
}
|
|
6765
|
-
getAll() {
|
|
6766
|
-
return hashValuesToArray(this.currentMap);
|
|
6767
|
-
}
|
|
6768
6723
|
}
|
|
6769
6724
|
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
return Math.ceil(largestWidth); // <table> elements work best with integers. round up to ensure contents fits
|
|
6777
|
-
}
|
|
6778
|
-
function getSectionHasLiquidHeight(props, sectionConfig) {
|
|
6779
|
-
return props.liquid && sectionConfig.liquid; // does the section do liquid-height? (need to have whole scrollgrid liquid-height as well)
|
|
6780
|
-
}
|
|
6781
|
-
function getAllowYScrolling(props, sectionConfig) {
|
|
6782
|
-
return sectionConfig.maxHeight != null || // if its possible for the height to max out, we might need scrollbars
|
|
6783
|
-
getSectionHasLiquidHeight(props, sectionConfig); // if the section is liquid height, it might condense enough to require scrollbars
|
|
6784
|
-
}
|
|
6785
|
-
// TODO: ONLY use `arg`. force out internal function to use same API
|
|
6786
|
-
function renderChunkContent(sectionConfig, chunkConfig, arg, isHeader) {
|
|
6787
|
-
let { expandRows } = arg;
|
|
6788
|
-
let content = typeof chunkConfig.content === 'function' ?
|
|
6789
|
-
chunkConfig.content(arg) :
|
|
6790
|
-
createElement('table', {
|
|
6791
|
-
role: 'presentation',
|
|
6792
|
-
className: [
|
|
6793
|
-
chunkConfig.tableClassName,
|
|
6794
|
-
sectionConfig.syncRowHeights ? 'fc-scrollgrid-sync-table' : '',
|
|
6795
|
-
].join(' '),
|
|
6796
|
-
style: {
|
|
6797
|
-
minWidth: arg.tableMinWidth,
|
|
6798
|
-
width: arg.clientWidth,
|
|
6799
|
-
height: expandRows ? arg.clientHeight : '', // css `height` on a <table> serves as a min-height
|
|
6800
|
-
},
|
|
6801
|
-
}, arg.tableColGroupNode, createElement(isHeader ? 'thead' : 'tbody', {
|
|
6802
|
-
role: 'presentation',
|
|
6803
|
-
}, typeof chunkConfig.rowContent === 'function'
|
|
6804
|
-
? chunkConfig.rowContent(arg)
|
|
6805
|
-
: chunkConfig.rowContent));
|
|
6806
|
-
return content;
|
|
6807
|
-
}
|
|
6808
|
-
function isColPropsEqual(cols0, cols1) {
|
|
6809
|
-
return isArraysEqual(cols0, cols1, isPropsEqual);
|
|
6810
|
-
}
|
|
6811
|
-
function renderMicroColGroup(cols, shrinkWidth) {
|
|
6812
|
-
let colNodes = [];
|
|
6813
|
-
/*
|
|
6814
|
-
for ColProps with spans, it would have been great to make a single <col span="">
|
|
6815
|
-
HOWEVER, Chrome was getting messing up distributing the width to <td>/<th> elements with colspans.
|
|
6816
|
-
SOLUTION: making individual <col> elements makes Chrome behave.
|
|
6817
|
-
*/
|
|
6818
|
-
for (let colProps of cols) {
|
|
6819
|
-
let span = colProps.span || 1;
|
|
6820
|
-
for (let i = 0; i < span; i += 1) {
|
|
6821
|
-
colNodes.push(createElement("col", { style: {
|
|
6822
|
-
width: colProps.width === 'shrink' ? sanitizeShrinkWidth(shrinkWidth) : (colProps.width || ''),
|
|
6823
|
-
minWidth: colProps.minWidth || '',
|
|
6824
|
-
} }));
|
|
6825
|
-
}
|
|
6826
|
-
}
|
|
6827
|
-
return createElement('colgroup', {}, ...colNodes);
|
|
6828
|
-
}
|
|
6829
|
-
function sanitizeShrinkWidth(shrinkWidth) {
|
|
6830
|
-
/* why 4? if we do 0, it will kill any border, which are needed for computeSmallestCellWidth
|
|
6831
|
-
4 accounts for 2 2-pixel borders. TODO: better solution? */
|
|
6832
|
-
return shrinkWidth == null ? 4 : shrinkWidth;
|
|
6833
|
-
}
|
|
6834
|
-
function hasShrinkWidth(cols) {
|
|
6835
|
-
for (let col of cols) {
|
|
6836
|
-
if (col.width === 'shrink') {
|
|
6837
|
-
return true;
|
|
6838
|
-
}
|
|
6839
|
-
}
|
|
6840
|
-
return false;
|
|
6841
|
-
}
|
|
6842
|
-
function getScrollGridClassNames(liquid, context) {
|
|
6843
|
-
let classNames = [
|
|
6844
|
-
'fc-scrollgrid',
|
|
6845
|
-
context.theme.getClass('table'),
|
|
6846
|
-
];
|
|
6847
|
-
if (liquid) {
|
|
6848
|
-
classNames.push('fc-scrollgrid-liquid');
|
|
6725
|
+
class NowTimer extends Component {
|
|
6726
|
+
constructor(props, context) {
|
|
6727
|
+
super(props, context);
|
|
6728
|
+
this.initialNowDate = getNow(context.options.now, context.dateEnv);
|
|
6729
|
+
this.initialNowQueriedMs = new Date().valueOf();
|
|
6730
|
+
this.state = this.computeTiming().currentState;
|
|
6849
6731
|
}
|
|
6850
|
-
|
|
6851
|
-
}
|
|
6852
|
-
|
|
6853
|
-
let classNames = [
|
|
6854
|
-
'fc-scrollgrid-section',
|
|
6855
|
-
`fc-scrollgrid-section-${sectionConfig.type}`,
|
|
6856
|
-
sectionConfig.className, // used?
|
|
6857
|
-
];
|
|
6858
|
-
if (wholeTableVGrow && sectionConfig.liquid && sectionConfig.maxHeight == null) {
|
|
6859
|
-
classNames.push('fc-scrollgrid-section-liquid');
|
|
6732
|
+
render() {
|
|
6733
|
+
let { props, state } = this;
|
|
6734
|
+
return props.children(state.nowDate, state.todayRange);
|
|
6860
6735
|
}
|
|
6861
|
-
|
|
6862
|
-
|
|
6736
|
+
componentDidMount() {
|
|
6737
|
+
this.setTimeout();
|
|
6863
6738
|
}
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
minWidth: arg.tableMinWidth,
|
|
6870
|
-
} }));
|
|
6871
|
-
}
|
|
6872
|
-
function getStickyHeaderDates(options) {
|
|
6873
|
-
let { stickyHeaderDates } = options;
|
|
6874
|
-
if (stickyHeaderDates == null || stickyHeaderDates === 'auto') {
|
|
6875
|
-
stickyHeaderDates = options.height === 'auto' || options.viewHeight === 'auto';
|
|
6739
|
+
componentDidUpdate(prevProps) {
|
|
6740
|
+
if (prevProps.unit !== this.props.unit) {
|
|
6741
|
+
this.clearTimeout();
|
|
6742
|
+
this.setTimeout();
|
|
6743
|
+
}
|
|
6876
6744
|
}
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
function getStickyFooterScrollbar(options) {
|
|
6880
|
-
let { stickyFooterScrollbar } = options;
|
|
6881
|
-
if (stickyFooterScrollbar == null || stickyFooterScrollbar === 'auto') {
|
|
6882
|
-
stickyFooterScrollbar = options.height === 'auto' || options.viewHeight === 'auto';
|
|
6745
|
+
componentWillUnmount() {
|
|
6746
|
+
this.clearTimeout();
|
|
6883
6747
|
}
|
|
6884
|
-
|
|
6885
|
-
}
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
//
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
forceYScrollbars: false,
|
|
6898
|
-
scrollerClientWidths: {},
|
|
6899
|
-
scrollerClientHeights: {},
|
|
6900
|
-
};
|
|
6901
|
-
// TODO: can do a really simple print-view. dont need to join rows
|
|
6902
|
-
this.handleSizing = () => {
|
|
6903
|
-
this.safeSetState(Object.assign({ shrinkWidth: this.computeShrinkWidth() }, this.computeScrollerDims()));
|
|
6748
|
+
computeTiming() {
|
|
6749
|
+
let { props, context } = this;
|
|
6750
|
+
let unroundedNow = addMs(this.initialNowDate, new Date().valueOf() - this.initialNowQueriedMs);
|
|
6751
|
+
let currentUnitStart = context.dateEnv.startOf(unroundedNow, props.unit);
|
|
6752
|
+
let nextUnitStart = context.dateEnv.add(currentUnitStart, createDuration(1, props.unit));
|
|
6753
|
+
let waitMs = nextUnitStart.valueOf() - unroundedNow.valueOf();
|
|
6754
|
+
// there is a max setTimeout ms value (https://stackoverflow.com/a/3468650/96342)
|
|
6755
|
+
// ensure no longer than a day
|
|
6756
|
+
waitMs = Math.min(1000 * 60 * 60 * 24, waitMs);
|
|
6757
|
+
return {
|
|
6758
|
+
currentState: { nowDate: currentUnitStart, todayRange: buildDayRange(currentUnitStart) },
|
|
6759
|
+
nextState: { nowDate: nextUnitStart, todayRange: buildDayRange(nextUnitStart) },
|
|
6760
|
+
waitMs,
|
|
6904
6761
|
};
|
|
6905
6762
|
}
|
|
6906
|
-
|
|
6907
|
-
let {
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
classNames.push('fc-scrollgrid-collapsible');
|
|
6914
|
-
}
|
|
6915
|
-
// TODO: make DRY
|
|
6916
|
-
let configCnt = sectionConfigs.length;
|
|
6917
|
-
let configI = 0;
|
|
6918
|
-
let currentConfig;
|
|
6919
|
-
let headSectionNodes = [];
|
|
6920
|
-
let bodySectionNodes = [];
|
|
6921
|
-
let footSectionNodes = [];
|
|
6922
|
-
while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'header') {
|
|
6923
|
-
headSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));
|
|
6924
|
-
configI += 1;
|
|
6925
|
-
}
|
|
6926
|
-
while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'body') {
|
|
6927
|
-
bodySectionNodes.push(this.renderSection(currentConfig, microColGroupNode, false));
|
|
6928
|
-
configI += 1;
|
|
6929
|
-
}
|
|
6930
|
-
while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'footer') {
|
|
6931
|
-
footSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));
|
|
6932
|
-
configI += 1;
|
|
6933
|
-
}
|
|
6934
|
-
// firefox bug: when setting height on table and there is a thead or tfoot,
|
|
6935
|
-
// the necessary height:100% on the liquid-height body section forces the *whole* table to be taller. (bug #5524)
|
|
6936
|
-
// use getCanVGrowWithinCell as a way to detect table-stupid firefox.
|
|
6937
|
-
// if so, use a simpler dom structure, jam everything into a lone tbody.
|
|
6938
|
-
let isBuggy = !getCanVGrowWithinCell();
|
|
6939
|
-
const roleAttrs = { role: 'rowgroup' };
|
|
6940
|
-
return createElement('table', {
|
|
6941
|
-
role: 'grid',
|
|
6942
|
-
className: classNames.join(' '),
|
|
6943
|
-
style: { height: props.height },
|
|
6944
|
-
}, Boolean(!isBuggy && headSectionNodes.length) && createElement('thead', roleAttrs, ...headSectionNodes), Boolean(!isBuggy && bodySectionNodes.length) && createElement('tbody', roleAttrs, ...bodySectionNodes), Boolean(!isBuggy && footSectionNodes.length) && createElement('tfoot', roleAttrs, ...footSectionNodes), isBuggy && createElement('tbody', roleAttrs, ...headSectionNodes, ...bodySectionNodes, ...footSectionNodes));
|
|
6945
|
-
}
|
|
6946
|
-
renderSection(sectionConfig, microColGroupNode, isHeader) {
|
|
6947
|
-
if ('outerContent' in sectionConfig) {
|
|
6948
|
-
return (createElement(Fragment, { key: sectionConfig.key }, sectionConfig.outerContent));
|
|
6949
|
-
}
|
|
6950
|
-
return (createElement("tr", { key: sectionConfig.key, role: "presentation", className: getSectionClassNames(sectionConfig, this.props.liquid).join(' ') }, this.renderChunkTd(sectionConfig, microColGroupNode, sectionConfig.chunk, isHeader)));
|
|
6951
|
-
}
|
|
6952
|
-
renderChunkTd(sectionConfig, microColGroupNode, chunkConfig, isHeader) {
|
|
6953
|
-
if ('outerContent' in chunkConfig) {
|
|
6954
|
-
return chunkConfig.outerContent;
|
|
6955
|
-
}
|
|
6956
|
-
let { props } = this;
|
|
6957
|
-
let { forceYScrollbars, scrollerClientWidths, scrollerClientHeights } = this.state;
|
|
6958
|
-
let needsYScrolling = getAllowYScrolling(props, sectionConfig); // TODO: do lazily. do in section config?
|
|
6959
|
-
let isLiquid = getSectionHasLiquidHeight(props, sectionConfig);
|
|
6960
|
-
// for `!props.liquid` - is WHOLE scrollgrid natural height?
|
|
6961
|
-
// TODO: do same thing in advanced scrollgrid? prolly not b/c always has horizontal scrollbars
|
|
6962
|
-
let overflowY = !props.liquid ? 'visible' :
|
|
6963
|
-
forceYScrollbars ? 'scroll' :
|
|
6964
|
-
!needsYScrolling ? 'hidden' :
|
|
6965
|
-
'auto';
|
|
6966
|
-
let sectionKey = sectionConfig.key;
|
|
6967
|
-
let content = renderChunkContent(sectionConfig, chunkConfig, {
|
|
6968
|
-
tableColGroupNode: microColGroupNode,
|
|
6969
|
-
tableMinWidth: '',
|
|
6970
|
-
clientWidth: (!props.collapsibleWidth && scrollerClientWidths[sectionKey] !== undefined) ? scrollerClientWidths[sectionKey] : null,
|
|
6971
|
-
clientHeight: scrollerClientHeights[sectionKey] !== undefined ? scrollerClientHeights[sectionKey] : null,
|
|
6972
|
-
expandRows: sectionConfig.expandRows,
|
|
6973
|
-
syncRowHeights: false,
|
|
6974
|
-
rowSyncHeights: [],
|
|
6975
|
-
reportRowHeightChange: () => { },
|
|
6976
|
-
}, isHeader);
|
|
6977
|
-
return createElement(isHeader ? 'th' : 'td', {
|
|
6978
|
-
ref: chunkConfig.elRef,
|
|
6979
|
-
role: 'presentation',
|
|
6980
|
-
}, createElement("div", { className: `fc-scroller-harness${isLiquid ? ' fc-scroller-harness-liquid' : ''}` },
|
|
6981
|
-
createElement(Scroller, { ref: this.scrollerRefs.createRef(sectionKey), elRef: this.scrollerElRefs.createRef(sectionKey), overflowY: overflowY, overflowX: !props.liquid ? 'visible' : 'hidden' /* natural height? */, maxHeight: sectionConfig.maxHeight, liquid: isLiquid, liquidIsAbsolute // because its within a harness
|
|
6982
|
-
: true }, content)));
|
|
6983
|
-
}
|
|
6984
|
-
_handleScrollerEl(scrollerEl, key) {
|
|
6985
|
-
let section = getSectionByKey(this.props.sections, key);
|
|
6986
|
-
if (section) {
|
|
6987
|
-
setRef(section.chunk.scrollerElRef, scrollerEl);
|
|
6988
|
-
}
|
|
6989
|
-
}
|
|
6990
|
-
componentDidMount() {
|
|
6991
|
-
this.handleSizing();
|
|
6992
|
-
this.context.addResizeHandler(this.handleSizing);
|
|
6993
|
-
}
|
|
6994
|
-
componentDidUpdate() {
|
|
6995
|
-
// TODO: need better solution when state contains non-sizing things
|
|
6996
|
-
this.handleSizing();
|
|
6763
|
+
setTimeout() {
|
|
6764
|
+
let { nextState, waitMs } = this.computeTiming();
|
|
6765
|
+
this.timeoutId = setTimeout(() => {
|
|
6766
|
+
this.setState(nextState, () => {
|
|
6767
|
+
this.setTimeout();
|
|
6768
|
+
});
|
|
6769
|
+
}, waitMs);
|
|
6997
6770
|
}
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
computeShrinkWidth() {
|
|
7002
|
-
return hasShrinkWidth(this.props.cols)
|
|
7003
|
-
? computeShrinkWidth(this.scrollerElRefs.getAll())
|
|
7004
|
-
: 0;
|
|
7005
|
-
}
|
|
7006
|
-
computeScrollerDims() {
|
|
7007
|
-
let scrollbarWidth = getScrollbarWidths();
|
|
7008
|
-
let { scrollerRefs, scrollerElRefs } = this;
|
|
7009
|
-
let forceYScrollbars = false;
|
|
7010
|
-
let scrollerClientWidths = {};
|
|
7011
|
-
let scrollerClientHeights = {};
|
|
7012
|
-
for (let sectionKey in scrollerRefs.currentMap) {
|
|
7013
|
-
let scroller = scrollerRefs.currentMap[sectionKey];
|
|
7014
|
-
if (scroller && scroller.needsYScrolling()) {
|
|
7015
|
-
forceYScrollbars = true;
|
|
7016
|
-
break;
|
|
7017
|
-
}
|
|
7018
|
-
}
|
|
7019
|
-
for (let section of this.props.sections) {
|
|
7020
|
-
let sectionKey = section.key;
|
|
7021
|
-
let scrollerEl = scrollerElRefs.currentMap[sectionKey];
|
|
7022
|
-
if (scrollerEl) {
|
|
7023
|
-
let harnessEl = scrollerEl.parentNode; // TODO: weird way to get this. need harness b/c doesn't include table borders
|
|
7024
|
-
scrollerClientWidths[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().width - (forceYScrollbars
|
|
7025
|
-
? scrollbarWidth.y // use global because scroller might not have scrollbars yet but will need them in future
|
|
7026
|
-
: 0));
|
|
7027
|
-
scrollerClientHeights[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().height);
|
|
7028
|
-
}
|
|
6771
|
+
clearTimeout() {
|
|
6772
|
+
if (this.timeoutId) {
|
|
6773
|
+
clearTimeout(this.timeoutId);
|
|
7029
6774
|
}
|
|
7030
|
-
return { forceYScrollbars, scrollerClientWidths, scrollerClientHeights };
|
|
7031
6775
|
}
|
|
7032
6776
|
}
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
for (let section of sections) {
|
|
7039
|
-
if (section.key === key) {
|
|
7040
|
-
return section;
|
|
7041
|
-
}
|
|
7042
|
-
}
|
|
7043
|
-
return null;
|
|
6777
|
+
NowTimer.contextType = ViewContextType;
|
|
6778
|
+
function buildDayRange(date) {
|
|
6779
|
+
let start = startOfDay(date);
|
|
6780
|
+
let end = addDays(start, 1);
|
|
6781
|
+
return { start, end };
|
|
7044
6782
|
}
|
|
7045
6783
|
|
|
7046
6784
|
class EventContainer extends BaseComponent {
|
|
@@ -7049,15 +6787,14 @@ class EventContainer extends BaseComponent {
|
|
|
7049
6787
|
this.handleEl = (el) => {
|
|
7050
6788
|
this.el = el;
|
|
7051
6789
|
if (el) {
|
|
7052
|
-
|
|
6790
|
+
setElEventRange(el, this.props.eventRange);
|
|
7053
6791
|
}
|
|
7054
6792
|
};
|
|
7055
6793
|
}
|
|
7056
6794
|
render() {
|
|
7057
6795
|
const { props, context } = this;
|
|
7058
6796
|
const { options } = context;
|
|
7059
|
-
const {
|
|
7060
|
-
const { eventRange } = seg;
|
|
6797
|
+
const { eventRange } = props;
|
|
7061
6798
|
const { ui } = eventRange;
|
|
7062
6799
|
const renderProps = {
|
|
7063
6800
|
event: new EventImpl(context, eventRange.def, eventRange.instance),
|
|
@@ -7066,12 +6803,12 @@ class EventContainer extends BaseComponent {
|
|
|
7066
6803
|
textColor: ui.textColor,
|
|
7067
6804
|
backgroundColor: ui.backgroundColor,
|
|
7068
6805
|
borderColor: ui.borderColor,
|
|
7069
|
-
isDraggable: !props.disableDragging &&
|
|
7070
|
-
isStartResizable: !props.disableResizing &&
|
|
7071
|
-
isEndResizable: !props.disableResizing &&
|
|
6806
|
+
isDraggable: !props.disableDragging && computeEventRangeDraggable(eventRange, context),
|
|
6807
|
+
isStartResizable: !props.disableResizing && props.isStart && eventRange.ui.durationEditable && options.eventResizableFromStart,
|
|
6808
|
+
isEndResizable: !props.disableResizing && props.isEnd && eventRange.ui.durationEditable,
|
|
7072
6809
|
isMirror: Boolean(props.isDragging || props.isResizing || props.isDateSelecting),
|
|
7073
|
-
isStart: Boolean(
|
|
7074
|
-
isEnd: Boolean(
|
|
6810
|
+
isStart: Boolean(props.isStart),
|
|
6811
|
+
isEnd: Boolean(props.isEnd),
|
|
7075
6812
|
isPast: Boolean(props.isPast),
|
|
7076
6813
|
isFuture: Boolean(props.isFuture),
|
|
7077
6814
|
isToday: Boolean(props.isToday),
|
|
@@ -7081,13 +6818,13 @@ class EventContainer extends BaseComponent {
|
|
|
7081
6818
|
};
|
|
7082
6819
|
return (createElement(ContentContainer, Object.assign({}, props /* contains children */, { elRef: this.handleEl, elClasses: [
|
|
7083
6820
|
...getEventClassNames(renderProps),
|
|
7084
|
-
...
|
|
6821
|
+
...eventRange.ui.classNames,
|
|
7085
6822
|
...(props.elClasses || []),
|
|
7086
6823
|
], renderProps: renderProps, generatorName: "eventContent", customGenerator: options.eventContent, defaultGenerator: props.defaultGenerator, classNameGenerator: options.eventClassNames, didMount: options.eventDidMount, willUnmount: options.eventWillUnmount })));
|
|
7087
6824
|
}
|
|
7088
6825
|
componentDidUpdate(prevProps) {
|
|
7089
|
-
if (this.el && this.props.
|
|
7090
|
-
|
|
6826
|
+
if (this.el && this.props.eventRange !== prevProps.eventRange) {
|
|
6827
|
+
setElEventRange(this.el, this.props.eventRange);
|
|
7091
6828
|
}
|
|
7092
6829
|
}
|
|
7093
6830
|
}
|
|
@@ -7097,24 +6834,24 @@ class StandardEvent extends BaseComponent {
|
|
|
7097
6834
|
render() {
|
|
7098
6835
|
let { props, context } = this;
|
|
7099
6836
|
let { options } = context;
|
|
7100
|
-
let {
|
|
7101
|
-
let { ui } =
|
|
6837
|
+
let { eventRange } = props;
|
|
6838
|
+
let { ui } = eventRange;
|
|
7102
6839
|
let timeFormat = options.eventTimeFormat || props.defaultTimeFormat;
|
|
7103
|
-
let timeText =
|
|
6840
|
+
let timeText = buildEventRangeTimeText(eventRange, timeFormat, context, props.defaultDisplayEventTime, props.defaultDisplayEventEnd, props.startOverride, props.endOverride);
|
|
7104
6841
|
return (createElement(EventContainer, Object.assign({}, props /* includes elRef */, { elTag: "a", elStyle: {
|
|
7105
6842
|
borderColor: ui.borderColor,
|
|
7106
6843
|
backgroundColor: ui.backgroundColor,
|
|
7107
|
-
}, elAttrs:
|
|
7108
|
-
createElement(InnerContent, { elTag: "div", elClasses: ['fc-event-
|
|
6844
|
+
}, elAttrs: getEventRangeAnchorAttrs(eventRange, context), defaultGenerator: renderInnerContent$1, timeText: timeText }), (InnerContent, eventContentArg) => (createElement(Fragment, null,
|
|
6845
|
+
createElement(InnerContent, { elTag: "div", elClasses: ['fc-event-inner'], elStyle: { color: eventContentArg.textColor } }),
|
|
7109
6846
|
Boolean(eventContentArg.isStartResizable) && (createElement("div", { className: "fc-event-resizer fc-event-resizer-start" })),
|
|
7110
6847
|
Boolean(eventContentArg.isEndResizable) && (createElement("div", { className: "fc-event-resizer fc-event-resizer-end" }))))));
|
|
7111
6848
|
}
|
|
7112
6849
|
}
|
|
7113
6850
|
function renderInnerContent$1(innerProps) {
|
|
7114
|
-
return (createElement(
|
|
6851
|
+
return (createElement(Fragment, null,
|
|
7115
6852
|
innerProps.timeText && (createElement("div", { className: "fc-event-time" }, innerProps.timeText)),
|
|
7116
|
-
createElement("div", { className: "fc-event-title-
|
|
7117
|
-
createElement("div", { className: "fc-event-title
|
|
6853
|
+
createElement("div", { className: "fc-event-title-outer" },
|
|
6854
|
+
createElement("div", { className: "fc-event-title" }, innerProps.event.title || createElement(Fragment, null, "\u00A0")))));
|
|
7118
6855
|
}
|
|
7119
6856
|
|
|
7120
6857
|
const NowIndicatorContainer = (props) => (createElement(ViewContextType.Consumer, null, (context) => {
|
|
@@ -7127,50 +6864,11 @@ const NowIndicatorContainer = (props) => (createElement(ViewContextType.Consumer
|
|
|
7127
6864
|
return (createElement(ContentContainer, Object.assign({}, props /* includes children */, { elTag: props.elTag || 'div', renderProps: renderProps, generatorName: "nowIndicatorContent", customGenerator: options.nowIndicatorContent, classNameGenerator: options.nowIndicatorClassNames, didMount: options.nowIndicatorDidMount, willUnmount: options.nowIndicatorWillUnmount })));
|
|
7128
6865
|
}));
|
|
7129
6866
|
|
|
7130
|
-
|
|
7131
|
-
class DayCellContainer extends BaseComponent {
|
|
7132
|
-
constructor() {
|
|
7133
|
-
super(...arguments);
|
|
7134
|
-
this.refineRenderProps = memoizeObjArg(refineRenderProps);
|
|
7135
|
-
}
|
|
7136
|
-
render() {
|
|
7137
|
-
let { props, context } = this;
|
|
7138
|
-
let { options } = context;
|
|
7139
|
-
let renderProps = this.refineRenderProps({
|
|
7140
|
-
date: props.date,
|
|
7141
|
-
dateProfile: props.dateProfile,
|
|
7142
|
-
todayRange: props.todayRange,
|
|
7143
|
-
isMonthStart: props.isMonthStart || false,
|
|
7144
|
-
showDayNumber: props.showDayNumber,
|
|
7145
|
-
extraRenderProps: props.extraRenderProps,
|
|
7146
|
-
viewApi: context.viewApi,
|
|
7147
|
-
dateEnv: context.dateEnv,
|
|
7148
|
-
monthStartFormat: options.monthStartFormat,
|
|
7149
|
-
});
|
|
7150
|
-
return (createElement(ContentContainer, Object.assign({}, props /* includes children */, { elClasses: [
|
|
7151
|
-
...getDayClassNames(renderProps, context.theme),
|
|
7152
|
-
...(props.elClasses || []),
|
|
7153
|
-
], elAttrs: Object.assign(Object.assign({}, props.elAttrs), (renderProps.isDisabled ? {} : { 'data-date': formatDayString(props.date) })), renderProps: renderProps, generatorName: "dayCellContent", customGenerator: options.dayCellContent, defaultGenerator: props.defaultGenerator, classNameGenerator:
|
|
7154
|
-
// don't use custom classNames if disabled
|
|
7155
|
-
renderProps.isDisabled ? undefined : options.dayCellClassNames, didMount: options.dayCellDidMount, willUnmount: options.dayCellWillUnmount })));
|
|
7156
|
-
}
|
|
7157
|
-
}
|
|
7158
|
-
function hasCustomDayCellContent(options) {
|
|
7159
|
-
return Boolean(options.dayCellContent || hasCustomRenderingHandler('dayCellContent', options));
|
|
7160
|
-
}
|
|
7161
|
-
function refineRenderProps(raw) {
|
|
7162
|
-
let { date, dateEnv, dateProfile, isMonthStart } = raw;
|
|
7163
|
-
let dayMeta = getDateMeta(date, raw.todayRange, null, dateProfile);
|
|
7164
|
-
let dayNumberText = raw.showDayNumber ? (dateEnv.format(date, isMonthStart ? raw.monthStartFormat : DAY_NUM_FORMAT)) : '';
|
|
7165
|
-
return Object.assign(Object.assign(Object.assign({ date: dateEnv.toDate(date), view: raw.viewApi }, dayMeta), { isMonthStart,
|
|
7166
|
-
dayNumberText }), raw.extraRenderProps);
|
|
7167
|
-
}
|
|
7168
|
-
|
|
7169
|
-
class BgEvent extends BaseComponent {
|
|
6867
|
+
class BgEvent extends BaseComponent {
|
|
7170
6868
|
render() {
|
|
7171
6869
|
let { props } = this;
|
|
7172
|
-
let {
|
|
7173
|
-
return (createElement(EventContainer, { elTag: "div", elClasses: ['fc-bg-event'], elStyle: { backgroundColor:
|
|
6870
|
+
let { eventRange } = props;
|
|
6871
|
+
return (createElement(EventContainer, { elTag: "div", elClasses: ['fc-bg-event'], elStyle: { backgroundColor: eventRange.ui.backgroundColor }, defaultGenerator: renderInnerContent, eventRange: eventRange, isStart: props.isStart, isEnd: props.isEnd, timeText: "", isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false, isPast: props.isPast, isFuture: props.isFuture, isToday: props.isToday, disableDragging: true, disableResizing: true }));
|
|
7174
6872
|
}
|
|
7175
6873
|
}
|
|
7176
6874
|
function renderInnerContent(props) {
|
|
@@ -7195,250 +6893,384 @@ function renderInner(innerProps) {
|
|
|
7195
6893
|
return innerProps.text;
|
|
7196
6894
|
}
|
|
7197
6895
|
|
|
7198
|
-
|
|
7199
|
-
|
|
7200
|
-
|
|
7201
|
-
|
|
7202
|
-
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
|
|
7213
|
-
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
|
|
6896
|
+
/*
|
|
6897
|
+
Calendar instance for ALL frameworks
|
|
6898
|
+
*/
|
|
6899
|
+
class CalendarImpl {
|
|
6900
|
+
getCurrentData() {
|
|
6901
|
+
return this.currentDataManager.getCurrentData();
|
|
6902
|
+
}
|
|
6903
|
+
dispatch(action) {
|
|
6904
|
+
this.currentDataManager.dispatch(action);
|
|
6905
|
+
}
|
|
6906
|
+
get view() { return this.getCurrentData().viewApi; }
|
|
6907
|
+
batchRendering(callback) {
|
|
6908
|
+
callback();
|
|
6909
|
+
}
|
|
6910
|
+
updateSize() {
|
|
6911
|
+
console.warn('Doesnt do anything!');
|
|
6912
|
+
}
|
|
6913
|
+
// Options
|
|
6914
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
6915
|
+
setOption(name, val) {
|
|
6916
|
+
this.dispatch({
|
|
6917
|
+
type: 'SET_OPTION',
|
|
6918
|
+
optionName: name,
|
|
6919
|
+
rawOptionValue: val,
|
|
6920
|
+
});
|
|
6921
|
+
}
|
|
6922
|
+
getOption(name) {
|
|
6923
|
+
return this.currentDataManager.currentCalendarOptionsInput[name];
|
|
6924
|
+
}
|
|
6925
|
+
getAvailableLocaleCodes() {
|
|
6926
|
+
return Object.keys(this.getCurrentData().availableRawLocales);
|
|
6927
|
+
}
|
|
6928
|
+
// Trigger
|
|
6929
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
6930
|
+
on(handlerName, handler) {
|
|
6931
|
+
let { currentDataManager } = this;
|
|
6932
|
+
if (currentDataManager.currentCalendarOptionsRefiners[handlerName]) {
|
|
6933
|
+
currentDataManager.emitter.on(handlerName, handler);
|
|
6934
|
+
}
|
|
6935
|
+
else {
|
|
6936
|
+
console.warn(`Unknown listener name '${handlerName}'`);
|
|
6937
|
+
}
|
|
6938
|
+
}
|
|
6939
|
+
off(handlerName, handler) {
|
|
6940
|
+
this.currentDataManager.emitter.off(handlerName, handler);
|
|
6941
|
+
}
|
|
6942
|
+
// not meant for public use
|
|
6943
|
+
trigger(handlerName, ...args) {
|
|
6944
|
+
this.currentDataManager.emitter.trigger(handlerName, ...args);
|
|
6945
|
+
}
|
|
6946
|
+
// View
|
|
6947
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
6948
|
+
changeView(viewType, dateOrRange) {
|
|
6949
|
+
this.batchRendering(() => {
|
|
6950
|
+
this.unselect();
|
|
6951
|
+
if (dateOrRange) {
|
|
6952
|
+
if (dateOrRange.start && dateOrRange.end) { // a range
|
|
6953
|
+
this.dispatch({
|
|
6954
|
+
type: 'CHANGE_VIEW_TYPE',
|
|
6955
|
+
viewType,
|
|
6956
|
+
});
|
|
6957
|
+
this.dispatch({
|
|
6958
|
+
type: 'SET_OPTION',
|
|
6959
|
+
optionName: 'visibleRange',
|
|
6960
|
+
rawOptionValue: dateOrRange,
|
|
6961
|
+
});
|
|
6962
|
+
}
|
|
6963
|
+
else {
|
|
6964
|
+
let { dateEnv } = this.getCurrentData();
|
|
6965
|
+
this.dispatch({
|
|
6966
|
+
type: 'CHANGE_VIEW_TYPE',
|
|
6967
|
+
viewType,
|
|
6968
|
+
dateMarker: dateEnv.createMarker(dateOrRange),
|
|
6969
|
+
});
|
|
6970
|
+
}
|
|
7217
6971
|
}
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
6972
|
+
else {
|
|
6973
|
+
this.dispatch({
|
|
6974
|
+
type: 'CHANGE_VIEW_TYPE',
|
|
6975
|
+
viewType,
|
|
6976
|
+
});
|
|
7222
6977
|
}
|
|
7223
|
-
};
|
|
7224
|
-
|
|
7225
|
-
|
|
7226
|
-
|
|
7227
|
-
|
|
6978
|
+
});
|
|
6979
|
+
}
|
|
6980
|
+
// Forces navigation to a view for the given date.
|
|
6981
|
+
// `viewType` can be a specific view name or a generic one like "week" or "day".
|
|
6982
|
+
// needs to change
|
|
6983
|
+
zoomTo(dateMarker, viewType) {
|
|
6984
|
+
let state = this.getCurrentData();
|
|
6985
|
+
let spec;
|
|
6986
|
+
viewType = viewType || 'day'; // day is default zoom
|
|
6987
|
+
spec = state.viewSpecs[viewType] || this.getUnitViewSpec(viewType);
|
|
6988
|
+
this.unselect();
|
|
6989
|
+
if (spec) {
|
|
6990
|
+
this.dispatch({
|
|
6991
|
+
type: 'CHANGE_VIEW_TYPE',
|
|
6992
|
+
viewType: spec.type,
|
|
6993
|
+
dateMarker,
|
|
6994
|
+
});
|
|
6995
|
+
}
|
|
6996
|
+
else {
|
|
6997
|
+
this.dispatch({
|
|
6998
|
+
type: 'CHANGE_DATE',
|
|
6999
|
+
dateMarker,
|
|
7000
|
+
});
|
|
7001
|
+
}
|
|
7002
|
+
}
|
|
7003
|
+
// Given a duration singular unit, like "week" or "day", finds a matching view spec.
|
|
7004
|
+
// Preference is given to views that have corresponding buttons.
|
|
7005
|
+
getUnitViewSpec(unit) {
|
|
7006
|
+
let { viewSpecs, toolbarConfig } = this.getCurrentData();
|
|
7007
|
+
let viewTypes = [].concat(toolbarConfig.header ? toolbarConfig.header.viewsWithButtons : [], toolbarConfig.footer ? toolbarConfig.footer.viewsWithButtons : []);
|
|
7008
|
+
let i;
|
|
7009
|
+
let spec;
|
|
7010
|
+
for (let viewType in viewSpecs) {
|
|
7011
|
+
viewTypes.push(viewType);
|
|
7012
|
+
}
|
|
7013
|
+
for (i = 0; i < viewTypes.length; i += 1) {
|
|
7014
|
+
spec = viewSpecs[viewTypes[i]];
|
|
7015
|
+
if (spec) {
|
|
7016
|
+
if (spec.singleUnit === unit) {
|
|
7017
|
+
return spec;
|
|
7018
|
+
}
|
|
7228
7019
|
}
|
|
7229
|
-
}
|
|
7020
|
+
}
|
|
7021
|
+
return null;
|
|
7230
7022
|
}
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
|
|
7235
|
-
|
|
7236
|
-
theme.getClass('popover'),
|
|
7237
|
-
].concat(props.extraClassNames || []);
|
|
7238
|
-
return createPortal(createElement("div", Object.assign({}, props.extraAttrs, { id: props.id, className: classNames.join(' '), "aria-labelledby": state.titleId, ref: this.handleRootEl }),
|
|
7239
|
-
createElement("div", { className: 'fc-popover-header ' + theme.getClass('popoverHeader') },
|
|
7240
|
-
createElement("span", { className: "fc-popover-title", id: state.titleId }, props.title),
|
|
7241
|
-
createElement("span", { className: 'fc-popover-close ' + theme.getIconClass('close'), title: options.closeHint, onClick: this.handleCloseClick })),
|
|
7242
|
-
createElement("div", { className: 'fc-popover-body ' + theme.getClass('popoverContent') }, props.children)), props.parentEl);
|
|
7023
|
+
// Current Date
|
|
7024
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
7025
|
+
prev() {
|
|
7026
|
+
this.unselect();
|
|
7027
|
+
this.dispatch({ type: 'PREV' });
|
|
7243
7028
|
}
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
this.updateSize();
|
|
7029
|
+
next() {
|
|
7030
|
+
this.unselect();
|
|
7031
|
+
this.dispatch({ type: 'NEXT' });
|
|
7248
7032
|
}
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7033
|
+
prevYear() {
|
|
7034
|
+
let state = this.getCurrentData();
|
|
7035
|
+
this.unselect();
|
|
7036
|
+
this.dispatch({
|
|
7037
|
+
type: 'CHANGE_DATE',
|
|
7038
|
+
dateMarker: state.dateEnv.addYears(state.currentDate, -1),
|
|
7039
|
+
});
|
|
7252
7040
|
}
|
|
7253
|
-
|
|
7254
|
-
let
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7267
|
-
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7041
|
+
nextYear() {
|
|
7042
|
+
let state = this.getCurrentData();
|
|
7043
|
+
this.unselect();
|
|
7044
|
+
this.dispatch({
|
|
7045
|
+
type: 'CHANGE_DATE',
|
|
7046
|
+
dateMarker: state.dateEnv.addYears(state.currentDate, 1),
|
|
7047
|
+
});
|
|
7048
|
+
}
|
|
7049
|
+
today() {
|
|
7050
|
+
let state = this.getCurrentData();
|
|
7051
|
+
this.unselect();
|
|
7052
|
+
this.dispatch({
|
|
7053
|
+
type: 'CHANGE_DATE',
|
|
7054
|
+
dateMarker: getNow(state.calendarOptions.now, state.dateEnv),
|
|
7055
|
+
});
|
|
7056
|
+
}
|
|
7057
|
+
gotoDate(zonedDateInput) {
|
|
7058
|
+
let state = this.getCurrentData();
|
|
7059
|
+
this.unselect();
|
|
7060
|
+
this.dispatch({
|
|
7061
|
+
type: 'CHANGE_DATE',
|
|
7062
|
+
dateMarker: state.dateEnv.createMarker(zonedDateInput),
|
|
7063
|
+
});
|
|
7064
|
+
}
|
|
7065
|
+
incrementDate(deltaInput) {
|
|
7066
|
+
let state = this.getCurrentData();
|
|
7067
|
+
let delta = createDuration(deltaInput);
|
|
7068
|
+
if (delta) { // else, warn about invalid input?
|
|
7069
|
+
this.unselect();
|
|
7070
|
+
this.dispatch({
|
|
7071
|
+
type: 'CHANGE_DATE',
|
|
7072
|
+
dateMarker: state.dateEnv.add(state.currentDate, delta),
|
|
7073
|
+
});
|
|
7074
|
+
}
|
|
7075
|
+
}
|
|
7076
|
+
getDate() {
|
|
7077
|
+
let state = this.getCurrentData();
|
|
7078
|
+
return state.dateEnv.toDate(state.currentDate);
|
|
7079
|
+
}
|
|
7080
|
+
// Date Formatting Utils
|
|
7081
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
7082
|
+
formatDate(d, formatter) {
|
|
7083
|
+
let { dateEnv } = this.getCurrentData();
|
|
7084
|
+
return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter));
|
|
7085
|
+
}
|
|
7086
|
+
// `settings` is for formatter AND isEndExclusive
|
|
7087
|
+
formatRange(d0, d1, settings) {
|
|
7088
|
+
let { dateEnv } = this.getCurrentData();
|
|
7089
|
+
return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings), settings);
|
|
7090
|
+
}
|
|
7091
|
+
formatIso(d, omitTime) {
|
|
7092
|
+
let { dateEnv } = this.getCurrentData();
|
|
7093
|
+
return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime });
|
|
7094
|
+
}
|
|
7095
|
+
// Date Selection / Event Selection / DayClick
|
|
7096
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
7097
|
+
select(dateOrObj, endDate) {
|
|
7098
|
+
let selectionInput;
|
|
7099
|
+
if (endDate == null) {
|
|
7100
|
+
if (dateOrObj.start != null) {
|
|
7101
|
+
selectionInput = dateOrObj;
|
|
7102
|
+
}
|
|
7103
|
+
else {
|
|
7104
|
+
selectionInput = {
|
|
7105
|
+
start: dateOrObj,
|
|
7106
|
+
end: null,
|
|
7107
|
+
};
|
|
7108
|
+
}
|
|
7109
|
+
}
|
|
7110
|
+
else {
|
|
7111
|
+
selectionInput = {
|
|
7112
|
+
start: dateOrObj,
|
|
7113
|
+
end: endDate,
|
|
7114
|
+
};
|
|
7115
|
+
}
|
|
7116
|
+
let state = this.getCurrentData();
|
|
7117
|
+
let selection = parseDateSpan(selectionInput, state.dateEnv, createDuration({ days: 1 }));
|
|
7118
|
+
if (selection) { // throw parse error otherwise?
|
|
7119
|
+
this.dispatch({ type: 'SELECT_DATES', selection });
|
|
7120
|
+
triggerDateSelect(selection, null, state);
|
|
7121
|
+
}
|
|
7122
|
+
}
|
|
7123
|
+
unselect(pev) {
|
|
7124
|
+
let state = this.getCurrentData();
|
|
7125
|
+
if (state.dateSelection) {
|
|
7126
|
+
this.dispatch({ type: 'UNSELECT_DATES' });
|
|
7127
|
+
triggerDateUnselect(pev, state);
|
|
7128
|
+
}
|
|
7129
|
+
}
|
|
7130
|
+
// Public Events API
|
|
7131
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
7132
|
+
addEvent(eventInput, sourceInput) {
|
|
7133
|
+
if (eventInput instanceof EventImpl) {
|
|
7134
|
+
let def = eventInput._def;
|
|
7135
|
+
let instance = eventInput._instance;
|
|
7136
|
+
let currentData = this.getCurrentData();
|
|
7137
|
+
// not already present? don't want to add an old snapshot
|
|
7138
|
+
if (!currentData.eventStore.defs[def.defId]) {
|
|
7139
|
+
this.dispatch({
|
|
7140
|
+
type: 'ADD_EVENTS',
|
|
7141
|
+
eventStore: eventTupleToStore({ def, instance }), // TODO: better util for two args?
|
|
7142
|
+
});
|
|
7143
|
+
this.triggerEventAdd(eventInput);
|
|
7144
|
+
}
|
|
7145
|
+
return eventInput;
|
|
7146
|
+
}
|
|
7147
|
+
let state = this.getCurrentData();
|
|
7148
|
+
let eventSource;
|
|
7149
|
+
if (sourceInput instanceof EventSourceImpl) {
|
|
7150
|
+
eventSource = sourceInput.internalEventSource;
|
|
7151
|
+
}
|
|
7152
|
+
else if (typeof sourceInput === 'boolean') {
|
|
7153
|
+
if (sourceInput) { // true. part of the first event source
|
|
7154
|
+
[eventSource] = hashValuesToArray(state.eventSources);
|
|
7155
|
+
}
|
|
7156
|
+
}
|
|
7157
|
+
else if (sourceInput != null) { // an ID. accepts a number too
|
|
7158
|
+
let sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function
|
|
7159
|
+
if (!sourceApi) {
|
|
7160
|
+
console.warn(`Could not find an event source with ID "${sourceInput}"`); // TODO: test
|
|
7161
|
+
return null;
|
|
7162
|
+
}
|
|
7163
|
+
eventSource = sourceApi.internalEventSource;
|
|
7164
|
+
}
|
|
7165
|
+
let tuple = parseEvent(eventInput, eventSource, state, false);
|
|
7166
|
+
if (tuple) {
|
|
7167
|
+
let newEventApi = new EventImpl(state, tuple.def, tuple.def.recurringDef ? null : tuple.instance);
|
|
7168
|
+
this.dispatch({
|
|
7169
|
+
type: 'ADD_EVENTS',
|
|
7170
|
+
eventStore: eventTupleToStore(tuple),
|
|
7273
7171
|
});
|
|
7172
|
+
this.triggerEventAdd(newEventApi);
|
|
7173
|
+
return newEventApi;
|
|
7274
7174
|
}
|
|
7175
|
+
return null;
|
|
7275
7176
|
}
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7284
|
-
|
|
7285
|
-
el: rootEl,
|
|
7286
|
-
useEventCenter: false,
|
|
7177
|
+
triggerEventAdd(eventApi) {
|
|
7178
|
+
let { emitter } = this.getCurrentData();
|
|
7179
|
+
emitter.trigger('eventAdd', {
|
|
7180
|
+
event: eventApi,
|
|
7181
|
+
relatedEvents: [],
|
|
7182
|
+
revert: () => {
|
|
7183
|
+
this.dispatch({
|
|
7184
|
+
type: 'REMOVE_EVENTS',
|
|
7185
|
+
eventStore: eventApiToStore(eventApi),
|
|
7287
7186
|
});
|
|
7187
|
+
},
|
|
7188
|
+
});
|
|
7189
|
+
}
|
|
7190
|
+
// TODO: optimize
|
|
7191
|
+
getEventById(id) {
|
|
7192
|
+
let state = this.getCurrentData();
|
|
7193
|
+
let { defs, instances } = state.eventStore;
|
|
7194
|
+
id = String(id);
|
|
7195
|
+
for (let defId in defs) {
|
|
7196
|
+
let def = defs[defId];
|
|
7197
|
+
if (def.publicId === id) {
|
|
7198
|
+
if (def.recurringDef) {
|
|
7199
|
+
return new EventImpl(state, def, null);
|
|
7200
|
+
}
|
|
7201
|
+
for (let instanceId in instances) {
|
|
7202
|
+
let instance = instances[instanceId];
|
|
7203
|
+
if (instance.defId === def.defId) {
|
|
7204
|
+
return new EventImpl(state, def, instance);
|
|
7205
|
+
}
|
|
7206
|
+
}
|
|
7288
7207
|
}
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
}
|
|
7292
|
-
};
|
|
7208
|
+
}
|
|
7209
|
+
return null;
|
|
7293
7210
|
}
|
|
7294
|
-
|
|
7295
|
-
let
|
|
7296
|
-
|
|
7297
|
-
let { startDate, todayRange, dateProfile } = props;
|
|
7298
|
-
let title = dateEnv.format(startDate, options.dayPopoverFormat);
|
|
7299
|
-
return (createElement(DayCellContainer, { elRef: this.handleRootEl, date: startDate, dateProfile: dateProfile, todayRange: todayRange }, (InnerContent, renderProps, elAttrs) => (createElement(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 },
|
|
7300
|
-
hasCustomDayCellContent(options) && (createElement(InnerContent, { elTag: "div", elClasses: ['fc-more-popover-misc'] })),
|
|
7301
|
-
props.children))));
|
|
7211
|
+
getEvents() {
|
|
7212
|
+
let currentData = this.getCurrentData();
|
|
7213
|
+
return buildEventApis(currentData.eventStore, currentData);
|
|
7302
7214
|
}
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
rect: {
|
|
7315
|
-
left: 0,
|
|
7316
|
-
top: 0,
|
|
7317
|
-
right: elWidth,
|
|
7318
|
-
bottom: elHeight,
|
|
7319
|
-
},
|
|
7320
|
-
layer: 1, // important when comparing with hits from other components
|
|
7321
|
-
};
|
|
7215
|
+
removeAllEvents() {
|
|
7216
|
+
this.dispatch({ type: 'REMOVE_ALL_EVENTS' });
|
|
7217
|
+
}
|
|
7218
|
+
// Public Event Sources API
|
|
7219
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
7220
|
+
getEventSources() {
|
|
7221
|
+
let state = this.getCurrentData();
|
|
7222
|
+
let sourceHash = state.eventSources;
|
|
7223
|
+
let sourceApis = [];
|
|
7224
|
+
for (let internalId in sourceHash) {
|
|
7225
|
+
sourceApis.push(new EventSourceImpl(state, sourceHash[internalId]));
|
|
7322
7226
|
}
|
|
7323
|
-
return
|
|
7227
|
+
return sourceApis;
|
|
7324
7228
|
}
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
popoverId: getUniqueDomId(),
|
|
7333
|
-
};
|
|
7334
|
-
this.handleLinkEl = (linkEl) => {
|
|
7335
|
-
this.linkEl = linkEl;
|
|
7336
|
-
if (this.props.elRef) {
|
|
7337
|
-
setRef(this.props.elRef, linkEl);
|
|
7338
|
-
}
|
|
7339
|
-
};
|
|
7340
|
-
this.handleClick = (ev) => {
|
|
7341
|
-
let { props, context } = this;
|
|
7342
|
-
let { moreLinkClick } = context.options;
|
|
7343
|
-
let date = computeRange(props).start;
|
|
7344
|
-
function buildPublicSeg(seg) {
|
|
7345
|
-
let { def, instance, range } = seg.eventRange;
|
|
7346
|
-
return {
|
|
7347
|
-
event: new EventImpl(context, def, instance),
|
|
7348
|
-
start: context.dateEnv.toDate(range.start),
|
|
7349
|
-
end: context.dateEnv.toDate(range.end),
|
|
7350
|
-
isStart: seg.isStart,
|
|
7351
|
-
isEnd: seg.isEnd,
|
|
7352
|
-
};
|
|
7229
|
+
getEventSourceById(id) {
|
|
7230
|
+
let state = this.getCurrentData();
|
|
7231
|
+
let sourceHash = state.eventSources;
|
|
7232
|
+
id = String(id);
|
|
7233
|
+
for (let sourceId in sourceHash) {
|
|
7234
|
+
if (sourceHash[sourceId].publicId === id) {
|
|
7235
|
+
return new EventSourceImpl(state, sourceHash[sourceId]);
|
|
7353
7236
|
}
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7237
|
+
}
|
|
7238
|
+
return null;
|
|
7239
|
+
}
|
|
7240
|
+
addEventSource(sourceInput) {
|
|
7241
|
+
let state = this.getCurrentData();
|
|
7242
|
+
if (sourceInput instanceof EventSourceImpl) {
|
|
7243
|
+
// not already present? don't want to add an old snapshot
|
|
7244
|
+
if (!state.eventSources[sourceInput.internalEventSource.sourceId]) {
|
|
7245
|
+
this.dispatch({
|
|
7246
|
+
type: 'ADD_EVENT_SOURCES',
|
|
7247
|
+
sources: [sourceInput.internalEventSource],
|
|
7362
7248
|
});
|
|
7363
7249
|
}
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
|
|
7369
|
-
|
|
7370
|
-
}
|
|
7371
|
-
|
|
7372
|
-
this.setState({ isPopoverOpen: false });
|
|
7373
|
-
};
|
|
7374
|
-
}
|
|
7375
|
-
render() {
|
|
7376
|
-
let { props, state } = this;
|
|
7377
|
-
return (createElement(ViewContextType.Consumer, null, (context) => {
|
|
7378
|
-
let { viewApi, options, calendarApi } = context;
|
|
7379
|
-
let { moreLinkText } = options;
|
|
7380
|
-
let { moreCnt } = props;
|
|
7381
|
-
let range = computeRange(props);
|
|
7382
|
-
let text = typeof moreLinkText === 'function' // TODO: eventually use formatWithOrdinals
|
|
7383
|
-
? moreLinkText.call(calendarApi, moreCnt)
|
|
7384
|
-
: `+${moreCnt} ${moreLinkText}`;
|
|
7385
|
-
let hint = formatWithOrdinals(options.moreLinkHint, [moreCnt], text);
|
|
7386
|
-
let renderProps = {
|
|
7387
|
-
num: moreCnt,
|
|
7388
|
-
shortText: `+${moreCnt}`,
|
|
7389
|
-
text,
|
|
7390
|
-
view: viewApi,
|
|
7391
|
-
};
|
|
7392
|
-
return (createElement(Fragment, null,
|
|
7393
|
-
Boolean(props.moreCnt) && (createElement(ContentContainer, { elTag: props.elTag || 'a', elRef: this.handleLinkEl, elClasses: [
|
|
7394
|
-
...(props.elClasses || []),
|
|
7395
|
-
'fc-more-link',
|
|
7396
|
-
], elStyle: props.elStyle, elAttrs: Object.assign(Object.assign(Object.assign({}, props.elAttrs), createAriaClickAttrs(this.handleClick)), { title: hint, 'aria-expanded': state.isPopoverOpen, 'aria-controls': state.isPopoverOpen ? state.popoverId : '' }), renderProps: renderProps, generatorName: "moreLinkContent", customGenerator: options.moreLinkContent, defaultGenerator: props.defaultGenerator || renderMoreLinkInner, classNameGenerator: options.moreLinkClassNames, didMount: options.moreLinkDidMount, willUnmount: options.moreLinkWillUnmount }, props.children)),
|
|
7397
|
-
state.isPopoverOpen && (createElement(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 ?
|
|
7398
|
-
props.alignmentElRef.current :
|
|
7399
|
-
this.linkEl, alignGridTop: props.alignGridTop, forceTimed: props.forceTimed, onClose: this.handlePopoverClose }, props.popoverContent()))));
|
|
7400
|
-
}));
|
|
7250
|
+
return sourceInput;
|
|
7251
|
+
}
|
|
7252
|
+
let eventSource = parseEventSource(sourceInput, state);
|
|
7253
|
+
if (eventSource) { // TODO: error otherwise?
|
|
7254
|
+
this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] });
|
|
7255
|
+
return new EventSourceImpl(state, eventSource);
|
|
7256
|
+
}
|
|
7257
|
+
return null;
|
|
7401
7258
|
}
|
|
7402
|
-
|
|
7403
|
-
this.
|
|
7259
|
+
removeAllEventSources() {
|
|
7260
|
+
this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' });
|
|
7404
7261
|
}
|
|
7405
|
-
|
|
7406
|
-
this.
|
|
7262
|
+
refetchEvents() {
|
|
7263
|
+
this.dispatch({ type: 'FETCH_EVENT_SOURCES', isRefetch: true });
|
|
7407
7264
|
}
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7265
|
+
// Scroll
|
|
7266
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
7267
|
+
scrollToTime(timeInput) {
|
|
7268
|
+
let time = createDuration(timeInput);
|
|
7269
|
+
if (time) {
|
|
7270
|
+
this.trigger('_timeScrollRequest', time);
|
|
7411
7271
|
}
|
|
7412
7272
|
}
|
|
7413
7273
|
}
|
|
7414
|
-
function renderMoreLinkInner(props) {
|
|
7415
|
-
return props.text;
|
|
7416
|
-
}
|
|
7417
|
-
function computeRange(props) {
|
|
7418
|
-
if (props.allDayDate) {
|
|
7419
|
-
return {
|
|
7420
|
-
start: props.allDayDate,
|
|
7421
|
-
end: addDays(props.allDayDate, 1),
|
|
7422
|
-
};
|
|
7423
|
-
}
|
|
7424
|
-
let { hiddenSegs } = props;
|
|
7425
|
-
return {
|
|
7426
|
-
start: computeEarliestSegStart(hiddenSegs),
|
|
7427
|
-
end: computeLatestSegEnd(hiddenSegs),
|
|
7428
|
-
};
|
|
7429
|
-
}
|
|
7430
|
-
function computeEarliestSegStart(segs) {
|
|
7431
|
-
return segs.reduce(pickEarliestStart).eventRange.range.start;
|
|
7432
|
-
}
|
|
7433
|
-
function pickEarliestStart(seg0, seg1) {
|
|
7434
|
-
return seg0.eventRange.range.start < seg1.eventRange.range.start ? seg0 : seg1;
|
|
7435
|
-
}
|
|
7436
|
-
function computeLatestSegEnd(segs) {
|
|
7437
|
-
return segs.reduce(pickLatestEnd).eventRange.range.end;
|
|
7438
|
-
}
|
|
7439
|
-
function pickLatestEnd(seg0, seg1) {
|
|
7440
|
-
return seg0.eventRange.range.end > seg1.eventRange.range.end ? seg0 : seg1;
|
|
7441
|
-
}
|
|
7442
7274
|
|
|
7443
7275
|
class Store {
|
|
7444
7276
|
constructor() {
|
|
@@ -7484,4 +7316,4 @@ class CustomRenderingStore extends Store {
|
|
|
7484
7316
|
}
|
|
7485
7317
|
}
|
|
7486
7318
|
|
|
7487
|
-
export {
|
|
7319
|
+
export { EventImpl as $, memoizeObjArg as A, BaseComponent as B, ContentContainer as C, DelayedRunner as D, isPropsEqual as E, Emitter as F, getInitialDate as G, rangeContainsMarker as H, createEmptyEventStore as I, reduceCurrentDate as J, reduceEventStore as K, rezoneEventStoreDates as L, mergeRawOptions as M, BASE_OPTION_REFINERS as N, CALENDAR_LISTENER_REFINERS as O, CALENDAR_OPTION_REFINERS as P, COMPLEX_OPTION_COMPARATORS as Q, VIEW_OPTION_REFINERS as R, DateEnv as S, Theme as T, DateProfileGenerator as U, ViewContextType as V, createEventUi as W, parseBusinessHours as X, Interaction as Y, getElEventRange as Z, elementClosest as _, mapHash as a, getSlotClassNames as a$, listenBySelector as a0, listenToHoverBySelector as a1, PureComponent as a2, buildViewContext as a3, parseInteractionSettings as a4, interactionSettingsStore as a5, getNow as a6, getIsHeightAuto as a7, CalendarImpl as a8, flushSync as a9, removeExact as aA, memoizeArraylike as aB, memoizeHashlike as aC, intersectRects as aD, pointInsideRect as aE, constrainPoint as aF, getRectCenter as aG, diffPoints as aH, translateRect as aI, compareObjs as aJ, collectFromHash as aK, findElements as aL, findDirectChildren as aM, removeElement as aN, applyStyle as aO, elementMatches as aP, getEventTargetViaRoot as aQ, getUniqueDomId as aR, parseClassNames as aS, fracToCssDim as aT, mergeEventStores as aU, getRelevantEvents as aV, eventTupleToStore as aW, combineEventUis as aX, Splitter as aY, getDayClassNames as aZ, getDateMeta as a_, CalendarRoot as aa, RenderId as ab, ensureElHasStyles as ac, applyStyleProp as ad, sliceEventStore as ae, JsonRequestError as af, createContext as ag, refineProps as ah, createEventInstance as ai, parseEventDef as aj, refineEventDef as ak, padStart as al, isInt as am, parseFieldSpecs as an, compareByFieldSpecs as ao, flexibleCompare as ap, preventSelection as aq, allowSelection as ar, preventContextMenu as as, allowContextMenu as at, compareNumbers as au, enableCursor as av, disableCursor as aw, computeVisibleDayRange as ax, isMultiDayRange as ay, diffDates as az, buildViewClassNames as b, setNormalizedScrollX as b$, setStateDimMap as b0, isDimMapsEqual as b1, isDimsEqual as b2, watchSize as b3, watchWidth as b4, watchHeight as b5, afterSize as b6, buildNavLinkAttrs as b7, preventDefault as b8, whenTransitionDone as b9, wholeDivideDurations as bA, formatIsoTimeString as bB, formatDayString as bC, buildIsoString as bD, formatIsoMonthStr as bE, NamedTimeZoneImpl as bF, parse as bG, SegHierarchy as bH, buildEntryKey as bI, getEntrySpanEnd as bJ, binarySearch as bK, groupIntersectingEntries as bL, intersectSpans as bM, interactionSettingsToStore as bN, ElementDragging as bO, config as bP, parseDragMeta as bQ, DaySeriesModel as bR, hasBgRendering as bS, buildEventRangeTimeText as bT, sortEventSegs as bU, getEventRangeMeta as bV, buildEventRangeKey as bW, getEventRangeAnchorAttrs as bX, DayTableModel as bY, Scroller as bZ, getNormalizedScrollX as b_, computeInnerRect as ba, computeEdges as bb, getClippingParents as bc, computeRect as bd, rangesEqual as be, rangesIntersect as bf, rangeContainsRange as bg, PositionCache as bh, ScrollController as bi, ElementScrollController as bj, WindowScrollController as bk, DateComponent as bl, isDateSpansEqual as bm, addMs as bn, addWeeks as bo, diffWeeks as bp, diffWholeWeeks as bq, diffDayAndTime as br, diffDays as bs, isValidDate as bt, asCleanDays as bu, multiplyDuration as bv, addDurations as bw, asRoughMinutes as bx, asRoughSeconds as by, asRoughMs as bz, greatestDurationDenominator as c, Slicer as c0, applyMutationToEventStore as c1, isPropsValid as c2, isInteractionValid as c3, isDateSelectionValid as c4, setRef as c5, getStickyFooterScrollbar as c6, getStickyHeaderDates as c7, getScrollerSyncerClass as c8, getScrollbarWidths as c9, RefMap as ca, getIsRtlScrollbarOnLeft as cb, NowTimer as cc, StandardEvent as cd, NowIndicatorContainer as ce, DayCellContainer as cf, hasCustomDayCellContent as cg, EventContainer as ch, renderFill as ci, BgEvent as cj, WeekNumberContainer as ck, MoreLinkContainer as cl, computeEarliestSegStart as cm, ViewContainer as cn, triggerDateSelect as co, getDefaultEventEnd as cp, injectStyles as cq, buildElAttrs as cr, CustomRenderingStore as cs, createDuration as d, BASE_OPTION_DEFAULTS as e, arrayToHash as f, guid as g, filterHash as h, isArraysEqual as i, buildEventSourceRefiners as j, formatWithOrdinals as k, buildRangeApiWithTimeZone as l, mergeProps as m, identity as n, intersectRanges as o, parseEventSource as p, startOfDay as q, requestJson as r, subtractDurations as s, addDays as t, unpromisify as u, hashValuesToArray as v, buildEventApis as w, createFormatter as x, diffWholeDays as y, memoize as z };
|