@fullcalendar/core 5.11.3 → 6.0.0-beta.2
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/{LICENSE.txt → LICENSE.md} +0 -0
- package/README.md +3 -3
- package/index.cjs +1545 -0
- package/index.d.ts +44 -0
- package/{main.global.js → index.global.js} +7130 -7704
- package/index.global.min.js +6 -0
- package/index.js +1536 -0
- package/internal-common.cjs +8064 -0
- package/internal-common.d.ts +2783 -0
- package/internal-common.js +7826 -0
- package/internal.cjs +198 -0
- package/internal.d.ts +4 -0
- package/internal.js +3 -0
- package/locales/af.cjs +26 -0
- package/locales/af.d.ts +5 -2
- package/locales/af.global.js +29 -24
- package/locales/af.global.min.js +6 -0
- package/locales/af.js +20 -24
- package/locales/ar-dz.cjs +27 -0
- package/locales/ar-dz.d.ts +5 -2
- package/locales/ar-dz.global.js +30 -25
- package/locales/ar-dz.global.min.js +6 -0
- package/locales/ar-dz.js +21 -25
- package/locales/ar-kw.cjs +27 -0
- package/locales/ar-kw.d.ts +5 -2
- package/locales/ar-kw.global.js +30 -25
- package/locales/ar-kw.global.min.js +6 -0
- package/locales/ar-kw.js +21 -25
- package/locales/ar-ly.cjs +27 -0
- package/locales/ar-ly.d.ts +5 -2
- package/locales/ar-ly.global.js +30 -25
- package/locales/ar-ly.global.min.js +6 -0
- package/locales/ar-ly.js +21 -25
- package/locales/ar-ma.cjs +27 -0
- package/locales/ar-ma.d.ts +5 -2
- package/locales/ar-ma.global.js +30 -25
- package/locales/ar-ma.global.min.js +6 -0
- package/locales/ar-ma.js +21 -25
- package/locales/ar-sa.cjs +27 -0
- package/locales/ar-sa.d.ts +5 -2
- package/locales/ar-sa.global.js +30 -25
- package/locales/ar-sa.global.min.js +6 -0
- package/locales/ar-sa.js +21 -25
- package/locales/ar-tn.cjs +27 -0
- package/locales/ar-tn.d.ts +5 -2
- package/locales/ar-tn.global.js +30 -25
- package/locales/ar-tn.global.min.js +6 -0
- package/locales/ar-tn.js +21 -25
- package/locales/ar.cjs +27 -0
- package/locales/ar.d.ts +5 -2
- package/locales/ar.global.js +30 -25
- package/locales/ar.global.min.js +6 -0
- package/locales/ar.js +21 -25
- package/locales/az.cjs +28 -0
- package/locales/az.d.ts +5 -2
- package/locales/az.global.js +31 -26
- package/locales/az.global.min.js +6 -0
- package/locales/az.js +22 -26
- package/locales/bg.cjs +27 -0
- package/locales/bg.d.ts +5 -2
- package/locales/bg.global.js +30 -25
- package/locales/bg.global.min.js +6 -0
- package/locales/bg.js +21 -25
- package/locales/bn.cjs +28 -0
- package/locales/bn.d.ts +5 -2
- package/locales/bn.global.js +31 -26
- package/locales/bn.global.min.js +6 -0
- package/locales/bn.js +22 -26
- package/locales/bs.cjs +28 -0
- package/locales/bs.d.ts +5 -2
- package/locales/bs.global.js +31 -26
- package/locales/bs.global.min.js +6 -0
- package/locales/bs.js +22 -26
- package/locales/ca.cjs +26 -0
- package/locales/ca.d.ts +5 -2
- package/locales/ca.global.js +29 -24
- package/locales/ca.global.min.js +6 -0
- package/locales/ca.js +20 -24
- package/locales/cs.cjs +28 -0
- package/locales/cs.d.ts +5 -2
- package/locales/cs.global.js +31 -26
- package/locales/cs.global.min.js +6 -0
- package/locales/cs.js +22 -26
- package/locales/cy.cjs +27 -0
- package/locales/cy.d.ts +5 -2
- package/locales/cy.global.js +30 -25
- package/locales/cy.global.min.js +6 -0
- package/locales/cy.js +21 -25
- package/locales/da.cjs +26 -0
- package/locales/da.d.ts +5 -2
- package/locales/da.global.js +29 -24
- package/locales/da.global.min.js +6 -0
- package/locales/da.js +20 -24
- package/locales/de-at.cjs +63 -0
- package/locales/de-at.d.ts +5 -2
- package/locales/de-at.global.js +66 -56
- package/locales/de-at.global.min.js +6 -0
- package/locales/de-at.js +53 -52
- package/locales/de.cjs +63 -0
- package/locales/de.d.ts +5 -2
- package/locales/de.global.js +66 -56
- package/locales/de.global.min.js +6 -0
- package/locales/de.js +53 -52
- package/locales/el.cjs +26 -0
- package/locales/el.d.ts +5 -2
- package/locales/el.global.js +29 -24
- package/locales/el.global.min.js +6 -0
- package/locales/el.js +20 -24
- package/locales/en-au.cjs +23 -0
- package/locales/en-au.d.ts +5 -2
- package/locales/en-au.global.js +26 -21
- package/locales/en-au.global.min.js +6 -0
- package/locales/en-au.js +17 -21
- package/locales/en-gb.cjs +23 -0
- package/locales/en-gb.d.ts +5 -2
- package/locales/en-gb.global.js +26 -21
- package/locales/en-gb.global.min.js +6 -0
- package/locales/en-gb.js +17 -21
- package/locales/en-nz.cjs +23 -0
- package/locales/en-nz.d.ts +5 -2
- package/locales/en-nz.global.js +26 -21
- package/locales/en-nz.global.min.js +6 -0
- package/locales/en-nz.js +17 -21
- package/locales/eo.cjs +26 -0
- package/locales/eo.d.ts +5 -2
- package/locales/eo.global.js +29 -24
- package/locales/eo.global.min.js +6 -0
- package/locales/eo.js +20 -24
- package/locales/es-us.cjs +26 -0
- package/locales/es-us.d.ts +5 -2
- package/locales/es-us.global.js +29 -24
- package/locales/es-us.global.min.js +6 -0
- package/locales/es-us.js +20 -24
- package/locales/es.cjs +45 -0
- package/locales/es.d.ts +5 -2
- package/locales/es.global.js +48 -42
- package/locales/es.global.min.js +6 -0
- package/locales/es.js +39 -42
- package/locales/et.cjs +28 -0
- package/locales/et.d.ts +5 -2
- package/locales/et.global.js +31 -26
- package/locales/et.global.min.js +6 -0
- package/locales/et.js +22 -26
- package/locales/eu.cjs +26 -0
- package/locales/eu.d.ts +5 -2
- package/locales/eu.global.js +29 -24
- package/locales/eu.global.min.js +6 -0
- package/locales/eu.js +20 -24
- package/locales/fa.cjs +29 -0
- package/locales/fa.d.ts +5 -2
- package/locales/fa.global.js +32 -27
- package/locales/fa.global.min.js +6 -0
- package/locales/fa.js +23 -27
- package/locales/fi.cjs +26 -0
- package/locales/fi.d.ts +5 -2
- package/locales/fi.global.js +29 -24
- package/locales/fi.global.min.js +6 -0
- package/locales/fi.js +20 -24
- package/locales/fr-ca.cjs +23 -0
- package/locales/fr-ca.d.ts +5 -2
- package/locales/fr-ca.global.js +26 -21
- package/locales/fr-ca.global.min.js +6 -0
- package/locales/fr-ca.js +17 -21
- package/locales/fr-ch.cjs +27 -0
- package/locales/fr-ch.d.ts +5 -2
- package/locales/fr-ch.global.js +30 -25
- package/locales/fr-ch.global.min.js +6 -0
- package/locales/fr-ch.js +21 -25
- package/locales/fr.cjs +27 -0
- package/locales/fr.d.ts +5 -2
- package/locales/fr.global.js +30 -25
- package/locales/fr.global.min.js +6 -0
- package/locales/fr.js +21 -25
- package/locales/gl.cjs +26 -0
- package/locales/gl.d.ts +5 -2
- package/locales/gl.global.js +29 -24
- package/locales/gl.global.min.js +6 -0
- package/locales/gl.js +20 -24
- package/locales/he.cjs +23 -0
- package/locales/he.d.ts +5 -2
- package/locales/he.global.js +26 -21
- package/locales/he.global.min.js +6 -0
- package/locales/he.js +17 -21
- package/locales/hi.cjs +28 -0
- package/locales/hi.d.ts +5 -2
- package/locales/hi.global.js +31 -26
- package/locales/hi.global.min.js +6 -0
- package/locales/hi.js +22 -26
- package/locales/hr.cjs +28 -0
- package/locales/hr.d.ts +5 -2
- package/locales/hr.global.js +31 -26
- package/locales/hr.global.min.js +6 -0
- package/locales/hr.js +22 -26
- package/locales/hu.cjs +26 -0
- package/locales/hu.d.ts +5 -2
- package/locales/hu.global.js +29 -24
- package/locales/hu.global.min.js +6 -0
- package/locales/hu.js +20 -24
- package/locales/hy-am.cjs +28 -0
- package/locales/hy-am.d.ts +5 -2
- package/locales/hy-am.global.js +31 -26
- package/locales/hy-am.global.min.js +6 -0
- package/locales/hy-am.js +22 -26
- package/locales/id.cjs +26 -0
- package/locales/id.d.ts +5 -2
- package/locales/id.global.js +29 -24
- package/locales/id.global.min.js +6 -0
- package/locales/id.js +20 -24
- package/locales/is.cjs +26 -0
- package/locales/is.d.ts +5 -2
- package/locales/is.global.js +29 -24
- package/locales/is.global.min.js +6 -0
- package/locales/is.js +20 -24
- package/locales/it.cjs +28 -0
- package/locales/it.d.ts +5 -2
- package/locales/it.global.js +31 -26
- package/locales/it.global.min.js +6 -0
- package/locales/it.js +22 -26
- package/locales/ja.cjs +24 -0
- package/locales/ja.d.ts +5 -2
- package/locales/ja.global.js +27 -22
- package/locales/ja.global.min.js +6 -0
- package/locales/ja.js +18 -22
- package/locales/ka.cjs +28 -0
- package/locales/ka.d.ts +5 -2
- package/locales/ka.global.js +31 -26
- package/locales/ka.global.min.js +6 -0
- package/locales/ka.js +22 -26
- package/locales/kk.cjs +28 -0
- package/locales/kk.d.ts +5 -2
- package/locales/kk.global.js +31 -26
- package/locales/kk.global.min.js +6 -0
- package/locales/kk.js +22 -26
- package/locales/km.cjs +27 -0
- package/locales/km.d.ts +5 -2
- package/locales/km.global.js +30 -25
- package/locales/km.global.min.js +6 -0
- package/locales/km.js +21 -25
- package/locales/ko.cjs +22 -0
- package/locales/ko.d.ts +5 -2
- package/locales/ko.global.js +25 -20
- package/locales/ko.global.min.js +6 -0
- package/locales/ko.js +16 -20
- package/locales/ku.cjs +27 -0
- package/locales/ku.d.ts +5 -2
- package/locales/ku.global.js +30 -25
- package/locales/ku.global.min.js +6 -0
- package/locales/ku.js +21 -25
- package/locales/lb.cjs +26 -0
- package/locales/lb.d.ts +5 -2
- package/locales/lb.global.js +29 -24
- package/locales/lb.global.min.js +6 -0
- package/locales/lb.js +20 -24
- package/locales/lt.cjs +26 -0
- package/locales/lt.d.ts +5 -2
- package/locales/lt.global.js +29 -24
- package/locales/lt.global.min.js +6 -0
- package/locales/lt.js +20 -24
- package/locales/lv.cjs +28 -0
- package/locales/lv.d.ts +5 -2
- package/locales/lv.global.js +31 -26
- package/locales/lv.global.min.js +6 -0
- package/locales/lv.js +22 -26
- package/locales/mk.cjs +24 -0
- package/locales/mk.d.ts +5 -2
- package/locales/mk.global.js +27 -22
- package/locales/mk.global.min.js +6 -0
- package/locales/mk.js +18 -22
- package/locales/ms.cjs +28 -0
- package/locales/ms.d.ts +5 -2
- package/locales/ms.global.js +31 -26
- package/locales/ms.global.min.js +6 -0
- package/locales/ms.js +22 -26
- package/locales/nb.cjs +37 -0
- package/locales/nb.d.ts +5 -2
- package/locales/nb.global.js +40 -35
- package/locales/nb.global.min.js +6 -0
- package/locales/nb.js +31 -35
- package/locales/ne.cjs +26 -0
- package/locales/ne.d.ts +5 -2
- package/locales/ne.global.js +29 -24
- package/locales/ne.global.min.js +6 -0
- package/locales/ne.js +20 -24
- package/locales/nl.cjs +26 -0
- package/locales/nl.d.ts +5 -2
- package/locales/nl.global.js +29 -24
- package/locales/nl.global.min.js +6 -0
- package/locales/nl.js +20 -24
- package/locales/nn.cjs +26 -0
- package/locales/nn.d.ts +5 -2
- package/locales/nn.global.js +29 -24
- package/locales/nn.global.min.js +6 -0
- package/locales/nn.js +20 -24
- package/locales/pl.cjs +26 -0
- package/locales/pl.d.ts +5 -2
- package/locales/pl.global.js +29 -24
- package/locales/pl.global.min.js +6 -0
- package/locales/pl.js +20 -24
- package/locales/pt-br.cjs +24 -0
- package/locales/pt-br.d.ts +5 -2
- package/locales/pt-br.global.js +27 -22
- package/locales/pt-br.global.min.js +6 -0
- package/locales/pt-br.js +18 -22
- package/locales/pt.cjs +26 -0
- package/locales/pt.d.ts +5 -2
- package/locales/pt.global.js +29 -24
- package/locales/pt.global.min.js +6 -0
- package/locales/pt.js +20 -24
- package/locales/ro.cjs +28 -0
- package/locales/ro.d.ts +5 -2
- package/locales/ro.global.js +31 -26
- package/locales/ro.global.min.js +6 -0
- package/locales/ro.js +22 -26
- package/locales/ru.cjs +28 -0
- package/locales/ru.d.ts +5 -2
- package/locales/ru.global.js +31 -26
- package/locales/ru.global.min.js +6 -0
- package/locales/ru.js +22 -26
- package/locales/si-lk.cjs +26 -0
- package/locales/si-lk.d.ts +5 -2
- package/locales/si-lk.global.js +29 -24
- package/locales/si-lk.global.min.js +6 -0
- package/locales/si-lk.js +20 -24
- package/locales/sk.cjs +28 -0
- package/locales/sk.d.ts +5 -2
- package/locales/sk.global.js +31 -26
- package/locales/sk.global.min.js +6 -0
- package/locales/sk.js +22 -26
- package/locales/sl.cjs +26 -0
- package/locales/sl.d.ts +5 -2
- package/locales/sl.global.js +29 -24
- package/locales/sl.global.min.js +6 -0
- package/locales/sl.js +20 -24
- package/locales/sm.cjs +22 -0
- package/locales/sm.d.ts +5 -2
- package/locales/sm.global.js +25 -20
- package/locales/sm.global.min.js +6 -0
- package/locales/sm.js +16 -20
- package/locales/sq.cjs +28 -0
- package/locales/sq.d.ts +5 -2
- package/locales/sq.global.js +31 -26
- package/locales/sq.global.min.js +6 -0
- package/locales/sq.js +22 -26
- package/locales/sr-cyrl.cjs +28 -0
- package/locales/sr-cyrl.d.ts +5 -2
- package/locales/sr-cyrl.global.js +31 -26
- package/locales/sr-cyrl.global.min.js +6 -0
- package/locales/sr-cyrl.js +22 -26
- package/locales/sr.cjs +28 -0
- package/locales/sr.d.ts +5 -2
- package/locales/sr.global.js +31 -26
- package/locales/sr.global.min.js +6 -0
- package/locales/sr.js +22 -26
- package/locales/sv.cjs +46 -0
- package/locales/sv.d.ts +5 -2
- package/locales/sv.global.js +49 -44
- package/locales/sv.global.min.js +6 -0
- package/locales/sv.js +38 -42
- package/locales/ta-in.cjs +28 -0
- package/locales/ta-in.d.ts +5 -2
- package/locales/ta-in.global.js +31 -26
- package/locales/ta-in.global.min.js +6 -0
- package/locales/ta-in.js +22 -26
- package/locales/th.cjs +29 -0
- package/locales/th.d.ts +5 -2
- package/locales/th.global.js +32 -27
- package/locales/th.global.min.js +6 -0
- package/locales/th.js +23 -27
- package/locales/tr.cjs +26 -0
- package/locales/tr.d.ts +5 -2
- package/locales/tr.global.js +29 -24
- package/locales/tr.global.min.js +6 -0
- package/locales/tr.js +20 -24
- package/locales/ug.cjs +16 -0
- package/locales/ug.d.ts +5 -2
- package/locales/ug.global.js +19 -14
- package/locales/ug.global.min.js +6 -0
- package/locales/ug.js +10 -14
- package/locales/uk.cjs +28 -0
- package/locales/uk.d.ts +5 -2
- package/locales/uk.global.js +31 -26
- package/locales/uk.global.min.js +6 -0
- package/locales/uk.js +22 -26
- package/locales/uz.cjs +20 -0
- package/locales/uz.d.ts +5 -2
- package/locales/uz.global.js +23 -18
- package/locales/uz.global.min.js +6 -0
- package/locales/uz.js +14 -18
- package/locales/vi.cjs +28 -0
- package/locales/vi.d.ts +5 -2
- package/locales/vi.global.js +31 -26
- package/locales/vi.global.min.js +6 -0
- package/locales/vi.js +22 -26
- package/locales/zh-cn.cjs +29 -0
- package/locales/zh-cn.d.ts +5 -2
- package/locales/zh-cn.global.js +32 -26
- package/locales/zh-cn.global.min.js +6 -0
- package/locales/zh-cn.js +23 -26
- package/locales/zh-tw.cjs +22 -0
- package/locales/zh-tw.d.ts +5 -2
- package/locales/zh-tw.global.js +25 -20
- package/locales/zh-tw.global.min.js +6 -0
- package/locales/zh-tw.js +16 -20
- package/locales-all.cjs +88 -0
- package/locales-all.d.ts +6 -2
- package/locales-all.global.js +1792 -1852
- package/locales-all.global.min.js +6 -1
- package/locales-all.js +80 -1849
- package/package.json +61 -18
- package/preact.cjs +22 -0
- package/preact.d.ts +8 -0
- package/preact.js +3 -0
- package/main.cjs.js +0 -138
- package/main.d.ts +0 -30
- package/main.global.min.js +0 -6
- package/main.js +0 -128
- package/main.js.map +0 -1
- package/vdom.cjs.js +0 -105
- package/vdom.d.ts +0 -23
- package/vdom.js +0 -80
package/index.cjs
ADDED
|
@@ -0,0 +1,1545 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var internalCommon = require('./internal-common.cjs');
|
|
6
|
+
var preact = require('preact');
|
|
7
|
+
require('preact/compat');
|
|
8
|
+
|
|
9
|
+
var css_248z = "\n/*\nfor css vars only.\nthese values are automatically known in all stylesheets.\nthe :root statement itself is only included in the common stylesheet.\nthis file is not processed by postcss when imported into the postcss-custom-properties plugin,\nso only write standard css!\n\nNOTE: for old browsers, will need to restart watcher after changing a variable\n*/\n\n:root {\n --fc-small-font-size: .85em;\n --fc-page-bg-color: #fff;\n --fc-neutral-bg-color: rgba(208, 208, 208, 0.3);\n --fc-neutral-text-color: #808080;\n --fc-border-color: #ddd;\n\n --fc-button-text-color: #fff;\n --fc-button-bg-color: #2C3E50;\n --fc-button-border-color: #2C3E50;\n --fc-button-hover-bg-color: #1e2b37;\n --fc-button-hover-border-color: #1a252f;\n --fc-button-active-bg-color: #1a252f;\n --fc-button-active-border-color: #151e27;\n\n --fc-event-bg-color: #3788d8;\n --fc-event-border-color: #3788d8;\n --fc-event-text-color: #fff;\n --fc-event-selected-overlay-color: rgba(0, 0, 0, 0.25);\n\n --fc-more-link-bg-color: #d0d0d0;\n --fc-more-link-text-color: inherit;\n\n --fc-event-resizer-thickness: 8px;\n --fc-event-resizer-dot-total-width: 8px;\n --fc-event-resizer-dot-border-width: 1px;\n\n --fc-non-business-color: rgba(215, 215, 215, 0.3);\n --fc-bg-event-color: rgb(143, 223, 130);\n --fc-bg-event-opacity: 0.3;\n --fc-highlight-color: rgba(188, 232, 241, 0.3);\n --fc-today-bg-color: rgba(255, 220, 40, 0.15);\n --fc-now-indicator-color: red;\n}\n\n/* classes attached to <body> */\n\n/* TODO: make fc-event selector work when calender in shadow DOM */\n\n.fc-not-allowed,\n.fc-not-allowed .fc-event { /* override events' custom cursors */\n cursor: not-allowed;\n}\n\n/* TODO: not attached to body. attached to specific els. move */\n\n.fc-unselectable {\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n -webkit-touch-callout: none;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n.fc {\n /* layout of immediate children */\n display: flex;\n flex-direction: column;\n\n font-size: 1em\n}\n.fc,\n .fc *,\n .fc *:before,\n .fc *:after {\n box-sizing: border-box;\n }\n.fc table {\n border-collapse: collapse;\n border-spacing: 0;\n font-size: 1em; /* normalize cross-browser */\n }\n.fc th {\n text-align: center;\n }\n.fc th,\n .fc td {\n vertical-align: top;\n padding: 0;\n }\n.fc a[data-navlink] {\n cursor: pointer;\n }\n.fc a[data-navlink]:hover {\n text-decoration: underline;\n }\n.fc-direction-ltr {\n direction: ltr;\n text-align: left;\n}\n.fc-direction-rtl {\n direction: rtl;\n text-align: right;\n}\n.fc-theme-standard td,\n .fc-theme-standard th {\n border: 1px solid var(--fc-border-color);\n }\n/* for FF, which doesn't expand a 100% div within a table cell. use absolute positioning */\n/* inner-wrappers are responsible for being absolute */\n/* TODO: best place for this? */\n.fc-liquid-hack td,\n .fc-liquid-hack th {\n position: relative;\n }\n\n@font-face {\n font-family: 'fcicons';\n 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');\n font-weight: normal;\n font-style: normal;\n}\n\n.fc-icon {\n /* added for fc */\n display: inline-block;\n width: 1em;\n height: 1em;\n text-align: center;\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n\n /* use !important to prevent issues with browser extensions that change fonts */\n font-family: 'fcicons' !important;\n speak: none;\n font-style: normal;\n font-weight: normal;\n font-variant: normal;\n text-transform: none;\n line-height: 1;\n\n /* Better Font Rendering =========== */\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n.fc-icon-chevron-left:before {\n content: \"\\e900\";\n}\n\n.fc-icon-chevron-right:before {\n content: \"\\e901\";\n}\n\n.fc-icon-chevrons-left:before {\n content: \"\\e902\";\n}\n\n.fc-icon-chevrons-right:before {\n content: \"\\e903\";\n}\n\n.fc-icon-minus-square:before {\n content: \"\\e904\";\n}\n\n.fc-icon-plus-square:before {\n content: \"\\e905\";\n}\n\n.fc-icon-x:before {\n content: \"\\e906\";\n}\n/*\nLots taken from Flatly (MIT): https://bootswatch.com/4/flatly/bootstrap.css\n\nThese styles only apply when the standard-theme is activated.\nWhen it's NOT activated, the fc-button classes won't even be in the DOM.\n*/\n.fc {\n\n /* reset */\n\n}\n.fc .fc-button {\n border-radius: 0;\n overflow: visible;\n text-transform: none;\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n }\n.fc .fc-button:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n }\n.fc .fc-button {\n -webkit-appearance: button;\n }\n.fc .fc-button:not(:disabled) {\n cursor: pointer;\n }\n.fc .fc-button::-moz-focus-inner {\n padding: 0;\n border-style: none;\n }\n.fc {\n\n /* theme */\n\n}\n.fc .fc-button {\n display: inline-block;\n font-weight: 400;\n text-align: center;\n vertical-align: middle;\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n background-color: transparent;\n border: 1px solid transparent;\n padding: 0.4em 0.65em;\n font-size: 1em;\n line-height: 1.5;\n border-radius: 0.25em;\n }\n.fc .fc-button:hover {\n text-decoration: none;\n }\n.fc .fc-button:focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(44, 62, 80, 0.25);\n }\n.fc .fc-button:disabled {\n opacity: 0.65;\n }\n.fc {\n\n /* \"primary\" coloring */\n\n}\n.fc .fc-button-primary {\n color: var(--fc-button-text-color);\n background-color: var(--fc-button-bg-color);\n border-color: var(--fc-button-border-color);\n }\n.fc .fc-button-primary:hover {\n color: var(--fc-button-text-color);\n background-color: var(--fc-button-hover-bg-color);\n border-color: var(--fc-button-hover-border-color);\n }\n.fc .fc-button-primary:disabled { /* not DRY */\n color: var(--fc-button-text-color);\n background-color: var(--fc-button-bg-color);\n border-color: var(--fc-button-border-color); /* overrides :hover */\n }\n.fc .fc-button-primary:focus {\n box-shadow: 0 0 0 0.2rem rgba(76, 91, 106, 0.5);\n }\n.fc .fc-button-primary:not(:disabled):active,\n .fc .fc-button-primary:not(:disabled).fc-button-active {\n color: var(--fc-button-text-color);\n background-color: var(--fc-button-active-bg-color);\n border-color: var(--fc-button-active-border-color);\n }\n.fc .fc-button-primary:not(:disabled):active:focus,\n .fc .fc-button-primary:not(:disabled).fc-button-active:focus {\n box-shadow: 0 0 0 0.2rem rgba(76, 91, 106, 0.5);\n }\n.fc {\n\n /* icons within buttons */\n\n}\n.fc .fc-button .fc-icon {\n vertical-align: middle;\n font-size: 1.5em; /* bump up the size (but don't make it bigger than line-height of button, which is 1.5em also) */\n }\n.fc .fc-button-group {\n position: relative;\n display: inline-flex;\n vertical-align: middle;\n }\n.fc .fc-button-group > .fc-button {\n position: relative;\n flex: 1 1 auto;\n }\n.fc .fc-button-group > .fc-button:hover {\n z-index: 1;\n }\n.fc .fc-button-group > .fc-button:focus,\n .fc .fc-button-group > .fc-button:active,\n .fc .fc-button-group > .fc-button.fc-button-active {\n z-index: 1;\n }\n.fc-direction-ltr .fc-button-group > .fc-button:not(:first-child) {\n margin-left: -1px;\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n.fc-direction-ltr .fc-button-group > .fc-button:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n.fc-direction-rtl .fc-button-group > .fc-button:not(:first-child) {\n margin-right: -1px;\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n.fc-direction-rtl .fc-button-group > .fc-button:not(:last-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n.fc .fc-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n.fc .fc-toolbar.fc-header-toolbar {\n margin-bottom: 1.5em;\n }\n.fc .fc-toolbar.fc-footer-toolbar {\n margin-top: 1.5em;\n }\n.fc .fc-toolbar-title {\n font-size: 1.75em;\n margin: 0;\n }\n.fc-direction-ltr .fc-toolbar > * > :not(:first-child) {\n margin-left: .75em; /* space between */\n }\n.fc-direction-rtl .fc-toolbar > * > :not(:first-child) {\n margin-right: .75em; /* space between */\n }\n.fc-direction-rtl .fc-toolbar-ltr { /* when the toolbar-chunk positioning system is explicitly left-to-right */\n flex-direction: row-reverse;\n }\n.fc .fc-scroller {\n -webkit-overflow-scrolling: touch;\n position: relative; /* for abs-positioned elements within */\n }\n.fc .fc-scroller-liquid {\n height: 100%;\n }\n.fc .fc-scroller-liquid-absolute {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n bottom: 0;\n }\n.fc .fc-scroller-harness {\n position: relative;\n overflow: hidden;\n direction: ltr;\n /* hack for chrome computing the scroller's right/left wrong for rtl. undone below... */\n /* TODO: demonstrate in codepen */\n }\n.fc .fc-scroller-harness-liquid {\n height: 100%;\n }\n.fc-direction-rtl .fc-scroller-harness > .fc-scroller { /* undo above hack */\n direction: rtl;\n }\n.fc-theme-standard .fc-scrollgrid {\n border: 1px solid var(--fc-border-color); /* bootstrap does this. match */\n }\n.fc .fc-scrollgrid,\n .fc .fc-scrollgrid table { /* all tables (self included) */\n width: 100%; /* because tables don't normally do this */\n table-layout: fixed;\n }\n.fc .fc-scrollgrid table { /* inner tables */\n border-top-style: hidden;\n border-left-style: hidden;\n border-right-style: hidden;\n }\n.fc .fc-scrollgrid {\n\n border-collapse: separate;\n border-right-width: 0;\n border-bottom-width: 0;\n\n }\n.fc .fc-scrollgrid-liquid {\n height: 100%;\n }\n.fc .fc-scrollgrid-section { /* a <tr> */\n height: 1px /* better than 0, for firefox */\n\n }\n.fc .fc-scrollgrid-section > td {\n height: 1px; /* needs a height so inner div within grow. better than 0, for firefox */\n }\n.fc .fc-scrollgrid-section table {\n height: 1px;\n /* for most browsers, if a height isn't set on the table, can't do liquid-height within cells */\n /* serves as a min-height. harmless */\n }\n.fc .fc-scrollgrid-section-liquid > td {\n height: 100%; /* better than `auto`, for firefox */\n }\n.fc .fc-scrollgrid-section > * {\n border-top-width: 0;\n border-left-width: 0;\n }\n.fc .fc-scrollgrid-section-header > *,\n .fc .fc-scrollgrid-section-footer > * {\n border-bottom-width: 0;\n }\n.fc .fc-scrollgrid-section-body table,\n .fc .fc-scrollgrid-section-footer table {\n border-bottom-style: hidden; /* head keeps its bottom border tho */\n }\n.fc {\n\n /* stickiness */\n\n}\n.fc .fc-scrollgrid-section-sticky > * {\n background: var(--fc-page-bg-color);\n position: sticky;\n z-index: 3; /* TODO: var */\n /* TODO: box-shadow when sticking */\n }\n.fc .fc-scrollgrid-section-header.fc-scrollgrid-section-sticky > * {\n top: 0; /* because border-sharing causes a gap at the top */\n /* TODO: give safari -1. has bug */\n }\n.fc .fc-scrollgrid-section-footer.fc-scrollgrid-section-sticky > * {\n bottom: 0; /* known bug: bottom-stickiness doesn't work in safari */\n }\n.fc .fc-scrollgrid-sticky-shim { /* for horizontal scrollbar */\n height: 1px; /* needs height to create scrollbars */\n margin-bottom: -1px;\n }\n.fc-sticky { /* no .fc wrap because used as child of body */\n position: sticky;\n}\n.fc .fc-view-harness {\n flex-grow: 1; /* because this harness is WITHIN the .fc's flexbox */\n position: relative;\n }\n.fc {\n\n /* when the harness controls the height, make the view liquid */\n\n}\n.fc .fc-view-harness-active > .fc-view {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n }\n.fc .fc-col-header-cell-cushion {\n display: inline-block; /* x-browser for when sticky (when multi-tier header) */\n padding: 2px 4px;\n }\n.fc .fc-bg-event,\n .fc .fc-non-business,\n .fc .fc-highlight {\n /* will always have a harness with position:relative/absolute, so absolutely expand */\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n }\n.fc .fc-non-business {\n background: var(--fc-non-business-color);\n }\n.fc .fc-bg-event {\n background: var(--fc-bg-event-color);\n opacity: var(--fc-bg-event-opacity)\n }\n.fc .fc-bg-event .fc-event-title {\n margin: .5em;\n font-size: var(--fc-small-font-size);\n font-style: italic;\n }\n.fc .fc-highlight {\n background: var(--fc-highlight-color);\n }\n.fc .fc-cell-shaded,\n .fc .fc-day-disabled {\n background: var(--fc-neutral-bg-color);\n }\n/* link resets */\n/* ---------------------------------------------------------------------------------------------------- */\na.fc-event,\na.fc-event:hover {\n text-decoration: none;\n}\n/* cursor */\n.fc-event[href],\n.fc-event.fc-event-draggable {\n cursor: pointer;\n}\n/* event text content */\n/* ---------------------------------------------------------------------------------------------------- */\n.fc-event .fc-event-main {\n position: relative;\n z-index: 2;\n }\n/* dragging */\n/* ---------------------------------------------------------------------------------------------------- */\n.fc-event-dragging:not(.fc-event-selected) { /* MOUSE */\n opacity: 0.75;\n }\n.fc-event-dragging.fc-event-selected { /* TOUCH */\n box-shadow: 0 2px 7px rgba(0, 0, 0, 0.3);\n }\n/* resizing */\n/* ---------------------------------------------------------------------------------------------------- */\n/* (subclasses should hone positioning for touch and non-touch) */\n.fc-event .fc-event-resizer {\n display: none;\n position: absolute;\n z-index: 4;\n }\n.fc-event:hover, /* MOUSE */\n.fc-event-selected { /* TOUCH */\n\n}\n.fc-event:hover .fc-event-resizer, .fc-event-selected .fc-event-resizer {\n display: block;\n }\n.fc-event-selected .fc-event-resizer {\n border-radius: calc(var(--fc-event-resizer-dot-total-width) / 2);\n border-width: var(--fc-event-resizer-dot-border-width);\n width: var(--fc-event-resizer-dot-total-width);\n height: var(--fc-event-resizer-dot-total-width);\n border-style: solid;\n border-color: inherit;\n background: var(--fc-page-bg-color)\n\n /* expand hit area */\n\n }\n.fc-event-selected .fc-event-resizer:before {\n content: '';\n position: absolute;\n top: -20px;\n left: -20px;\n right: -20px;\n bottom: -20px;\n }\n/* selecting (always TOUCH) */\n/* OR, focused by tab-index */\n/* (TODO: maybe not the best focus-styling for .fc-daygrid-dot-event) */\n/* ---------------------------------------------------------------------------------------------------- */\n.fc-event-selected,\n.fc-event:focus {\n box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2)\n\n /* expand hit area (subclasses should expand) */\n\n}\n.fc-event-selected:before, .fc-event:focus:before {\n content: \"\";\n position: absolute;\n z-index: 3;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n }\n.fc-event-selected,\n.fc-event:focus {\n\n /* dimmer effect */\n\n}\n.fc-event-selected:after, .fc-event:focus:after {\n content: \"\";\n background: var(--fc-event-selected-overlay-color);\n position: absolute;\n z-index: 1;\n\n /* assume there's a border on all sides. overcome it. */\n /* sometimes there's NOT a border, in which case the dimmer will go over */\n /* an adjacent border, which looks fine. */\n top: -1px;\n left: -1px;\n right: -1px;\n bottom: -1px;\n }\n/*\nA HORIZONTAL event\n*/\n.fc-h-event { /* allowed to be top-level */\n display: block;\n border: 1px solid var(--fc-event-border-color);\n background-color: var(--fc-event-bg-color)\n\n}\n.fc-h-event .fc-event-main {\n color: var(--fc-event-text-color);\n }\n.fc-h-event .fc-event-main-frame {\n display: flex; /* for make fc-event-title-container expand */\n }\n.fc-h-event .fc-event-time {\n max-width: 100%; /* clip overflow on this element */\n overflow: hidden;\n }\n.fc-h-event .fc-event-title-container { /* serves as a container for the sticky cushion */\n flex-grow: 1;\n flex-shrink: 1;\n min-width: 0; /* important for allowing to shrink all the way */\n }\n.fc-h-event .fc-event-title {\n display: inline-block; /* need this to be sticky cross-browser */\n vertical-align: top; /* for not messing up line-height */\n left: 0; /* for sticky */\n right: 0; /* for sticky */\n max-width: 100%; /* clip overflow on this element */\n overflow: hidden;\n }\n.fc-h-event.fc-event-selected:before {\n /* expand hit area */\n top: -10px;\n bottom: -10px;\n }\n/* adjust border and border-radius (if there is any) for non-start/end */\n.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-start),\n.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-end) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n border-left-width: 0;\n}\n.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-end),\n.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-start) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n border-right-width: 0;\n}\n/* resizers */\n.fc-h-event:not(.fc-event-selected) .fc-event-resizer {\n top: 0;\n bottom: 0;\n width: var(--fc-event-resizer-thickness);\n}\n.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start,\n.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end {\n cursor: w-resize;\n left: calc(-0.5 * var(--fc-event-resizer-thickness));\n}\n.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end,\n.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start {\n cursor: e-resize;\n right: calc(-0.5 * var(--fc-event-resizer-thickness));\n}\n/* resizers for TOUCH */\n.fc-h-event.fc-event-selected .fc-event-resizer {\n top: 50%;\n margin-top: calc(-0.5 * var(--fc-event-resizer-dot-total-width));\n}\n.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-start,\n.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-end {\n left: calc(-0.5 * var(--fc-event-resizer-dot-total-width));\n}\n.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-end,\n.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-start {\n right: calc(-0.5 * var(--fc-event-resizer-dot-total-width));\n}\n.fc .fc-popover {\n position: absolute;\n z-index: 9999;\n box-shadow: 0 2px 6px rgba(0,0,0,.15);\n }\n.fc .fc-popover-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n padding: 3px 4px;\n }\n.fc .fc-popover-title {\n margin: 0 2px;\n }\n.fc .fc-popover-close {\n cursor: pointer;\n opacity: 0.65;\n font-size: 1.1em;\n }\n.fc-theme-standard .fc-popover {\n border: 1px solid var(--fc-border-color);\n background: var(--fc-page-bg-color);\n }\n.fc-theme-standard .fc-popover-header {\n background: var(--fc-neutral-bg-color);\n }\n";
|
|
10
|
+
internalCommon.injectStyles(css_248z);
|
|
11
|
+
|
|
12
|
+
const MINIMAL_RAW_EN_LOCALE = {
|
|
13
|
+
code: 'en',
|
|
14
|
+
week: {
|
|
15
|
+
dow: 0,
|
|
16
|
+
doy: 4, // 4 days need to be within the year to be considered the first week
|
|
17
|
+
},
|
|
18
|
+
direction: 'ltr',
|
|
19
|
+
buttonText: {
|
|
20
|
+
prev: 'prev',
|
|
21
|
+
next: 'next',
|
|
22
|
+
prevYear: 'prev year',
|
|
23
|
+
nextYear: 'next year',
|
|
24
|
+
year: 'year',
|
|
25
|
+
today: 'today',
|
|
26
|
+
month: 'month',
|
|
27
|
+
week: 'week',
|
|
28
|
+
day: 'day',
|
|
29
|
+
list: 'list',
|
|
30
|
+
},
|
|
31
|
+
weekText: 'W',
|
|
32
|
+
weekTextLong: 'Week',
|
|
33
|
+
closeHint: 'Close',
|
|
34
|
+
timeHint: 'Time',
|
|
35
|
+
eventHint: 'Event',
|
|
36
|
+
allDayText: 'all-day',
|
|
37
|
+
moreLinkText: 'more',
|
|
38
|
+
noEventsText: 'No events to display',
|
|
39
|
+
};
|
|
40
|
+
const RAW_EN_LOCALE = Object.assign(Object.assign({}, MINIMAL_RAW_EN_LOCALE), {
|
|
41
|
+
// Includes things we don't want other locales to inherit,
|
|
42
|
+
// things that derive from other translatable strings.
|
|
43
|
+
buttonHints: {
|
|
44
|
+
prev: 'Previous $0',
|
|
45
|
+
next: 'Next $0',
|
|
46
|
+
today(buttonText, unit) {
|
|
47
|
+
return (unit === 'day')
|
|
48
|
+
? 'Today'
|
|
49
|
+
: `This ${buttonText}`;
|
|
50
|
+
},
|
|
51
|
+
}, viewHint: '$0 view', navLinkHint: 'Go to $0', moreLinkHint(eventCnt) {
|
|
52
|
+
return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;
|
|
53
|
+
} });
|
|
54
|
+
function organizeRawLocales(explicitRawLocales) {
|
|
55
|
+
let defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en';
|
|
56
|
+
let allRawLocales = internalCommon.globalLocales.concat(explicitRawLocales);
|
|
57
|
+
let rawLocaleMap = {
|
|
58
|
+
en: RAW_EN_LOCALE,
|
|
59
|
+
};
|
|
60
|
+
for (let rawLocale of allRawLocales) {
|
|
61
|
+
rawLocaleMap[rawLocale.code] = rawLocale;
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
map: rawLocaleMap,
|
|
65
|
+
defaultCode,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function buildLocale(inputSingular, available) {
|
|
69
|
+
if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) {
|
|
70
|
+
return parseLocale(inputSingular.code, [inputSingular.code], inputSingular);
|
|
71
|
+
}
|
|
72
|
+
return queryLocale(inputSingular, available);
|
|
73
|
+
}
|
|
74
|
+
function queryLocale(codeArg, available) {
|
|
75
|
+
let codes = [].concat(codeArg || []); // will convert to array
|
|
76
|
+
let raw = queryRawLocale(codes, available) || RAW_EN_LOCALE;
|
|
77
|
+
return parseLocale(codeArg, codes, raw);
|
|
78
|
+
}
|
|
79
|
+
function queryRawLocale(codes, available) {
|
|
80
|
+
for (let i = 0; i < codes.length; i += 1) {
|
|
81
|
+
let parts = codes[i].toLocaleLowerCase().split('-');
|
|
82
|
+
for (let j = parts.length; j > 0; j -= 1) {
|
|
83
|
+
let simpleId = parts.slice(0, j).join('-');
|
|
84
|
+
if (available[simpleId]) {
|
|
85
|
+
return available[simpleId];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
function parseLocale(codeArg, codes, raw) {
|
|
92
|
+
let merged = internalCommon.mergeProps([MINIMAL_RAW_EN_LOCALE, raw], ['buttonText']);
|
|
93
|
+
delete merged.code; // don't want this part of the options
|
|
94
|
+
let { week } = merged;
|
|
95
|
+
delete merged.week;
|
|
96
|
+
return {
|
|
97
|
+
codeArg,
|
|
98
|
+
codes,
|
|
99
|
+
week,
|
|
100
|
+
simpleNumberFormat: new Intl.NumberFormat(codeArg),
|
|
101
|
+
options: merged,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
class StandardTheme extends internalCommon.Theme {
|
|
106
|
+
}
|
|
107
|
+
StandardTheme.prototype.classes = {
|
|
108
|
+
root: 'fc-theme-standard',
|
|
109
|
+
tableCellShaded: 'fc-cell-shaded',
|
|
110
|
+
buttonGroup: 'fc-button-group',
|
|
111
|
+
button: 'fc-button fc-button-primary',
|
|
112
|
+
buttonActive: 'fc-button-active',
|
|
113
|
+
};
|
|
114
|
+
StandardTheme.prototype.baseIconClass = 'fc-icon';
|
|
115
|
+
StandardTheme.prototype.iconClasses = {
|
|
116
|
+
close: 'fc-icon-x',
|
|
117
|
+
prev: 'fc-icon-chevron-left',
|
|
118
|
+
next: 'fc-icon-chevron-right',
|
|
119
|
+
prevYear: 'fc-icon-chevrons-left',
|
|
120
|
+
nextYear: 'fc-icon-chevrons-right',
|
|
121
|
+
};
|
|
122
|
+
StandardTheme.prototype.rtlIconClasses = {
|
|
123
|
+
prev: 'fc-icon-chevron-right',
|
|
124
|
+
next: 'fc-icon-chevron-left',
|
|
125
|
+
prevYear: 'fc-icon-chevrons-right',
|
|
126
|
+
nextYear: 'fc-icon-chevrons-left',
|
|
127
|
+
};
|
|
128
|
+
StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; // TODO: make TS-friendly
|
|
129
|
+
StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon';
|
|
130
|
+
StandardTheme.prototype.iconOverridePrefix = 'fc-icon-';
|
|
131
|
+
|
|
132
|
+
function compileViewDefs(defaultConfigs, overrideConfigs) {
|
|
133
|
+
let hash = {};
|
|
134
|
+
let viewType;
|
|
135
|
+
for (viewType in defaultConfigs) {
|
|
136
|
+
ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
|
|
137
|
+
}
|
|
138
|
+
for (viewType in overrideConfigs) {
|
|
139
|
+
ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
|
|
140
|
+
}
|
|
141
|
+
return hash;
|
|
142
|
+
}
|
|
143
|
+
function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
|
|
144
|
+
if (hash[viewType]) {
|
|
145
|
+
return hash[viewType];
|
|
146
|
+
}
|
|
147
|
+
let viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs);
|
|
148
|
+
if (viewDef) {
|
|
149
|
+
hash[viewType] = viewDef;
|
|
150
|
+
}
|
|
151
|
+
return viewDef;
|
|
152
|
+
}
|
|
153
|
+
function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
|
|
154
|
+
let defaultConfig = defaultConfigs[viewType];
|
|
155
|
+
let overrideConfig = overrideConfigs[viewType];
|
|
156
|
+
let queryProp = (name) => ((defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] :
|
|
157
|
+
((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null));
|
|
158
|
+
let theComponent = queryProp('component');
|
|
159
|
+
let superType = queryProp('superType');
|
|
160
|
+
let superDef = null;
|
|
161
|
+
if (superType) {
|
|
162
|
+
if (superType === viewType) {
|
|
163
|
+
throw new Error('Can\'t have a custom view type that references itself');
|
|
164
|
+
}
|
|
165
|
+
superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs);
|
|
166
|
+
}
|
|
167
|
+
if (!theComponent && superDef) {
|
|
168
|
+
theComponent = superDef.component;
|
|
169
|
+
}
|
|
170
|
+
if (!theComponent) {
|
|
171
|
+
return null; // don't throw a warning, might be settings for a single-unit view
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
type: viewType,
|
|
175
|
+
component: theComponent,
|
|
176
|
+
defaults: Object.assign(Object.assign({}, (superDef ? superDef.defaults : {})), (defaultConfig ? defaultConfig.rawOptions : {})),
|
|
177
|
+
overrides: Object.assign(Object.assign({}, (superDef ? superDef.overrides : {})), (overrideConfig ? overrideConfig.rawOptions : {})),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function parseViewConfigs(inputs) {
|
|
182
|
+
return internalCommon.mapHash(inputs, parseViewConfig);
|
|
183
|
+
}
|
|
184
|
+
function parseViewConfig(input) {
|
|
185
|
+
let rawOptions = typeof input === 'function' ?
|
|
186
|
+
{ component: input } :
|
|
187
|
+
input;
|
|
188
|
+
let { component } = rawOptions;
|
|
189
|
+
if (rawOptions.content) {
|
|
190
|
+
component = createViewHookComponent(rawOptions);
|
|
191
|
+
// TODO: remove content/classNames/didMount/etc from options?
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
superType: rawOptions.type,
|
|
195
|
+
component: component,
|
|
196
|
+
rawOptions, // includes type and component too :(
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function createViewHookComponent(options) {
|
|
200
|
+
return (viewProps) => (preact.createElement(internalCommon.ViewContextType.Consumer, null, (context) => (preact.createElement(internalCommon.ContentContainer, { elTag: "div", elClasses: internalCommon.buildViewClassNames(context.viewSpec), renderProps: Object.assign(Object.assign({}, viewProps), { nextDayThreshold: context.options.nextDayThreshold }), generatorName: undefined, generator: options.content, classNameGenerator: options.classNames, didMount: options.didMount, willUnmount: options.willUnmount }))));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function buildViewSpecs(defaultInputs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
|
|
204
|
+
let defaultConfigs = parseViewConfigs(defaultInputs);
|
|
205
|
+
let overrideConfigs = parseViewConfigs(optionOverrides.views);
|
|
206
|
+
let viewDefs = compileViewDefs(defaultConfigs, overrideConfigs);
|
|
207
|
+
return internalCommon.mapHash(viewDefs, (viewDef) => buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults));
|
|
208
|
+
}
|
|
209
|
+
function buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
|
|
210
|
+
let durationInput = viewDef.overrides.duration ||
|
|
211
|
+
viewDef.defaults.duration ||
|
|
212
|
+
dynamicOptionOverrides.duration ||
|
|
213
|
+
optionOverrides.duration;
|
|
214
|
+
let duration = null;
|
|
215
|
+
let durationUnit = '';
|
|
216
|
+
let singleUnit = '';
|
|
217
|
+
let singleUnitOverrides = {};
|
|
218
|
+
if (durationInput) {
|
|
219
|
+
duration = createDurationCached(durationInput);
|
|
220
|
+
if (duration) { // valid?
|
|
221
|
+
let denom = internalCommon.greatestDurationDenominator(duration);
|
|
222
|
+
durationUnit = denom.unit;
|
|
223
|
+
if (denom.value === 1) {
|
|
224
|
+
singleUnit = durationUnit;
|
|
225
|
+
singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].rawOptions : {};
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
let queryButtonText = (optionsSubset) => {
|
|
230
|
+
let buttonTextMap = optionsSubset.buttonText || {};
|
|
231
|
+
let buttonTextKey = viewDef.defaults.buttonTextKey;
|
|
232
|
+
if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) {
|
|
233
|
+
return buttonTextMap[buttonTextKey];
|
|
234
|
+
}
|
|
235
|
+
if (buttonTextMap[viewDef.type] != null) {
|
|
236
|
+
return buttonTextMap[viewDef.type];
|
|
237
|
+
}
|
|
238
|
+
if (buttonTextMap[singleUnit] != null) {
|
|
239
|
+
return buttonTextMap[singleUnit];
|
|
240
|
+
}
|
|
241
|
+
return null;
|
|
242
|
+
};
|
|
243
|
+
let queryButtonTitle = (optionsSubset) => {
|
|
244
|
+
let buttonHints = optionsSubset.buttonHints || {};
|
|
245
|
+
let buttonKey = viewDef.defaults.buttonTextKey; // use same key as text
|
|
246
|
+
if (buttonKey != null && buttonHints[buttonKey] != null) {
|
|
247
|
+
return buttonHints[buttonKey];
|
|
248
|
+
}
|
|
249
|
+
if (buttonHints[viewDef.type] != null) {
|
|
250
|
+
return buttonHints[viewDef.type];
|
|
251
|
+
}
|
|
252
|
+
if (buttonHints[singleUnit] != null) {
|
|
253
|
+
return buttonHints[singleUnit];
|
|
254
|
+
}
|
|
255
|
+
return null;
|
|
256
|
+
};
|
|
257
|
+
return {
|
|
258
|
+
type: viewDef.type,
|
|
259
|
+
component: viewDef.component,
|
|
260
|
+
duration,
|
|
261
|
+
durationUnit,
|
|
262
|
+
singleUnit,
|
|
263
|
+
optionDefaults: viewDef.defaults,
|
|
264
|
+
optionOverrides: Object.assign(Object.assign({}, singleUnitOverrides), viewDef.overrides),
|
|
265
|
+
buttonTextOverride: queryButtonText(dynamicOptionOverrides) ||
|
|
266
|
+
queryButtonText(optionOverrides) || // constructor-specified buttonText lookup hash takes precedence
|
|
267
|
+
viewDef.overrides.buttonText,
|
|
268
|
+
buttonTextDefault: queryButtonText(localeDefaults) ||
|
|
269
|
+
viewDef.defaults.buttonText ||
|
|
270
|
+
queryButtonText(internalCommon.BASE_OPTION_DEFAULTS) ||
|
|
271
|
+
viewDef.type,
|
|
272
|
+
// not DRY
|
|
273
|
+
buttonTitleOverride: queryButtonTitle(dynamicOptionOverrides) ||
|
|
274
|
+
queryButtonTitle(optionOverrides) ||
|
|
275
|
+
viewDef.overrides.buttonHint,
|
|
276
|
+
buttonTitleDefault: queryButtonTitle(localeDefaults) ||
|
|
277
|
+
viewDef.defaults.buttonHint ||
|
|
278
|
+
queryButtonTitle(internalCommon.BASE_OPTION_DEFAULTS),
|
|
279
|
+
// will eventually fall back to buttonText
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
// hack to get memoization working
|
|
283
|
+
let durationInputMap = {};
|
|
284
|
+
function createDurationCached(durationInput) {
|
|
285
|
+
let json = JSON.stringify(durationInput);
|
|
286
|
+
let res = durationInputMap[json];
|
|
287
|
+
if (res === undefined) {
|
|
288
|
+
res = internalCommon.createDuration(durationInput);
|
|
289
|
+
durationInputMap[json] = res;
|
|
290
|
+
}
|
|
291
|
+
return res;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function reduceViewType(viewType, action) {
|
|
295
|
+
switch (action.type) {
|
|
296
|
+
case 'CHANGE_VIEW_TYPE':
|
|
297
|
+
viewType = action.viewType;
|
|
298
|
+
}
|
|
299
|
+
return viewType;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function reduceDynamicOptionOverrides(dynamicOptionOverrides, action) {
|
|
303
|
+
switch (action.type) {
|
|
304
|
+
case 'SET_OPTION':
|
|
305
|
+
return Object.assign(Object.assign({}, dynamicOptionOverrides), { [action.optionName]: action.rawOptionValue });
|
|
306
|
+
default:
|
|
307
|
+
return dynamicOptionOverrides;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function reduceDateProfile(currentDateProfile, action, currentDate, dateProfileGenerator) {
|
|
312
|
+
let dp;
|
|
313
|
+
switch (action.type) {
|
|
314
|
+
case 'CHANGE_VIEW_TYPE':
|
|
315
|
+
return dateProfileGenerator.build(action.dateMarker || currentDate);
|
|
316
|
+
case 'CHANGE_DATE':
|
|
317
|
+
return dateProfileGenerator.build(action.dateMarker);
|
|
318
|
+
case 'PREV':
|
|
319
|
+
dp = dateProfileGenerator.buildPrev(currentDateProfile, currentDate);
|
|
320
|
+
if (dp.isValid) {
|
|
321
|
+
return dp;
|
|
322
|
+
}
|
|
323
|
+
break;
|
|
324
|
+
case 'NEXT':
|
|
325
|
+
dp = dateProfileGenerator.buildNext(currentDateProfile, currentDate);
|
|
326
|
+
if (dp.isValid) {
|
|
327
|
+
return dp;
|
|
328
|
+
}
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
return currentDateProfile;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function reduceDateSelection(currentSelection, action) {
|
|
335
|
+
switch (action.type) {
|
|
336
|
+
case 'UNSELECT_DATES':
|
|
337
|
+
return null;
|
|
338
|
+
case 'SELECT_DATES':
|
|
339
|
+
return action.selection;
|
|
340
|
+
default:
|
|
341
|
+
return currentSelection;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function reduceSelectedEvent(currentInstanceId, action) {
|
|
346
|
+
switch (action.type) {
|
|
347
|
+
case 'UNSELECT_EVENT':
|
|
348
|
+
return '';
|
|
349
|
+
case 'SELECT_EVENT':
|
|
350
|
+
return action.eventInstanceId;
|
|
351
|
+
default:
|
|
352
|
+
return currentInstanceId;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function reduceEventDrag(currentDrag, action) {
|
|
357
|
+
let newDrag;
|
|
358
|
+
switch (action.type) {
|
|
359
|
+
case 'UNSET_EVENT_DRAG':
|
|
360
|
+
return null;
|
|
361
|
+
case 'SET_EVENT_DRAG':
|
|
362
|
+
newDrag = action.state;
|
|
363
|
+
return {
|
|
364
|
+
affectedEvents: newDrag.affectedEvents,
|
|
365
|
+
mutatedEvents: newDrag.mutatedEvents,
|
|
366
|
+
isEvent: newDrag.isEvent,
|
|
367
|
+
};
|
|
368
|
+
default:
|
|
369
|
+
return currentDrag;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function reduceEventResize(currentResize, action) {
|
|
374
|
+
let newResize;
|
|
375
|
+
switch (action.type) {
|
|
376
|
+
case 'UNSET_EVENT_RESIZE':
|
|
377
|
+
return null;
|
|
378
|
+
case 'SET_EVENT_RESIZE':
|
|
379
|
+
newResize = action.state;
|
|
380
|
+
return {
|
|
381
|
+
affectedEvents: newResize.affectedEvents,
|
|
382
|
+
mutatedEvents: newResize.mutatedEvents,
|
|
383
|
+
isEvent: newResize.isEvent,
|
|
384
|
+
};
|
|
385
|
+
default:
|
|
386
|
+
return currentResize;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function parseToolbars(calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
|
|
391
|
+
let header = calendarOptions.headerToolbar ? parseToolbar(calendarOptions.headerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
|
|
392
|
+
let footer = calendarOptions.footerToolbar ? parseToolbar(calendarOptions.footerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
|
|
393
|
+
return { header, footer };
|
|
394
|
+
}
|
|
395
|
+
function parseToolbar(sectionStrHash, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
|
|
396
|
+
let sectionWidgets = {};
|
|
397
|
+
let viewsWithButtons = [];
|
|
398
|
+
let hasTitle = false;
|
|
399
|
+
for (let sectionName in sectionStrHash) {
|
|
400
|
+
let sectionStr = sectionStrHash[sectionName];
|
|
401
|
+
let sectionRes = parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi);
|
|
402
|
+
sectionWidgets[sectionName] = sectionRes.widgets;
|
|
403
|
+
viewsWithButtons.push(...sectionRes.viewsWithButtons);
|
|
404
|
+
hasTitle = hasTitle || sectionRes.hasTitle;
|
|
405
|
+
}
|
|
406
|
+
return { sectionWidgets, viewsWithButtons, hasTitle };
|
|
407
|
+
}
|
|
408
|
+
/*
|
|
409
|
+
BAD: querying icons and text here. should be done at render time
|
|
410
|
+
*/
|
|
411
|
+
function parseSection(sectionStr, calendarOptions, // defaults+overrides, then refined
|
|
412
|
+
calendarOptionOverrides, // overrides only!, unrefined :(
|
|
413
|
+
theme, viewSpecs, calendarApi) {
|
|
414
|
+
let isRtl = calendarOptions.direction === 'rtl';
|
|
415
|
+
let calendarCustomButtons = calendarOptions.customButtons || {};
|
|
416
|
+
let calendarButtonTextOverrides = calendarOptionOverrides.buttonText || {};
|
|
417
|
+
let calendarButtonText = calendarOptions.buttonText || {};
|
|
418
|
+
let calendarButtonHintOverrides = calendarOptionOverrides.buttonHints || {};
|
|
419
|
+
let calendarButtonHints = calendarOptions.buttonHints || {};
|
|
420
|
+
let sectionSubstrs = sectionStr ? sectionStr.split(' ') : [];
|
|
421
|
+
let viewsWithButtons = [];
|
|
422
|
+
let hasTitle = false;
|
|
423
|
+
let widgets = sectionSubstrs.map((buttonGroupStr) => (buttonGroupStr.split(',').map((buttonName) => {
|
|
424
|
+
if (buttonName === 'title') {
|
|
425
|
+
hasTitle = true;
|
|
426
|
+
return { buttonName };
|
|
427
|
+
}
|
|
428
|
+
let customButtonProps;
|
|
429
|
+
let viewSpec;
|
|
430
|
+
let buttonClick;
|
|
431
|
+
let buttonIcon; // only one of these will be set
|
|
432
|
+
let buttonText; // "
|
|
433
|
+
let buttonHint;
|
|
434
|
+
// ^ for the title="" attribute, for accessibility
|
|
435
|
+
if ((customButtonProps = calendarCustomButtons[buttonName])) {
|
|
436
|
+
buttonClick = (ev) => {
|
|
437
|
+
if (customButtonProps.click) {
|
|
438
|
+
customButtonProps.click.call(ev.target, ev, ev.target); // TODO: use Calendar this context?
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
(buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) ||
|
|
442
|
+
(buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
|
|
443
|
+
(buttonText = customButtonProps.text);
|
|
444
|
+
buttonHint = customButtonProps.hint || customButtonProps.text;
|
|
445
|
+
}
|
|
446
|
+
else if ((viewSpec = viewSpecs[buttonName])) {
|
|
447
|
+
viewsWithButtons.push(buttonName);
|
|
448
|
+
buttonClick = () => {
|
|
449
|
+
calendarApi.changeView(buttonName);
|
|
450
|
+
};
|
|
451
|
+
(buttonText = viewSpec.buttonTextOverride) ||
|
|
452
|
+
(buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
|
|
453
|
+
(buttonText = viewSpec.buttonTextDefault);
|
|
454
|
+
let textFallback = viewSpec.buttonTextOverride ||
|
|
455
|
+
viewSpec.buttonTextDefault;
|
|
456
|
+
buttonHint = internalCommon.formatWithOrdinals(viewSpec.buttonTitleOverride ||
|
|
457
|
+
viewSpec.buttonTitleDefault ||
|
|
458
|
+
calendarOptions.viewHint, [textFallback, buttonName], // view-name = buttonName
|
|
459
|
+
textFallback);
|
|
460
|
+
}
|
|
461
|
+
else if (calendarApi[buttonName]) { // a calendarApi method
|
|
462
|
+
buttonClick = () => {
|
|
463
|
+
calendarApi[buttonName]();
|
|
464
|
+
};
|
|
465
|
+
(buttonText = calendarButtonTextOverrides[buttonName]) ||
|
|
466
|
+
(buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
|
|
467
|
+
(buttonText = calendarButtonText[buttonName]); // everything else is considered default
|
|
468
|
+
if (buttonName === 'prevYear' || buttonName === 'nextYear') {
|
|
469
|
+
let prevOrNext = buttonName === 'prevYear' ? 'prev' : 'next';
|
|
470
|
+
buttonHint = internalCommon.formatWithOrdinals(calendarButtonHintOverrides[prevOrNext] ||
|
|
471
|
+
calendarButtonHints[prevOrNext], [
|
|
472
|
+
calendarButtonText.year || 'year',
|
|
473
|
+
'year',
|
|
474
|
+
], calendarButtonText[buttonName]);
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
buttonHint = (navUnit) => internalCommon.formatWithOrdinals(calendarButtonHintOverrides[buttonName] ||
|
|
478
|
+
calendarButtonHints[buttonName], [
|
|
479
|
+
calendarButtonText[navUnit] || navUnit,
|
|
480
|
+
navUnit,
|
|
481
|
+
], calendarButtonText[buttonName]);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
return { buttonName, buttonClick, buttonIcon, buttonText, buttonHint };
|
|
485
|
+
})));
|
|
486
|
+
return { widgets, viewsWithButtons, hasTitle };
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// always represents the current view. otherwise, it'd need to change value every time date changes
|
|
490
|
+
class ViewImpl {
|
|
491
|
+
constructor(type, getCurrentData, dateEnv) {
|
|
492
|
+
this.type = type;
|
|
493
|
+
this.getCurrentData = getCurrentData;
|
|
494
|
+
this.dateEnv = dateEnv;
|
|
495
|
+
}
|
|
496
|
+
get calendar() {
|
|
497
|
+
return this.getCurrentData().calendarApi;
|
|
498
|
+
}
|
|
499
|
+
get title() {
|
|
500
|
+
return this.getCurrentData().viewTitle;
|
|
501
|
+
}
|
|
502
|
+
get activeStart() {
|
|
503
|
+
return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.start);
|
|
504
|
+
}
|
|
505
|
+
get activeEnd() {
|
|
506
|
+
return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.end);
|
|
507
|
+
}
|
|
508
|
+
get currentStart() {
|
|
509
|
+
return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.start);
|
|
510
|
+
}
|
|
511
|
+
get currentEnd() {
|
|
512
|
+
return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.end);
|
|
513
|
+
}
|
|
514
|
+
getOption(name) {
|
|
515
|
+
return this.getCurrentData().options[name]; // are the view-specific options
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
class TaskRunner {
|
|
520
|
+
constructor(runTaskOption, drainedOption) {
|
|
521
|
+
this.runTaskOption = runTaskOption;
|
|
522
|
+
this.drainedOption = drainedOption;
|
|
523
|
+
this.queue = [];
|
|
524
|
+
this.delayedRunner = new internalCommon.DelayedRunner(this.drain.bind(this));
|
|
525
|
+
}
|
|
526
|
+
request(task, delay) {
|
|
527
|
+
this.queue.push(task);
|
|
528
|
+
this.delayedRunner.request(delay);
|
|
529
|
+
}
|
|
530
|
+
pause(scope) {
|
|
531
|
+
this.delayedRunner.pause(scope);
|
|
532
|
+
}
|
|
533
|
+
resume(scope, force) {
|
|
534
|
+
this.delayedRunner.resume(scope, force);
|
|
535
|
+
}
|
|
536
|
+
drain() {
|
|
537
|
+
let { queue } = this;
|
|
538
|
+
while (queue.length) {
|
|
539
|
+
let completedTasks = [];
|
|
540
|
+
let task;
|
|
541
|
+
while ((task = queue.shift())) {
|
|
542
|
+
this.runTask(task);
|
|
543
|
+
completedTasks.push(task);
|
|
544
|
+
}
|
|
545
|
+
this.drained(completedTasks);
|
|
546
|
+
} // keep going, in case new tasks were added in the drained handler
|
|
547
|
+
}
|
|
548
|
+
runTask(task) {
|
|
549
|
+
if (this.runTaskOption) {
|
|
550
|
+
this.runTaskOption(task);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
drained(completedTasks) {
|
|
554
|
+
if (this.drainedOption) {
|
|
555
|
+
this.drainedOption(completedTasks);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// Computes what the title at the top of the calendarApi should be for this view
|
|
561
|
+
function buildTitle(dateProfile, viewOptions, dateEnv) {
|
|
562
|
+
let range;
|
|
563
|
+
// for views that span a large unit of time, show the proper interval, ignoring stray days before and after
|
|
564
|
+
if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) {
|
|
565
|
+
range = dateProfile.currentRange;
|
|
566
|
+
}
|
|
567
|
+
else { // for day units or smaller, use the actual day range
|
|
568
|
+
range = dateProfile.activeRange;
|
|
569
|
+
}
|
|
570
|
+
return dateEnv.formatRange(range.start, range.end, internalCommon.createFormatter(viewOptions.titleFormat || buildTitleFormat(dateProfile)), {
|
|
571
|
+
isEndExclusive: dateProfile.isRangeAllDay,
|
|
572
|
+
defaultSeparator: viewOptions.titleRangeSeparator,
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
// Generates the format string that should be used to generate the title for the current date range.
|
|
576
|
+
// Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
|
|
577
|
+
function buildTitleFormat(dateProfile) {
|
|
578
|
+
let { currentRangeUnit } = dateProfile;
|
|
579
|
+
if (currentRangeUnit === 'year') {
|
|
580
|
+
return { year: 'numeric' };
|
|
581
|
+
}
|
|
582
|
+
if (currentRangeUnit === 'month') {
|
|
583
|
+
return { year: 'numeric', month: 'long' }; // like "September 2014"
|
|
584
|
+
}
|
|
585
|
+
let days = internalCommon.diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end);
|
|
586
|
+
if (days !== null && days > 1) {
|
|
587
|
+
// multi-day range. shorter, like "Sep 9 - 10 2014"
|
|
588
|
+
return { year: 'numeric', month: 'short', day: 'numeric' };
|
|
589
|
+
}
|
|
590
|
+
// one day. longer, like "September 9 2014"
|
|
591
|
+
return { year: 'numeric', month: 'long', day: 'numeric' };
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// in future refactor, do the redux-style function(state=initial) for initial-state
|
|
595
|
+
// also, whatever is happening in constructor, have it happen in action queue too
|
|
596
|
+
class CalendarDataManager {
|
|
597
|
+
constructor(props) {
|
|
598
|
+
this.computeOptionsData = internalCommon.memoize(this._computeOptionsData);
|
|
599
|
+
this.computeCurrentViewData = internalCommon.memoize(this._computeCurrentViewData);
|
|
600
|
+
this.organizeRawLocales = internalCommon.memoize(organizeRawLocales);
|
|
601
|
+
this.buildLocale = internalCommon.memoize(buildLocale);
|
|
602
|
+
this.buildPluginHooks = internalCommon.buildBuildPluginHooks();
|
|
603
|
+
this.buildDateEnv = internalCommon.memoize(buildDateEnv$1);
|
|
604
|
+
this.buildTheme = internalCommon.memoize(buildTheme);
|
|
605
|
+
this.parseToolbars = internalCommon.memoize(parseToolbars);
|
|
606
|
+
this.buildViewSpecs = internalCommon.memoize(buildViewSpecs);
|
|
607
|
+
this.buildDateProfileGenerator = internalCommon.memoizeObjArg(buildDateProfileGenerator);
|
|
608
|
+
this.buildViewApi = internalCommon.memoize(buildViewApi);
|
|
609
|
+
this.buildViewUiProps = internalCommon.memoizeObjArg(buildViewUiProps);
|
|
610
|
+
this.buildEventUiBySource = internalCommon.memoize(buildEventUiBySource, internalCommon.isPropsEqual);
|
|
611
|
+
this.buildEventUiBases = internalCommon.memoize(buildEventUiBases);
|
|
612
|
+
this.parseContextBusinessHours = internalCommon.memoizeObjArg(parseContextBusinessHours);
|
|
613
|
+
this.buildTitle = internalCommon.memoize(buildTitle);
|
|
614
|
+
this.emitter = new internalCommon.Emitter();
|
|
615
|
+
this.actionRunner = new TaskRunner(this._handleAction.bind(this), this.updateData.bind(this));
|
|
616
|
+
this.currentCalendarOptionsInput = {};
|
|
617
|
+
this.currentCalendarOptionsRefined = {};
|
|
618
|
+
this.currentViewOptionsInput = {};
|
|
619
|
+
this.currentViewOptionsRefined = {};
|
|
620
|
+
this.currentCalendarOptionsRefiners = {};
|
|
621
|
+
this.getCurrentData = () => this.data;
|
|
622
|
+
this.dispatch = (action) => {
|
|
623
|
+
this.actionRunner.request(action); // protects against recursive calls to _handleAction
|
|
624
|
+
};
|
|
625
|
+
this.props = props;
|
|
626
|
+
this.actionRunner.pause();
|
|
627
|
+
let dynamicOptionOverrides = {};
|
|
628
|
+
let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
|
|
629
|
+
let currentViewType = optionsData.calendarOptions.initialView || optionsData.pluginHooks.initialView;
|
|
630
|
+
let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
|
|
631
|
+
// wire things up
|
|
632
|
+
// TODO: not DRY
|
|
633
|
+
props.calendarApi.currentDataManager = this;
|
|
634
|
+
this.emitter.setThisContext(props.calendarApi);
|
|
635
|
+
this.emitter.setOptions(currentViewData.options);
|
|
636
|
+
let currentDate = internalCommon.getInitialDate(optionsData.calendarOptions, optionsData.dateEnv);
|
|
637
|
+
let dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
|
|
638
|
+
if (!internalCommon.rangeContainsMarker(dateProfile.activeRange, currentDate)) {
|
|
639
|
+
currentDate = dateProfile.currentRange.start;
|
|
640
|
+
}
|
|
641
|
+
let calendarContext = {
|
|
642
|
+
dateEnv: optionsData.dateEnv,
|
|
643
|
+
options: optionsData.calendarOptions,
|
|
644
|
+
pluginHooks: optionsData.pluginHooks,
|
|
645
|
+
calendarApi: props.calendarApi,
|
|
646
|
+
dispatch: this.dispatch,
|
|
647
|
+
emitter: this.emitter,
|
|
648
|
+
getCurrentData: this.getCurrentData,
|
|
649
|
+
};
|
|
650
|
+
// needs to be after setThisContext
|
|
651
|
+
for (let callback of optionsData.pluginHooks.contextInit) {
|
|
652
|
+
callback(calendarContext);
|
|
653
|
+
}
|
|
654
|
+
// NOT DRY
|
|
655
|
+
let eventSources = internalCommon.initEventSources(optionsData.calendarOptions, dateProfile, calendarContext);
|
|
656
|
+
let initialState = {
|
|
657
|
+
dynamicOptionOverrides,
|
|
658
|
+
currentViewType,
|
|
659
|
+
currentDate,
|
|
660
|
+
dateProfile,
|
|
661
|
+
businessHours: this.parseContextBusinessHours(calendarContext),
|
|
662
|
+
eventSources,
|
|
663
|
+
eventUiBases: {},
|
|
664
|
+
eventStore: internalCommon.createEmptyEventStore(),
|
|
665
|
+
renderableEventStore: internalCommon.createEmptyEventStore(),
|
|
666
|
+
dateSelection: null,
|
|
667
|
+
eventSelection: '',
|
|
668
|
+
eventDrag: null,
|
|
669
|
+
eventResize: null,
|
|
670
|
+
selectionConfig: this.buildViewUiProps(calendarContext).selectionConfig,
|
|
671
|
+
};
|
|
672
|
+
let contextAndState = Object.assign(Object.assign({}, calendarContext), initialState);
|
|
673
|
+
for (let reducer of optionsData.pluginHooks.reducers) {
|
|
674
|
+
Object.assign(initialState, reducer(null, null, contextAndState));
|
|
675
|
+
}
|
|
676
|
+
if (computeIsLoading(initialState, calendarContext)) {
|
|
677
|
+
this.emitter.trigger('loading', true); // NOT DRY
|
|
678
|
+
}
|
|
679
|
+
this.state = initialState;
|
|
680
|
+
this.updateData();
|
|
681
|
+
this.actionRunner.resume();
|
|
682
|
+
}
|
|
683
|
+
resetOptions(optionOverrides, append) {
|
|
684
|
+
let { props } = this;
|
|
685
|
+
props.optionOverrides = append
|
|
686
|
+
? Object.assign(Object.assign({}, props.optionOverrides), optionOverrides) : optionOverrides;
|
|
687
|
+
this.actionRunner.request({
|
|
688
|
+
type: 'NOTHING',
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
_handleAction(action) {
|
|
692
|
+
let { props, state, emitter } = this;
|
|
693
|
+
let dynamicOptionOverrides = reduceDynamicOptionOverrides(state.dynamicOptionOverrides, action);
|
|
694
|
+
let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
|
|
695
|
+
let currentViewType = reduceViewType(state.currentViewType, action);
|
|
696
|
+
let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
|
|
697
|
+
// wire things up
|
|
698
|
+
// TODO: not DRY
|
|
699
|
+
props.calendarApi.currentDataManager = this;
|
|
700
|
+
emitter.setThisContext(props.calendarApi);
|
|
701
|
+
emitter.setOptions(currentViewData.options);
|
|
702
|
+
let calendarContext = {
|
|
703
|
+
dateEnv: optionsData.dateEnv,
|
|
704
|
+
options: optionsData.calendarOptions,
|
|
705
|
+
pluginHooks: optionsData.pluginHooks,
|
|
706
|
+
calendarApi: props.calendarApi,
|
|
707
|
+
dispatch: this.dispatch,
|
|
708
|
+
emitter,
|
|
709
|
+
getCurrentData: this.getCurrentData,
|
|
710
|
+
};
|
|
711
|
+
let { currentDate, dateProfile } = state;
|
|
712
|
+
if (this.data && this.data.dateProfileGenerator !== currentViewData.dateProfileGenerator) { // hack
|
|
713
|
+
dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
|
|
714
|
+
}
|
|
715
|
+
currentDate = internalCommon.reduceCurrentDate(currentDate, action);
|
|
716
|
+
dateProfile = reduceDateProfile(dateProfile, action, currentDate, currentViewData.dateProfileGenerator);
|
|
717
|
+
if (action.type === 'PREV' || // TODO: move this logic into DateProfileGenerator
|
|
718
|
+
action.type === 'NEXT' || // "
|
|
719
|
+
!internalCommon.rangeContainsMarker(dateProfile.currentRange, currentDate)) {
|
|
720
|
+
currentDate = dateProfile.currentRange.start;
|
|
721
|
+
}
|
|
722
|
+
let eventSources = internalCommon.reduceEventSources(state.eventSources, action, dateProfile, calendarContext);
|
|
723
|
+
let eventStore = internalCommon.reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendarContext);
|
|
724
|
+
let isEventsLoading = internalCommon.computeEventSourcesLoading(eventSources); // BAD. also called in this func in computeIsLoading
|
|
725
|
+
let renderableEventStore = (isEventsLoading && !currentViewData.options.progressiveEventRendering) ?
|
|
726
|
+
(state.renderableEventStore || eventStore) : // try from previous state
|
|
727
|
+
eventStore;
|
|
728
|
+
let { eventUiSingleBase, selectionConfig } = this.buildViewUiProps(calendarContext); // will memoize obj
|
|
729
|
+
let eventUiBySource = this.buildEventUiBySource(eventSources);
|
|
730
|
+
let eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource);
|
|
731
|
+
let newState = {
|
|
732
|
+
dynamicOptionOverrides,
|
|
733
|
+
currentViewType,
|
|
734
|
+
currentDate,
|
|
735
|
+
dateProfile,
|
|
736
|
+
eventSources,
|
|
737
|
+
eventStore,
|
|
738
|
+
renderableEventStore,
|
|
739
|
+
selectionConfig,
|
|
740
|
+
eventUiBases,
|
|
741
|
+
businessHours: this.parseContextBusinessHours(calendarContext),
|
|
742
|
+
dateSelection: reduceDateSelection(state.dateSelection, action),
|
|
743
|
+
eventSelection: reduceSelectedEvent(state.eventSelection, action),
|
|
744
|
+
eventDrag: reduceEventDrag(state.eventDrag, action),
|
|
745
|
+
eventResize: reduceEventResize(state.eventResize, action),
|
|
746
|
+
};
|
|
747
|
+
let contextAndState = Object.assign(Object.assign({}, calendarContext), newState);
|
|
748
|
+
for (let reducer of optionsData.pluginHooks.reducers) {
|
|
749
|
+
Object.assign(newState, reducer(state, action, contextAndState)); // give the OLD state, for old value
|
|
750
|
+
}
|
|
751
|
+
let wasLoading = computeIsLoading(state, calendarContext);
|
|
752
|
+
let isLoading = computeIsLoading(newState, calendarContext);
|
|
753
|
+
// TODO: use propSetHandlers in plugin system
|
|
754
|
+
if (!wasLoading && isLoading) {
|
|
755
|
+
emitter.trigger('loading', true);
|
|
756
|
+
}
|
|
757
|
+
else if (wasLoading && !isLoading) {
|
|
758
|
+
emitter.trigger('loading', false);
|
|
759
|
+
}
|
|
760
|
+
this.state = newState;
|
|
761
|
+
if (props.onAction) {
|
|
762
|
+
props.onAction(action);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
updateData() {
|
|
766
|
+
let { props, state } = this;
|
|
767
|
+
let oldData = this.data;
|
|
768
|
+
let optionsData = this.computeOptionsData(props.optionOverrides, state.dynamicOptionOverrides, props.calendarApi);
|
|
769
|
+
let currentViewData = this.computeCurrentViewData(state.currentViewType, optionsData, props.optionOverrides, state.dynamicOptionOverrides);
|
|
770
|
+
let data = this.data = Object.assign(Object.assign(Object.assign({ viewTitle: this.buildTitle(state.dateProfile, currentViewData.options, optionsData.dateEnv), calendarApi: props.calendarApi, dispatch: this.dispatch, emitter: this.emitter, getCurrentData: this.getCurrentData }, optionsData), currentViewData), state);
|
|
771
|
+
let changeHandlers = optionsData.pluginHooks.optionChangeHandlers;
|
|
772
|
+
let oldCalendarOptions = oldData && oldData.calendarOptions;
|
|
773
|
+
let newCalendarOptions = optionsData.calendarOptions;
|
|
774
|
+
if (oldCalendarOptions && oldCalendarOptions !== newCalendarOptions) {
|
|
775
|
+
if (oldCalendarOptions.timeZone !== newCalendarOptions.timeZone) {
|
|
776
|
+
// hack
|
|
777
|
+
state.eventSources = data.eventSources = internalCommon.reduceEventSourcesNewTimeZone(data.eventSources, state.dateProfile, data);
|
|
778
|
+
state.eventStore = data.eventStore = internalCommon.rezoneEventStoreDates(data.eventStore, oldData.dateEnv, data.dateEnv);
|
|
779
|
+
}
|
|
780
|
+
for (let optionName in changeHandlers) {
|
|
781
|
+
if (oldCalendarOptions[optionName] !== newCalendarOptions[optionName]) {
|
|
782
|
+
changeHandlers[optionName](newCalendarOptions[optionName], data);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
if (props.onData) {
|
|
787
|
+
props.onData(data);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
_computeOptionsData(optionOverrides, dynamicOptionOverrides, calendarApi) {
|
|
791
|
+
// TODO: blacklist options that are handled by optionChangeHandlers
|
|
792
|
+
let { refinedOptions, pluginHooks, localeDefaults, availableLocaleData, extra, } = this.processRawCalendarOptions(optionOverrides, dynamicOptionOverrides);
|
|
793
|
+
warnUnknownOptions(extra);
|
|
794
|
+
let dateEnv = this.buildDateEnv(refinedOptions.timeZone, refinedOptions.locale, refinedOptions.weekNumberCalculation, refinedOptions.firstDay, refinedOptions.weekText, pluginHooks, availableLocaleData, refinedOptions.defaultRangeSeparator);
|
|
795
|
+
let viewSpecs = this.buildViewSpecs(pluginHooks.views, optionOverrides, dynamicOptionOverrides, localeDefaults);
|
|
796
|
+
let theme = this.buildTheme(refinedOptions, pluginHooks);
|
|
797
|
+
let toolbarConfig = this.parseToolbars(refinedOptions, optionOverrides, theme, viewSpecs, calendarApi);
|
|
798
|
+
return {
|
|
799
|
+
calendarOptions: refinedOptions,
|
|
800
|
+
pluginHooks,
|
|
801
|
+
dateEnv,
|
|
802
|
+
viewSpecs,
|
|
803
|
+
theme,
|
|
804
|
+
toolbarConfig,
|
|
805
|
+
localeDefaults,
|
|
806
|
+
availableRawLocales: availableLocaleData.map,
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
// always called from behind a memoizer
|
|
810
|
+
processRawCalendarOptions(optionOverrides, dynamicOptionOverrides) {
|
|
811
|
+
let { locales, locale } = internalCommon.mergeRawOptions([
|
|
812
|
+
internalCommon.BASE_OPTION_DEFAULTS,
|
|
813
|
+
optionOverrides,
|
|
814
|
+
dynamicOptionOverrides,
|
|
815
|
+
]);
|
|
816
|
+
let availableLocaleData = this.organizeRawLocales(locales);
|
|
817
|
+
let availableRawLocales = availableLocaleData.map;
|
|
818
|
+
let localeDefaults = this.buildLocale(locale || availableLocaleData.defaultCode, availableRawLocales).options;
|
|
819
|
+
let pluginHooks = this.buildPluginHooks(optionOverrides.plugins || [], internalCommon.globalPlugins);
|
|
820
|
+
let refiners = this.currentCalendarOptionsRefiners = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, internalCommon.BASE_OPTION_REFINERS), internalCommon.CALENDAR_LISTENER_REFINERS), internalCommon.CALENDAR_OPTION_REFINERS), pluginHooks.listenerRefiners), pluginHooks.optionRefiners);
|
|
821
|
+
let extra = {};
|
|
822
|
+
let raw = internalCommon.mergeRawOptions([
|
|
823
|
+
internalCommon.BASE_OPTION_DEFAULTS,
|
|
824
|
+
localeDefaults,
|
|
825
|
+
optionOverrides,
|
|
826
|
+
dynamicOptionOverrides,
|
|
827
|
+
]);
|
|
828
|
+
let refined = {};
|
|
829
|
+
let currentRaw = this.currentCalendarOptionsInput;
|
|
830
|
+
let currentRefined = this.currentCalendarOptionsRefined;
|
|
831
|
+
let anyChanges = false;
|
|
832
|
+
for (let optionName in raw) {
|
|
833
|
+
if (optionName !== 'plugins') { // because plugins is special-cased
|
|
834
|
+
if (raw[optionName] === currentRaw[optionName] ||
|
|
835
|
+
(internalCommon.COMPLEX_OPTION_COMPARATORS[optionName] &&
|
|
836
|
+
(optionName in currentRaw) &&
|
|
837
|
+
internalCommon.COMPLEX_OPTION_COMPARATORS[optionName](currentRaw[optionName], raw[optionName]))) {
|
|
838
|
+
refined[optionName] = currentRefined[optionName];
|
|
839
|
+
}
|
|
840
|
+
else if (refiners[optionName]) {
|
|
841
|
+
refined[optionName] = refiners[optionName](raw[optionName]);
|
|
842
|
+
anyChanges = true;
|
|
843
|
+
}
|
|
844
|
+
else {
|
|
845
|
+
extra[optionName] = currentRaw[optionName];
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
if (anyChanges) {
|
|
850
|
+
this.currentCalendarOptionsInput = raw;
|
|
851
|
+
this.currentCalendarOptionsRefined = refined;
|
|
852
|
+
}
|
|
853
|
+
return {
|
|
854
|
+
rawOptions: this.currentCalendarOptionsInput,
|
|
855
|
+
refinedOptions: this.currentCalendarOptionsRefined,
|
|
856
|
+
pluginHooks,
|
|
857
|
+
availableLocaleData,
|
|
858
|
+
localeDefaults,
|
|
859
|
+
extra,
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
_computeCurrentViewData(viewType, optionsData, optionOverrides, dynamicOptionOverrides) {
|
|
863
|
+
let viewSpec = optionsData.viewSpecs[viewType];
|
|
864
|
+
if (!viewSpec) {
|
|
865
|
+
throw new Error(`viewType "${viewType}" is not available. Please make sure you've loaded all neccessary plugins`);
|
|
866
|
+
}
|
|
867
|
+
let { refinedOptions, extra } = this.processRawViewOptions(viewSpec, optionsData.pluginHooks, optionsData.localeDefaults, optionOverrides, dynamicOptionOverrides);
|
|
868
|
+
warnUnknownOptions(extra);
|
|
869
|
+
let dateProfileGenerator = this.buildDateProfileGenerator({
|
|
870
|
+
dateProfileGeneratorClass: viewSpec.optionDefaults.dateProfileGeneratorClass,
|
|
871
|
+
duration: viewSpec.duration,
|
|
872
|
+
durationUnit: viewSpec.durationUnit,
|
|
873
|
+
usesMinMaxTime: viewSpec.optionDefaults.usesMinMaxTime,
|
|
874
|
+
dateEnv: optionsData.dateEnv,
|
|
875
|
+
calendarApi: this.props.calendarApi,
|
|
876
|
+
slotMinTime: refinedOptions.slotMinTime,
|
|
877
|
+
slotMaxTime: refinedOptions.slotMaxTime,
|
|
878
|
+
showNonCurrentDates: refinedOptions.showNonCurrentDates,
|
|
879
|
+
dayCount: refinedOptions.dayCount,
|
|
880
|
+
dateAlignment: refinedOptions.dateAlignment,
|
|
881
|
+
dateIncrement: refinedOptions.dateIncrement,
|
|
882
|
+
hiddenDays: refinedOptions.hiddenDays,
|
|
883
|
+
weekends: refinedOptions.weekends,
|
|
884
|
+
nowInput: refinedOptions.now,
|
|
885
|
+
validRangeInput: refinedOptions.validRange,
|
|
886
|
+
visibleRangeInput: refinedOptions.visibleRange,
|
|
887
|
+
monthMode: refinedOptions.monthMode,
|
|
888
|
+
fixedWeekCount: refinedOptions.fixedWeekCount,
|
|
889
|
+
});
|
|
890
|
+
let viewApi = this.buildViewApi(viewType, this.getCurrentData, optionsData.dateEnv);
|
|
891
|
+
return { viewSpec, options: refinedOptions, dateProfileGenerator, viewApi };
|
|
892
|
+
}
|
|
893
|
+
processRawViewOptions(viewSpec, pluginHooks, localeDefaults, optionOverrides, dynamicOptionOverrides) {
|
|
894
|
+
let raw = internalCommon.mergeRawOptions([
|
|
895
|
+
internalCommon.BASE_OPTION_DEFAULTS,
|
|
896
|
+
viewSpec.optionDefaults,
|
|
897
|
+
localeDefaults,
|
|
898
|
+
optionOverrides,
|
|
899
|
+
viewSpec.optionOverrides,
|
|
900
|
+
dynamicOptionOverrides,
|
|
901
|
+
]);
|
|
902
|
+
let refiners = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, internalCommon.BASE_OPTION_REFINERS), internalCommon.CALENDAR_LISTENER_REFINERS), internalCommon.CALENDAR_OPTION_REFINERS), internalCommon.VIEW_OPTION_REFINERS), pluginHooks.listenerRefiners), pluginHooks.optionRefiners);
|
|
903
|
+
let refined = {};
|
|
904
|
+
let currentRaw = this.currentViewOptionsInput;
|
|
905
|
+
let currentRefined = this.currentViewOptionsRefined;
|
|
906
|
+
let anyChanges = false;
|
|
907
|
+
let extra = {};
|
|
908
|
+
for (let optionName in raw) {
|
|
909
|
+
if (raw[optionName] === currentRaw[optionName] ||
|
|
910
|
+
(internalCommon.COMPLEX_OPTION_COMPARATORS[optionName] &&
|
|
911
|
+
internalCommon.COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], currentRaw[optionName]))) {
|
|
912
|
+
refined[optionName] = currentRefined[optionName];
|
|
913
|
+
}
|
|
914
|
+
else {
|
|
915
|
+
if (raw[optionName] === this.currentCalendarOptionsInput[optionName] ||
|
|
916
|
+
(internalCommon.COMPLEX_OPTION_COMPARATORS[optionName] &&
|
|
917
|
+
internalCommon.COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], this.currentCalendarOptionsInput[optionName]))) {
|
|
918
|
+
if (optionName in this.currentCalendarOptionsRefined) { // might be an "extra" prop
|
|
919
|
+
refined[optionName] = this.currentCalendarOptionsRefined[optionName];
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
else if (refiners[optionName]) {
|
|
923
|
+
refined[optionName] = refiners[optionName](raw[optionName]);
|
|
924
|
+
}
|
|
925
|
+
else {
|
|
926
|
+
extra[optionName] = raw[optionName];
|
|
927
|
+
}
|
|
928
|
+
anyChanges = true;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
if (anyChanges) {
|
|
932
|
+
this.currentViewOptionsInput = raw;
|
|
933
|
+
this.currentViewOptionsRefined = refined;
|
|
934
|
+
}
|
|
935
|
+
return {
|
|
936
|
+
rawOptions: this.currentViewOptionsInput,
|
|
937
|
+
refinedOptions: this.currentViewOptionsRefined,
|
|
938
|
+
extra,
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
function buildDateEnv$1(timeZone, explicitLocale, weekNumberCalculation, firstDay, weekText, pluginHooks, availableLocaleData, defaultSeparator) {
|
|
943
|
+
let locale = buildLocale(explicitLocale || availableLocaleData.defaultCode, availableLocaleData.map);
|
|
944
|
+
return new internalCommon.DateEnv({
|
|
945
|
+
calendarSystem: 'gregory',
|
|
946
|
+
timeZone,
|
|
947
|
+
namedTimeZoneImpl: pluginHooks.namedTimeZonedImpl,
|
|
948
|
+
locale,
|
|
949
|
+
weekNumberCalculation,
|
|
950
|
+
firstDay,
|
|
951
|
+
weekText,
|
|
952
|
+
cmdFormatter: pluginHooks.cmdFormatter,
|
|
953
|
+
defaultSeparator,
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
function buildTheme(options, pluginHooks) {
|
|
957
|
+
let ThemeClass = pluginHooks.themeClasses[options.themeSystem] || StandardTheme;
|
|
958
|
+
return new ThemeClass(options);
|
|
959
|
+
}
|
|
960
|
+
function buildDateProfileGenerator(props) {
|
|
961
|
+
let DateProfileGeneratorClass = props.dateProfileGeneratorClass || internalCommon.DateProfileGenerator;
|
|
962
|
+
return new DateProfileGeneratorClass(props);
|
|
963
|
+
}
|
|
964
|
+
function buildViewApi(type, getCurrentData, dateEnv) {
|
|
965
|
+
return new ViewImpl(type, getCurrentData, dateEnv);
|
|
966
|
+
}
|
|
967
|
+
function buildEventUiBySource(eventSources) {
|
|
968
|
+
return internalCommon.mapHash(eventSources, (eventSource) => eventSource.ui);
|
|
969
|
+
}
|
|
970
|
+
function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) {
|
|
971
|
+
let eventUiBases = { '': eventUiSingleBase };
|
|
972
|
+
for (let defId in eventDefs) {
|
|
973
|
+
let def = eventDefs[defId];
|
|
974
|
+
if (def.sourceId && eventUiBySource[def.sourceId]) {
|
|
975
|
+
eventUiBases[defId] = eventUiBySource[def.sourceId];
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
return eventUiBases;
|
|
979
|
+
}
|
|
980
|
+
function buildViewUiProps(calendarContext) {
|
|
981
|
+
let { options } = calendarContext;
|
|
982
|
+
return {
|
|
983
|
+
eventUiSingleBase: internalCommon.createEventUi({
|
|
984
|
+
display: options.eventDisplay,
|
|
985
|
+
editable: options.editable,
|
|
986
|
+
startEditable: options.eventStartEditable,
|
|
987
|
+
durationEditable: options.eventDurationEditable,
|
|
988
|
+
constraint: options.eventConstraint,
|
|
989
|
+
overlap: typeof options.eventOverlap === 'boolean' ? options.eventOverlap : undefined,
|
|
990
|
+
allow: options.eventAllow,
|
|
991
|
+
backgroundColor: options.eventBackgroundColor,
|
|
992
|
+
borderColor: options.eventBorderColor,
|
|
993
|
+
textColor: options.eventTextColor,
|
|
994
|
+
color: options.eventColor,
|
|
995
|
+
// classNames: options.eventClassNames // render hook will handle this
|
|
996
|
+
}, calendarContext),
|
|
997
|
+
selectionConfig: internalCommon.createEventUi({
|
|
998
|
+
constraint: options.selectConstraint,
|
|
999
|
+
overlap: typeof options.selectOverlap === 'boolean' ? options.selectOverlap : undefined,
|
|
1000
|
+
allow: options.selectAllow,
|
|
1001
|
+
}, calendarContext),
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
function computeIsLoading(state, context) {
|
|
1005
|
+
for (let isLoadingFunc of context.pluginHooks.isLoadingFuncs) {
|
|
1006
|
+
if (isLoadingFunc(state)) {
|
|
1007
|
+
return true;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
return false;
|
|
1011
|
+
}
|
|
1012
|
+
function parseContextBusinessHours(calendarContext) {
|
|
1013
|
+
return internalCommon.parseBusinessHours(calendarContext.options.businessHours, calendarContext);
|
|
1014
|
+
}
|
|
1015
|
+
function warnUnknownOptions(options, viewName) {
|
|
1016
|
+
for (let optionName in options) {
|
|
1017
|
+
console.warn(`Unknown option '${optionName}'` +
|
|
1018
|
+
(viewName ? ` for view '${viewName}'` : ''));
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
class ToolbarSection extends internalCommon.BaseComponent {
|
|
1023
|
+
render() {
|
|
1024
|
+
let children = this.props.widgetGroups.map((widgetGroup) => this.renderWidgetGroup(widgetGroup));
|
|
1025
|
+
return preact.createElement('div', { className: 'fc-toolbar-chunk' }, ...children);
|
|
1026
|
+
}
|
|
1027
|
+
renderWidgetGroup(widgetGroup) {
|
|
1028
|
+
let { props } = this;
|
|
1029
|
+
let { theme } = this.context;
|
|
1030
|
+
let children = [];
|
|
1031
|
+
let isOnlyButtons = true;
|
|
1032
|
+
for (let widget of widgetGroup) {
|
|
1033
|
+
let { buttonName, buttonClick, buttonText, buttonIcon, buttonHint } = widget;
|
|
1034
|
+
if (buttonName === 'title') {
|
|
1035
|
+
isOnlyButtons = false;
|
|
1036
|
+
children.push(preact.createElement("h2", { className: "fc-toolbar-title", id: props.titleId }, props.title));
|
|
1037
|
+
}
|
|
1038
|
+
else {
|
|
1039
|
+
let isPressed = buttonName === props.activeButton;
|
|
1040
|
+
let isDisabled = (!props.isTodayEnabled && buttonName === 'today') ||
|
|
1041
|
+
(!props.isPrevEnabled && buttonName === 'prev') ||
|
|
1042
|
+
(!props.isNextEnabled && buttonName === 'next');
|
|
1043
|
+
let buttonClasses = [`fc-${buttonName}-button`, theme.getClass('button')];
|
|
1044
|
+
if (isPressed) {
|
|
1045
|
+
buttonClasses.push(theme.getClass('buttonActive'));
|
|
1046
|
+
}
|
|
1047
|
+
children.push(preact.createElement("button", { type: "button", title: typeof buttonHint === 'function' ? buttonHint(props.navUnit) : buttonHint, disabled: isDisabled, "aria-pressed": isPressed, className: buttonClasses.join(' '), onClick: buttonClick }, buttonText || (buttonIcon ? preact.createElement("span", { className: buttonIcon }) : '')));
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
if (children.length > 1) {
|
|
1051
|
+
let groupClassName = (isOnlyButtons && theme.getClass('buttonGroup')) || '';
|
|
1052
|
+
return preact.createElement('div', { className: groupClassName }, ...children);
|
|
1053
|
+
}
|
|
1054
|
+
return children[0];
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
class Toolbar extends internalCommon.BaseComponent {
|
|
1059
|
+
render() {
|
|
1060
|
+
let { model, extraClassName } = this.props;
|
|
1061
|
+
let forceLtr = false;
|
|
1062
|
+
let startContent;
|
|
1063
|
+
let endContent;
|
|
1064
|
+
let sectionWidgets = model.sectionWidgets;
|
|
1065
|
+
let centerContent = sectionWidgets.center;
|
|
1066
|
+
if (sectionWidgets.left) {
|
|
1067
|
+
forceLtr = true;
|
|
1068
|
+
startContent = sectionWidgets.left;
|
|
1069
|
+
}
|
|
1070
|
+
else {
|
|
1071
|
+
startContent = sectionWidgets.start;
|
|
1072
|
+
}
|
|
1073
|
+
if (sectionWidgets.right) {
|
|
1074
|
+
forceLtr = true;
|
|
1075
|
+
endContent = sectionWidgets.right;
|
|
1076
|
+
}
|
|
1077
|
+
else {
|
|
1078
|
+
endContent = sectionWidgets.end;
|
|
1079
|
+
}
|
|
1080
|
+
let classNames = [
|
|
1081
|
+
extraClassName || '',
|
|
1082
|
+
'fc-toolbar',
|
|
1083
|
+
forceLtr ? 'fc-toolbar-ltr' : '',
|
|
1084
|
+
];
|
|
1085
|
+
return (preact.createElement("div", { className: classNames.join(' ') },
|
|
1086
|
+
this.renderSection('start', startContent || []),
|
|
1087
|
+
this.renderSection('center', centerContent || []),
|
|
1088
|
+
this.renderSection('end', endContent || [])));
|
|
1089
|
+
}
|
|
1090
|
+
renderSection(key, widgetGroups) {
|
|
1091
|
+
let { props } = this;
|
|
1092
|
+
return (preact.createElement(ToolbarSection, { key: key, widgetGroups: widgetGroups, title: props.title, navUnit: props.navUnit, activeButton: props.activeButton, isTodayEnabled: props.isTodayEnabled, isPrevEnabled: props.isPrevEnabled, isNextEnabled: props.isNextEnabled, titleId: props.titleId }));
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
// TODO: do function component?
|
|
1097
|
+
class ViewContainer extends internalCommon.BaseComponent {
|
|
1098
|
+
constructor() {
|
|
1099
|
+
super(...arguments);
|
|
1100
|
+
this.state = {
|
|
1101
|
+
availableWidth: null,
|
|
1102
|
+
};
|
|
1103
|
+
this.handleEl = (el) => {
|
|
1104
|
+
this.el = el;
|
|
1105
|
+
internalCommon.setRef(this.props.elRef, el);
|
|
1106
|
+
this.updateAvailableWidth();
|
|
1107
|
+
};
|
|
1108
|
+
this.handleResize = () => {
|
|
1109
|
+
this.updateAvailableWidth();
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
render() {
|
|
1113
|
+
let { props, state } = this;
|
|
1114
|
+
let { aspectRatio } = props;
|
|
1115
|
+
let classNames = [
|
|
1116
|
+
'fc-view-harness',
|
|
1117
|
+
(aspectRatio || props.liquid || props.height)
|
|
1118
|
+
? 'fc-view-harness-active' // harness controls the height
|
|
1119
|
+
: 'fc-view-harness-passive', // let the view do the height
|
|
1120
|
+
];
|
|
1121
|
+
let height = '';
|
|
1122
|
+
let paddingBottom = '';
|
|
1123
|
+
if (aspectRatio) {
|
|
1124
|
+
if (state.availableWidth !== null) {
|
|
1125
|
+
height = state.availableWidth / aspectRatio;
|
|
1126
|
+
}
|
|
1127
|
+
else {
|
|
1128
|
+
// while waiting to know availableWidth, we can't set height to *zero*
|
|
1129
|
+
// because will cause lots of unnecessary scrollbars within scrollgrid.
|
|
1130
|
+
// BETTER: don't start rendering ANYTHING yet until we know container width
|
|
1131
|
+
// NOTE: why not always use paddingBottom? Causes height oscillation (issue 5606)
|
|
1132
|
+
paddingBottom = `${(1 / aspectRatio) * 100}%`;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
else {
|
|
1136
|
+
height = props.height || '';
|
|
1137
|
+
}
|
|
1138
|
+
return (preact.createElement("div", { "aria-labelledby": props.labeledById, ref: this.handleEl, className: classNames.join(' '), style: { height, paddingBottom } }, props.children));
|
|
1139
|
+
}
|
|
1140
|
+
componentDidMount() {
|
|
1141
|
+
this.context.addResizeHandler(this.handleResize);
|
|
1142
|
+
}
|
|
1143
|
+
componentWillUnmount() {
|
|
1144
|
+
this.context.removeResizeHandler(this.handleResize);
|
|
1145
|
+
}
|
|
1146
|
+
updateAvailableWidth() {
|
|
1147
|
+
if (this.el && // needed. but why?
|
|
1148
|
+
this.props.aspectRatio // aspectRatio is the only height setting that needs availableWidth
|
|
1149
|
+
) {
|
|
1150
|
+
this.setState({ availableWidth: this.el.offsetWidth });
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
/*
|
|
1156
|
+
Detects when the user clicks on an event within a DateComponent
|
|
1157
|
+
*/
|
|
1158
|
+
class EventClicking extends internalCommon.Interaction {
|
|
1159
|
+
constructor(settings) {
|
|
1160
|
+
super(settings);
|
|
1161
|
+
this.handleSegClick = (ev, segEl) => {
|
|
1162
|
+
let { component } = this;
|
|
1163
|
+
let { context } = component;
|
|
1164
|
+
let seg = internalCommon.getElSeg(segEl);
|
|
1165
|
+
if (seg && // might be the <div> surrounding the more link
|
|
1166
|
+
component.isValidSegDownEl(ev.target)) {
|
|
1167
|
+
// our way to simulate a link click for elements that can't be <a> tags
|
|
1168
|
+
// grab before trigger fired in case trigger trashes DOM thru rerendering
|
|
1169
|
+
let hasUrlContainer = internalCommon.elementClosest(ev.target, '.fc-event-forced-url');
|
|
1170
|
+
let url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : '';
|
|
1171
|
+
context.emitter.trigger('eventClick', {
|
|
1172
|
+
el: segEl,
|
|
1173
|
+
event: new internalCommon.EventImpl(component.context, seg.eventRange.def, seg.eventRange.instance),
|
|
1174
|
+
jsEvent: ev,
|
|
1175
|
+
view: context.viewApi,
|
|
1176
|
+
});
|
|
1177
|
+
if (url && !ev.defaultPrevented) {
|
|
1178
|
+
window.location.href = url;
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
this.destroy = internalCommon.listenBySelector(settings.el, 'click', '.fc-event', // on both fg and bg events
|
|
1183
|
+
this.handleSegClick);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
/*
|
|
1188
|
+
Triggers events and adds/removes core classNames when the user's pointer
|
|
1189
|
+
enters/leaves event-elements of a component.
|
|
1190
|
+
*/
|
|
1191
|
+
class EventHovering extends internalCommon.Interaction {
|
|
1192
|
+
constructor(settings) {
|
|
1193
|
+
super(settings);
|
|
1194
|
+
// for simulating an eventMouseLeave when the event el is destroyed while mouse is over it
|
|
1195
|
+
this.handleEventElRemove = (el) => {
|
|
1196
|
+
if (el === this.currentSegEl) {
|
|
1197
|
+
this.handleSegLeave(null, this.currentSegEl);
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
this.handleSegEnter = (ev, segEl) => {
|
|
1201
|
+
if (internalCommon.getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper
|
|
1202
|
+
this.currentSegEl = segEl;
|
|
1203
|
+
this.triggerEvent('eventMouseEnter', ev, segEl);
|
|
1204
|
+
}
|
|
1205
|
+
};
|
|
1206
|
+
this.handleSegLeave = (ev, segEl) => {
|
|
1207
|
+
if (this.currentSegEl) {
|
|
1208
|
+
this.currentSegEl = null;
|
|
1209
|
+
this.triggerEvent('eventMouseLeave', ev, segEl);
|
|
1210
|
+
}
|
|
1211
|
+
};
|
|
1212
|
+
this.removeHoverListeners = internalCommon.listenToHoverBySelector(settings.el, '.fc-event', // on both fg and bg events
|
|
1213
|
+
this.handleSegEnter, this.handleSegLeave);
|
|
1214
|
+
}
|
|
1215
|
+
destroy() {
|
|
1216
|
+
this.removeHoverListeners();
|
|
1217
|
+
}
|
|
1218
|
+
triggerEvent(publicEvName, ev, segEl) {
|
|
1219
|
+
let { component } = this;
|
|
1220
|
+
let { context } = component;
|
|
1221
|
+
let seg = internalCommon.getElSeg(segEl);
|
|
1222
|
+
if (!ev || component.isValidSegDownEl(ev.target)) {
|
|
1223
|
+
context.emitter.trigger(publicEvName, {
|
|
1224
|
+
el: segEl,
|
|
1225
|
+
event: new internalCommon.EventImpl(context, seg.eventRange.def, seg.eventRange.instance),
|
|
1226
|
+
jsEvent: ev,
|
|
1227
|
+
view: context.viewApi,
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
class CalendarContent extends internalCommon.PureComponent {
|
|
1234
|
+
constructor() {
|
|
1235
|
+
super(...arguments);
|
|
1236
|
+
this.buildViewContext = internalCommon.memoize(internalCommon.buildViewContext);
|
|
1237
|
+
this.buildViewPropTransformers = internalCommon.memoize(buildViewPropTransformers);
|
|
1238
|
+
this.buildToolbarProps = internalCommon.memoize(buildToolbarProps);
|
|
1239
|
+
this.headerRef = preact.createRef();
|
|
1240
|
+
this.footerRef = preact.createRef();
|
|
1241
|
+
this.interactionsStore = {};
|
|
1242
|
+
// eslint-disable-next-line
|
|
1243
|
+
this.state = {
|
|
1244
|
+
viewLabelId: internalCommon.getUniqueDomId(),
|
|
1245
|
+
};
|
|
1246
|
+
// Component Registration
|
|
1247
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
1248
|
+
this.registerInteractiveComponent = (component, settingsInput) => {
|
|
1249
|
+
let settings = internalCommon.parseInteractionSettings(component, settingsInput);
|
|
1250
|
+
let DEFAULT_INTERACTIONS = [
|
|
1251
|
+
EventClicking,
|
|
1252
|
+
EventHovering,
|
|
1253
|
+
];
|
|
1254
|
+
let interactionClasses = DEFAULT_INTERACTIONS.concat(this.props.pluginHooks.componentInteractions);
|
|
1255
|
+
let interactions = interactionClasses.map((TheInteractionClass) => new TheInteractionClass(settings));
|
|
1256
|
+
this.interactionsStore[component.uid] = interactions;
|
|
1257
|
+
internalCommon.interactionSettingsStore[component.uid] = settings;
|
|
1258
|
+
};
|
|
1259
|
+
this.unregisterInteractiveComponent = (component) => {
|
|
1260
|
+
let listeners = this.interactionsStore[component.uid];
|
|
1261
|
+
if (listeners) {
|
|
1262
|
+
for (let listener of listeners) {
|
|
1263
|
+
listener.destroy();
|
|
1264
|
+
}
|
|
1265
|
+
delete this.interactionsStore[component.uid];
|
|
1266
|
+
}
|
|
1267
|
+
delete internalCommon.interactionSettingsStore[component.uid];
|
|
1268
|
+
};
|
|
1269
|
+
// Resizing
|
|
1270
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
1271
|
+
this.resizeRunner = new internalCommon.DelayedRunner(() => {
|
|
1272
|
+
this.props.emitter.trigger('_resize', true); // should window resizes be considered "forced" ?
|
|
1273
|
+
this.props.emitter.trigger('windowResize', { view: this.props.viewApi });
|
|
1274
|
+
});
|
|
1275
|
+
this.handleWindowResize = (ev) => {
|
|
1276
|
+
let { options } = this.props;
|
|
1277
|
+
if (options.handleWindowResize &&
|
|
1278
|
+
ev.target === window // avoid jqui events
|
|
1279
|
+
) {
|
|
1280
|
+
this.resizeRunner.request(options.windowResizeDelay);
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
/*
|
|
1285
|
+
renders INSIDE of an outer div
|
|
1286
|
+
*/
|
|
1287
|
+
render() {
|
|
1288
|
+
let { props } = this;
|
|
1289
|
+
let { toolbarConfig, options } = props;
|
|
1290
|
+
let toolbarProps = this.buildToolbarProps(props.viewSpec, props.dateProfile, props.dateProfileGenerator, props.currentDate, internalCommon.getNow(props.options.now, props.dateEnv), // TODO: use NowTimer????
|
|
1291
|
+
props.viewTitle);
|
|
1292
|
+
let viewVGrow = false;
|
|
1293
|
+
let viewHeight = '';
|
|
1294
|
+
let viewAspectRatio;
|
|
1295
|
+
if (props.isHeightAuto || props.forPrint) {
|
|
1296
|
+
viewHeight = '';
|
|
1297
|
+
}
|
|
1298
|
+
else if (options.height != null) {
|
|
1299
|
+
viewVGrow = true;
|
|
1300
|
+
}
|
|
1301
|
+
else if (options.contentHeight != null) {
|
|
1302
|
+
viewHeight = options.contentHeight;
|
|
1303
|
+
}
|
|
1304
|
+
else {
|
|
1305
|
+
viewAspectRatio = Math.max(options.aspectRatio, 0.5); // prevent from getting too tall
|
|
1306
|
+
}
|
|
1307
|
+
let viewContext = this.buildViewContext(props.viewSpec, props.viewApi, props.options, props.dateProfileGenerator, props.dateEnv, props.theme, props.pluginHooks, props.dispatch, props.getCurrentData, props.emitter, props.calendarApi, this.registerInteractiveComponent, this.unregisterInteractiveComponent);
|
|
1308
|
+
let viewLabelId = (toolbarConfig.header && toolbarConfig.header.hasTitle)
|
|
1309
|
+
? this.state.viewLabelId
|
|
1310
|
+
: '';
|
|
1311
|
+
return (preact.createElement(internalCommon.ViewContextType.Provider, { value: viewContext },
|
|
1312
|
+
toolbarConfig.header && (preact.createElement(Toolbar, Object.assign({ ref: this.headerRef, extraClassName: "fc-header-toolbar", model: toolbarConfig.header, titleId: viewLabelId }, toolbarProps))),
|
|
1313
|
+
preact.createElement(ViewContainer, { liquid: viewVGrow, height: viewHeight, aspectRatio: viewAspectRatio, labeledById: viewLabelId },
|
|
1314
|
+
this.renderView(props),
|
|
1315
|
+
this.buildAppendContent()),
|
|
1316
|
+
toolbarConfig.footer && (preact.createElement(Toolbar, Object.assign({ ref: this.footerRef, extraClassName: "fc-footer-toolbar", model: toolbarConfig.footer, titleId: "" }, toolbarProps)))));
|
|
1317
|
+
}
|
|
1318
|
+
componentDidMount() {
|
|
1319
|
+
let { props } = this;
|
|
1320
|
+
this.calendarInteractions = props.pluginHooks.calendarInteractions
|
|
1321
|
+
.map((CalendarInteractionClass) => new CalendarInteractionClass(props));
|
|
1322
|
+
window.addEventListener('resize', this.handleWindowResize);
|
|
1323
|
+
let { propSetHandlers } = props.pluginHooks;
|
|
1324
|
+
for (let propName in propSetHandlers) {
|
|
1325
|
+
propSetHandlers[propName](props[propName], props);
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
componentDidUpdate(prevProps) {
|
|
1329
|
+
let { props } = this;
|
|
1330
|
+
let { propSetHandlers } = props.pluginHooks;
|
|
1331
|
+
for (let propName in propSetHandlers) {
|
|
1332
|
+
if (props[propName] !== prevProps[propName]) {
|
|
1333
|
+
propSetHandlers[propName](props[propName], props);
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
componentWillUnmount() {
|
|
1338
|
+
window.removeEventListener('resize', this.handleWindowResize);
|
|
1339
|
+
this.resizeRunner.clear();
|
|
1340
|
+
for (let interaction of this.calendarInteractions) {
|
|
1341
|
+
interaction.destroy();
|
|
1342
|
+
}
|
|
1343
|
+
this.props.emitter.trigger('_unmount');
|
|
1344
|
+
}
|
|
1345
|
+
buildAppendContent() {
|
|
1346
|
+
let { props } = this;
|
|
1347
|
+
let children = props.pluginHooks.viewContainerAppends.map((buildAppendContent) => buildAppendContent(props));
|
|
1348
|
+
return preact.createElement(preact.Fragment, {}, ...children);
|
|
1349
|
+
}
|
|
1350
|
+
renderView(props) {
|
|
1351
|
+
let { pluginHooks } = props;
|
|
1352
|
+
let { viewSpec } = props;
|
|
1353
|
+
let viewProps = {
|
|
1354
|
+
dateProfile: props.dateProfile,
|
|
1355
|
+
businessHours: props.businessHours,
|
|
1356
|
+
eventStore: props.renderableEventStore,
|
|
1357
|
+
eventUiBases: props.eventUiBases,
|
|
1358
|
+
dateSelection: props.dateSelection,
|
|
1359
|
+
eventSelection: props.eventSelection,
|
|
1360
|
+
eventDrag: props.eventDrag,
|
|
1361
|
+
eventResize: props.eventResize,
|
|
1362
|
+
isHeightAuto: props.isHeightAuto,
|
|
1363
|
+
forPrint: props.forPrint,
|
|
1364
|
+
};
|
|
1365
|
+
let transformers = this.buildViewPropTransformers(pluginHooks.viewPropsTransformers);
|
|
1366
|
+
for (let transformer of transformers) {
|
|
1367
|
+
Object.assign(viewProps, transformer.transform(viewProps, props));
|
|
1368
|
+
}
|
|
1369
|
+
let ViewComponent = viewSpec.component;
|
|
1370
|
+
return (preact.createElement(ViewComponent, Object.assign({}, viewProps)));
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
function buildToolbarProps(viewSpec, dateProfile, dateProfileGenerator, currentDate, now, title) {
|
|
1374
|
+
// don't force any date-profiles to valid date profiles (the `false`) so that we can tell if it's invalid
|
|
1375
|
+
let todayInfo = dateProfileGenerator.build(now, undefined, false); // TODO: need `undefined` or else INFINITE LOOP for some reason
|
|
1376
|
+
let prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate, false);
|
|
1377
|
+
let nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate, false);
|
|
1378
|
+
return {
|
|
1379
|
+
title,
|
|
1380
|
+
activeButton: viewSpec.type,
|
|
1381
|
+
navUnit: viewSpec.singleUnit,
|
|
1382
|
+
isTodayEnabled: todayInfo.isValid && !internalCommon.rangeContainsMarker(dateProfile.currentRange, now),
|
|
1383
|
+
isPrevEnabled: prevInfo.isValid,
|
|
1384
|
+
isNextEnabled: nextInfo.isValid,
|
|
1385
|
+
};
|
|
1386
|
+
}
|
|
1387
|
+
// Plugin
|
|
1388
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
1389
|
+
function buildViewPropTransformers(theClasses) {
|
|
1390
|
+
return theClasses.map((TheClass) => new TheClass());
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
class Calendar extends internalCommon.CalendarImpl {
|
|
1394
|
+
constructor(el, optionOverrides = {}) {
|
|
1395
|
+
super();
|
|
1396
|
+
this.isRendering = false;
|
|
1397
|
+
this.isRendered = false;
|
|
1398
|
+
this.currentClassNames = [];
|
|
1399
|
+
this.customContentRenderId = 0;
|
|
1400
|
+
this.handleAction = (action) => {
|
|
1401
|
+
// actions we know we want to render immediately
|
|
1402
|
+
switch (action.type) {
|
|
1403
|
+
case 'SET_EVENT_DRAG':
|
|
1404
|
+
case 'SET_EVENT_RESIZE':
|
|
1405
|
+
this.renderRunner.tryDrain();
|
|
1406
|
+
}
|
|
1407
|
+
};
|
|
1408
|
+
this.handleData = (data) => {
|
|
1409
|
+
this.currentData = data;
|
|
1410
|
+
this.renderRunner.request(data.calendarOptions.rerenderDelay);
|
|
1411
|
+
};
|
|
1412
|
+
this.handleRenderRequest = () => {
|
|
1413
|
+
if (this.isRendering) {
|
|
1414
|
+
this.isRendered = true;
|
|
1415
|
+
let { currentData } = this;
|
|
1416
|
+
internalCommon.flushSync(() => {
|
|
1417
|
+
preact.render(preact.createElement(internalCommon.CalendarRoot, { options: currentData.calendarOptions, theme: currentData.theme, emitter: currentData.emitter }, (classNames, height, isHeightAuto, forPrint) => {
|
|
1418
|
+
this.setClassNames(classNames);
|
|
1419
|
+
this.setHeight(height);
|
|
1420
|
+
return (preact.createElement(internalCommon.RenderId.Provider, { value: this.customContentRenderId },
|
|
1421
|
+
preact.createElement(CalendarContent, Object.assign({ isHeightAuto: isHeightAuto, forPrint: forPrint }, currentData))));
|
|
1422
|
+
}), this.el);
|
|
1423
|
+
});
|
|
1424
|
+
}
|
|
1425
|
+
else if (this.isRendered) {
|
|
1426
|
+
this.isRendered = false;
|
|
1427
|
+
preact.render(null, this.el);
|
|
1428
|
+
this.setClassNames([]);
|
|
1429
|
+
this.setHeight('');
|
|
1430
|
+
}
|
|
1431
|
+
};
|
|
1432
|
+
this.el = el;
|
|
1433
|
+
this.renderRunner = new internalCommon.DelayedRunner(this.handleRenderRequest);
|
|
1434
|
+
new CalendarDataManager({
|
|
1435
|
+
optionOverrides,
|
|
1436
|
+
calendarApi: this,
|
|
1437
|
+
onAction: this.handleAction,
|
|
1438
|
+
onData: this.handleData,
|
|
1439
|
+
});
|
|
1440
|
+
}
|
|
1441
|
+
render() {
|
|
1442
|
+
let wasRendering = this.isRendering;
|
|
1443
|
+
if (!wasRendering) {
|
|
1444
|
+
this.isRendering = true;
|
|
1445
|
+
}
|
|
1446
|
+
else {
|
|
1447
|
+
this.customContentRenderId += 1;
|
|
1448
|
+
}
|
|
1449
|
+
this.renderRunner.request();
|
|
1450
|
+
if (wasRendering) {
|
|
1451
|
+
this.updateSize();
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
destroy() {
|
|
1455
|
+
if (this.isRendering) {
|
|
1456
|
+
this.isRendering = false;
|
|
1457
|
+
this.renderRunner.request();
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
updateSize() {
|
|
1461
|
+
internalCommon.flushSync(() => {
|
|
1462
|
+
super.updateSize();
|
|
1463
|
+
});
|
|
1464
|
+
}
|
|
1465
|
+
batchRendering(func) {
|
|
1466
|
+
this.renderRunner.pause('batchRendering');
|
|
1467
|
+
func();
|
|
1468
|
+
this.renderRunner.resume('batchRendering');
|
|
1469
|
+
}
|
|
1470
|
+
pauseRendering() {
|
|
1471
|
+
this.renderRunner.pause('pauseRendering');
|
|
1472
|
+
}
|
|
1473
|
+
resumeRendering() {
|
|
1474
|
+
this.renderRunner.resume('pauseRendering', true);
|
|
1475
|
+
}
|
|
1476
|
+
resetOptions(optionOverrides, append) {
|
|
1477
|
+
this.currentDataManager.resetOptions(optionOverrides, append);
|
|
1478
|
+
}
|
|
1479
|
+
setClassNames(classNames) {
|
|
1480
|
+
if (!internalCommon.isArraysEqual(classNames, this.currentClassNames)) {
|
|
1481
|
+
let { classList } = this.el;
|
|
1482
|
+
for (let className of this.currentClassNames) {
|
|
1483
|
+
classList.remove(className);
|
|
1484
|
+
}
|
|
1485
|
+
for (let className of classNames) {
|
|
1486
|
+
classList.add(className);
|
|
1487
|
+
}
|
|
1488
|
+
this.currentClassNames = classNames;
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
setHeight(height) {
|
|
1492
|
+
internalCommon.applyStyleProp(this.el, 'height', height);
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
function formatDate(dateInput, options = {}) {
|
|
1497
|
+
let dateEnv = buildDateEnv(options);
|
|
1498
|
+
let formatter = internalCommon.createFormatter(options);
|
|
1499
|
+
let dateMeta = dateEnv.createMarkerMeta(dateInput);
|
|
1500
|
+
if (!dateMeta) { // TODO: warning?
|
|
1501
|
+
return '';
|
|
1502
|
+
}
|
|
1503
|
+
return dateEnv.format(dateMeta.marker, formatter, {
|
|
1504
|
+
forcedTzo: dateMeta.forcedTzo,
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
function formatRange(startInput, endInput, options) {
|
|
1508
|
+
let dateEnv = buildDateEnv(typeof options === 'object' && options ? options : {}); // pass in if non-null object
|
|
1509
|
+
let formatter = internalCommon.createFormatter(options);
|
|
1510
|
+
let startMeta = dateEnv.createMarkerMeta(startInput);
|
|
1511
|
+
let endMeta = dateEnv.createMarkerMeta(endInput);
|
|
1512
|
+
if (!startMeta || !endMeta) { // TODO: warning?
|
|
1513
|
+
return '';
|
|
1514
|
+
}
|
|
1515
|
+
return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, {
|
|
1516
|
+
forcedStartTzo: startMeta.forcedTzo,
|
|
1517
|
+
forcedEndTzo: endMeta.forcedTzo,
|
|
1518
|
+
isEndExclusive: options.isEndExclusive,
|
|
1519
|
+
defaultSeparator: internalCommon.BASE_OPTION_DEFAULTS.defaultRangeSeparator,
|
|
1520
|
+
});
|
|
1521
|
+
}
|
|
1522
|
+
// TODO: more DRY and optimized
|
|
1523
|
+
function buildDateEnv(settings) {
|
|
1524
|
+
let locale = buildLocale(settings.locale || 'en', organizeRawLocales([]).map); // TODO: don't hardcode 'en' everywhere
|
|
1525
|
+
return new internalCommon.DateEnv(Object.assign(Object.assign({ timeZone: internalCommon.BASE_OPTION_DEFAULTS.timeZone, calendarSystem: 'gregory' }, settings), { locale }));
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
// HELPERS
|
|
1529
|
+
/*
|
|
1530
|
+
if nextDayThreshold is specified, slicing is done in an all-day fashion.
|
|
1531
|
+
you can get nextDayThreshold from context.nextDayThreshold
|
|
1532
|
+
*/
|
|
1533
|
+
function sliceEvents(props, allDay) {
|
|
1534
|
+
return internalCommon.sliceEventStore(props.eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? props.nextDayThreshold : null).fg;
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
const version = '6.0.0-beta.2';
|
|
1538
|
+
|
|
1539
|
+
exports.JsonRequestError = internalCommon.JsonRequestError;
|
|
1540
|
+
exports.createPlugin = internalCommon.createPlugin;
|
|
1541
|
+
exports.Calendar = Calendar;
|
|
1542
|
+
exports.formatDate = formatDate;
|
|
1543
|
+
exports.formatRange = formatRange;
|
|
1544
|
+
exports.sliceEvents = sliceEvents;
|
|
1545
|
+
exports.version = version;
|