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